improve error handling for tools and server methods (#311)

- Fix tool error handling to properly distinguish between protocol
errors and tool execution errors
- Return structured JSON-RPC errors directly for protocol-level issues
- Embed regular tool errors in CallToolResult as per MCP specification
- Improve server error responses for unknown prompts and tools
- Add comprehensive tests for both structured and regular error handling
This commit is contained in:
Shusaku Yasoda 2025-08-21 01:31:11 +09:00 • committed by GitHub
commit 719f68d0bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -328,8 +328,11 @@ func (s *Server) getPrompt(ctx context.Context, req *ServerRequest[*GetPromptPar
prompt, ok := s.prompts.get(req.Params.Name)
s.mu.Unlock()
if !ok {
// TODO: surface the error code over the wire, instead of flattening it into the string.
return nil, fmt.Errorf("%s: unknown prompt %q", jsonrpc2.ErrInvalidParams, req.Params.Name)
// Return a proper JSON-RPC error with the correct error code
return nil, &jsonrpc2.WireError{
Code: CodeInvalidParams,
Message: fmt.Sprintf("unknown prompt %q", req.Params.Name),
}
}
return prompt.handler(ctx, req.Session, req.Params)
}
@ -353,7 +356,10 @@ func (s *Server) callTool(ctx context.Context, req *ServerRequest[*CallToolParam
st, ok := s.tools.get(req.Params.Name)
s.mu.Unlock()
if !ok {
return nil, fmt.Errorf("%s: unknown tool %q", jsonrpc2.ErrInvalidParams, req.Params.Name)
return nil, &jsonrpc2.WireError{
Code: CodeInvalidParams,
Message: fmt.Sprintf("unknown tool %q", req.Params.Name),
}
}
// TODO: if handler returns nil content, it will serialize as null.
// Add a test and fix.