-
Notifications
You must be signed in to change notification settings - Fork 341
Description
Describe the bug
When the generic type for CallToolResultFor is a pointer in the ToolHandlerFor, the tool is not included in clients.
This is likely due to the response schema for tools/list being invalid.
To Reproduce
Prove that tools are included in the response with non-pointer types:
-
Create a small server:
package main import ( "context" "net/http" "github.com/modelcontextprotocol/go-sdk/mcp" ) func main() { server := mcp.NewServer(&mcp.Implementation{Name: "hello"}, nil) mcp.AddTool(server, &mcp.Tool{ Name: "greet", Description: "Say hello", }, func(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[struct{}]) (*mcp.CallToolResultFor[struct{}], error) { return &mcp.CallToolResultFor[struct{}]{ Content: []mcp.Content{ &mcp.TextContent{Text: "hello"}, }, }, nil }) http.ListenAndServe(":8080", mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server }, nil)) }
-
Start the server:
go run main.go
-
List the tools:
SESSION_ID=$(curl -sfo /dev/null -w '%header{mcp-session-id}' localhost:8080 \ -H 'Accept: application/json,text/event-stream' \ -H 'Mcp-Protocol-Version: 2025-06-18' \ -d '{ "jsonrpc":"2.0", "id":1, "method":"initialize", "params":{ "protocolVersion":"2025-06-18", "capabilities":{}, "clientInfo":{"name":"Seth", "title":"Seth Test Client", "version":"1.0.0"} } }' )
curl -v localhost:8080 \ -H "Accept: application/json,text/event-stream" \ -H "Mcp-Protocol-Version: 2025-06-18" \ -H "Mcp-Session-Id: ${SESSION_ID}" \ -d '{ "jsonrpc":"2.0", "method":"notifications/initialized" }'
curl -v localhost:8080 \ -H 'Accept: application/json,text/event-stream' \ -H "Mcp-Protocol-Version: 2025-06-18" \ -H "Mcp-Session-Id: ${SESSION_ID}" \ -d '{ "jsonrpc":"2.0", "id":1, "method":"tools/list", "params":{} }'
-
Get a response:
event: message id: 3_0 data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"description":"Say hello","inputSchema":{"type":"object","additionalProperties":{"not":{}}},"name":"greet","outputSchema":{"type":"object","additionalProperties":{"not":{}}}}]}} -
Stop the server
-
Alter the code to use a pointer in
mcp.CallToolResultFor:- }, func(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[struct{}]) (*mcp.CallToolResultFor[struct{}], error) { + }, func(ctx context.Context, ss *mcp.ServerSession, params *mcp.CallToolParamsFor[struct{}]) (*mcp.CallToolResultFor[*struct{}], error) {
-
Start the server:
go run main.go
-
Run the same commands from step 3 above:
SESSION_ID=$(curl -sfo /dev/null -w '%header{mcp-session-id}' localhost:8080 \ -H 'Accept: application/json,text/event-stream' \ -H 'Mcp-Protocol-Version: 2025-06-18' \ -d '{ "jsonrpc":"2.0", "id":1, "method":"initialize", "params":{ "protocolVersion":"2025-06-18", "capabilities":{}, "clientInfo":{"name":"Seth", "title":"Seth Test Client", "version":"1.0.0"} } }' )
curl -v localhost:8080 \ -H "Accept: application/json,text/event-stream" \ -H "Mcp-Protocol-Version: 2025-06-18" \ -H "Mcp-Session-Id: ${SESSION_ID}" \ -d '{ "jsonrpc":"2.0", "method":"notifications/initialized" }'
curl -v localhost:8080 \ -H 'Accept: application/json,text/event-stream' \ -H "Mcp-Protocol-Version: 2025-06-18" \ -H "Mcp-Session-Id: ${SESSION_ID}" \ -d '{ "jsonrpc":"2.0", "id":1, "method":"tools/list", "params":{} }'
-
Get a response:
event: message id: 3_0 data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"description":"Say hello","inputSchema":{"type":"object","additionalProperties":{"not":{}}},"name":"greet","outputSchema":{"type":["null","object"],"additionalProperties":{"not":{}}}}]}}
Expected behavior
I expect pointer types to be permitted. Unfortunately the response from the pointer-types is invalid and not recognized by Gemini CLI or Claude Code Desktop (I did not try other clients, but I expect it's the same). Diff from the resposnes:
// concrete type
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"description": "Say hello",
"inputSchema": {
"type": "object",
"additionalProperties": {
"not": {}
}
},
"name": "greet",
"outputSchema": {
"type": "object",
"additionalProperties": {
"not": {}
}
}
}
]
}
}// pointer
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"description": "Say hello",
"inputSchema": {
"type": "object",
"additionalProperties": {
"not": {}
}
},
"name": "greet",
"outputSchema": {
"type": [
"null",
"object"
],
"additionalProperties": {
"not": {}
}
}
}
]
}
}Logs
N/A
Additional context