-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Describe the bug
According to the docs (and the relevant portion of the MCP spec), tool execution errors should look like the following:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "Failed to fetch weather data: API rate limit exceeded"
}
],
"isError": true
}
}
But instead, they look like the following (i.e., protocol error format):
{
"jsonrpc": "2.0",
"id": 4,
"error": {
"code": -32603,
"message": "Internal error",
"data": "Internal error calling tool fetch_weather_data"
}
}
So the actual behavior of the MCP gem stack is:
- Tool raises an exception (e.g.,
ActiveRecord::RecordNotFound
) - MCP Server's
call_tool
catches it and re-raises asRequestHandlerError
- Seemingly, it is caught and re-raised here and somewhere
JsonRpcHandler
catches that and returns a JSON-RPC error response (had a bit of trouble finding exactly where the caught error lands).
Unless I'm missing something, this means the MCP gem documentation is incorrect - it does not automatically convert exceptions to isError: true
responses. Instead, raising exceptions get converted to JSON-RPC protocol errors (code -32603).
Returning Tool::Response.new(content, error: true)
would work as documented, but requires manual exception handling as a workaround.
To Reproduce
Steps to reproduce the behavior:
- Raise an error inside a tool call.
- Verify that response matches what the MCP spec deems a protocol error rather than a tool execution error.
Expected behavior
I expect for raised errors within tool calls (e.g., ActiveRecord::RecordNotFound
) that are not deemed internal server errors to be handled intuitively, as tool call execution errors, rather than protocol (-32603) errors. This is what the README says should be the current default behavior for raised errors within tool calls.