-
Notifications
You must be signed in to change notification settings - Fork 104
Protocol errors still returned as tool execution errors (invalid arguments, server errors) #284
Description
Describe the bug
Two of the three protocol error cases defined by the spec are still returned as tool execution errors (isError: true results) instead of JSON-RPC error responses:
- Invalid arguments — missing required arguments and schema validation failures both return
isError: true - Server errors — internal exceptions during tool execution return
isError: true
This is the same class of bug as #228, which was fixed for unknown tool calls in PR #231. The other two cases were not addressed.
To Reproduce
- Define a tool with a required argument
- Call it with the argument missing
server = MCP::Server.new(tools: [MyTool])
response = server.handle({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: { name: "my_tool", arguments: {} }
})- Response is a successful JSON-RPC result with
isError: true:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{"type": "text", "text": "Missing required arguments: required_argument"}],
"isError": true
}
}Same behavior for invalid schema validation and internal server errors.
Expected behavior
A JSON-RPC protocol error, consistent with how unknown tool calls are handled:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params",
"data": "Missing required arguments: required_argument"
}
}Additional context
The MCP spec draws a clear line between protocol errors and tool execution errors:
Protocol Errors: Standard JSON-RPC errors for issues like:
- Unknown tools
- Invalid arguments
- Server errors
Tool Execution Errors: Reported in tool results with
isError: true:
- API failures
- Invalid input data
- Business logic errors
A note on server errors: #159 raised a valid concern that tool execution errors like ActiveRecord::RecordNotFound shouldn't be protocol errors. But the fix for that is for the tool to catch those exceptions and return Tool::Response.new(content, error: true) — that's the tool reporting a known failure. If an exception bubbles up uncaught, the server can't distinguish a business error from an actual crash, so treating it as a server error (protocol error) is the correct default.
The trail:
- PR Fix tool error handling to follow MCP spec #165 moved all three protocol error cases from
RequestHandlerError(JSON-RPC errors) toerror_tool_response(isError: true) - Wrong kinds of MCP errors returned in some cases #228 flagged this as a spec violation
- PR Return JSON-RPC protocol errors for unknown tool calls #231 fixed unknown tools only — invalid arguments and server errors still return
isError: true
The remaining two cases in Server#call_tool need to raise RequestHandlerError instead of returning error_tool_response, matching the pattern PR #231 restored for unknown tools.