Logo
Agentailor

· 10 min read

MCP v2: What's Changing, What's Deprecated, and Why

MCP v2 breaking changes explained: the protocol goes stateless and deprecates sampling, roots, and logging. What changed across every MCP SDK, why, and how to plan your migration.

avatarAli Ibrahim@ialijr/

Copy a command, then paste it into the command palette (Ctrl K to open).

/summarizeget a summary of this article
/find <topic>explore related posts

Introduction

If you have built anything on the Model Context Protocol, this one matters. MCP v2 (protocol revision 2026-07-28) is final. The release candidate was locked on May 21, 2026, SDK maintainers validated it against real workloads during a ten-week window, and the spec was published on July 28, 2026.

This is not a point release. v2 makes the protocol stateless, formalizes extensions as first-class components, and deprecates three subsystems that many existing servers rely on: sampling, roots, and logging.

This article is the language-agnostic companion to our SDK-specific guides. It covers what changed and why, so you understand the shape of the migration regardless of whether you write TypeScript, Python, Go, or C#.

If you want to build on v2 today, two hands-on guides pick up where this one ends: Build an MCP v2 Server in TypeScript walks through a working server and the v1 to v2 migration, and Securing an MCP v2 Server with OAuth and Keycloak covers what changes for auth. The MCP TypeScript SDK: A Complete Guide remains the v1 deep dive, and will get a v2 rewrite if the SDK surface settles enough to justify one.

NOTE

This article was written while v2 was still a release candidate and the SDKs were in beta. Both have since shipped: the spec was published on July 28, 2026, and the TypeScript v2 packages went stable at 2.0.0 the day before, with Python, Go, and C# following. The concepts below are unchanged, but where the text talks about waiting for stable, that wait is over.

What you'll learn:

  • The headline change: why MCP is going stateless
  • Which subsystems are deprecated (sampling, roots, logging) and what replaces each
  • What the stateless shift means for the SDKs you build on
  • What extensions are, and the two official ones shipping with v2
  • Whether you should migrate now or wait for stable

The Headline Change: MCP Goes Stateless

The single biggest change in v2 is that the protocol becomes stateless.

In v1, every session began with an initialize / initialized handshake, and the server issued an Mcp-Session-Id that the client sent back on every subsequent request. That session ID pinned a client to a specific server instance. If you scaled your server horizontally, you needed sticky sessions so that follow-up requests landed on the same process that ran the handshake.

v2 removes all of that:

  • No initialize / initialized handshake.
  • No Mcp-Session-Id header.
  • Client information now travels in _meta fields on each request, so any request is self-contained.
  • Two new operational headers, Mcp-Method and Mcp-Name, let infrastructure route and observe requests without parsing the body.
  • Caching metadata (ttlMs and cacheScope) is now part of the protocol.

The practical payoff: a request can be handled by any server instance. No sticky sessions, no session affinity, no shared session store. This is a much better fit for serverless and autoscaled deployments, where you cannot assume the next request reaches the same box.

This one change is also the reason behind most of the deprecations below. Several v1 features quietly assumed a long-lived, stateful connection between one client and one server process. Once that assumption is gone, those features no longer fit.

What's Deprecated, and Why

Three subsystems are deprecated under v2's new lifecycle policy. Deprecated does not mean removed. Each remains functional during a one-year grace period, so existing v1 servers keep working. But new code should adopt the replacements.

Sampling

What it was: Sampling let a server ask the client's LLM to generate text mid-execution (via createMessage in the TypeScript SDK). It powered "agentic servers" that could reason and make decisions internally by borrowing the client's model.

Why it's going away: Sampling requires the server to reach back into the client while it is not handling a client request, which only works over a persistent, stateful connection. That is exactly the assumption v2 removes. In a stateless world, the server processing your request may not be the one holding a connection to your client at all.

What replaces it:

  • Direct integration with LLM provider APIs. If your server needs a model, call the provider (Anthropic, OpenAI, etc.) directly from the server. You control the model, the keys, and the cost.
  • The InputRequiredResult pattern for the cases where you genuinely need something from the client mid-task. Instead of a live callback, the server returns a result that says "I need this input," and the client retries the request with the answer. Because each round-trip is a fresh, self-contained request, it can be retried against any server instance, keeping the interaction stateless.

If you use sampling today, this is the deprecation most likely to require real rework, because the replacement changes where the model call happens (server-side, not client-side).

Roots

What it was: Roots were URIs the client provided to scope what the server should operate on, for example file:///home/user/my-project to tell a code-analysis server which directory to scan. Servers read them with listRoots().

Why it's going away: Roots were another piece of session-scoped state pushed from client to server and held for the life of a connection.

What replaces it: Pass the same information explicitly, per request:

  • Tool parameters — accept the working directory or scope as a tool input.
  • Resource URIs — encode the scope directly in the resource being requested.
  • Server configuration — set boundaries at deploy time when they are static.

Logging

What it was: Structured log messages sent from the server to the client over the MCP protocol, filtered by a client-set level (logging/setLevel).

Why it's going away: Protocol-level logging tied observability to a live client connection, which is awkward for stateless, multi-instance deployments and duplicates tooling that already exists.

What replaces it:

  • stderr for stdio transports. Write logs to standard error; the host captures them. (This was already the recommended practice for stdio servers in v1, since stdout is reserved for the protocol.)
  • OpenTelemetry for structured, production-grade observability. Emit traces and metrics to your existing OTel pipeline rather than through MCP.

What the Stateless Shift Means for the SDKs

Beyond the deprecations, statelessness ripples through every SDK's surface. The specifics differ by language, so this is a map of what kind of change to expect rather than a list of exact symbols. Three patterns show up regardless of which SDK you use:

  • Transports get reshaped. Removing sessions is a transport-level change, so expect HTTP transports to be renamed or split by runtime, and expect the old SSE transport (a two-endpoint design built around a persistent stream) to disappear. A single, unified request/response transport fits the stateless model; a long-lived stream does not.
  • Errors split into protocol errors and local SDK errors. v2 draws a clearer line between "the request itself was malformed" (a wire-protocol error the other side should see) and "something failed locally, like the HTTP connection dropped." If your code inspects error types, expect that distinction to surface in the API.
  • Request context becomes transport-aware. Because a stdio server has no HTTP request behind it, the per-request context object separates protocol-level fields from transport-specific ones (like auth info that only exists over HTTP). Handlers read those optional fields defensively.

It is a map of what the migration touches so you can gauge its size for your codebase, whatever language you build in. For the concrete TypeScript renames, Build an MCP v2 Server in TypeScript works through them against real code.

AGENT BRIEFINGS

What actually matters for building and scaling AI agents in production — and what's just hype. Straight from the work, no filler.

Should You Migrate Now?

Short answer: you can, and there is no rush. Here is the state of play:

  • The v2 SDKs are stable. TypeScript shipped 2.0.0 on July 27, 2026, and Python, Go, and C# have been updated to match the spec. Rust is still pre-stable. Check each SDK's releases rather than trusting a version number quoted here.
  • Upgrading the SDK is not the same as adopting v2. The new packages serve both protocol eras. A v2 server falls back to legacy behaviour for older clients, so moving your dependencies does not force your clients to move.
  • Pin exact versions anyway. Not because anything is unstable now, but because reproducible builds are worth more than automatic minor bumps in a protocol layer.
  • Nothing is being taken away yet. The deprecated subsystems have a one-year grace period from July 28, 2026.

A reasonable plan for most teams:

  1. Audit first. Find where you use sampling, roots, and logging, and where you rely on session state. That tells you the real size of the job.
  2. Migrate a non-critical server. Work through the renamed imports and the deprecated subsystems on something low-stakes. Build an MCP v2 Server in TypeScript covers this end to end, including the official codemod that automates the mechanical renames.
  3. Within the grace year: Migrate the rest before the deprecated subsystems are removed.

What's New: Extensions

v2 does not only subtract. It also formalizes extensions as first-class protocol components with reverse-DNS identifiers and independent versioning. Instead of bolting capabilities onto the core spec, features can now evolve as versioned extensions.

Two official extensions launch with v2:

  • MCP Apps — server-rendered UIs, so a server can present a rich interface to the user rather than only returning text and structured data.
  • Tasks — a standard pattern for long-running operations, so a server can kick off work that outlives a single request and report on it. This pairs naturally with the stateless core: a task is addressable across instances rather than tied to one connection.

Expect the extension model to be where much of MCP's future capability growth happens, precisely because extensions can ship and version without waiting on a full spec revision.

What This Means for Your Existing v1 Servers

If you have MCP servers in production today, nothing broke on July 28. To recap:

  • v1 servers keep working. Deprecations have a one-year grace period.
  • You are not forced to migrate on a deadline; you are forced to migrate before the grace period ends.
  • The biggest real change is sampling. Roots and logging have straightforward replacements you may already be halfway to. Sampling moves the model call from client to server, which is an architectural shift, not a rename.
  • Statelessness is a gift if you run at scale. It removes sticky-session complexity from your infrastructure.

Plan for it now, migrate on stable, and you will have a full year of runway.

Resources

AGENT BRIEFINGS

Stay measured as the field moves.

What actually matters for building and scaling AI agents in production — and what's just hype. Straight from the work, no filler.