How does MCP handle protocol versioning?

4 minintermediatemcpversioningprotocol

Quick Answer

MCP versions its specification using date-based strings (e.g. 2024-11-05, 2025-03-26, 2025-06-18) rather than semver. During initialize, the client proposes the latest version it supports; the server replies with the version it will actually use for the session, which may be an older version both sides can agree on. If the client doesn't support whatever version the server chose, it should terminate the connection rather than continue with mismatched expectations. For the Streamable HTTP transport specifically, most requests after initialization are also expected to carry an MCP-Protocol-Version header, so a server can validate the negotiated version on every subsequent call, not just at handshake time.

Detailed Answer

Unlike libraries that use semver (2.3.1), MCP versions its wire protocol with a release date string. The spec itself is versioned like a standards document, not a package.

How negotiation works

// Client proposes its newest known version
{"method": "initialize", "params": {"protocolVersion": "2025-06-18", ...}}

// Server responds with whatever version it can actually support
{"result": {"protocolVersion": "2025-03-26", ...}}

If the server's chosen version isn't one the client can work with, the client should close the connection. Otherwise it risks confusing failures later, when it hits a method or field the server's version doesn't understand.

Why this shape, not semver

A date string signals "this is the state of the spec as of this date." That fits a standard that evolves by adding whole new primitives and capabilities — sampling arrived, then elicitation, then structured tool output — rather than incrementing isolated API surface numbers. It also sidesteps semver's implicit promise of a strict compatibility contract (minor = compatible, major = breaking), which doesn't map cleanly onto a protocol negotiated per-connection rather than pinned per-dependency.

Practical implications for implementers

  • A server built against an older spec date can keep working against newer clients, as long as it negotiates down to a version it supports. It doesn't need a rewrite every time the spec adds something new.
  • A server should validate the negotiated version on every request, not just accept it once at initialize and ignore it after. Over Streamable HTTP especially, the MCP-Protocol-Version header on later requests lets a server catch a client that's inconsistent about which version it's actually speaking.
  • SDK authors typically pin to (and advertise) the newest spec version they've implemented, while still negotiating down for older clients. That's why "which protocol version does this SDK/server support" is a normal, useful question when integrating two MCP implementations built at different times.

Related Resources