Research guide · MCP interoperability · 13 September 2026
MCP HeaderMismatch (-32020): fix x-mcp-header and Mcp-Param errors
A -32020 HeaderMismatch, missing Mcp-Param-owner or unexplained HTTP 400 on a modern MCP tool call usually means the transport headers and JSON-RPC body no longer describe the same request. MCP 2026-07-28 made those headers part of the Streamable HTTP routing contract, and current SDKs are still exposing edge cases around tool-definition caches and recovery.
Published 13 September 2026 · sources checked 13 September 2026
-32020
Current HeaderMismatch error code
2026-07-28
MCP revision that standardised the modern routing headers
Mcp-Method
Mirrors the JSON-RPC method for modern HTTP routing
Mcp-Param-*
Mirrors only tool parameters explicitly annotated with x-mcp-header
What changed
MCP requests became routable without parsing the JSON body
MCP 2026-07-28 moved the protocol core toward stateless request/response HTTP. On the modern Streamable HTTP path, requests carry MCP-Protocol-Version plus routing information such as Mcp-Method and, where the request has a principal name, Mcp-Name. Gateways can route and authorize the call from headers, but that only works safely if the headers agree with the JSON-RPC body.
SEP-2243 also lets a tool mark selected primitive input properties with x-mcp-header. A conforming client mirrors those argument values into headers such as Mcp-Param-Owner. The server validates the mirrored value against the body before dispatch. Missing, malformed or conflicting values are rejected rather than trusted.
Current official SDK documentation assigns -32020 to HeaderMismatch. Some older proposal text still shows the pre-final allocation -32001; do not hard-code the historical number when diagnosing a current 2026-07-28 implementation.
Fast diagnosis
Map the exact error to the boundary that failed
| Signal | Likely boundary | First action |
|---|---|---|
missing Mcp-Method | A modern Streamable HTTP request did not carry the JSON-RPC method in the required routing header. | Confirm the request negotiated 2026-07-28 and let a current SDK generate Mcp-Method from the body method. |
Mcp-Name mismatch | The routing name in the header and the principal request name in the body disagree. | Compare Mcp-Name with the exact tool, prompt, resource or task identifier in the JSON-RPC request. |
missing Mcp-Param-owner | A tool schema declares x-mcp-header for owner, but the client sent the body argument without the mirrored header. | Refresh the tool definition and ensure the current HTTP client knows the x-mcp-header annotation before tools/call. |
HeaderMismatch after a tool changed | The client may be using a stale cached tools/list definition while the server validates against a newer schema. | Re-list tools, invalidate the relevant catalog cache and retry once with the current definition. |
Works on legacy, fails on 2026-07-28 | The stricter modern HTTP path validates standard and annotated routing headers against the body. | Fix the modern request instead of suppressing validation or silently downgrading protocol versions. |
Works on one SDK, fails on another | The protocol rule may be valid while one SDK still has a recovery, declaration or compatibility gap. | Check the SDK's 2026-07-28 support notes and current issue tracker before changing server semantics. |
Repair sequence
Seven checks before changing server behavior
- 1. Confirm the negotiated protocol version. If the request claims
2026-07-28, debug it as a modern request. Do not assume a server URL implies one protocol era. - 2. Inspect the actual failing HTTP request. Compare
MCP-Protocol-Version,Mcp-MethodandMcp-Namewith the corresponding JSON-RPC fields rather than looking only at SDK logs. - 3. Fetch the current tool definition. Re-run
tools/listor use the SDK's supported explicit tool-definition option so the client sees any currentx-mcp-headerannotations. - 4. Mirror only annotated parameters. If
owneris annotated asx-mcp-header: "owner", send the body argument and its matchingMcp-Param-ownervalue together. Unannotated arguments do not need custom MCP parameter headers. - 5. Check encoding and types. Current SDK guidance limits these routed properties to supported primitive types and applies transport encoding where necessary. Let the SDK codec do this when possible instead of manually inventing header serialization.
- 6. Treat a retry as schema recovery, not brute force. If the failure was caused by a stale tool definition, refresh the definition once and retry with the same logical operation. Repeating the same malformed request does not improve interoperability.
- 7. If it is SDK-specific, isolate the compatibility gap. Reproduce the same tool definition and call with a known-conforming SDK before weakening server validation. A client bug and a protocol requirement are different verdicts.
Current SDK traps
Fresh issue reports show why “the schema looks right” is not enough
Two open Python SDK issues from 9 September 2026 focus directly on this boundary. One reports that the client does not yet perform the expected recovery after -32020 when it did not already know the tool's x-mcp-header map. Another reports that the high-level server API can expose an invalid annotation without a declaration/validation path that makes the intended header behavior usable end to end. These are implementation reports, not changes to the protocol contract.
A separate TypeScript SDK issue documents a different compatibility hole: a hosted server required Mcp-Param-* headers while negotiation had fallen back to an older protocol era, but the SDK intentionally gated automatic mirroring to modern 2026-07-28 connections. The lesson is not to send modern headers everywhere. It is to identify the negotiated era and the server's actual requirement before choosing a workaround.
Browsers add another boundary: dynamically named custom headers can interact badly with credentialed CORS policy. If a browser client fails while a server-side client works, inspect preflight and SDK browser behavior before blaming the tool schema.
Security
Do not turn routing metadata into a secret channel
x-mcp-header exists to expose selected routing-relevant tool parameters to HTTP infrastructure. That makes those values easier for gateways, proxies, observability systems and logs to see. Do not annotate API keys, bearer tokens, private credentials or unnecessary personal information merely to make a call pass.
Keep authentication in the MCP authorization flow and use header-routed tool parameters only where the server intentionally needs that non-secret value for routing, rate limiting, authorization policy or infrastructure selection. A request that cannot be represented safely should fail closed rather than leak a secret into infrastructure metadata.
Related zFinia guides
Continue from transport integrity into trust and authorization
- MCP OAuth 401/403 troubleshooting
Separate header-routing failures from resource metadata, audience and insufficient-scope authorization failures.
- MCP Client ID Metadata Documents
Fix client-registration and CIMD/DCR migration problems before debugging the tool transport.
- Verify an MCP server before connecting
Check identity, ownership, scopes and runtime behavior before granting credentials or state-changing authority.
- zFinia machine services
Browse machine-readable services and current contracts for agent and machine-economy workflows.
Sources
Primary specification and implementation references
- Model Context Protocol — 2026-07-28 specification release
- SEP-2243 — HTTP Header Standardization for Streamable HTTP
- MCP Python SDK — v1 to v2 migration and Mcp-Param validation
- MCP TypeScript SDK — supporting protocol revision 2026-07-28
- Python SDK issue #3484 — HeaderMismatch recovery and x-mcp-header map
- Python SDK issue #3486 — x-mcp-header declaration and validation gap
- TypeScript SDK issue #2639 — legacy-era Mcp-Param interoperability gap