fix: return protocol errors for invalid arguments and server errors

Per the MCP spec, invalid arguments and server errors are protocol
errors (JSON-RPC error responses), not tool execution errors
(isError: true). PR #165 moved all error cases to isError: true,
and PR #231 only restored protocol errors for unknown tools.

This fixes the remaining two cases: invalid arguments (-32602) and
server errors (-32603).

Ref: https://modelcontextprotocol.io/specification/2024-11-05/server/tools#error-handling
This commit is contained in:
Sarah Pickett 2026-04-01 11:08:05 -04:00
commit 8dd0379f16
No known key found for this signature in database
GPG key ID: 9EFE291931498465

View file

@ -316,13 +316,12 @@ module MCP
add_instrumentation_data(client: client) if client
result
rescue RequestHandlerError => e
report_exception(e.original_error || e, { request: request })
add_instrumentation_data(error: e.error_type)
raise e
rescue => e
report_exception(e, { request: request })
if e.is_a?(RequestHandlerError)
add_instrumentation_data(error: e.error_type)
raise e
end
add_instrumentation_data(error: :internal_error)
raise RequestHandlerError.new("Internal error handling #{method} request", request, original_error: e)
end
@ -421,7 +420,7 @@ module MCP
add_instrumentation_data(error: :missing_required_arguments)
missing = tool.input_schema.missing_required_arguments(arguments).join(", ")
return error_tool_response("Missing required arguments: #{missing}")
raise RequestHandlerError.new("Missing required arguments: #{missing}", request, error_type: :invalid_params)
end
if configuration.validate_tool_call_arguments && tool.input_schema
@ -430,7 +429,7 @@ module MCP
rescue Tool::InputSchema::ValidationError => e
add_instrumentation_data(error: :invalid_schema)
return error_tool_response(e.message)
raise RequestHandlerError.new(e.message, request, error_type: :invalid_params)
end
end
@ -440,9 +439,12 @@ module MCP
rescue RequestHandlerError
raise
rescue => e
report_exception(e, request: request)
error_tool_response("Internal error calling tool #{tool_name}: #{e.message}")
raise RequestHandlerError.new(
"Internal error calling tool #{tool_name}: #{e.message}",
request,
error_type: :internal_error,
original_error: e,
)
end
def list_prompts(request)