createmcps.com

Spec explainer

MCP error codes in 2026-07-28: -32020, -32021, -32022

Last verified: 10 August 2026 · spec 2026-07-28 · ruleset 1.4.2

2026-07-28 partitioned the JSON-RPC server-error range and added three codes: -32020 HeaderMismatch, -32021 MissingRequiredClientCapability and -32022 UnsupportedProtocolVersion. Two were retired — -32002 and -32042 — and must not be emitted.

Every code at a glance

MCP error codes under 2026-07-28, with HTTP status and status in the revision
CodeNameHTTPWhenStatus
-32020HeaderMismatch400A header value contradicts the request bodynew
-32021MissingRequiredClientCapability400The request needs a capability the client did not declarenew
-32022UnsupportedProtocolVersion400The requested protocol version is not implementednew
-32601Method not found404The RPC method is not implementedkept
-32602Invalid params400Malformed params — including resource-not-foundkept
-32002Resource not foundReplaced by -32602retired
-32042URL elicitation required2025-11-25 onlyretired

The partitioned range

JSON-RPC's server-error band, split in two
-32000 … -32019   legacy sub-range
                  → new codes MUST NOT be allocated here
                  → new implementations SHOULD NOT use it at all

-32020 … -32099   reserved by the MCP specification
                  → only spec-defined codes, only with their
                    specified meanings
Implementations MUST NOT emit any code from this sub-range that is not defined by this specification and MUST use defined codes only with their specified meanings.
MCP-ERR-005 MUST_NOT · spec 2026-07-28
New codes MUST NOT be allocated in this sub-range, and new implementations SHOULD NOT use codes from this sub-range at all.
MCP-ERR-008 SHOULD_NOT · spec 2026-07-28

This is the change most likely to make previously-correct code non-conformant. Picking a free number in the -32020+ band for your own error was reasonable before this revision; afterwards that band belongs to the spec, and a number that is free today may be defined tomorrow.

The three new codes

If the server does not implement the requested version, it MUST respond with an UnsupportedProtocolVersionError listing the versions it does support.
MCP-ERR-001 MUST · spec 2026-07-28

-32022 is the one that makes version negotiation work without a handshake. Because there is no initialize exchange to agree a version in, the error itself has to carry the list — otherwise a client whose version is refused has nothing to try next.

A conforming -32022
HTTP/1.1 400 Bad Request

{
  "jsonrpc": "2.0", "id": 1,
  "error": {
    "code": -32022,
    "message": "Unsupported protocol version",
    "data": { "supported": ["2026-07-28"] }
  }
}
If processing a request requires a capability the client did not include, the server MUST return a MissingRequiredClientCapabilityError whose data.requiredCapabilities lists the missing capabilities.
MCP-ERR-007 MUST · spec 2026-07-28

-32021 follows the same principle: name what was missing, in data.requiredCapabilities, so the client can act rather than guess. -32020 HeaderMismatch is covered in depth on the Mcp-Method page.

Our recommendation, not a spec quote: the pattern across all three new codes is worth internalising: a stateless protocol cannot rely on a client remembering a negotiation, so every error that a client could recover from carries the recovery information in data. If you add your own errors, copy that.

The two retired codes

-32002 — resource not found (2025-11-25 and earlier; replaced by -32602). Implementations of this protocol version MUST NOT emit these codes.
MCP-ERR-003 MUST_NOT · spec 2026-07-28
-32042 — URL elicitation required (2025-11-25 only).
MCP-ERR-004 MUST_NOT · spec 2026-07-28
The renumbering
// Before
{ "error": { "code": -32002, "message": "Resource not found" } }

// After — resource-not-found is a params problem
{ "error": { "code": -32602, "message": "Resource not found: file:///…" } }

MUST NOT emit is stronger than deprecated. A server still returning -32002 is non-conformant even though the number is not reused, because a modern client has no definition for it.

Pairing the JSON-RPC code with an HTTP status

The revision is specific about this in two places, and both are easy to miss if you treat JSON-RPC as transport-agnostic:

If the server does not implement the requested RPC method, it MUST respond with 404 Not Found and a JSON-RPC error with code -32601 (Method not found).
MCP-ERR-002 MUST · spec 2026-07-28
A request missing any required field is malformed; the server MUST reject it with JSON-RPC error code -32602 (Invalid params). On HTTP, the response status MUST be 400 Bad Request.
MCP-ERR-006 MUST · spec 2026-07-28
HTTP 200 with an error body is not enough: For these cases the specification names the status and the code. A 200 carrying -32601 is a finding, not a stylistic choice — every intermediary between you and the client reads the status, and none of them parse your body.

Defining your own error codes

  • Not in -32020-32099. Reserved by the specification.
  • Not in -32000-32019. Legacy; SHOULD NOT be used by new implementations at all.
  • Carry recovery data. Follow the data.supported / data.requiredCapabilities pattern rather than relying on a human reading message.

The 8 error-code rules we check

RuleWhat we checkLevelIf it fails
MCP-ERR-001Unsupported version returns -32022 with data.supported[]MUSTfail
MCP-ERR-002Unknown method returns HTTP 404 and JSON-RPC -32601MUSTfail
MCP-ERR-003Resource-not-found uses -32602, not the retired -32002MUST_NOTfail
MCP-ERR-004The retired -32042 code is never emittedMUST_NOTfail
MCP-ERR-005No undefined code is emitted in the reserved -32020…-32099 rangeMUST_NOTfail
MCP-ERR-006Missing required _meta field returns HTTP 400 + JSON-RPC -32602MUSTfail
MCP-ERR-007Missing client capability returns -32021 with data.requiredCapabilitiesMUSTfail
MCP-ERR-008New implementation-defined codes avoid the legacy -32000…-32019 rangeSHOULD_NOTwarn

All eight carry a verbatim spec sentence.

Check your error codes

The validator deliberately sends unknown methods, unsupported versions and malformed requests, then checks both the JSON-RPC code and the HTTP status you answer with.

Validate a server →

Frequently asked

What is MCP error -32020?

HeaderMismatch, added in 2026-07-28. A server returns it with HTTP 400 when the Mcp-Method, Mcp-Name or MCP-Protocol-Version header on a request does not match the corresponding value in the request body. It exists because those headers are routing metadata that intermediaries act on, so a header allowed to disagree with the body would let policy be bypassed.

What is error -32022 in MCP?

UnsupportedProtocolVersion. If a server does not implement the protocol version a client requested, it must respond with this code and list the versions it does support in the error's data.supported field, so the client can retry rather than guess.

Why can't I use -32002 any more?

It was retired in 2026-07-28 and replaced by -32602 (Invalid params) for resource-not-found. The spec states that implementations of this revision must not emit it. Servers built against 2025-11-25 or earlier commonly still do, which is why it's one of the more frequent findings when an older server is first validated.

Which error codes can I define myself in MCP?

Not -32020 to -32099, which the specification reserves for itself, and preferably not -32000 to -32019, which is the legacy sub-range that new implementations should avoid entirely. That leaves codes outside the JSON-RPC server-error band for implementation-defined use.

What HTTP status should an MCP error use?

It depends on the error. An unknown method is HTTP 404 alongside JSON-RPC -32601. A malformed request — including a missing required _meta field — is HTTP 400 alongside -32602. A header mismatch is HTTP 400 with -32020. Returning HTTP 200 with a JSON-RPC error in the body is not conformant for these cases.

What is -32021 MissingRequiredClientCapability?

The code a server returns when processing a request requires a capability the client did not include in its per-request capabilities. The error's data.requiredCapabilities must list what was missing, so the client can decide whether it can retry with them declared.