@@ -160,6 +160,12 @@ type ClientOptions struct {
160160 KeepAlive time.Duration
161161}
162162
163+ // toolContextKeyType is the context key type for passing tool definitions
164+ // from CallTool to the transport layer.
165+ type toolContextKeyType struct {}
166+
167+ var toolContextKey = toolContextKeyType {}
168+
163169// bind implements the binder[*ClientSession] interface, so that Clients can
164170// be connected using [connect].
165171func (c * Client ) bind (mcpConn Connection , conn * jsonrpc2.Connection , state * clientSessionState , onClose func ()) * ClientSession {
@@ -318,6 +324,13 @@ type ClientSession struct {
318324 // Pending URL elicitations waiting for completion notifications.
319325 pendingElicitationsMu sync.Mutex
320326 pendingElicitations map [string ]chan struct {}
327+
328+ // toolCacheMu guards toolCache.
329+ toolCacheMu sync.RWMutex
330+ // toolCache stores tool definitions keyed by name.
331+ // It is used to look up x-mcp-header annotations when
332+ // constructing Mcp-Param-* headers for tools/call requests.
333+ toolCache map [string ]* Tool
321334}
322335
323336type clientSessionState struct {
@@ -363,6 +376,21 @@ func (cs *ClientSession) Wait() error {
363376 return cs .conn .Wait ()
364377}
365378
379+ func (cs * ClientSession ) cacheTools (tools []* Tool ) {
380+ cs .toolCacheMu .Lock ()
381+ defer cs .toolCacheMu .Unlock ()
382+ cs .toolCache = make (map [string ]* Tool , len (tools ))
383+ for _ , tool := range tools {
384+ cs .toolCache [tool .Name ] = tool
385+ }
386+ }
387+
388+ func (cs * ClientSession ) getCachedTool (name string ) * Tool {
389+ cs .toolCacheMu .RLock ()
390+ defer cs .toolCacheMu .RUnlock ()
391+ return cs .toolCache [name ]
392+ }
393+
366394// registerElicitationWaiter registers a waiter for an elicitation complete
367395// notification with the given elicitation ID. It returns two functions: an await
368396// function that waits for the notification or context cancellation, and a cleanup
@@ -981,7 +1009,13 @@ func (cs *ClientSession) GetPrompt(ctx context.Context, params *GetPromptParams)
9811009
9821010// ListTools lists tools that are currently available on the server.
9831011func (cs * ClientSession ) ListTools (ctx context.Context , params * ListToolsParams ) (* ListToolsResult , error ) {
984- return handleSend [* ListToolsResult ](ctx , methodListTools , newClientRequest (cs , orZero [Params ](params )))
1012+ result , err := handleSend [* ListToolsResult ](ctx , methodListTools , newClientRequest (cs , orZero [Params ](params )))
1013+ if err != nil {
1014+ return nil , err
1015+ }
1016+ result .Tools = filterValidTools (cs .client .opts .Logger , result .Tools )
1017+ cs .cacheTools (result .Tools )
1018+ return result , nil
9851019}
9861020
9871021// CallTool calls the tool with the given parameters.
@@ -995,6 +1029,9 @@ func (cs *ClientSession) CallTool(ctx context.Context, params *CallToolParams) (
9951029 // Avoid sending nil over the wire.
9961030 params .Arguments = map [string ]any {}
9971031 }
1032+ if tool := cs .getCachedTool (params .Name ); tool != nil {
1033+ ctx = context .WithValue (ctx , toolContextKey , tool )
1034+ }
9981035 return handleSend [* CallToolResult ](ctx , methodCallTool , newClientRequest (cs , orZero [Params ](params )))
9991036}
10001037
0 commit comments