Description
SEP-1303 ("Input Validation Errors as Tool Execution Errors", status: Final) reclassified tool argument validation failures from Protocol Errors to Tool Execution Errors. The previous spec listed "Invalid arguments" under Protocol Errors (-32602); SEP-1303 moves them under Tool Execution Errors (isError: true).
rmcp's #[tool] macro runs serde deserialization before the tool handler. When deserialization fails (missing required field, wrong type, null for non-optional), the SDK returns a JSON-RPC -32602 error. The tool handler never runs, so the server author has no way to intercept or customize the response.
This means models never see the validation error message in their context window. They receive a protocol-level error that MCP clients typically treat as non-recoverable, preventing self-correction.
Observed behavior
Tested with mcp-assert fuzz against an rmcp-based server (eresende/pitlane-mcp, 8 tools):
93 crashes across 8 tools, 240 total runs
Every failure returns:
{"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"invalid params: failed to deserialize parameters: missing field `project`"}}
Expected per SEP-1303:
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"missing required field: project"}],"isError":true}}
Failure modes affected:
- Missing required field
- Wrong type (int for string, string for bool)
- Null value for required param
- Empty object
Impact
Every rmcp-based server inherits this behavior. From SEP-1303's motivation:
Models can learn from tool input validation error messages and retry a tools/call with corrected parameters accordingly, but only if they receive the error feedback in their context window. Protocol Errors are caught at the application level by the MCP Client. Only Tool Execution Errors are forwarded back to the model.
References
Reproduce
pip install mcp-assert
mcp-assert fuzz --server "pitlane-mcp" --runs 30
I'm happy to submit a PR for this if the approach is agreed on. The fix would likely involve catching serde deserialization errors in the tool dispatch path and wrapping them in a CallToolResult with isError: true instead of propagating them as JSON-RPC errors.
Description
SEP-1303 ("Input Validation Errors as Tool Execution Errors", status: Final) reclassified tool argument validation failures from Protocol Errors to Tool Execution Errors. The previous spec listed "Invalid arguments" under Protocol Errors (-32602); SEP-1303 moves them under Tool Execution Errors (
isError: true).rmcp's
#[tool]macro runs serde deserialization before the tool handler. When deserialization fails (missing required field, wrong type, null for non-optional), the SDK returns a JSON-RPC-32602error. The tool handler never runs, so the server author has no way to intercept or customize the response.This means models never see the validation error message in their context window. They receive a protocol-level error that MCP clients typically treat as non-recoverable, preventing self-correction.
Observed behavior
Tested with mcp-assert fuzz against an rmcp-based server (eresende/pitlane-mcp, 8 tools):
Every failure returns:
{"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"invalid params: failed to deserialize parameters: missing field `project`"}}Expected per SEP-1303:
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"missing required field: project"}],"isError":true}}Failure modes affected:
Impact
Every rmcp-based server inherits this behavior. From SEP-1303's motivation:
References
Reproduce
pip install mcp-assert mcp-assert fuzz --server "pitlane-mcp" --runs 30I'm happy to submit a PR for this if the approach is agreed on. The fix would likely involve catching serde deserialization errors in the tool dispatch path and wrapping them in a
CallToolResultwithisError: trueinstead of propagating them as JSON-RPC errors.