createmcps.com

Error

MCP error: “Mcp-Session-Id header is required”

Against MCP 2026-07-28 · verified 10 August 2026

The server is running 2025-era session semantics against a client that speaks 2026-07-28. The header it is asking for no longer exists in the specification.

The error

Bad Request: Mcp-Session-Id header is required
How often we see this:

8 of the 16 real MCP servers we probed on 2026-08-11 tripped MCP-DSC-001. That is a snapshot of hand-picked public servers, not a random sample of the ecosystem — it shows the failure is common in practice, not that a given percentage of all servers have it.

What causes it

`Mcp-Session-Id` was removed from Streamable HTTP in the 2026-07-28 revision, along with the `initialize` / `notifications/initialized` handshake that produced it. The protocol core is stateless: every request now carries what it needs in headers and `params._meta`, and a server has nothing to look a session up by.

A modern client therefore sends its very first real request cold — no handshake, no session header. A server built against 2025-11-25 sees a missing header it considers mandatory and rejects the request with a 400 before it ever parses the body. From the client's side the server looks completely dead: discovery fails, so no tools are listed, so nothing works.

This is the single most common failure we have measured in the wild, and it is worth being precise about why: the server is not broken. It is correctly implementing a specification that a breaking revision replaced.

How to fix it

The fix

Stop requiring the headerRemove the guard that rejects requests without a session. Nothing else should be read from it — the session id is not a stand-in for authentication, and if you were using it as one, that is a separate and more urgent problem.

The fix

Read per-request context from params._meta insteadEverything the handshake used to establish now arrives on each request. Protocol version, client identity and capabilities are in `params._meta`, and the protocol version is also on the `MCP-Protocol-Version` header, which must agree with it.
A modern request carries its own context
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "_meta": {
      "protocolVersion": "2026-07-28",
      "clientInfo": { "name": "example-client", "version": "1.0.0" },
      "capabilities": {}
    }
  }
}

The fix

If you need continuity, key it on something you ownStateless does not mean you cannot have state — it means the PROTOCOL does not carry it. If a tool genuinely needs to correlate calls, use an authenticated identity or an explicit tool parameter. Do not reintroduce a transport-level session under a different header name; a client has no reason to send it.

The fix

Serve both eras during the migrationYou can accept legacy and modern requests from the same endpoint: branch on whether the request arrives with an `initialize` handshake or with `params._meta` and the 2026-07-28 headers. That lets old clients keep working while new ones succeed, and it is the safest order — make modern requests work first, then remove legacy support once your traffic has moved.

Rules involved

Each of these is checked against a live server, and each links to the exact sentence of the specification it comes from.

RuleWhat we checkLevelIf it fails
MCP-DSC-001server/discover is implementedMUSTfail
MCP-STL-001Server never mints or echoes Mcp-Session-IdMUST_NOTfail
MCP-STL-002A client-supplied Mcp-Session-Id is ignored, not requiredMUST_NOTfail

FAQ

Frequently asked

Why does my MCP server say Mcp-Session-Id header is required?

Because it was built against a 2025-era MCP specification, where Streamable HTTP used a session established by an initialize handshake. The 2026-07-28 revision removed both the handshake and the Mcp-Session-Id header, so a modern client never sends one and your server rejects the request before reading it.

Is Mcp-Session-Id deprecated or removed?

Removed. It is not a deprecation with a transition window — the 2026-07-28 revision made the protocol core stateless, and the header has no meaning in it. Servers should neither require nor emit it.

How do I keep state between MCP tool calls now?

Key it on something you control rather than on the transport: an authenticated user or token identity, or an explicit parameter the client passes to the tool. The protocol no longer provides a session to hang state from, and inventing a replacement header will not work because clients have no reason to send it.

Can one server support both the old session flow and the new stateless one?

Yes, and during a migration it is the safest option. Branch on how the request arrives: a legacy client opens with initialize and expects a session id back, while a modern client sends params._meta and the 2026-07-28 headers with no handshake. Support both, move your traffic, then drop the legacy path.

Check this against your own server

Point the validator at a live MCP server and it reports every rule on this page as pass, warn or fail — each linked to the exact spec sentence it comes from.

Validate a server →