Skip to content

Commit 113a4ec

Browse files
a6b8claude
andcommitted
feat(elicitation): sub-agent proxy + createToolClient chain
- SubAgentToolClient: elicitation/create handler forwarding to onElicit - ToolRegistry.createToolClient: passes onElicit to connect() - AgentToolsServer: onElicit chain from server → toolClient → sub-agent - 127 tests passing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 67575fa commit 113a4ec

3 files changed

Lines changed: 44 additions & 19 deletions

File tree

src/AgentToolsServer.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,21 @@ class AgentToolsServer extends EventEmitter {
325325
const taskId = randomUUID()
326326
const query = args.query || JSON.stringify( args )
327327

328-
const { toolClient } = await toolRegistry.createToolClient( { name: toolName } )
328+
const onElicit = mcpServer && toolConfig.elicitation?.enabled
329+
? async ( { message, requestedSchema }: { message: string, requestedSchema: any } ) => {
330+
try {
331+
const result = await mcpServer.elicitInput( { message, requestedSchema } )
332+
333+
return result
334+
} catch( err: any ) {
335+
Logger.error( 'AgentServer', `Elicitation failed: ${err.message}` )
336+
337+
return { action: 'cancel' as const }
338+
}
339+
}
340+
: undefined
341+
342+
const { toolClient } = await toolRegistry.createToolClient( { name: toolName, onElicit } )
329343

330344
if( !toolClient ) {
331345
return {
@@ -359,19 +373,7 @@ class AgentToolsServer extends EventEmitter {
359373
apiKey,
360374
answerSchema: agent.answerSchema || null,
361375
elicitationConfig: toolConfig.elicitation || undefined,
362-
onElicit: mcpServer && toolConfig.elicitation?.enabled
363-
? async ( { message, requestedSchema }: { message: string, requestedSchema: any } ) => {
364-
try {
365-
const result = await mcpServer.elicitInput( { message, requestedSchema } )
366-
367-
return result
368-
} catch( err: any ) {
369-
Logger.error( 'AgentServer', `Elicitation failed: ${err.message}` )
370-
371-
return { action: 'cancel' as const }
372-
}
373-
}
374-
: undefined,
376+
onElicit,
375377
onStatus: ( { status, round, message }: { status: string, round: number, message: string } ) => {
376378
Logger.info( 'AgentServer', `sync | ${toolName} | ${status} | Round ${round} | ${message}` )
377379

src/client/SubAgentToolClient.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
22
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
3+
import { ElicitRequestSchema } from '@modelcontextprotocol/sdk/types.js'
34

4-
import type { ToolClient, Tool, ToolResult } from '../types/index.js'
5+
import { Logger } from '../logging/Logger.js'
6+
import type { ToolClient, Tool, ToolResult, ElicitCallback } from '../types/index.js'
57

68

79
class SubAgentToolClient implements ToolClient {
@@ -11,6 +13,7 @@ class SubAgentToolClient implements ToolClient {
1113
#name: string
1214
#tools: Map<string, Tool>
1315
#connected: boolean
16+
#onElicit: ElicitCallback | null
1417

1518

1619
constructor( { url, name = 'sub-agent' }: { url: string, name?: string } ) {
@@ -20,10 +23,13 @@ class SubAgentToolClient implements ToolClient {
2023
this.#connected = false
2124
this.#client = null
2225
this.#transport = null
26+
this.#onElicit = null
2327
}
2428

2529

26-
async connect() {
30+
async connect( { onElicit }: { onElicit?: ElicitCallback } = {} ) {
31+
this.#onElicit = onElicit || null
32+
2733
this.#transport = new StreamableHTTPClientTransport(
2834
new URL( this.#url )
2935
)
@@ -33,6 +39,23 @@ class SubAgentToolClient implements ToolClient {
3339
{ capabilities: {} }
3440
)
3541

42+
if( this.#onElicit ) {
43+
const elicitCallback = this.#onElicit
44+
45+
this.#client.setRequestHandler( ElicitRequestSchema, async ( request: any ) => {
46+
const { message, requestedSchema } = request.params
47+
48+
Logger.debug( 'SubAgentToolClient', `Elicitation request from sub-agent "${this.#name}": ${message}` )
49+
50+
const response = await elicitCallback( { message, requestedSchema } )
51+
52+
return {
53+
action: response.action,
54+
content: response.content
55+
}
56+
} )
57+
}
58+
3659
await this.#client.connect( this.#transport )
3760
this.#connected = true
3861

src/registry/ToolRegistry.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { InProcessToolClient } from '../client/InProcessToolClient.js'
22
import { CompositeToolClient } from '../client/CompositeToolClient.js'
33
import { SubAgentToolClient } from '../client/SubAgentToolClient.js'
44
import { Logger } from '../logging/Logger.js'
5-
import type { ToolClient } from '../types/index.js'
5+
import type { ToolClient, ElicitCallback } from '../types/index.js'
66

77

88
class ToolRegistry {
@@ -55,7 +55,7 @@ class ToolRegistry {
5555
}
5656

5757

58-
async createToolClient( { name }: { name: string } ): Promise<{ toolClient: ToolClient | null }> {
58+
async createToolClient( { name, onElicit }: { name: string, onElicit?: ElicitCallback } ): Promise<{ toolClient: ToolClient | null }> {
5959
const { toolConfig } = this.getToolConfig( { name } )
6060

6161
if( !toolConfig ) {
@@ -75,7 +75,7 @@ class ToolRegistry {
7575
const client = ToolRegistry.#createClientFromSource( { source } )
7676

7777
if( client && ( client as any ).connect ) {
78-
await ( client as any ).connect()
78+
await ( client as any ).connect( { onElicit } )
7979
}
8080

8181
return client

0 commit comments

Comments
 (0)