Tutorials Logic, IN info@tutorialslogic.com

MCP Versioning and Migration: Stable Specs, Drafts, and Compatibility

MCP Version Strategy

MCP revisions use date strings such as `2025-11-25`. The date identifies the most recent backwards-incompatible protocol change, not a package release or marketing version. Client and server negotiate one revision during initialization and must interpret the rest of that connection under the agreed contract.

As of July 12, 2026, `2025-11-25` is the current stable protocol revision. A larger `2026-07-28` release candidate is available for validation but is not yet the final stable specification. Production systems should pin supported revisions and adopt draft behavior only in isolated compatibility testing.

Migration is broader than changing the initialize message. Schemas, capabilities, HTTP headers, task semantics, authorization discovery, SDK behavior, and extension support may all move together.

Revision Status

Track Use Engineering Rule
Current stable Production interoperability Implement the published specification and pin contract tests.
Release candidate Pre-release validation Use isolated environments and expect final corrections.
Final historical revision Existing compatibility Support only while real clients or servers require it.
Unversioned custom behavior Private experiments Place behind an explicit extension or remove it.

Revision Identifiers

Protocol revision strings follow `YYYY-MM-DD`. A backwards-compatible clarification can update documentation without changing the revision, while an incompatible wire change requires a new date. Do not compare revision strings to SDK package versions; they describe different contracts.

Store protocol support as an explicit set, not a vague minimum. A newer date does not guarantee that an implementation can safely reinterpret every older message, especially when experimental features or extensions changed shape.

  • Treat protocol revisions and SDK releases separately.
  • Declare an exact supported revision set.
  • Keep experimental capabilities outside stable assumptions.
  • Record the negotiated revision in every session trace.

Initialization Negotiation

The client proposes a protocol revision in `initialize`. If the server supports it, the server returns that revision. If not, the server returns another revision it supports. The client then decides whether the returned value is acceptable or terminates the connection.

Normal capability discovery must wait until initialization succeeds. For Streamable HTTP, the client also sends the negotiated revision through `MCP-Protocol-Version` on later requests. A proxy that drops the header can create failures that look like schema or authorization bugs.

  • Never infer compatibility from a successful TCP or HTTP connection.
  • Stop when no mutually supported revision exists.
  • Discover capabilities only after negotiation.
  • Preserve version metadata through gateways and traces.

Stable and Draft Tracks

Stable specifications are the interoperability target. Drafts and release candidates exist so SDK and host maintainers can validate major changes before final publication. They are useful for test environments but should not silently become the production default.

The `2026-07-28` release candidate proposes a stateless core, a formal extensions mechanism, revised long-running task support, authorization changes, and explicit deprecation policy. These are important migration signals, but code should follow the final published schema before claiming production conformance.

Keep draft adapters behind a feature flag and label their traces, fixtures, and test reports clearly. Remove or update them when the final revision ships rather than carrying an unofficial hybrid forward.

  • Use stable documentation for production claims.
  • Validate release candidates in a separate compatibility lane.
  • Do not combine fields from different revisions in one message.
  • Recheck the final changelog before release.

November 2025 Changes

The stable `2025-11-25` revision added URL-mode elicitation, sampling with tools, Client ID Metadata Documents, richer implementation metadata, and experimental core tasks. It also made implicit sampling context less central by soft-deprecating the broad `includeContext` values.

A server can use these features only when the other party advertised the matching capability. An older client may still initialize successfully while lacking URL elicitation, sampling tools, or tasks, so revision support never replaces capability negotiation.

  • Gate sampling tools on `sampling.tools`.
  • Use URL elicitation for secrets and payment authorization.
  • Negotiate experimental tasks explicitly.
  • Treat implementation descriptions as metadata, not authority.

Task Compatibility

The experimental core task API in `2025-11-25` and the newer Tasks extension are not wire-compatible. Core tasks include `tasks/result` and `tasks/list`; the extension removes those methods, adds `tasks/update`, changes result discrimination, and negotiates under `io.modelcontextprotocol/tasks`.

A bridge can support both surfaces, but it must choose from the negotiated protocol and extension capabilities. Never send both task capability shapes or guess the contract from method availability after a failure.

Test task creation, polling, input-required state, cancellation, terminal results, expired handles, and authorization binding independently for each supported surface.

  • Name the task surface in configuration and logs.
  • Keep fixtures for each wire contract separate.
  • Reject cross-user task access on every method.
  • Provide a tested removal date for legacy adapters.

Migration Matrix

Build a matrix with client, server, SDK, transport, protocol revision, capability set, extension set, and authorization profile. Run it against the combinations that customers actually use, including one expected incompatibility so the failure message is tested.

Compare more than parsing. Verify discovery, tool and resource schemas, sampling and elicitation flows, cancellation, error codes, HTTP headers, trace fields, and user consent. A request that returns JSON can still behave under the wrong protocol contract.

  • Test negotiated and rejected revisions.
  • Replay representative capability workflows.
  • Shadow remote calls with writes disabled.
  • Preserve rollback for SDK, schema, and server deployment.

Deprecation Plan

A deprecation plan names the old contract, affected users, telemetry signal, replacement, warning period, removal date, and rollback. Avoid permanent dual support when no real client still uses the older path.

Telemetry should count negotiated revisions and capability use without storing sensitive request content. Contact users of old revisions before removal, then fail with a precise compatibility message instead of a generic internal error.

  • Measure actual revision use.
  • Publish migration instructions before removal.
  • Return actionable incompatibility errors.
  • Delete dead adapters and fixtures after the support window.

Revision Negotiation Test

MCP revision identifiers use `YYYY-MM-DD` and change for backward-incompatible protocol updates. The current revision is `2025-11-25`; older finalized revisions remain relevant for compatibility. Draft documents are design work, not a contract a production peer can assume.

During initialize, the client sends its latest supported version and may support older revisions. The server returns the version it wants to use, which may differ. If the client cannot support that selection, it must disconnect. Capability negotiation then determines optional behavior within the agreed revision; revision support alone does not imply tasks, sampling, roots, or list-change notifications.

A migration suite should pair old and new clients and servers, compare schemas, and test missing fields, changed defaults, removed methods, transport headers, and extension fallbacks. Record the negotiated version in traces and error reports so failures are reproducible instead of attributed vaguely to “MCP compatibility.”

  • Pin stable revisions and label draft or experimental behavior visibly.
  • Test both successful negotiation and a required disconnect.
  • Gate optional methods on capabilities after the revision is agreed.
  • Keep a compatibility matrix for supported client-server pairs.

Version Negotiation Examples

Negotiate an Exact Revision

This simulation selects one mutually supported revision and rejects an unsupported server response.

Negotiate an Exact Revision
CLIENT_SUPPORT = ["2025-11-25", "2025-06-18"]
SERVER_SUPPORT = {"2025-11-25", "2025-03-26"}

def negotiate(client_preference: list[str], server_support: set[str]) -> str:
    for revision in client_preference:
        if revision in server_support:
            return revision
    raise RuntimeError("No mutually supported MCP revision")

selected = negotiate(CLIENT_SUPPORT, SERVER_SUPPORT)
print("Selected:", selected)
print("HTTP header: MCP-Protocol-Version:", selected)
Output
Selected: 2025-11-25
HTTP header: MCP-Protocol-Version: 2025-11-25

Preference order is explicit; the function does not assume that every newer server supports every older revision.

Block an Untested Migration

A release gate checks that every required compatibility lane passed before a protocol change ships.

Block an Untested Migration
lanes = {
    "stable_stdio": True,
    "stable_http": True,
    "old_client_compatibility": True,
    "release_candidate_shadow": False,
}

required = {"stable_stdio", "stable_http", "old_client_compatibility"}
failed = sorted(name for name in required if not lanes[name])

print("SHIP" if not failed else "BLOCK")
for name in failed:
    print("- Failed:", name)
Output
SHIP

The draft shadow lane is informative until the team deliberately makes it a release requirement.

Before you move on

Migration Readiness

4 checks
  • Supported protocol and extension sets are explicit.
  • Stable and pre-release test lanes cannot be confused.
  • Wire fixtures cover negotiation, capabilities, errors, and headers.
  • Rollback and deprecation plans use real adoption telemetry.

Version Decisions

0 of 2 checked

Q1. What does an MCP revision date represent?

Q2. Can the 2025-11-25 task API and the Tasks extension share one wire implementation?

Migration Traps

  • SDK equals protocol

    Record both versions and test the actual negotiated wire behavior.
  • Draft fields in stable messages

    Keep release-candidate adapters isolated until the final schema is published.
  • Silent fallback

    Reject unsupported contracts with an actionable compatibility message.

Try this next

Migration Exercises

0 of 3 completed

  1. List every client, server, SDK, transport, revision, and extension combination your product promises.
  2. Verify the exact message and trace when no mutually supported revision exists.
  3. Write the core-task and extension-task methods side by side and mark every incompatible field.

Versioning Questions

No. Support the revisions real clients require, measure use, publish a migration window, and remove obsolete adapters when the support commitment ends.

Not as of July 12, 2026. It is a release candidate intended for validation before the planned final publication date.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.