Bad Request: Unsupported protocol version: 2026-07-28

Node.js · updated 2026-11-12

Returned with HTTP 400 (code -32000) by HTTP MCP servers built on @modelcontextprotocol/sdk 1.x when a request's MCP-Protocol-Version header names a version the SDK does not know. SDK 1.32.2, the last 1.x release, supports 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05 and 2024-10-07. MCP 2026-07-28 is the first stateless revision: it drops the initialize handshake, so a client speaking it sends the version on every request, and the Python SDK 2.x lists it as its latest version.

HTTP/1.1 400 Bad Request
Content-Type: application/json

{"jsonrpc":"2.0","error":{"code":-32000,"message":"Bad Request: Unsupported protocol version: 2026-07-28 (supported versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)"},"id":null}

Quick fix

If clients still connect, there is nothing to fix today: a client that supports both eras treats a 400 without a modern error body as a legacy server and falls back to initialize, which your 1.x server answers. To serve clients that speak only 2026-07-28, move the server to the v2 package (@modelcontextprotocol/server), which supports both. Do not fake the new protocol's UnsupportedProtocolVersionError (-32022) from a 1.x server: that error tells a client the server is modern, so it stops falling back.

  1. Check whether the client connected anyway: a dual-era client logs this 400, then retries with initialize and works.
  2. If a client only speaks 2026-07-28, it cannot use a 1.x server at all. Plan the move to @modelcontextprotocol/server 2.x.
  3. Until then, leave the 400 as it is; don't rewrite the header or the error code.
  4. Log the MCP-Protocol-Version header on rejected requests (transport.onerror receives the message) so you can see how many clients need the new protocol.
typescript
import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';

const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
// The SDK calls onerror before it answers a 400, with the reason in the message.
transport.onerror = (err) => {
  console.log('mcp rejected', {
    protocolVersion: request.headers.get('mcp-protocol-version'),
    userAgent: request.headers.get('user-agent'),
    error: err.message,
  });
};
Fix it with your coding agent

Paste this into Claude Code, Cursor or Codex in the project that throws it. The agent reads this guide in plain text and applies the fix that matches your stack.

prompttext
Read https://runheed.com/errors/mcp-unsupported-protocol-version.md and fix this error in this project.

Why it happens

A client on the newest protocol

MCP 2026-07-28 removed initialize and sends the version with every request. Clients built on the newest SDKs try it first.

A server on SDK 1.x

@modelcontextprotocol/sdk 1.x stops at 2025-11-25; only the v2 packages know 2026-07-28.

A hand-written client or test

A curl test or custom client that hard-codes a version header the server does not support.

Other fixes

  • The Python MCP client 2.x, connecting to a 1.x TypeScript server, still works: it sends no version header on initialize and settles on 2025-11-25.
  • Under 2026-07-28 a modern server answers an unsupported version with error -32022 and the list of versions it supports, so the client can retry.

Same error, other wording

  • Bad Request: Unsupported protocol version: 2026-07-28 (supported versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05, 2024-10-07)
  • Unsupported protocol version (code -32022, from a 2026-07-28 server)

Let your coding agent catch the next one

Your MCP server answers this with an HTTP error response and throws nothing, so unless your handler reports it Runheed doesn't record it. What it does record is the exceptions your running server code throws (route handlers, server rendering, API errors and background jobs) with the stack trace and the breadcrumbs before them, and serves those errors to Claude Code, Cursor or any MCP client.

Setup for Node.js and Express or Vercel Functions, then have your agent fix and resolve it.

Building an MCP server? Track the errors your tools raise, in TypeScript or Python, so a failing tool shows up with its line instead of only in your users' client logs.

Related errors

More in MCP servers and clients

References: MCP specification 2026-07-28: versioning and compatibility, MCP specification 2026-07-28: key changes, MCP TypeScript SDK repository

Spotted a mistake? Email hello@greatwork.company. About Runheed.