99
1010 "github.com/github/github-mcp-server/internal/githubv4mock"
1111 "github.com/github/github-mcp-server/internal/toolsnaps"
12+ "github.com/github/github-mcp-server/pkg/inventory"
1213 "github.com/github/github-mcp-server/pkg/translations"
1314 "github.com/google/go-github/v92/github"
1415 "github.com/google/jsonschema-go/jsonschema"
@@ -255,23 +256,30 @@ func TestContextToolsTypedRegistration(t *testing.T) {
255256 server := mcp .NewServer (& mcp.Implementation {Name : "test-server" , Version : "v0.0.1" }, nil )
256257 server .AddReceivingMiddleware (InjectDepsMiddleware (deps ))
257258 getMeTool := GetMe (translations .NullTranslationHelper )
258- getMeTool .RegisterFunc (server , nil )
259259 getTeamsTool := GetTeams (translations .NullTranslationHelper )
260- getTeamsTool .RegisterFunc (server , nil )
261260 teamMembersTool := GetTeamMembers (translations .NullTranslationHelper )
262- teamMembersTool .RegisterFunc (server , nil )
261+ inv , err := inventory .NewBuilder ().
262+ SetTools ([]inventory.ServerTool {getMeTool , getTeamsTool , teamMembersTool }).
263+ WithToolsets ([]string {"all" }).
264+ Build ()
265+ require .NoError (t , err )
266+ inv .RegisterTools (context .Background (), server , deps )
263267
264268 serverTransport , clientTransport := mcp .NewInMemoryTransports ()
265269 serverSession , err := server .Connect (context .Background (), serverTransport , nil )
266270 require .NoError (t , err )
267271 t .Cleanup (func () { _ = serverSession .Close () })
268272
269273 client := mcp .NewClient (& mcp.Implementation {Name : "test-client" , Version : "v0.0.1" }, nil )
270- clientSession , err := client .Connect (context .Background (), clientTransport , nil )
274+ clientSession , err := client .Connect (context .Background (), clientTransport , & mcp.ClientSessionOptions {
275+ ProtocolVersion : inventory .ProtocolVersionMultiRoundTrip ,
276+ })
271277 require .NoError (t , err )
278+ require .Equal (t , inventory .ProtocolVersionMultiRoundTrip , clientSession .InitializeResult ().ProtocolVersion )
272279 t .Cleanup (func () { _ = clientSession .Close () })
273280
274- list , err := clientSession .ListTools (context .Background (), nil )
281+ protocolMeta := mcp.Meta {mcp .MetaKeyProtocolVersion : inventory .ProtocolVersionMultiRoundTrip }
282+ list , err := clientSession .ListTools (context .Background (), & mcp.ListToolsParams {Meta : protocolMeta })
275283 require .NoError (t , err )
276284 require .Len (t , list .Tools , 3 )
277285 outputSchemas := make (map [string ]* jsonschema.Resolved )
@@ -299,9 +307,7 @@ func TestContextToolsTypedRegistration(t *testing.T) {
299307 AdditionalProperties * bool `json:"additionalProperties"`
300308 }
301309 require .NoError (t , json .Unmarshal (schemaJSON , & schemaMetadata ))
302- if schemaMetadata .AdditionalProperties != nil {
303- assert .True (t , * schemaMetadata .AdditionalProperties , "explicit true must retain the legacy default" )
304- }
310+ assert .Nil (t , schemaMetadata .AdditionalProperties , "advertised input schema must match the legacy snapshot bytes" )
305311 for propertyName , property := range schema .Properties {
306312 var propertySchema jsonschema.Schema
307313 require .NoError (t , json .Unmarshal (property , & propertySchema ))
@@ -340,6 +346,7 @@ func TestContextToolsTypedRegistration(t *testing.T) {
340346 result , err := clientSession .CallTool (context .Background (), & mcp.CallToolParams {
341347 Name : "get_me" ,
342348 Arguments : map [string ]any {"legacy_ignored_argument" : true },
349+ Meta : protocolMeta ,
343350 })
344351 require .NoError (t , err )
345352 require .False (t , result .IsError )
@@ -362,52 +369,56 @@ func TestContextToolsTypedRegistration(t *testing.T) {
362369 result , err = clientSession .CallTool (context .Background (), & mcp.CallToolParams {
363370 Name : "get_teams" ,
364371 Arguments : map [string ]any {"user" : "specificuser" , "legacy_ignored_argument" : true },
372+ Meta : protocolMeta ,
365373 })
366374 require .NoError (t , err )
367375 require .False (t , result .IsError )
368376 structuredJSON , err = json .Marshal (result .StructuredContent )
369377 require .NoError (t , err )
370378 assert .JSONEq (t , `[{"org":"testorg","teams":[{"name":"team1","slug":"team1","description":"Team 1"}]}]` , string (structuredJSON ))
371- assert .Equal (t , string (structuredJSON ), getTextResult (t , result ).Text )
379+ assert .JSONEq (t , string (structuredJSON ), getTextResult (t , result ).Text )
372380 request = createMCPRequest (map [string ]any {"user" : "specificuser" })
373381 legacyResult , err = getTeamsTool .Handler (deps )(ContextWithDeps (context .Background (), deps ), & request )
374382 require .NoError (t , err )
375383 assert .Equal (t , `[{"org":"testorg","teams":[{"name":"team1","slug":"team1","description":"Team 1"}]}]` , getTextResult (t , legacyResult ).Text )
376384 require .NoError (t , outputSchemas ["get_teams" ].Validate (result .StructuredContent ))
377- assert .Equal (t , 1 , graphQLCalls )
385+ assert .Equal (t , 2 , graphQLCalls )
378386
379387 result , err = clientSession .CallTool (context .Background (), & mcp.CallToolParams {
380388 Name : "get_team_members" ,
381389 Arguments : map [string ]any {"org" : "testorg" , "team_slug" : "testteam" , "legacy_ignored_argument" : true },
390+ Meta : protocolMeta ,
382391 })
383392 require .NoError (t , err )
384393 require .False (t , result .IsError )
385394 structuredJSON , err = json .Marshal (result .StructuredContent )
386395 require .NoError (t , err )
387396 assert .JSONEq (t , `["user1","user2"]` , string (structuredJSON ))
388- assert .Equal (t , string (structuredJSON ), getTextResult (t , result ).Text )
397+ assert .JSONEq (t , string (structuredJSON ), getTextResult (t , result ).Text )
389398 request = createMCPRequest (map [string ]any {"org" : "testorg" , "team_slug" : "testteam" })
390399 legacyResult , err = teamMembersTool .Handler (deps )(ContextWithDeps (context .Background (), deps ), & request )
391400 require .NoError (t , err )
392401 assert .Equal (t , `["user1","user2"]` , getTextResult (t , legacyResult ).Text )
393402 require .NoError (t , outputSchemas ["get_team_members" ].Validate (result .StructuredContent ))
394- assert .Equal (t , 2 , graphQLCalls )
403+ assert .Equal (t , 4 , graphQLCalls )
395404
396405 result , err = clientSession .CallTool (context .Background (), & mcp.CallToolParams {
397406 Name : "get_team_members" ,
398407 Arguments : map [string ]any {},
408+ Meta : protocolMeta ,
399409 })
400410 require .NoError (t , err )
401411 assert .True (t , result .IsError , "missing required arguments should be rejected by the inferred input schema" )
402- assert .Equal (t , 2 , graphQLCalls , "schema validation must happen before invoking the handler" )
412+ assert .Equal (t , 4 , graphQLCalls , "schema validation must happen before invoking the handler" )
403413
404414 result , err = clientSession .CallTool (context .Background (), & mcp.CallToolParams {
405415 Name : "get_team_members" ,
406416 Arguments : map [string ]any {"org" : "" , "team_slug" : "testteam" },
417+ Meta : protocolMeta ,
407418 })
408419 require .NoError (t , err )
409420 assert .True (t , result .IsError , "empty required strings should remain invalid" )
410- assert .Equal (t , 2 , graphQLCalls , "handler validation must reject empty identifiers before acquiring GraphQL" )
421+ assert .Equal (t , 4 , graphQLCalls , "handler validation must reject empty identifiers before acquiring GraphQL" )
411422
412423 for _ , tc := range []struct {
413424 name string
@@ -430,20 +441,20 @@ func TestContextToolsTypedRegistration(t *testing.T) {
430441 require .NoError (t , err )
431442 require .False (t , legacyResult .IsError )
432443 assert .Equal (t , tc .text , getTextResult (t , legacyResult ).Text )
433- result , err := clientSession .CallTool (context .Background (), & mcp.CallToolParams {Name : tc .name , Arguments : tc .args })
444+ result , err := clientSession .CallTool (context .Background (), & mcp.CallToolParams {Name : tc .name , Arguments : tc .args , Meta : protocolMeta })
434445 require .NoError (t , err )
435446 require .False (t , result .IsError )
436447 require .NotNil (t , result .StructuredContent , "empty successful collections must have structured content on the wire" )
437448 require .Len (t , result .Content , 1 , "SDK fallback must not duplicate the legacy text" )
438449 structuredJSON , err := json .Marshal (result .StructuredContent )
439450 require .NoError (t , err )
440451 assert .JSONEq (t , tc .structured , string (structuredJSON ))
441- assert .Equal (t , string (structuredJSON ), getTextResult (t , result ).Text )
452+ assert .JSONEq (t , string (structuredJSON ), getTextResult (t , result ).Text )
442453 require .NoError (t , outputSchemas [tc .name ].Validate (result .StructuredContent ))
443454 }
444455
445456 failGetMe = true
446- result , err = clientSession .CallTool (context .Background (), & mcp.CallToolParams {Name : "get_me" })
457+ result , err = clientSession .CallTool (context .Background (), & mcp.CallToolParams {Name : "get_me" , Meta : protocolMeta })
447458 require .NoError (t , err )
448459 assert .True (t , result .IsError )
449460 assert .Nil (t , result .StructuredContent , "handler errors must not expose a successful typed output" )
0 commit comments