Skip to main content
  • Pricing
News

MCP 2026-07-28 Spec Explained: What Changed in the Stateless Release and How to Migrate

By Oakgen TeamPublished 10 min read

Share
MCP 2026-07-28 Spec Explained: What Changed in the Stateless Release and How to Migrate

The MCP 2026-07-28 spec is final in the sense that matters to builders. The official MCP blog announced the release on July 28, 2026, the specification repository tags it as the stable release, and the spec site names it the current version. It is no longer a release candidate, even though pages written before that date still say it is.

The change is simple to state. MCP stopped being a stateful protocol. The initialize handshake and the Mcp-Session-Id header are gone, and every request carries what the server needs. If you run a remote server, you must implement server/discover, validate new routing headers, add cache hints to list results, and move mid-call questions to Multi Round-Trip Requests. Keep serving the old version too, because a legacy client cannot talk to a modern-only server.

Building with MCP for creative work?

Oakgen runs an MCP server for image, video and audio generation. See what it exposes and how teams connect an agent to it.

See Oakgen's MCP server

The short version

QuestionShort answerSource
Is it final?Released July 28, 2026. GitHub marks it the stable release and Latest. The spec site calls it Current.MCP blog, Jul 28 2026 and GitHub releases
Biggest changeNo handshake and no protocol session. Every request is self-describing.Changelog
New required methodserver/discover, which servers must implement. Clients may skip it.Discovery page
New HTTP headersMcp-Method on every request, Mcp-Name on named calls, both checked against the body.Streamable HTTP page
Server asks the user somethingReturn input_required and let the client retry (MRTR).MRTR page
Next releaseOfficial plan is 2027-03-30. Some secondary pages say December 15, 2026.MCP blog, Nov 11 2026

Disclosure. Oakgen is our product and we do not make MCP. This explainer is written from the official pages, and Oakgen appears only in two short notes and the banners.

Is it final or a release candidate?

It is released, and the sources that disagree are mostly out of date rather than wrong. Here is every status signal we found, dated.

SourceDateWhat it saysHow to read it
MCP blog, release candidate postMay 21, 2026Candidate locked, final to ship July 28Correct then, stale now
GitHub release 2026-07-28 RCMay 29, 2026Marked Pre-release, "this specification is not final"Correct then, stale now
Agentic AI Foundation explainerJul 21, 2026Covers the candidate, says check details against the final textPre-final. Calls the deprecations "proposed"
MCP blog, release postJul 28, 2026"Officially pushing the release button"Primary, final
GitHub release 2026-07-28Jul 28, 2026"Marks the stable release", tagged LatestPrimary, final
Spec site, versioning pageRead Nov 12, 2026"The current protocol version is 2026-07-28"Primary, current

One wording trap is worth knowing. The spec site's versioning page defines three labels. Draft is in progress, Current is ready for use, and Final means past, complete specifications that will not change. By that vocabulary 2026-07-28 is Current, not Final, because it can still receive backwards compatible changes. Anyone who says "final" means "shipped".

Who this is for

You maintain a remote MCP server and are tired of sticky sessions, or you build a client or gateway and need to know what changes on the wire. If you only use MCP servers through a desktop app, the advice is to update the app.

How we checked this

On November 12, 2026 we opened the 2026-07-28 changelog and the Streamable HTTP, MRTR, caching, discovery, versioning and deprecated-features pages on modelcontextprotocol.io, the GitHub releases page, the official MCP blog posts, and SDK release notes for TypeScript, Python, Go and Ruby.

We did not run a conformance suite or test any SDK. Behavior statements are the spec's own wording, and SDK versions move quickly, so re-check them before you pin.

What changed, in plain words

No handshake, no session

The changelog removes protocol-level sessions and the Mcp-Session-Id header (SEP-2567), and removes the initialize and notifications/initialized exchange (SEP-2575). Each request now carries its protocol version and client capabilities in _meta. Clients should also send their identity, and servers should return theirs in each result's _meta.

A request now looks like this on the wire, using the official blog's example.

POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search

{"jsonrpc":"2.0","id":1,"method":"tools/call",
 "params":{"name":"search","arguments":{"q":"otters"},
 "_meta":{"io.modelcontextprotocol/clientInfo":{"name":"my-app","version":"1.0"}}}}

In the official post's words, any request can land on any instance behind a plain round-robin load balancer. If your app needs state across calls, mint an explicit handle, such as a basket id, and let the model pass it back as a normal argument.

Discovery is a method, not a handshake

Servers must implement server/discover. It returns supportedVersions, capabilities, optional instructions and a self-reported serverInfo, with caching hints. Clients may call it first, but are not required to. They can send any request directly and handle UnsupportedProtocolVersionError if the version is wrong.

On stdio, a client that supports old and new servers should probe with server/discover first.

Server questions become Multi Round-Trip Requests

A server can no longer open a request to the client mid-call. For elicitation/create, sampling/createMessage and roots/list, the server now answers with resultType: "input_required" plus inputRequests, and the client retries the original call with inputResponses. The MRTR page allows this only on tools/call, resources/read and prompts/get.

The part developers miss is requestState. It is an opaque string the server hands out and the client echoes back unchanged. The spec says servers must treat it as attacker-controlled input and protect its integrity with an HMAC or AEAD whenever it influences authorization, resource access or business logic. It suggests binding it to the principal, a short expiry and a digest of the originating request.

The spec adds that this bounds replay but does not make state single-use. Enforce one-time redemption on the server.

Routing headers and header validation

Every POST must carry MCP-Protocol-Version, matching the version in _meta. Mcp-Method is required on all requests. Mcp-Name is required on tools/call, resources/read and prompts/get, taken from params.name or params.uri. Non-ASCII values use a Base64 sentinel encoding.

Servers must reject any request whose headers disagree with its body, with HTTP 400 and JSON-RPC error -32020 (HeaderMismatch). The reason is that a load balancer might route on the header while the server executes on the body.

An optional x-mcp-header annotation on a tool parameter mirrors its value into an Mcp-Param-{Name} header. It allows only string, integer and boolean parameters, so number is out. Clients on Streamable HTTP must drop a tool whose annotation is invalid.

Cacheable lists

Complete results from server/discover, tools/list, prompts/list, resources/list, resources/templates/list and resources/read must carry ttlMs (zero or more) and cacheScope, either public or private. Servers should also return tools in a deterministic order. A private result must not be shared across authorization contexts, and MRTR retry results must not be cached.

Everything else

Change notifications move to a single subscriptions/listen stream that clients opt into per type. Tasks leave the core and become the io.modelcontextprotocol/tasks extension, with tasks/get polling and a new tasks/update (SEP-2663). ping, logging/setLevel and SSE resumability with Last-Event-ID are removed, so a dropped stream loses the in-flight request and the client must re-issue it with a new id.

On authorization, clients must validate the iss parameter (RFC 9207) before redeeming a code, must set application_type in Dynamic Client Registration, and must bind credentials to the issuer that created them. Dynamic Client Registration is deprecated in favor of Client ID Metadata Documents.

A missing resource now returns -32602 instead of -32002, and MCP-reserved error codes sit in -32020 to -32099. Every result carries a required resultType.

Before and after, change by change

Keep this table open while you migrate. "Before" is 2025-11-25 behavior as described in the 2026-07-28 changelog and transport pages.

AreaBefore (2025-11-25)After (2026-07-28)What you do
Connection startinitialize then notifications/initializedRemoved. Version and capabilities ride in _meta on every requestDelete handshake state. Read _meta per request
SessionMcp-Session-Id, DELETE to endRemoved. Modern-only servers ignore the headerMint explicit handles for app state
Capability discoveryExchanged once in the handshakeserver/discover, mandatory on servers, optional for clientsImplement it, return versions, capabilities, identity
Server asks the clientelicitation/create, sampling/createMessage, roots/list on an open streaminput_required result, client retries with inputResponsesRewrite those tools as retryable calls and sign requestState
RoutingParse the JSON bodyMcp-Method, Mcp-Name, MCP-Protocol-Version headers, validated against the bodyAdd header checks and -32020 errors
Change notificationsHTTP GET stream, resources/subscribesubscriptions/listen stream, opt in per typeRework listeners or set list changes to false
Stream recoveryLast-Event-ID resumabilityRemoved. Re-issue the request with a new idMake tool calls safe to retry
List cachingNo hintsRequired ttlMs and cacheScope, deterministic orderAdd both fields to every list and read result
Long-running workExperimental core Tasksio.modelcontextprotocol/tasks extension, tasks/get and tasks/update, no tasks/listMigrate if you shipped the experimental API
Client registrationDCRDCR deprecated, Client ID Metadata Documents preferred, application_type requiredPlan the move. Set application_type now
Roots, SamplingCore client featuresDeprecated, still working, earliest removal after July 28, 2027Do not adopt in new code
TransportStreamable HTTP, deprecated HTTP+SSE still describedHTTP+SSE reclassified as DeprecatedLeave it if you must, plan the exit

See how a creative agent talks to a real MCP server

Oakgen's MCP page lists the tools an agent can call for images, video and audio, and the limits that apply.

Explore Oakgen MCP tools

Migration checklist

Our own checklist, built from the changelog and the transport, MRTR and caching pages.

Server developers

  • Remove every code path that reads or writes Mcp-Session-Id, and every assumption that initialize ran first.
  • Read io.modelcontextprotocol/protocolVersion from _meta on each request, and return UnsupportedProtocolVersionError with a supported list when it is not one you serve.
  • Implement server/discover with supportedVersions, capabilities, instructions if useful, and serverInfo.
  • Require MCP-Protocol-Version, Mcp-Method and, for tools/call, resources/read and prompts/get, Mcp-Name. Return 400 and -32020 when a header is missing or disagrees with the body.
  • Add resultType, ttlMs and cacheScope to complete results, and return tools/list in a stable order. Use private for anything user-specific.
  • Replace server-initiated elicitation with input_required results. Sign requestState with an HMAC or AEAD, and bind it to the user, a short expiry and the originating request.
  • Make tool calls safe to retry. A broken stream can no longer resume.
  • If you used x-mcp-header, check every annotated parameter is a string, integer or boolean at a statically reachable path.
  • Decide on dual-era support, and test one legacy and one modern client against the same endpoint.

Client and host developers

  • Send version, capabilities and identity in _meta on every request, plus the MCP-Protocol-Version and Mcp-Method headers, and Mcp-Name where it applies. Treat a result without resultType as complete.
  • Mirror x-mcp-header parameters into Mcp-Param-* headers, and exclude tools with invalid annotations.
  • Handle input_required. Gather input, retry with a new request id, echo requestState byte for byte, and never cache the retry.
  • Honor ttlMs and cacheScope, checking freshness on use. Re-issue broken requests with a new id.
  • Match -32602 for a missing resource, validate iss, key stored credentials by issuer, and set application_type if you still register dynamically.
  • On stdio, probe with server/discover first, and fall back to initialize on any error that is not a recognized modern one.

Gateway and platform teams

  • Route and rate limit on Mcp-Method and Mcp-Name, but only after confirming MCP-Protocol-Version says the request needs header and body validation.
  • Forward unknown Mcp-Param-* headers untouched, and never share cached private results across authorization contexts.

What the SDKs do

The July 28 release post listed the TypeScript, Python, Go and C# SDKs as ready, with Rust in beta. The official SDK page on November 12, 2026 lists Rust and Ruby as Tier 1 too. Support is not automatic.

SDKWhat we foundSource
TypeScriptv2 packages. Release 2.4.0 of Oct 23, 2026 notes a number parameter with x-mcp-header is rejected, and the server answers -32020TypeScript SDK releases
Pythonv2 renames FastMCP to MCPServer. Release v2.3.0 of Oct 2, 2026 fails registration for an invalid x-mcp-headerPython SDK releases, beta post
Gov1.7.0 serves 2026-07-28 over HTTP only when StreamableHTTPOptions.Stateless is trueGo SDK v1.7.0
RubyTier 1 assessment dated Aug 15, 2026 says v1.2.0 implemented the revision 18 days after the specIssue 3247

The Python rename and the TypeScript opt-in note come from the June 29 beta post, so re-check them against current release notes. The official Python tutorial requires Python SDK 2.0.0 or higher, and library authors who want to stay on v1 were told to cap the dependency, for example mcp>=1.27,<2.

Where the official sources disagree with each other

Two small conflicts sit inside the official material.

  • HTTP+SSE timing. The July 28 blog says the legacy transport has a "year-long offramp". The registry says earliest removal is "three months after SEP-2596 reaches Final". Plan around neither date.
  • Dynamic Client Registration timing. The blog says it "will be removed in a future version". The registry gives the first revision released on or after July 28, 2027, and adds that removal is a Core Maintainer decision that may come later.

Our inference, not an official statement. The registry's removal date is a floor, not a schedule. On the six-month calendar, the first release after July 28, 2027 would be the September 2027 one in the official timeline graphic.

How a creative team would apply this

Most creative teams will never touch the wire format. They will notice that a tool can now pause to ask the user to confirm something, such as a cost, before it acts, because MRTR makes that a protocol pattern. Our MCP security checklist for creative teams covers the approval side, and the MCP versus API comparison covers when you need MCP at all.

A note on our own server. The Oakgen repository runs its MCP endpoint as a stateless JSON transport with no session ids, on the TypeScript SDK 1.x line. We have not migrated it to 2026-07-28, so this post does not claim Oakgen speaks the new revision.

Common mistakes

  1. Treating the release candidate posts as current. Several still rank. Check the date and the status line.
  2. Shipping a modern-only server too early. A legacy client against it fails.
  3. Trusting requestState. It passes through the client, so unsigned state is attacker-controlled input.
  4. Caching a private list for everyone. That leaks tool lists across users.
  5. Putting a number parameter under x-mcp-header. Clients drop the tool, and some SDKs refuse it at registration.
  6. Upgrading the SDK and assuming the wire changed. The Go and TypeScript notes show the new revision can be an explicit opt-in.

Decision framework

Your situationMove nowCan wait
Remote server with sticky sessions or a shared session storeMigrate and serve both erasSession code on legacy paths
Remote server, already stateless JSON, no server-initiated requestsAdd server/discover, headers, cache hintsMRTR
Server that uses elicitation or samplingPlan the MRTR rewrite, stop adopting samplingRemoving sampling, due no earlier than mid-2027
stdio-only local serverUpdate the SDK when it supports the revisionHeader work, which is HTTP-only
Client or agent hostDual-era client with discover probeSubscriptions rework if you do not use list changes

What I would do

I would ship dual-era first. Keep the legacy path alive, add the modern path next to it, and test one old and one new client against the same URL. The spec's own matrix shows that a dual-era server works with legacy and modern clients alike.

Next I would take the cheap wins. server/discover, header validation and ttlMs are small. MRTR is the real rewrite, so I would do it tool by tool, starting with tools that need user confirmation.

I would not use Roots, Sampling or Logging in new code, and I would not rush removing old code either, since no removal can come before July 28, 2027. For what comes after, read our post on the six-month MCP release cycle, and for the gateway side the MCP gateways explainer.

Plan creative work with an agent, then generate the assets

Start a brief in Oakgen Agent Chat, review the plan, and generate images, video and audio from the same workspace.

Open Agent Chat

Connect an agent to Oakgen's MCP server

If you are wiring an agent to a creative toolset, start from the Oakgen MCP page and pick the client you already use.

Connect your agent

Frequently asked questions

Is the MCP 2026-07-28 specification final or a release candidate?

It is released. The official MCP blog announced it on July 28, 2026, the specification repository's GitHub release for 2026-07-28 says it marks the stable release and is tagged Latest, and the spec site's versioning page names 2026-07-28 as the current protocol version. The release candidate was a separate pre-release dated May 29, 2026 on GitHub. Pages written before July 28, including the official release candidate post and an Agentic AI Foundation explainer dated July 21, still describe it as a candidate. Those are out of date on status. One wording detail is that the site's own versioning page reserves the label Final for past revisions and calls 2026-07-28 Current.

Does my existing MCP server break because of the new spec?

Not on its own. The official SDK beta post says that nothing breaks on July 28 for existing clients and servers, because that date only publishes the normative text. What breaks is the pairing of a legacy client (one that sends initialize) with a server that supports only 2026-07-28. The spec's compatibility matrix says that combination fails, and a modern-only client talking to a legacy server fails too. The fix is a dual-era implementation that serves both until your clients have moved.

What replaced the initialize handshake and the Mcp-Session-Id header?

Every request now carries its protocol version, client capabilities and (as a SHOULD) client identity in its _meta field, and over HTTP the version also goes in the MCP-Protocol-Version header. A new server/discover method, which servers must implement and clients may call, returns supported versions, capabilities and identity. State that must survive between calls is carried by explicit handles the server mints and the model passes back as ordinary tool arguments.

What happens to elicitation and sampling in a stateless protocol?

Servers can no longer send requests to the client on an open stream. Under Multi Round-Trip Requests (SEP-2322), the server answers a tools/call, resources/read or prompts/get with an input_required result that lists what it needs, and the client retries the original request with the answers in inputResponses. Roots, Sampling and Logging are deprecated and still work for at least twelve months. The registry lists the earliest removal as the first revision released on or after July 28, 2027.

Which SDK versions support MCP 2026-07-28?

The official release post of July 28, 2026 lists the TypeScript, Python, Go and C# SDKs as supporting it, with the Rust SDK in beta. When we read the SDK page on November 12, 2026 it listed Rust and Ruby as Tier 1 as well. Check each SDK's release notes, because adoption is not automatic. For example, the Go SDK v1.7.0 notes say HTTP serves 2026-07-28 only when StreamableHTTPOptions.Stateless is true, and the official Python server tutorial requires Python SDK 2.0.0 or higher.

When is the next MCP specification release?

The official MCP blog post of November 11, 2026 says specification releases move to a six-month schedule, generally the last Tuesday of March and September, and targets March 30, 2027 for version 2027-03-30. Some secondary pages, including a dev.to weekly dated November 11, 2026 and a GitHub issue from August 2026, say the next release is December 15, 2026. We did not find that date on an official MCP page, so treat the official post as the current plan.

Do I have to move from Dynamic Client Registration to Client ID Metadata Documents now?

No. The changelog deprecates Dynamic Client Registration in favor of Client ID Metadata Documents, but says it remains available for authorization servers that do not support them. The deprecated features registry lists the earliest removal as the first revision released on or after July 28, 2027, and says actual removal is a Core Maintainer decision that may happen later. If you keep using DCR, the new rule is that clients must set an appropriate application_type.

What is the first thing to change in a remote MCP server?

Stop reading session state from the transport. Remove any dependency on Mcp-Session-Id and on the initialize handshake, accept the per-request _meta fields, implement server/discover, validate Mcp-Method, Mcp-Name and MCP-Protocol-Version against the request body, and add ttlMs and cacheScope to list results. Then decide whether to stay dual-era. That order gets you to a server that runs behind a plain round-robin load balancer.

Sources

  1. Model Context Protocol, 2026-07-28 changelog, Key Changes (read 2026-11-12)
  2. Model Context Protocol, Specification 2026-07-28 (read 2026-11-12)
  3. Model Context Protocol, Versioning, Draft, Current and Final revisions (read 2026-11-12)
  4. Model Context Protocol, Versioning and Compatibility, 2026-07-28 (read 2026-11-12)
  5. Model Context Protocol, Streamable HTTP transport, 2026-07-28 (read 2026-11-12)
  6. Model Context Protocol, Multi Round-Trip Requests, 2026-07-28 (read 2026-11-12)
  7. Model Context Protocol, Caching, 2026-07-28 (read 2026-11-12)
  8. Model Context Protocol, Discovery, server/discover, 2026-07-28 (read 2026-11-12)
  9. Model Context Protocol, Deprecated Features registry, 2026-07-28 (read 2026-11-12)
  10. MCP blog, The 2026-07-28 Specification, Jul 28 2026 (read 2026-11-12)
  11. MCP blog, The 2026-07-28 MCP Specification Release Candidate, May 21 2026 (read 2026-11-12)
  12. MCP blog, Beta SDKs for the 2026-07-28 release candidate, Jun 29 2026 (read 2026-11-12)
  13. MCP blog, A More Predictable Release Cycle for MCP, Nov 11 2026 (read 2026-11-12)
  14. GitHub, modelcontextprotocol releases, 2026-07-28 and 2026-07-28 RC (read 2026-11-12)
  15. Model Context Protocol, official SDKs and tiers (read 2026-11-12)
  16. Model Context Protocol, Build an MCP server, 2026-07-28 docs (read 2026-11-12)
  17. GitHub, MCP Go SDK v1.7.0 release notes (read 2026-11-12)
  18. GitHub, MCP TypeScript SDK releases, 2.4.0 of Oct 23 2026 (read 2026-11-12)
  19. GitHub, MCP Python SDK releases, v2.3.0 of Oct 2 2026 (read 2026-11-12)
  20. Agentic AI Foundation, MCP 2026-07-28 What's Changing and How to Migrate, Jul 21 2026 (read 2026-11-12)
  21. GitHub, Ruby SDK Tier 1 assessment, issue 3247, Aug 15 2026 (read 2026-11-12)
  22. dev.to, AI Weekly, Fable 5.2, Muse Ember, and TPU 8i Max, Nov 11 2026 (read 2026-11-12)
Share