What are MCP's standard JSON-RPC error codes, and how do custom errors extend them?
Quick Answer
MCP reuses JSON-RPC 2.0's standard error codes for protocol-level failures: -32700 (Parse error — invalid JSON), -32600 (Invalid Request), -32601 (Method not found), -32602 (Invalid params), and -32603 (Internal error). These live in the top-level error object of a JSON-RPC response, distinct from tool-execution failures (which use isError: true inside a normal result, as covered under tool error handling). Implementations are free to define their own error codes for domain-specific protocol failures, and the convention (inherited from JSON-RPC) is to use codes in the range -32000 to -32099 (the "server error" reserved range) for these custom, implementation-defined errors, keeping them clearly separate from the standard codes.
Detailed Answer
Getting error codes right matters because a client's error-handling logic often branches on the numeric code, not just the message string.
Standard codes
| Code | Meaning |
|---|---|
-32700 | Parse error — the message wasn't valid JSON |
-32600 | Invalid Request — valid JSON, but not a valid JSON-RPC request object |
-32601 | Method not found — no handler for the requested method name |
-32602 | Invalid params — the method exists, but params doesn't match what it expects |
-32603 | Internal error — an unexpected failure inside the server while handling an otherwise-valid request |
{"jsonrpc": "2.0", "id": 4, "error": {
"code": -32601,
"message": "Method not found: tools/execute"
}}
Custom, implementation-defined codes
{"jsonrpc": "2.0", "id": 4, "error": {
"code": -32001,
"message": "Rate limit exceeded",
"data": {"retryAfterMs": 5000}
}}
The -32000 to -32099 range is reserved by the JSON-RPC spec for "server error" — implementation-specific codes outside the standard set. Use a code in this range for a custom error, rather than inventing an arbitrary number or colliding with a standard code. That keeps a server's errors unambiguous to any spec-aware client, even one that doesn't recognize the specific custom code.
The optional data field
Any error object can carry an optional data field with extra structured detail beyond the human-readable message, like the retryAfterMs above. Clients that understand a particular custom error code can use data programmatically — actually waiting before retrying, say. Clients that don't recognize the code can still fall back to showing message to the user.
The important boundary to remember
None of this applies to a tool that runs but fails at the business-logic level. That's still isError: true in a normal result, not a JSON-RPC error. These error codes are strictly for failures in handling the request itself — bad method, bad params, internal crash — not failures in whatever the request asked the server to do.