Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite7d2547

Browse files
feat(tools): implicitly register capabilities (#292)
When users add tools via AddTool or AddSessionTool, implicitly set thetools capability. If the user has not already calledWithToolCapabilities, then default listChanged to true, but honor anyexisting value.This mimics the behavior of the official typescript sdk, which registers`tools.listChanged: true` when the user adds a tool to the MCP server.
1 parentc1e70f3 commite7d2547

File tree

4 files changed

+113
-3
lines changed

4 files changed

+113
-3
lines changed

‎server/server.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,20 +411,29 @@ func (s *MCPServer) AddTool(tool mcp.Tool, handler ToolHandlerFunc) {
411411
s.AddTools(ServerTool{Tool:tool,Handler:handler})
412412
}
413413

414-
// AddTools registers multiple tools at once
415-
func (s*MCPServer)AddTools(tools...ServerTool) {
414+
// Register tool capabilities due to a tool being added. Default to
415+
// listChanged: true, but don't change the value if we've already explicitly
416+
// registered tools.listChanged false.
417+
func (s*MCPServer)implicitlyRegisterToolCapabilities() {
416418
s.capabilitiesMu.RLock()
417419
ifs.capabilities.tools==nil {
418420
s.capabilitiesMu.RUnlock()
419421

420422
s.capabilitiesMu.Lock()
421423
ifs.capabilities.tools==nil {
422-
s.capabilities.tools=&toolCapabilities{}
424+
s.capabilities.tools=&toolCapabilities{
425+
listChanged:true,
426+
}
423427
}
424428
s.capabilitiesMu.Unlock()
425429
}else {
426430
s.capabilitiesMu.RUnlock()
427431
}
432+
}
433+
434+
// AddTools registers multiple tools at once
435+
func (s*MCPServer)AddTools(tools...ServerTool) {
436+
s.implicitlyRegisterToolCapabilities()
428437

429438
s.toolsMu.Lock()
430439
for_,entry:=rangetools {

‎server/server_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,3 +1624,46 @@ func BenchmarkMCPServer_PaginationForReflect(b *testing.B) {
16241624
_,_,_=listByPaginationForReflect[mcp.Tool](ctx,server,"dG9vbDY1NA==",list)
16251625
}
16261626
}
1627+
1628+
funcTestMCPServer_ToolCapabilitiesBehavior(t*testing.T) {
1629+
tests:= []struct {
1630+
namestring
1631+
serverOptions []ServerOption
1632+
validateServerfunc(t*testing.T,s*MCPServer)
1633+
}{
1634+
{
1635+
name:"no tool capabilities provided",
1636+
serverOptions: []ServerOption{
1637+
// No WithToolCapabilities
1638+
},
1639+
validateServer:func(t*testing.T,s*MCPServer) {
1640+
s.capabilitiesMu.RLock()
1641+
defers.capabilitiesMu.RUnlock()
1642+
1643+
require.NotNil(t,s.capabilities.tools,"tools capability should be initialized")
1644+
assert.True(t,s.capabilities.tools.listChanged,"listChanged should be true when no capabilities were provided")
1645+
},
1646+
},
1647+
{
1648+
name:"tools.listChanged set to false",
1649+
serverOptions: []ServerOption{
1650+
WithToolCapabilities(false),
1651+
},
1652+
validateServer:func(t*testing.T,s*MCPServer) {
1653+
s.capabilitiesMu.RLock()
1654+
defers.capabilitiesMu.RUnlock()
1655+
1656+
require.NotNil(t,s.capabilities.tools,"tools capability should be initialized")
1657+
assert.False(t,s.capabilities.tools.listChanged,"listChanged should remain false when explicitly set to false")
1658+
},
1659+
},
1660+
}
1661+
1662+
for_,tt:=rangetests {
1663+
t.Run(tt.name,func(t*testing.T) {
1664+
server:=NewMCPServer("test-server","1.0.0",tt.serverOptions...)
1665+
server.AddTool(mcp.NewTool("test-tool"),nil)
1666+
tt.validateServer(t,server)
1667+
})
1668+
}
1669+
}

‎server/session.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ func (s *MCPServer) AddSessionTools(sessionID string, tools ...ServerTool) error
224224
returnErrSessionDoesNotSupportTools
225225
}
226226

227+
s.implicitlyRegisterToolCapabilities()
228+
227229
// Get existing tools (this should return a thread-safe copy)
228230
sessionTools:=session.GetSessionTools()
229231

‎server/session_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,3 +802,59 @@ func TestMCPServer_NotificationChannelBlocked(t *testing.T) {
802802
assert.Equal(t,"blocked-session",localErrorSessionID,"Session ID should be captured in the error hook")
803803
assert.Equal(t,"broadcast-message",localErrorMethod,"Method should be captured in the error hook")
804804
}
805+
806+
funcTestMCPServer_SessionToolCapabilitiesBehavior(t*testing.T) {
807+
tests:= []struct {
808+
namestring
809+
serverOptions []ServerOption
810+
validateServerfunc(t*testing.T,s*MCPServer,session*sessionTestClientWithTools)
811+
}{
812+
{
813+
name:"no tool capabilities provided",
814+
serverOptions: []ServerOption{
815+
// No WithToolCapabilities
816+
},
817+
validateServer:func(t*testing.T,s*MCPServer,session*sessionTestClientWithTools) {
818+
s.capabilitiesMu.RLock()
819+
defers.capabilitiesMu.RUnlock()
820+
821+
require.NotNil(t,s.capabilities.tools,"tools capability should be initialized")
822+
assert.True(t,s.capabilities.tools.listChanged,"listChanged should be true when no capabilities were provided")
823+
},
824+
},
825+
{
826+
name:"tools.listChanged set to false",
827+
serverOptions: []ServerOption{
828+
WithToolCapabilities(false),
829+
},
830+
validateServer:func(t*testing.T,s*MCPServer,session*sessionTestClientWithTools) {
831+
s.capabilitiesMu.RLock()
832+
defers.capabilitiesMu.RUnlock()
833+
834+
require.NotNil(t,s.capabilities.tools,"tools capability should be initialized")
835+
assert.False(t,s.capabilities.tools.listChanged,"listChanged should remain false when explicitly set to false")
836+
},
837+
},
838+
}
839+
840+
for_,tt:=rangetests {
841+
t.Run(tt.name,func(t*testing.T) {
842+
server:=NewMCPServer("test-server","1.0.0",tt.serverOptions...)
843+
844+
// Create and register a session
845+
session:=&sessionTestClientWithTools{
846+
sessionID:"test-session",
847+
notificationChannel:make(chan mcp.JSONRPCNotification,10),
848+
initialized:true,
849+
}
850+
err:=server.RegisterSession(context.Background(),session)
851+
require.NoError(t,err)
852+
853+
// Add a session tool and verify listChanged remains false
854+
err=server.AddSessionTool(session.SessionID(),mcp.NewTool("test-tool"),nil)
855+
require.NoError(t,err)
856+
857+
tt.validateServer(t,server,session)
858+
})
859+
}
860+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp