Return tool argument validation failures as tool execution errors#333
Open
koic wants to merge 1 commit intomodelcontextprotocol:mainfrom
Open
Return tool argument validation failures as tool execution errors#333koic wants to merge 1 commit intomodelcontextprotocol:mainfrom
koic wants to merge 1 commit intomodelcontextprotocol:mainfrom
Conversation
## Motivation and Context
MCP 2025-11-25 (SEP-1303) clarifies that input validation errors for `tools/call`
should be returned as Tool Execution Errors (`{ content: [...], isError: true }`)
rather than as JSON-RPC `-32602` protocol errors, so models can observe
the validation message and self-correct on a follow-up call.
modelcontextprotocol/modelcontextprotocol#1303
This is a clarification rather than a brand-new requirement: the 2024-11-05, 2025-03-26,
and 2025-06-18 specifications all defined two error categories with overlapping language
("Invalid arguments" listed under Protocol Errors *and* "Invalid input data" listed under
Tool Execution Errors), leaving the routing of JSON-Schema validation failures ambiguous.
The Ruby SDK had selected the "Protocol Errors / Invalid arguments" interpretation,
while the TypeScript SDK (`packages/server/src/server/mcp.ts`, which wraps
`validateToolInput` errors via `createToolError`) and Python SDK's FastMCP
(which routes through the generic `is_error=True` path) had selected the other.
SEP-1303 in 2025-11-25 disambiguates this by replacing the bullets with
"Malformed requests (requests that fail to satisfy CallToolRequest schema)"
under Protocol Errors and "Input validation errors (e.g., date in wrong format,
value out of range)" under Tool Execution Errors, and explicitly states that the latter
"contain actionable feedback that language models can use to self-correct".
`tool_not_found` continues to be returned as a JSON-RPC `-32602` protocol error since
the spec change only covers input validation.
## How Has This Been Tested?
Updated existing tests that previously asserted `-32602` and "Invalid arguments" /
"Missing required arguments" in the JSON-RPC error data to instead
assert `result[:isError] == true` with the same text in the `content` block.
Added new regression tests covering:
- Instrumentation still records `:missing_required_arguments` and
`:invalid_schema` on the new non-raising path
- Nested schema validation failure (deep arrays of objects with
required fields) returns a tool execution error rather than a
protocol error
- `tool_not_found` continues to return JSON-RPC `-32602` (regression
guard against accidentally widening the change)
`bundle exec rake test` and `bundle exec rake rubocop` both pass.
## Breaking Changes
Yes. Clients that detect tool argument validation errors via `error.code == -32602`
will need to switch to inspecting `result.isError == true` and reading `result.content[].text`.
Note that the Ruby SDK's previous behavior was a defensible reading of the 2024-11-05 /
2025-03-26 / 2025-06-18 spec wording. The 2025-11-25 disambiguation is what makes
the previous behavior non-conforming; the TypeScript and Python SDKs already shipped
the new behavior.
6e76890 to
48d4fb9
Compare
atesgoral
approved these changes
May 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
MCP 2025-11-25 (SEP-1303) clarifies that input validation errors for
tools/callshould be returned as Tool Execution Errors ({ content: [...], isError: true }) rather than as JSON-RPC-32602protocol errors, so models can observe the validation message and self-correct on a follow-up call.modelcontextprotocol/modelcontextprotocol#1303
This is a clarification rather than a brand-new requirement: the 2024-11-05, 2025-03-26, and 2025-06-18 specifications all defined two error categories with overlapping language ("Invalid arguments" listed under Protocol Errors and "Invalid input data" listed under Tool Execution Errors), leaving the routing of JSON-Schema validation failures ambiguous. The Ruby SDK had selected the "Protocol Errors / Invalid arguments" interpretation, while the TypeScript SDK (
packages/server/src/server/mcp.ts, which wrapsvalidateToolInputerrors viacreateToolError) and Python SDK's FastMCP (which routes through the genericis_error=Truepath) had selected the other. SEP-1303 in 2025-11-25 disambiguates this by replacing the bullets with "Malformed requests (requests that fail to satisfy CallToolRequest schema)" under Protocol Errors and "Input validation errors (e.g., date in wrong format, value out of range)" under Tool Execution Errors, and explicitly states that the latter "contain actionable feedback that language models can use to self-correct".tool_not_foundcontinues to be returned as a JSON-RPC-32602protocol error since the spec change only covers input validation.How Has This Been Tested?
Updated existing tests that previously asserted
-32602and "Invalid arguments" / "Missing required arguments" in the JSON-RPC error data to instead assertresult[:isError] == truewith the same text in thecontentblock. Added new regression tests covering::missing_required_argumentsand:invalid_schemaon the new non-raising pathtool_not_foundcontinues to return JSON-RPC-32602(regression guard against accidentally widening the change)bundle exec rake testandbundle exec rake rubocopboth pass.Breaking Changes
Yes. Clients that detect tool argument validation errors via
error.code == -32602will need to switch to inspectingresult.isError == trueand readingresult.content[].text.Note that the Ruby SDK's previous behavior was a defensible reading of the 2024-11-05 / 2025-03-26 / 2025-06-18 spec wording. The 2025-11-25 disambiguation is what makes the previous behavior non-conforming; the TypeScript and Python SDKs already shipped the new behavior.
Types of changes
Checklist