MCP's 2026-07-28 Spec: What Changes for AI Agents

Rows of server racks with network cables in a data center, representing scalable MCP server infrastructure

Your MCP server worked fine on your laptop, then fell over the moment you put it behind a load balancer with two instances. Session state, handshake negotiation, and server-initiated requests were the usual culprits, and the newest revision of the Model Context Protocol is built to remove exactly those problems. Here is what changed, what breaks, and what to do about it.

One framing note up front: this is not news from today. The 2026-07-28 specification was released on July 28, 2026, so the update has been out for a few months. This post is a working guide to what it means if you run, or plan to run, MCP servers.

What shipped, and how to read the "biggest update ever" claim

The 2026-07-28 spec is the largest revision of MCP since launch, and it contains breaking changes. That is the maintainers' own description. The release candidate locked on May 21, 2026, and the final spec plus SDKs for building clients and servers went out on July 28, 2026, per the official release post by lead maintainers David Soria Parra and Den Delimarsky. The release candidate announcement is where the "largest revision" language appears.

Two things to keep straight:

  • "Biggest ever" is a self-description. The maintainers say it. Press coverage quotes Soria Parra calling it "probably the biggest change we've ever made," and some people jokingly call it a v2. There is no official "v2" of the protocol. The version is simply 2026-07-28.
  • "Ready for massive enterprise deployments" is a claim from the maintainers and backers. Treat it as a design goal the spec now supports, not a guarantee about your deployment. The changes below are the actual evidence.

For context on governance: in December 2025, Anthropic donated MCP to the Agentic AI Foundation (AAIF), a directed fund under the Linux Foundation co-founded by Anthropic, Block and OpenAI. At that time Anthropic cited 97M+ monthly SDK downloads across Python and TypeScript. That is Anthropic's own figure from the December announcement, so it describes adoption at that moment, not today. Check the primary source for whichever figure you plan to cite.

The headline change: a stateless protocol core

MCP no longer has a session. The initialize handshake and the Mcp-Session-Id header are removed, and every request now carries its protocol version and client capabilities in _meta (see the changelog).

This sounds like plumbing, but it changes how you deploy. Before, a client negotiated capabilities once, got a session ID, and then every later request had to reach a server that remembered that session. That forced sticky routing or shared session storage. Now any request can land on any server instance behind a plain round-robin load balancer, with no shared session storage. That is the operational win the maintainers highlight.

Conceptually, each request now carries its protocol version and client capabilities in _meta instead of negotiating them once. The exact field names and payload layout are in the changelog, so confirm them there when you implement rather than copying a sketch.

What if your tool genuinely needs state?

Some workflows are stateful by nature: a shopping basket, a draft document, a multi-step form. The spec's answer is explicit handles. A tool mints an identifier (the release candidate post uses basket_id as the example), and the model passes it back as an ordinary argument on later calls.

# Illustrative pattern: state lives in YOUR datastore, keyed by a handle.
@mcp_tool
def start_quote(customer_id: str) -> dict:
    quote_id = db.create_draft_quote(customer_id)   # your database, not process memory
    return {"quote_id": quote_id}

@mcp_tool
def add_line_item(quote_id: str, sku: str, qty: int) -> dict:
    db.append_line(quote_id, sku, qty)
    return {"quote_id": quote_id, "lines": db.count_lines(quote_id)}

The practical rule I'd follow: if your server keeps anything in process memory between calls, move it to a database or cache keyed by a handle the model carries. Then every instance can serve every request.

Routing, caching, and the transport changes

Three smaller changes make MCP servers behave like ordinary HTTP services you can put real infrastructure in front of.

Routing headers. The Streamable HTTP transport now requires Mcp-Method and Mcp-Name headers (SEP-2243). Load balancers, gateways and rate-limiters can route on the operation without parsing the request body. In practice that means you can rate-limit tools/call for an expensive tool differently from cheap tools/list calls using only header rules.

Cache hints on list results. List responses (tools/list, prompts/list, resources/list and others) must now carry ttlMs and cacheScope (SEP-2549). ttlMs is a freshness hint in milliseconds; cacheScope is "public" or "private". If your tool list is the same for every user, mark it public and give it a sensible TTL so clients stop re-fetching it. If it varies by user permissions, mark it private.

HTTP+SSE is formally deprecated. The older HTTP+SSE transport had been deprecated since protocol version 2025-03-26 and is now classified Deprecated under the new lifecycle policy. The migration path is Streamable HTTP. If you are still running an SSE-based server from an early tutorial, this is your nudge.

Concern Before 2026-07-28
Session handling initialize + Mcp-Session-Id Removed; version and capabilities in _meta on every request
Load balancing Sticky routing or shared session store Plain round-robin works
Gateway routing Parse request body Mcp-Method / Mcp-Name headers required
List caching No standard hints ttlMs + cacheScope required on list results
Legacy transport HTTP+SSE Deprecated; use Streamable HTTP

Asking the user mid-task: Multi Round-Trip Requests

Server-initiated requests such as elicitation/create are replaced by Multi Round-Trip Requests, or MRTR (SEP-2322). Instead of the server opening a request back to the client, the server returns a result with resultType set to "input_required". The client then retries the original call with the answers in inputResponses.

Sketch of the flow (shape per the spec GA post source; check exact field layout there before coding):

// 1. Client calls the tool
{ "method": "tools/call", "params": { "name": "send_invoice", "arguments": { "invoice_id": "inv_9" } } }

// 2. Server needs a decision, so it returns instead of calling the client
{ "resultType": "input_required", "...": "description of what it needs" }

// 3. Client retries the SAME call, now with the user's answers
{ "method": "tools/call", "params": { "name": "send_invoice", "arguments": { "invoice_id": "inv_9" }, "inputResponses": { "...": "..." } } }

Why this matters: it fits the stateless model. The server doesn't hold an open conversation waiting on the client; each leg is a normal request that any instance can handle. For anything with human-in-the-loop approval (confirm before sending an email, pick between two matching customers), design the tool so the retry carries everything needed to finish.

Long-running work: Tasks become an extension

Tasks moved out of the experimental core into the official io.modelcontextprotocol/tasks extension (SEP-2663). It uses polling through tasks/get and a new tasks/update, and tasks/list was removed.

If you build agents that kick off slow jobs (report generation, a bulk import, a crawl), the pattern is: start the work, return a task reference, and have the client poll. Because tasks are an extension, you opt in rather than getting them by default. If you'd built against the experimental core version, expect to revisit that code, especially anything that relied on tasks/list.

Authorization: tighter by default

The auth changes are the ones security reviewers will care about.

  • RFC 9207 issuer validation (SEP-2468). Authorization servers SHOULD include the iss parameter. MCP clients MUST validate a present iss against the recorded issuer before redeeming the authorization code. Note the nuance: it is not universally mandatory. Servers should include it, and clients must check it when it's there. Some coverage overstates this as blanket enforcement; the changelog is more careful.
  • Dynamic Client Registration is deprecated. The replacement is Client ID Metadata Documents (CIMD). DCR keeps working for backward compatibility but will be removed in a future spec version.
  • Enterprise Managed Authorization. This is an official extension, with a corporate identity provider acting as gatekeeper. I haven't retrieved the detailed spec text, so I won't describe its mechanics beyond that.

For a small business, the practical takeaway: if your MCP server fronts anything sensitive (your CRM, billing, a customer database), plan the auth work now. Moving from DCR to CIMD is a migration you can schedule, not an emergency, but it is on the calendar.

Deprecations and the 12-month clock

The spec adopts a formal feature lifecycle (SEP-2596) with three states: Active, Deprecated, Removed. There is a minimum twelve-month deprecation window, measured from the release of the spec revision that first marks a feature Deprecated. Per the policy text, twelve months is a minimum, and removal is not automatic.

Deprecated as of 2026-07-28 (SEP-2577), with earliest removal on 2027-07-28:

Deprecated feature Replacement
Roots Tool parameters / resource URIs
Sampling Direct LLM provider APIs
Logging stderr / OpenTelemetry

Also deprecated: HTTP+SSE (use Streamable HTTP) and Dynamic Client Registration (use CIMD). Both are covered above, and neither gets the same earliest-removal date stated here.

The twelve-month window applies to individual features under SEP-2596.

MCP Apps: servers that ship UI

The third official extension alongside Tasks and Enterprise Managed Authorization is MCP Apps (SEP-1865). It lets servers ship interactive HTML interfaces that hosts render in a sandboxed iframe. Useful when a text reply is the wrong output: an approval screen, a filterable table, a form. It's an extension, so host support will vary. Check your target client before building a product on it.

Migrating: a practical order of operations

You probably don't need to rewrite everything this week. The SDK story is gentle: beta SDKs for the release candidate were published for Python, TypeScript, Go and C#, and existing servers keep working. A Python v2 server answers both protocol revisions from one endpoint, and TypeScript's createMcpHandler also serves 2025-11-25 traffic (see the SDK beta post).

Here is the order I'd work in:

  1. Inventory your servers. For each: which transport, what state it holds between calls, whether it uses sampling, roots, logging, or elicitation.
  2. Upgrade the SDK and run old and new clients against the same endpoint, since both revisions can be served together.
  3. Move in-memory state to handles. This is the real engineering work, and the thing that unlocks round-robin scaling.
  4. Add ttlMs and cacheScope to list results. Start with private if unsure; loosen later.
  5. Replace elicitation flows with input_required / inputResponses retries.
  6. Move off HTTP+SSE to Streamable HTTP if you haven't.
  7. Plan the auth migration: issuer validation on the client side, and DCR to CIMD on your own schedule.
  8. Replace deprecated features (Roots, Sampling, Logging) before the earliest removal date of 2027-07-28.

If you're a solo builder with one small server, steps 1 to 3 may take an afternoon. If you have several servers with real state, budget for step 3 properly and test with two instances behind a round-robin balancer before you call it done.

Where this fits in practice

I build AI automations for small teams, and the part that keeps paying off is the plain layer between a model and the software a business already uses: a CRM, an invoicing tool, an inbox, an internal database, exposed to Claude with sensible permissions so the agent works on real data. The 2026-07-28 changes make that layer easier to run, since the stateless core removes a class of deployment headaches and the caching and routing headers make gateways straightforward.

When you scope an integration like this, the first questions are what state the workflow really needs, what the agent should be allowed to touch, and what happens when it asks for approval. Those map directly onto the handle pattern, the auth model, and the input-required flow described above.


Work with BizFlowAI

If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.

Request a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.

More guides like this on the BizFlowAI blog.

Frequently asked questions

What changed in the MCP 2026-07-28 specification?

The 2026-07-28 revision of the Model Context Protocol is the largest since launch and includes breaking changes. It removes the initialize handshake and the Mcp-Session-Id header, making the protocol core stateless. Streamable HTTP now requires Mcp-Method and Mcp-Name routing headers, and list results must carry ttlMs and cacheScope cache hints. HTTP+SSE is deprecated, tasks moved into an extension, and authorization got stricter.

How do I run an MCP server behind a load balancer without sticky sessions?

With the 2026-07-28 spec, every request carries its protocol version and client capabilities in _meta, so there is no session for a specific instance to remember. Any request can land on any server instance behind a plain round-robin load balancer. If your tools keep state in process memory, move it to a database or cache keyed by an identifier the model passes back as an argument. That way every instance can serve every request.

How do I handle stateful tools like a shopping basket in a stateless MCP server?

Use explicit handles instead of sessions. A tool creates a record in your own datastore and returns an identifier such as a basket_id or quote_id. The model passes that identifier back as a normal argument on later tool calls. The state lives in your database rather than server memory, so any instance can handle any call.

How does MCP ask the user for input mid-task now that elicitation/create is replaced?

The new Multi Round-Trip Requests (MRTR) mechanism replaces server-initiated requests like elicitation/create. When a tool needs a decision, the server returns a result with resultType set to input_required instead of calling back into the client. The client then retries the original call with the user's answers in inputResponses. Each step is a normal request, so it fits the stateless model and works across multiple server instances.

Should I still use HTTP+SSE for my MCP server?

No. The HTTP+SSE transport has been deprecated since protocol version 2025-03-26 and is now formally classified Deprecated under the new lifecycle policy. The migration path is the Streamable HTTP transport. Streamable HTTP also adds required Mcp-Method and Mcp-Name headers, so gateways and rate-limiters can route requests without parsing the body.