What is MCP 2.0? The 2026-07-28 revision, explained and measured
There is officially no "MCP 2.0." The Model Context Protocol is versioned by date, and the revision everyone calls 2.0 is 2026-07-28. The nickname comes from the TypeScript SDK, which crossed to a 2.x major (@modelcontextprotocol/server) to implement it. If you search for MCP 2.0, this revision is what you mean, and this page uses both names so you can find it either way.
What actually changed on the wire
The 2026-07-28 revision removes the initialize handshake. A client no longer opens a session before doing work; every request carries its own identity in _meta - the protocol revision under io.modelcontextprotocol/protocolVersion, the client's name under io.modelcontextprotocol/clientInfo, and its capabilities under io.modelcontextprotocol/clientCapabilities. Over HTTP those claims are mirrored into headers (MCP-Protocol-Version, Mcp-Method, and Mcp-Name on tool calls), and a server must refuse a request whose headers and body disagree rather than guess. Capability discovery moved to a new method, server/discover, which returns the revisions a server supports and its capability set. Servers identify themselves on every response, stamping serverInfo into the result's _meta. The standalone SSE GET stream from the 2024-era HTTP transport is gone.
Everything before this - 2025-11-25 back to 2024-10-07 - is the initialize era. A server can serve both: the opening exchange of a connection decides which era that connection speaks.
Check any server yourself
One request answers whether an HTTP server speaks 2026-07-28. This is the exact probe we run against our own endpoint, and you can run it against ours right now:
curl -s https://mcpindex.ai/api/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: server/discover' \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"probe","version":"0"},"io.modelcontextprotocol/clientCapabilities":{}}}}'
A modern server answers with its supported revisions - ours returns "supportedVersions":["2026-07-28"] with serverInfo stamped in _meta. A legacy server has no server/discover; the spec-defined signals for that are error -32022 (unsupported protocol version), or -32601 paired with HTTP 404. A bare -32601 under HTTP 200 proves nothing - in our probing, servers return that for reasons that have nothing to do with protocol era, so treat it as inconclusive rather than sorting the server into a bucket.
The legacy leg is one request too:
curl -s https://mcpindex.ai/api/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}'
A server echoes the requested version if it supports it, or counter-offers its newest. Ours echoes 2025-06-18 here and serves every legacy revision back to 2024-10-07, so nothing you already run breaks.
Migrating a server: what we learned doing ours
Both of our MCP surfaces speak 2026-07-28: the hosted endpoint at mcpindex.ai/api/mcp and the npm package mcp-server-mcpindex (0.4.0 and later, stdio). The npm migration was a dependency swap, not a rewrite: @modelcontextprotocol/server 2.0's serveStdio with legacy: 'serve' serves both eras from one tool registry, and the era is selected per connection - existing Claude Desktop, Cursor, Cline, and Gemini CLI installs keep the exact initialize negotiation they had. Two things to know before you migrate. First, raw JSON Schema tool definitions port without a schema-library rewrite (fromJsonSchema), and the library then validates arguments before your handler runs, which is stricter than the 1.x SDK - clients that were sending sloppy arguments will start hearing about it. Second, check what you advertise: the 2.x library defaults tools.listChanged to true for registered tools, and if your server never emits that notification you are declaring a capability you do not have. Set it explicitly.
If you probe or crawl servers rather than run one, the lifecycle matters in the other direction: a tools/call sent with no opening is a protocol violation against a strict legacy server and an unstamped request against a strict modern one. Our own conformance prober had exactly this bug - rejections that servers earned for our lifecycle violation were being attributed to the tool under test - and fixing it changed verdicts. Open the era first, then measure.
How many servers actually speak it
Nobody publishes a measured answer, including, for now, us. Since 2026-08-13 a daily census has probed registry endpoints and recorded which era each answers - server/discover result, the spec-defined rejection codes, or the legacy initialize - and the adoption rate is deliberately withheld until enrollment covers a defensible share of remote-declaring servers. The current enrollment figure and the rate, when it publishes, live on the stats page, with the denominator attached. What we can say from probing already: bare error codes are not portable evidence (three SDK families return three different codes for the same condition), which is why the census counts only positive signals.
Where this fits in the trust problem
The protocol revision a server speaks says nothing about whether its tools do what they claim - that is a separate question, and it is the one this index exists to answer. A 2026-07-28 server can drift its tool contracts exactly as a legacy one can; the per-request envelope authenticates the conversation's shape, not the tools' behavior. If you are choosing servers, vet before you install; if you are running them, the drift gate holds contract changes regardless of era.
- Is there an official MCP 2.0?
- No. The Model Context Protocol is versioned by date, and the revision informally called MCP 2.0 is 2026-07-28. The 2.0 label comes from the TypeScript SDK's major version (@modelcontextprotocol/server 2.x), which implements that revision. When a page or changelog says MCP 2.0, read it as the 2026-07-28 protocol revision.
- How do I check if an MCP server supports MCP 2.0 (the 2026-07-28 revision)?
- Send one server/discover request with the per-request _meta envelope and the mirrored MCP-Protocol-Version and Mcp-Method headers. A modern server answers with its supportedVersions list. A legacy server either returns error -32022, or -32601 with HTTP 404, or simply answers nothing useful - and a bare -32601 under HTTP 200 is inconclusive, not proof of anything. The guide has the exact curl command, runnable against mcpindex.ai/api/mcp.
- Does MCP 2.0 break existing clients and servers?
- Not by itself. A server can serve both eras on one endpoint: the opening exchange of a connection decides whether it speaks the 2026-07-28 per-request envelope or the legacy initialize handshake. mcpindex.ai/api/mcp and the mcp-server-mcpindex npm package both do this - a 2026-era client gets server/discover, and every existing client keeps the initialize negotiation it had, down to 2024-10-07.
- How many MCP servers support MCP 2.0?
- No measured public number exists yet, from us or anyone. A daily census has probed registry endpoints since 2026-08-13 and records which protocol era each one speaks, and the adoption rate is deliberately withheld until enrollment covers a defensible share of remote-declaring servers. The enrollment figure and, once defensible, the rate itself publish on mcpindex.ai/stats with the denominator attached.
- What replaced the initialize handshake in the 2026-07-28 revision?
- Per-request metadata. Every request carries the protocol revision, client identity, and client capabilities in reserved _meta keys, mirrored into MCP-Protocol-Version, Mcp-Method, and Mcp-Name headers over HTTP; a conforming server rejects a request whose headers and body disagree. Capability discovery moved to the server/discover method, and servers stamp their serverInfo into every response.