Agentic AI Foundation Logo
MCP 2026-07-28: What's Changing and How to Migrate

MCP 2026-07-28: What's Changing and How to Migrate

Akash JaiswalJuly 21, 2026

Note: This post covers the 2026-07-28 release candidate. Details described as mandatory, removed, or finalized below reflect the RC as currently published and should be checked against the final spec once it ships on July 28, 2026.

The Model Context Protocol has its biggest update since launch. The new specification - officially versioned 2026-07-28 - is expected to ship on July 28, 2026, with a release candidate available now. It changes how MCP clients and servers communicate, what the protocol is responsible for, and how implementers should think about state, authorization, and extensions.

If you've built or consumed MCP servers, this post walks through every major change the release candidate introduces, explains what motivated it, and covers what you need to do about it.

Track the release work: https://github.com/modelcontextprotocol/modelcontextprotocol/milestone/6

MCP was originally designed for a specific environment: a single AI application (like Claude Desktop) talking to a local server process over stdio. In that world, a persistent, stateful connection made perfect sense. The client opened a connection, ran an initialize handshake, and both sides remembered each other for the life of the session.

That model breaks down the moment you try to deploy MCP at scale. When organisations started running MCP servers behind load balancers, inside Kubernetes clusters, or across multiple cloud regions, the statefulness became a bottleneck. Sticky sessions, shared session stores, reconnection logic after dropped connections — these are operational problems that have nothing to do with what MCP is supposed to solve.

The 2026-07-28 release candidate is a response to this reality. It redesigns MCP around a stateless core so the protocol works equally well on a developer's laptop and behind an enterprise API gateway.

AreaPrevious Spec2026-07-28 (Release Candidate)
Session modelMandatory initialize / initialized handshake.Moves toward stateless. No handshake proposed. Every request is self-contained.
Capability negotiationExchanged once during initialize.On-demand via server/discover RPC. Clients query capabilities whenever needed.
Load balancingRequires sticky sessions or shared session stores.Designed to support standard round-robin load balancing. Any compatible server instance should be able to handle a self-contained request.
Long-running operationsSynchronous tool calls block until completion. No standard async pattern.Tasks extension. Server returns a durable taskId; client polls via tasks/get, sends input via tasks/update.
Rich UI in chatNot supported. Clients receive raw data and build their own UI (or don't).MCP Apps extension Server declares interactive HTML that renders in a sandboxed iframe inside the chat.
AuthorizationBasic OAuth support. Dynamic Client Registration available.RC introduces OAuth 2.1 + OIDC as a requirement, plus an Enterprise-Managed Authorization (EMA) extension.
Transportstdio and session-capable Streamable HTTPstdio, Streamable HTTP (HTTP+SSE proposed for deprecation)
RootsCore feature. Client advertises filesystem roots to the server.Proposed for deprecation. Pass paths as tool parameters or server config instead.
SamplingCore feature. Server can request LLM completions from the client.Proposed for deprecation. Servers should call LLM APIs directly.
LoggingCore feature. Protocol-level log messages from server to client.Proposed for deprecation. Use stderr or OpenTelemetry.
Feature removal processNo formal policy. Breaking changes could arrive without warning.SEP-2596. 12-month minimum deprecation window before removal. Public registry of deprecated features.
At a Glance: Previous Spec vs. the 2026-07-28 Release Candidate

1. Stateless Core: No More Sessions

How it worked before

In the previous specification, every MCP connection started with a mandatory initialize / initialized handshake. This exchange:

  • Established a session (tracked via an Mcp-Session-Id header)
  • Negotiated protocol version compatibility
  • Exchanged client and server capabilities (what tools, resources, and features each side supports)

The session persisted for the life of the connection. If the connection dropped, the session state was lost, requiring the client to re-initialize.

What was wrong with it

Three problems compounded at scale:

  1. Load balancing was impractical. Because a client was "pinned" to whichever server instance held its session, standard round-robin load balancers couldn't distribute traffic. You needed sticky sessions or a shared session store — infrastructure overhead that has nothing to do with MCP's purpose.
  2. Connections were fragile. A dropped WebSocket or interrupted SSE stream meant the entire session state was gone. Clients needed complex reconnection and re-initialization logic.
  3. The protocol was chatty. Maintaining long-lived sessions resulted in overhead messages just to keep the connection alive, even when no real work was happening.

How it's proposed to work now

The initialize handshake would be removed. Every JSON-RPC request becomes self-contained. Clients include all the information a server needs to process the request inside a _meta object in the JSON-RPC envelope:

  • Protocol version
  • Client identity
  • Relevant capability flags

Any server instance in a pool could handle any request without prior knowledge of the client. No sticky sessions. No shared state. Standard round-robin load balancing works out of the box.

For capability discovery — which previously happened during the handshake — clients would instead call a server/discover RPC method on demand. This is a regular stateless request like any other.

The design philosophy is "pay-as-you-go" complexity: the default is stateless, and statefulness is introduced only when a specific feature explicitly requires it (like the Tasks extension, discussed below).

Before and after: on the wire

Previous spec (2025-11-25) — calling a tool required establishing a session first:

bash
# Step 1: Initialize and get a session ID
POST /mcp HTTP/1.1
Content-Type: application/json

{"jsonrpc":"2.0","id":1,"method":"initialize",
 "params":{"protocolVersion":"2025-11-25","capabilities":{},
 "clientInfo":{"name":"my-app","version":"1.0"}}}

# Server responds with Mcp-Session-Id: 1868a90c-3a3f-4f5b

# Step 2: Every subsequent request must carry the session ID
POST /mcp HTTP/1.1
Mcp-Session-Id: 1868a90c-3a3f-4f5b
Content-Type: application/json

{"jsonrpc":"2.0","id":2,"method":"tools/call",
 "params":{"name":"search","arguments":{"q":"otters"}}}

The client is pinned to whichever server instance issued that session ID.

Release candidate (2026-07-28) — the same tool call proposed as a single self-contained request:

bash
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json

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

No handshake. No session header. Any server instance can handle it. Note the Mcp-Method and Mcp-Name headers — these would let load balancers and gateways route traffic by operation without parsing the JSON body.

Stateless protocol, stateful applications

A common concern: "My server needs to track state across multiple tool calls. How does that work without sessions?"

The answer is the same pattern HTTP APIs have used for decades: explicit handles. Instead of relying on the protocol to silently maintain state, the server mints an identifier (a basket_id, a session_token, a workflow_id) from one tool call and returns it as part of the result. The LLM then passes that identifier back as an ordinary argument on subsequent calls.

1. Client calls: create_checkout({items: ["widget-a", "widget-b"]})
   Server returns: {basket_id: "bsk_8f3a", status: "created"}

2. Client calls: add_shipping(basket_id: "bsk_8f3a", address: {...})
   Server returns: {basket_id: "bsk_8f3a", status: "ready_to_pay"}

3. Client calls: confirm_order(basket_id: "bsk_8f3a"})
   Server returns: {order_id: "ord_91cb", status: "confirmed"}

This is more than just a workaround. It is often a better pattern than hidden session state. The model can reason about handles, compose them across tools, hand them off between workflow steps, and make decisions based on their values. Session state hidden in transport metadata was invisible to the model — explicit handles are not.

The protocol would no longer manage state for you, but it wouldn't prevent you from managing it yourself.

2. Extensions Framework

With the core protocol proposed to be lean and stateless, advanced behaviors are modelled as extensions — optional, self-contained modules that clients and servers can adopt independently. Two extensions ship with the release candidate: MCP Apps and Tasks.

MCP Apps: Server-Rendered Interactive UI

The problem

MCP tools return structured data — JSON objects, text, resource URIs. When users need to interact with that data (explore a dashboard, fill a form, review a document), the client has to build the UI. Every client builds it differently, or doesn't build it at all.

How MCP Apps work

MCP Apps allow servers to define interactive HTML interfaces that render directly inside the chat. The architecture has three components:

  1. Declaration. The server registers a tool and links it to a UI resource via a _meta.ui.resourceUri field pointing to a ui:// resource.
  2. Rendering. When the tool is invoked, the host renders the HTML/JS content inside a sandboxed iframe within the conversation. The sandbox prevents the UI from accessing the host page, cookies, or anything outside its container.
  3. Bidirectional communication. The UI talks to the host (and through it, back to the server) using JSON-RPC over postMessage. This creates a reactive loop: user actions in the UI trigger server-side logic, and server updates push back to the UI without reloading the iframe.

Why it matters

  • Context preservation. Users interact with dashboards, configuration wizards, or document reviews without leaving the chat.
  • Build once, run anywhere. One server-defined UI surface. A server can expose one UI surface that any compliant host can render, reducing per-client integration work.
  • Graceful degradation. If the host doesn't support MCP Apps, the server falls back to returning plain text or structured data. The tool still works.

Typical use cases: data exploration dashboards, multi-step configuration forms, document review interfaces, real-time monitoring widgets.

Tasks: Durable Long-Running Operations

The problem

In the previous specification, a tool call was synchronous: the client sent a request, the server processed it, and the server returned the result. If the operation took minutes (a CI/CD pipeline, a batch data migration, a complex analysis), the connection could time out. Every server that needed async behavior had to invent its own ad-hoc polling mechanism.

How Tasks work

The Tasks extension (io.modelcontextprotocol/tasks) introduces a standardised asynchronous pattern:

  1. Task creation. Instead of blocking, the server returns a CreateTaskResult containing a unique taskId, an initial status, and a suggested polling interval.
  2. Polling. The client calls tasks/get with the taskId to check progress. The server returns the current state: working, input_required, completed, failed, or cancelled.
  3. Mid-flight interaction. If a task enters input_required (e.g., waiting for human approval in a deployment pipeline), the client sends input via tasks/update. This enables multi-step, interactive workflows within a single task.
  4. Cancellation. Clients can request cancellation via tasks/cancel. This is cooperative — the server honours it when possible.
  5. Terminal states. Once a task reaches completed, failed, or cancelled, it is immutable. Results or error details are available on the terminal state object.

Key property: durability

Task handles are designed to survive connection drops. If a client disconnects and reconnects (or a different client instance picks up the work), it could resume polling with the same taskId. This is intended to make tasks crash-resilient by design.

3. Authorization Hardening

The release candidate proposes tighter authorization to close gaps exposed by real-world deployments.

What's changing

  • OAuth 2.1 and OpenID Connect alignment. Clients would be required to perform robust issuer validation (per RFC 9207). Support for both OAuth 2.0 and OIDC discovery mechanisms is proposed as mandatory.
  • Enterprise-Managed Authorization (EMA). A new extension that would allow IT administrators to centrally provision MCP server access through an identity provider. Users get connected to required servers automatically on login — no per-app OAuth prompts.
  • Incremental scope consent. Servers could request additional permissions mid-session via the WWW-Authenticate header, enabling more granular permission management instead of requesting all scopes upfront.
  • Dynamic Client Registration proposed for deprecation. In line with the broader move toward explicit, pre-configured authorization flows.

Why it matters

In early MCP deployments, authorization was often an afterthought — many servers ran locally with no auth at all. As MCP servers move to remote, multi-tenant environments, the authorization model needs to match what enterprises already use. EMA in particular is a direct response to feedback from organisations that couldn't adopt MCP without central IT control over which servers employees connect to. These specifics should be confirmed against the final spec once it ships.

4. Deprecation Policy and Legacy Cleanup (SEP-2596 & SEP-2577)

Protocol evolution is inevitable. Breaking changes without warning are unacceptable. The release candidate proposes a formal framework to manage this tension.

The Deprecation Policy (SEP-2596)

Any feature marked for deprecation would need to remain functional for at least 12 months before it can be removed. Deprecated features would be tracked in a public registry with clear timelines, giving implementers a predictable window to migrate.

What's Proposed for Deprecation (SEP-2577)

The following features are proposed for deprecation as of 2026-07-28, with earliest removal on or after July 28, 2027:

FeatureWhy It's Proposed for DeprecationMigration Path
RootsTightly coupled clients and servers around filesystem assumptions that don't generalise to remote or cloud environments.Pass directory/file paths as tool parameters or define them in server configuration.
SamplingCreated a reverse dependency where servers called back into the client's LLM. This complicated trust boundaries and made servers harder to reason about security-wise.Integrate directly with LLM provider APIs from the server side.
LoggingProtocol-level logging was redundant with existing, more capable observability infrastructure.Use stderr (stdio transports) or OpenTelemetry for structured observability.
Dynamic Client RegistrationConflicts with the move toward pre-configured, enterprise-managed authorization.Use explicit OAuth application registration.
HTTP+SSE TransportSuperseded by the Streamable HTTP transport, which is more flexible and works with the stateless core.Migrate to Streamable HTTP.

This table is not a removal notice — these features still work today and, if the deprecations are finalized, would continue to work for at least another year. But new implementations should track this closely and avoid them where practical.

What You Need to Do

If you maintain an MCP server

  1. Audit session dependencies. Review your server for reliance on initialize, Mcp-Session-Id, or any connection-level state, so you're ready if the stateless core ships as proposed.
  2. Watch for _meta handling. Be prepared for client identity and capabilities to arrive via _meta on each request.
  3. Track server/discover. This proposed RPC method would expose your server's capabilities.
  4. Plan deprecation migrations. If you use Roots, Sampling, or Logging, begin migrating to the recommended alternatives. The earliest removal window is July 2027, but earlier is better.
  5. Evaluate extensions. Consider whether MCP Apps or Tasks would improve the experience for your users.

If you maintain an MCP client

  1. Prepare to move off initialize. Plan for including _meta in every request and using server/discover for capability queries once finalized.
  2. Review authorization flows. Track OAuth 2.1 / OIDC discovery and issuer validation requirements, and evaluate EMA if you serve enterprise customers.
  3. Support extensions gracefully. If you don't yet support MCP Apps or Tasks, ensure your client handles responses from servers that use them without breaking.

If you're starting fresh

Beta SDKs (available for Python, TypeScript, Go, and C#) already target the 2026-07-28 release candidate. Building against the new stateless core from day one is reasonable, with the understanding that details may shift before final release.

DateMilestone
May 2026Release candidate published
July 28, 2026Final specification expected to ship
July 28, 2027Earliest removal date for deprecated features
Timeline

The release candidate and beta SDKs are available at modelcontextprotocol.io and the Model Context Protocol GitHub organisation.

Share

subscription section bg
Subscribe

Subscribe to the AAIF Briefing

Weekly signal on standards, governance, and the people building the future. No fluff. Just what matters.

About AAIF