You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Streamable HTTP returns -32600 instead of -32700 for malformed JSON #1918
The Streamable HTTP POST handler answers a body that is not valid JSON with -32600 (Invalid Request). JSON-RPC 2.0 §5.1 assigns -32700 (Parse error) to invalid JSON and keeps -32600 for JSON that parses but is not a valid request object.
Where
src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs, lines 80–93 on both v2.2.0 and main:
catch(JsonException){// The POST body was not a well-formed JSON-RPC message (malformed JSON, or a request whose// id was explicitly null, which MCP forbids). ...awaitWriteJsonRpcErrorAsync(context,"Bad Request: The POST body did not contain a valid JSON-RPC message.",StatusCodes.Status400BadRequest,(int)McpErrorCode.InvalidRequest);return;}
The one catch covers two cases: a syntax error, and a well-formed message the converter rejects (for example "id": null). Both get InvalidRequest.
Repro
With valid auth and the required headers (Accept: application/json, text/event-stream, a supported MCP-Protocol-Version), POST the truncated body {"jsonrpc": to a stateless Streamable HTTP endpoint.
It happens before protocol-version dispatch, so 2025-11-25 and 2026-07-28 both behave this way.
Suggested fix
Tell the two cases apart. One way: parse the body into a JsonDocument/JsonNode first, return McpErrorCode.ParseError if that throws, then deserialize the JsonRpcMessage and keep InvalidRequest for envelope failures. Two tests would pin it: one for malformed JSON (-32700), one for "id": null (-32600).
#1629 already returns ParseError for the stdio over-nesting case, so this would make HTTP consistent with stdio.
Related: the conformance test PostMalformedJson_Returns400_InvalidRequest_WithNullId currently asserts -32600 for malformed JSON, so it would change with the fix. Open PR #1844 edits the same catch to add parse detail and keeps InvalidRequest; this could land with it or after it.
Found during a conformance audit of a server built on 2.2.0.
Activity