FastestMCP supports MCP 2026-07-28 and 2025-11-25 over streamable HTTP and stdio. 2026-07-28 is preferred.

FastestMCP.supported_protocol_versions()
# => ["2026-07-28", "2025-11-25"]

FastestMCP.current_protocol_version()
# => "2026-07-28"

The two revisions are separate wire profiles, not one payload with a renamed version field:

Concern2026-07-282025-11-25
Profilemodernlegacy
Startupserver/discoverinitialize, then notifications/initialized
Staterequest-stateless protocol metadataserver-issued session
Version locationrequest _metainitialize result and HTTP header
Capabilitiessent on each request; extensions are first-classnegotiated during initialize
Tasksio.modelcontextprotocol/tasks extension v2experimental core Tasks v1

Use FastestMCP.Protocol.profile/1 when application code genuinely needs to branch on that profile. Do not infer the profile by date comparison.

Client Preference

The connected client accepts exactly:

protocol_version: :auto | "2026-07-28" | "2025-11-25"

The default is :auto. It probes 2026-07-28 with server/discover. On HTTP, it falls back only when the status/body is credible legacy evidence, such as a legacy method-not-found or an empty, unrecognized compatibility response; authentication failures, rate limits, server failures, TLS errors, and network errors do not silently downgrade. The stdio binding has a deliberately broader compatibility rule: any response error not recognized as modern, or a probe timeout, selects the legacy handshake on the same live child process. A recognized modern error never triggers legacy initialization on either transport.

Select an exact version for compatibility tests or a deployment migration:

client =
  FastestMCP.Client.connect!(endpoint,
    protocol_version: "2025-11-25",
    client_info: %{"name" => "migration-check", "version" => "1.0.0"}
  )

auto_initialize: false disables automatic negotiation. With an exact legacy selection, call FastestMCP.Client.initialize/3; with an exact modern selection, call FastestMCP.Client.discover/2. If it is combined with protocol_version: :auto, the application owns the probe and evidence-based fallback decision. Calling initialize/3 directly remains the backwards-compatible way to select the legacy handshake; it never pretends a modern connection has a session.

One Server, Both Revisions

A running FastestMCP server accepts both revisions at the same endpoint and in the same process. Version state belongs to the request or legacy session, not to a global server switch. This permits old and new clients to overlap during a rolling migration.

Do not translate one era into the other in a reverse proxy. In particular, session headers, modern request metadata, Tasks fields, and method sets have different semantics.

Verification

CI exercises both protocol revisions with native tests and the official @modelcontextprotocol/conformance@0.2.0-alpha.11 runner.

The MCP revisions are released protocol specifications. The alpha label is the maturity of the verification runner, not of MCP 2026-07-28. CI runs each runner requirement set separately and runs supported extension scenarios explicitly because extension results are not part of the runner's core score.

See Extensions, Transports, and Compatibility and Scope.