@@ -84,6 +84,41 @@ func TestTypedToolRegistrationInfersSchemasAndValidates(t *testing.T) {
8484 assert .Equal (t , 1 , handlerCalls , "SDK validation must reject invalid arguments before calling the handler" )
8585}
8686
87+ func TestTypedToolLegacySchemaRetainsHeaderRoutingMetadata (t * testing.T ) {
88+ tool := NewServerToolWithContextHandler (
89+ mcp.Tool {Name : "legacy_routing_tool" },
90+ testToolsetMetadata ("test" ),
91+ func (_ context.Context , _ * mcp.CallToolRequest , input typedTestInput ) (* mcp.CallToolResult , typedTestOutput , error ) {
92+ return & mcp.CallToolResult {
93+ Content : []mcp.Content {& mcp.TextContent {Text : "legacy text result" }},
94+ }, typedTestOutput {Query : input .Query }, nil
95+ },
96+ )
97+ server := mcp .NewServer (& mcp.Implementation {Name : "test-server" , Version : "v0.0.1" }, nil )
98+ tool .RegisterFunc (server , nil )
99+ session := connectTypedTestClient (t , server , "2025-11-25" )
100+
101+ list , err := session .ListTools (context .Background (), nil )
102+ require .NoError (t , err )
103+ require .Len (t , list .Tools , 1 )
104+ assert .Nil (t , list .Tools [0 ].OutputSchema )
105+ var inputSchema map [string ]any
106+ require .NoError (t , json .Unmarshal ([]byte (mustMarshalJSON (t , list .Tools [0 ].InputSchema )), & inputSchema ))
107+ properties := inputSchema ["properties" ].(map [string ]any )
108+ assert .Equal (t , "owner" , properties ["owner" ].(map [string ]any )["x-mcp-header" ])
109+ assert .Equal (t , "repo" , properties ["repo" ].(map [string ]any )["x-mcp-header" ])
110+
111+ result , err := session .CallTool (context .Background (), & mcp.CallToolParams {
112+ Name : "legacy_routing_tool" ,
113+ Arguments : map [string ]any {"owner" : "octo" , "repo" : "hello" , "query" : "is:open" },
114+ })
115+ require .NoError (t , err )
116+ require .False (t , result .IsError )
117+ assert .Nil (t , result .StructuredContent )
118+ require .Len (t , result .Content , 1 )
119+ assert .Equal (t , "legacy text result" , result .Content [0 ].(* mcp.TextContent ).Text )
120+ }
121+
87122func TestTypedToolInferredInputSchemaUsesStablePointer (t * testing.T ) {
88123 type input struct {
89124 Owner string `json:"owner"`
@@ -1723,11 +1758,18 @@ func TestTypedToolSupportsExplicitRootUnionOutputSchema(t *testing.T) {
17231758}
17241759
17251760func TestTypedOutputProtocolGateUsesStatelessRequestVersion (t * testing.T ) {
1761+ inputSchema := & jsonschema.Schema {
1762+ Type : "object" ,
1763+ Properties : map [string ]* jsonschema.Schema {
1764+ "owner" : {Type : "string" , Extra : map [string ]any {"x-mcp-header" : "owner" }},
1765+ },
1766+ }
17261767 modernTool := & mcp.Tool {
17271768 Name : "typed_tool" ,
1769+ InputSchema : inputSchema ,
17281770 OutputSchema : json .RawMessage (`{"type":"object"}` ),
17291771 }
1730- legacyTool := & mcp.Tool {Name : "typed_tool" }
1772+ legacyTool := & mcp.Tool {Name : "typed_tool" , InputSchema : inputSchema }
17311773 registration := & typedToolRegistration {
17321774 name : "typed_tool" ,
17331775 modernTool : modernTool ,
@@ -1765,6 +1807,8 @@ func TestTypedOutputProtocolGateUsesStatelessRequestVersion(t *testing.T) {
17651807 list := listResult .(* mcp.ListToolsResult )
17661808 require .Len (t , list .Tools , 1 )
17671809 assert .Same (t , tc .wantTool , list .Tools [0 ])
1810+ assert .Contains (t , mustMarshalJSON (t , list .Tools [0 ].InputSchema ), `"x-mcp-header":"owner"` ,
1811+ "legacy and unknown-version variants must retain routing metadata" )
17681812 })
17691813 }
17701814
0 commit comments