mcp: typed tool handlers lose wrapped JSON-RPC errors
Maintainers usually reply within 1 day
Nobody has claimed this yet.
- #1528 by @ktsoator — closed without merging
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- go
- Domain
- backend-api-design
Research direction
Start with toolForErr in the MCP package and the JSON-RPC error handling used by ClientSession.CallTool; compare direct *jsonrpc.Error handling with wrapped errors. Run the provided in-memory client/server reproduction, then verify that errors.As preserves the JSON-RPC code, message, and data and that the result is not incorrectly marked as an execution error. Add or update focused tests for wrapped and unwrapped protocol errors.
Written by the indexing model from the issue text.
Description
Checklist
- I searched the existing issues, and this has not been reported before.
- This is a real problem that I ran into myself, using the latest release of the SDK.
- I ran into it in a production system, not in a toy example, a benchmark, or an automated or AI-driven scan of the code.
- I (a human) examined the relevant SDK code, and wrote or reviewed every line of this report. It is not unreviewed AI output.
- This report is brief and concise, and sticks to the facts needed to understand the problem.
What happened?
A typed tool handler returning a wrapped *jsonrpc.Error is treated as a tool execution error. ClientSession.CallTool returns a nil Go error and a result with IsError: true, so the JSON-RPC error code and data are lost. Returning the same protocol error directly works.
toolForErr checks err.(*jsonrpc.Error) instead of searching the error chain. The expected result is a JSON-RPC error with the underlying code, message, and data preserved when wrapped with %w.
How to reproduce
Run this program with github.com/modelcontextprotocol/go-sdk v1.8.0:
package main
import (
"context"
"errors"
"fmt"
"github.com/modelcontextprotocol/go-sdk/jsonrpc"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
func main() {
ctx := context.Background()
s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "1"}, nil)
mcp.AddTool(s, &mcp.Tool{Name: "demo"}, func(context.Context, *mcp.CallToolRequest, map[string]any) (*mcp.CallToolResult, any, error) {
return nil, nil, fmt.Errorf("backend: %w", &jsonrpc.Error{
Code: jsonrpc.CodeInvalidParams,
Message: "bad input",
})
})
st, ct := mcp.NewInMemoryTransports()
ss, err := s.Connect(ctx, st, nil)
if err != nil {
panic(err)
}
defer ss.Close()
c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "1"}, nil)
cs, err := c.Connect(ctx, ct, nil)
if err != nil {
panic(err)
}
defer cs.Close()
result, err := cs.CallTool(ctx, &mcp.CallToolParams{Name: "demo"})
var rpcErr *jsonrpc.Error
fmt.Printf("protocolError=%v, err=%v\n", errors.As(err, &rpcErr), err)
if result != nil {
fmt.Printf("isError=%v\n", result.IsError)
}
}
Observed:
protocolError=false, err=<nil>
isError=true
Expected: protocolError=true, with JSON-RPC code -32602.
Where did you hit this?
Found during local code inspection and reproduced with an in-memory client and server.
Go MCP SDK version
v1.8.0
Go version
go1.26.10 darwin/arm64, also reproduced on main at 0fa5e8407aa3fda65166e4207156c03d084bfd44.
Proposed fix
Use errors.As and return the underlying protocol error.
- Dominant language
- Go
- Stars
- 5.3k
- Forks
- 614
- Avg merge
- 23h 55m
- Merged PRs (30d)
- 62
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from modelcontextprotocol/go-sdk
-
Expose generic `SendNotification` on `ServerSession` for custom protocol extensionsMay be free again A pull request for this issue was closed without being merged. Openneeds investigation
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
modelcontextprotocol/go-sdk#745 · 13 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
mcp: ClientSession.ReadResource keeps uncacheable and expired results until the session endsMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 3/5 1-2 days Newbie friendliness 74/100
modelcontextprotocol/go-sdk#1526 ·
Maintainers usually reply within 1 day
-
mcp: streamable client keeps the session ID from a rejected server/discover, so the fallback initialize failsPossibly taken @simon0191 claimed this 1 day ago. Open
modelcontextprotocol/go-sdk#1522 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
auth: OAuth client rejects protected resource metadata when the MCP server URL has a query stringPossibly taken @beiryu claimed this 2 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 74/100
modelcontextprotocol/go-sdk#1519 · 2 comments ·
Maintainers usually reply within 1 day
-
`ping` and `logging/setLevel` still sent for protocol 2026-07-28Possibly taken @nahapetyan-serob claimed this 1 day ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 65/100
modelcontextprotocol/go-sdk#1518 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
All issues in modelcontextprotocol/go-sdk
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
-
evener-transcript-v2-upgrade tool still scans transcript files through bufio's 4 KiB default bufferOpen
Difficulty 1/5 Under an hour Newbie friendliness 78/100
prime-radiant-inc/evener#6370 ·
Maintainers usually reply within 1 day
-
ManageSieve proxy: a backend's NO/BYE greeting is skipped as a capability line and reported as EOFOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Mend: dependency security vulnerability
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
Mend: dependency security vulnerability
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
ManageIQ/manageiq-pods#1476 ·
Maintainers usually reply within 1 day