Spec explainer
What is the Mcp-Method header in MCP?
Last verified: 10 August 2026 · spec 2026-07-28 · ruleset 1.4.2
Mcp-Method is an HTTP header required on every MCP Streamable HTTP request. Its value mirrors the JSON-RPC method field in the body, so a gateway or load balancer can route and inspect a request without parsing JSON. If the header and body disagree, the server must reject the request with 400 and -32020 HeaderMismatch.The short answer
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call ← mirrors "method" in the body
Mcp-Name: get_weather ← mirrors params.name
{
"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "location": "Seattle, WA" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}“Mcp-Method | method | All requests. These headers are REQUIRED for compliance.”
That last clause — REQUIRED for compliance — is what makes this a migration task rather than an optimisation. A server built against 2025-11-25 does not send or validate these headers at all.
Why the header exists
Everything in MCP's Streamable HTTP transport is a POST to the same URL. Before this revision, an intermediary that wanted to know what a request actually did — to rate-limit tools/call differently from tools/list, to route expensive tools to a bigger pool, to log operations — had to buffer and parse the JSON body. That is expensive, it defeats streaming, and it forces every proxy in the path to understand MCP.
Lifting the method into a header makes the request self-describing at the HTTP layer. An nginx or Envoy config can match on Mcp-Method the way it already matches on any other header, with no body inspection and no MCP awareness.
The three required headers
Mcp-Method arrived alongside two others, and they are easy to confuse because they are all required but not all required on the same requests.
| Header | Mirrors | Required on |
|---|---|---|
| MCP-Protocol-Version | _meta protocolVersion | Every POST |
| Mcp-Method | method | Every request |
| Mcp-Name | params.name or params.uri | tools/call, resources/read, prompts/get |
“Mcp-Name | params.name or params.uri | tools/call, resources/read, prompts/get requests.”
“Every POST request to the MCP endpoint MUST include an MCP-Protocol-Version header.”
Mismatches, and the -32020 error
The single normative rule that governs all three headers is that they must agree with the body:
“Servers that process the request body MUST reject requests where the values specified in the headers do not match the corresponding values in the request body.”
“The header value MUST match the io.modelcontextprotocol/protocolVersion field carried in the request body's _meta. If the values do not match, the server MUST reject the request with 400 Bad Request and a HeaderMismatch JSON-RPC error.”
POST /mcp
Mcp-Method: tools/list ← says list
{ "method": "tools/call", … } ← does call
// A server that dispatches on the body and ignores
// the header will happily run tools/call here.
// Every gateway in the path believed it was a list.HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32020,
"message": "Header mismatch: Mcp-Method does not match body method"
}
}-32020 sits in the -32020–-32099 range the specification reserves for itself, added in this revision. It is one of three new codes, next to -32021 MissingRequiredClientCapability and -32022 UnsupportedProtocolVersion.
-32601 Method not found for a mismatched header has validated in the wrong order — the spec states the MUST-reject requirement but does not state the ordering, so this is our inference from it, and it is the one HDR rule with no verbatim sentence behind it (MCP-HDR-010, which we grade as a warning rather than a failure for exactly that reason).Case-insensitivity is normative, not incidental
“Header names (called "field names" in RFC 9110) are case-insensitive. Clients and servers MUST use case-insensitive comparisons for header names.”
This one bites in production rather than in testing, because every client in your test suite probably sends the documented casing. The failure appears when a different client, an HTTP/2 stack that lowercases field names, or a proxy that normalises them, sends mcp-method and your exact-match lookup returns undefined — which your code then treats as a missing required header.
// Wrong: works only for one casing
const method = req.headers["Mcp-Method"]
// Right: Node lowercases incoming header names for you,
// but be explicit rather than relying on the runtime
const method = req.headers["mcp-method"]
// In a framework that hands you a raw Headers object:
const method = headers.get("mcp-method") // Headers.get is case-insensitiveThe Base64 sentinel encoding
HTTP header values are constrained to a narrow ASCII set, but tool and prompt names are not. The spec resolves that with a sentinel encoding — a name outside the safe set travels Base64-encoded — and puts the decoding obligation on the server:
“For headers that permit the Base64 sentinel encoding (Mcp-Name and Mcp-Param-{Name}), servers MUST decode encoded values before comparing them to the body value.”
The failure mode is quiet and complete: a server that compares the raw header against the body name will reject every request for a tool whose name needs encoding, while every ASCII-named tool keeps working. It looks like “that one tool is broken” rather than a header bug.
Mcp-Param-{Name}, for servers that opt in
A tool can promote individual input parameters into headers by marking them x-mcp-header in its inputSchema. That is opt-in — most servers never do it — but a server that declares it takes on two extra obligations:
“Any server that processes the message body MUST validate that encoded header values, after decoding if Base64-encoded, match the corresponding values in the request body.”
“Servers MUST reject requests with a recognized Mcp-Param-{Name} header that contains invalid characters.”
Both rules are marked v1: false in our catalogue, meaning we do not yet probe them automatically; they need a server that declares x-mcp-header in a published schema before there is anything to check. The schema-side constraints on those declarations are covered by the seven MCP-SCH-* rules.
The 10 header rules we check
| Rule | What we check | Level | If it fails |
|---|---|---|---|
| MCP-HDR-001 | Missing Mcp-Method rejected with 400 + HeaderMismatch | MUST | fail |
| MCP-HDR-002 | Missing Mcp-Name on tools/call rejected with 400 + HeaderMismatch | MUST | fail |
| MCP-HDR-003 | Mcp-Name header must match the request body | MUST | fail |
| MCP-HDR-004 | Missing MCP-Protocol-Version rejected (modern-only servers) | MUST | fail |
| MCP-HDR-005 | MCP-Protocol-Version header must match _meta.protocolVersion | MUST | fail |
| MCP-HDR-006 | Header names compared case-insensitively | MUST | fail |
| MCP-HDR-007 | Base64 sentinel-encoded header values decoded before comparison | MUST | fail |
| MCP-HDR-008 | Mcp-Param-{Name} validated against body when x-mcp-header is declared | MUST | fail |
| MCP-HDR-009 | Mcp-Param-{Name} containing invalid characters is rejected | MUST | fail |
| MCP-HDR-010 | Header validation runs before method dispatch | MAY | warn |
Nine of the ten carry a verbatim spec sentence. MCP-HDR-010 (validate before dispatch) is our inference, graded as a warning.
Check your header handling
The validator sends deliberately mismatched and missing headers and reports exactly which of these ten rules your server satisfies — including the ordering check that distinguishes a -32020 from a -32601.
Validate a server →Frequently asked
What is the Mcp-Method header?
A required HTTP header on every MCP Streamable HTTP request whose value mirrors the JSON-RPC method field in the request body — for example Mcp-Method: tools/call alongside "method": "tools/call". It lets a gateway, proxy or load balancer route and inspect a request without parsing the JSON body.
Is Mcp-Method required?
Yes. The 2026-07-28 specification lists it as REQUIRED for compliance on all requests. A server that processes the request body must reject a request whose header value does not match the body value with HTTP 400 Bad Request and JSON-RPC error code -32020 (HeaderMismatch).
What is the difference between Mcp-Method and Mcp-Name?
Mcp-Method carries the JSON-RPC method and is required on every request. Mcp-Name carries the target of that method — params.name or params.uri — and is required only on tools/call, resources/read and prompts/get. Together they let an intermediary see both what operation is being performed and on which tool or resource.
What is error -32020 HeaderMismatch?
The JSON-RPC error code a server must return, with HTTP 400, when a header value contradicts the corresponding value in the request body. It was added in 2026-07-28 as part of the reserved -32020 to -32099 range. Returning -32601 Method not found instead usually means header validation is running after method dispatch rather than before it.
Are MCP header names case-sensitive?
No. Header field names are case-insensitive under RFC 9110, and the specification requires clients and servers to use case-insensitive comparisons. Mcp-Method, MCP-METHOD and mcp-method are the same header, so matching on an exact-case string is a conformance bug even though it appears to work against clients that happen to use the documented casing.
What is the Base64 sentinel encoding in Mcp-Name?
HTTP header values cannot safely carry arbitrary Unicode, so a tool or prompt name outside the header-safe ASCII set is transmitted Base64-encoded behind a sentinel marker. Servers must decode such values before comparing them to the body value — comparing the encoded form against the raw body name would reject every conformant request using a non-ASCII name.