Describe the bug
The rmcp 3.4.0 client accepts a malformed JSON-RPC response containing both result and error. It resolves the pending tools/call as Ok(CallToolResult), using the result and silently ignoring the error.
JSON-RPC responses must contain either result or error, not both.
Environment
- rmcp: 3.4.0 (
rmcp-v3.4.0, commit fd7811f)
- rustc: 1.98.1
- macOS arm64
- Protocol: MCP
2026-07-28
- Transports: stdio and Streamable HTTP
To reproduce
- Connect an rmcp client to an MCP server.
- Send a
tools/call request.
- Have the server return a response shaped like:
{
"jsonrpc": "2.0",
"id": 1,
"result": { "content": [], "resultType": "complete" },
"error": { "code": -32603, "message": "injected error" }
}
A minimal client call is:
let result = client
.call_tool(
CallToolRequestParams::new("malformed_message")
.with_arguments(
serde_json::json!({"variant": "result-with-error"})
.as_object()
.unwrap()
.clone(),
),
)
.await;
assert!(result.is_err());
This was found while testing MCP Failure Lab 0.9.0. The malformed_message tool intentionally returned a response containing both result and error.
I reproduced it with the mcp-failure-lab@0.9.0 package and the v0.9.0 Git tag over stdio and Streamable HTTP.
Expected behavior
The client rejects the response as an invalid JSON-RPC message and returns an error for the pending request. The connection may remain usable afterward.
Actual behavior
call_tool returns Ok(CallToolResult). A subsequent normal request succeeds.
Additional context
The likely parser path is the untagged JsonRpcMessage enum: JsonRpcResponse accepts the result shape while Serde ignores the unexpected error field.
Other tested official clients, including C# ModelContextProtocol 2.2.0, reject the same wire response.
Describe the bug
The rmcp 3.4.0 client accepts a malformed JSON-RPC response containing both
resultanderror. It resolves the pendingtools/callasOk(CallToolResult), using the result and silently ignoring the error.JSON-RPC responses must contain either
resultorerror, not both.Environment
rmcp-v3.4.0, commitfd7811f)2026-07-28To reproduce
tools/callrequest.{ "jsonrpc": "2.0", "id": 1, "result": { "content": [], "resultType": "complete" }, "error": { "code": -32603, "message": "injected error" } }A minimal client call is:
This was found while testing MCP Failure Lab 0.9.0. The
malformed_messagetool intentionally returned a response containing bothresultanderror.I reproduced it with the
mcp-failure-lab@0.9.0package and thev0.9.0Git tag over stdio and Streamable HTTP.Expected behavior
The client rejects the response as an invalid JSON-RPC message and returns an error for the pending request. The connection may remain usable afterward.
Actual behavior
call_toolreturnsOk(CallToolResult). A subsequent normal request succeeds.Additional context
The likely parser path is the untagged
JsonRpcMessageenum:JsonRpcResponseaccepts theresultshape while Serde ignores the unexpectederrorfield.Other tested official clients, including C#
ModelContextProtocol2.2.0, reject the same wire response.