* Register elicitation request/completion handlers on connected MCP clients * that haven't been registered yet. SDK MCP servers are excluded because they * route through SdkControlClientTransport. Hooks run first (matching REPL * behavior); if no hook responds, the request is forwarded to t
(clients: MCPServerConnection[])
| 1289 | * consumer via the control protocol. |
| 1290 | */ |
| 1291 | function registerElicitationHandlers(clients: MCPServerConnection[]): void { |
| 1292 | for (const connection of clients) { |
| 1293 | if ( |
| 1294 | connection.type !== 'connected' || |
| 1295 | elicitationRegistered.has(connection.name) |
| 1296 | ) { |
| 1297 | continue |
| 1298 | } |
| 1299 | // Skip SDK MCP servers — elicitation flows through SdkControlClientTransport |
| 1300 | if (connection.config.type === 'sdk') { |
| 1301 | continue |
| 1302 | } |
| 1303 | const serverName = connection.name |
| 1304 | |
| 1305 | // Wrapped in try/catch because setRequestHandler throws if the client wasn't |
| 1306 | // created with elicitation capability declared (e.g., SDK-created clients). |
| 1307 | try { |
| 1308 | connection.client.setRequestHandler( |
| 1309 | ElicitRequestSchema, |
| 1310 | async (request, extra) => { |
| 1311 | logMCPDebug( |
| 1312 | serverName, |
| 1313 | `Elicitation request received in print mode: ${jsonStringify(request)}`, |
| 1314 | ) |
| 1315 | |
| 1316 | const mode = request.params.mode === 'url' ? 'url' : 'form' |
| 1317 | |
| 1318 | logEvent('tengu_mcp_elicitation_shown', { |
| 1319 | mode: mode as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 1320 | }) |
| 1321 | |
| 1322 | // Run elicitation hooks first — they can provide a response programmatically |
| 1323 | const hookResponse = await runElicitationHooks( |
| 1324 | serverName, |
| 1325 | request.params, |
| 1326 | extra.signal, |
| 1327 | ) |
| 1328 | if (hookResponse) { |
| 1329 | logMCPDebug( |
| 1330 | serverName, |
| 1331 | `Elicitation resolved by hook: ${jsonStringify(hookResponse)}`, |
| 1332 | ) |
| 1333 | logEvent('tengu_mcp_elicitation_response', { |
| 1334 | mode: mode as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 1335 | action: |
| 1336 | hookResponse.action as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 1337 | }) |
| 1338 | return hookResponse |
| 1339 | } |
| 1340 | |
| 1341 | // Delegate to SDK consumer via control protocol |
| 1342 | const url = |
| 1343 | 'url' in request.params |
| 1344 | ? (request.params.url as string) |
| 1345 | : undefined |
| 1346 | const requestedSchema = |
| 1347 | 'requestedSchema' in request.params |
| 1348 | ? (request.params.requestedSchema as |
no test coverage detected