Return JSON-RPC protocol errors for unknown tool calls

Per the MCP specification, an unknown tool call is a protocol-level error, not a tool execution error.
Return JSON-RPC -32602 (Invalid params) instead of successful responses with `isError: true`.
https://modelcontextprotocol.io/specification/2025-11-25/server/tools#error-handling

Fixes #228.
This commit is contained in:
Koichi ITO 2026-02-19 02:51:11 +09:00
commit 15710ef0aa
2 changed files with 14 additions and 12 deletions

View file

@ -377,7 +377,7 @@ module MCP
unless tool
add_instrumentation_data(tool_name: tool_name, error: :tool_not_found)
return error_tool_response("Tool not found: #{tool_name}")
raise RequestHandlerError.new("Tool not found: #{tool_name}", request, error_type: :invalid_params)
end
arguments = request[:arguments] || {}
@ -401,6 +401,8 @@ module MCP
end
call_tool_with_args(tool, arguments)
rescue RequestHandlerError
raise
rescue => e
report_exception(e, request: request)

View file

@ -527,7 +527,7 @@ module MCP
assert_match(/Internal error calling tool tool_with_faulty_schema: Unexpected schema error/, response[:result][:content][0][:text])
end
test "#handle tools/call returns error response with isError true for unknown tool" do
test "#handle tools/call returns JSON-RPC error for unknown tool" do
request = {
jsonrpc: "2.0",
method: "tools/call",
@ -539,14 +539,14 @@ module MCP
}
response = @server.handle(request)
assert_nil response[:error], "Expected no JSON-RPC error"
assert response[:result][:isError]
assert_equal "text", response[:result][:content][0][:type]
assert_equal "Tool not found: unknown_tool", response[:result][:content][0][:text]
assert_instrumentation_data({ method: "tools/call", tool_name: "unknown_tool", error: :tool_not_found })
assert_nil response[:result]
assert_equal(-32602, response[:error][:code])
assert_equal "Invalid params", response[:error][:message]
assert_includes response[:error][:data], "Tool not found: unknown_tool"
assert_instrumentation_data({ method: "tools/call", tool_name: "unknown_tool", error: :invalid_params })
end
test "#handle_json returns error response with isError true for unknown tool" do
test "#handle_json returns JSON-RPC error for unknown tool" do
request = JSON.generate({
jsonrpc: "2.0",
method: "tools/call",
@ -558,10 +558,10 @@ module MCP
})
response = JSON.parse(@server.handle_json(request), symbolize_names: true)
assert_nil response[:error], "Expected no JSON-RPC error"
assert response[:result][:isError]
assert_equal "text", response[:result][:content][0][:type]
assert_equal "Tool not found: unknown_tool", response[:result][:content][0][:text]
assert_nil response[:result]
assert_equal(-32602, response[:error][:code])
assert_equal "Invalid params", response[:error][:message]
assert_includes response[:error][:data], "Tool not found: unknown_tool"
end
test "#tools_call_handler sets the tools/call handler" do