Skip to content

Track support for MCP protocol revision 2026-07-28 (stateless core) #72

Description

@li45

Summary

Request to track support for MCP protocol revision 2026-07-28, which makes the protocol core stateless. This revision has unusually large implications for a gateway/proxy like MCPX — larger than for a plain MCP server — so it seems worth planning for early even though the upstream SDK is not there yet.

Current state (as far as I can tell from the code)

  • packages/mcpx-server/package.json depends on @modelcontextprotocol/sdk ^1.29.0
  • packages/mcpx-server/src/server/mcp-gateway.ts:40MIN_PROTOCOL_VERSION_FOR_KEEPALIVE = "2025-11-25"
  • packages/mcpx-server/src/server/metadata.ts:14 — client icon schema is annotated version 2025-11-25

Upstream dependency: @modelcontextprotocol/sdk@1.30.0 (latest, published 2026-07-27) still declares LATEST_PROTOCOL_VERSION = '2025-11-25', so this is presumably blocked on the TypeScript SDK first. Filing this mainly so the gateway-specific work is visible early.

Please correct me if any of the above is out of date.

Why this matters for MCPX specifically

1. It would fix the multi-pod problem in #55.

In #55 a user hit Session not found when MCPX ran with 2 pods, and asked "Is the gateway exposed as a stateful mcp server to the clients?". Under 2026-07-28 that question disappears: initialize and the Mcp-Session-Id header are removed, and every request carries its own protocol version and client capabilities in _meta. A gateway becomes horizontally scalable behind an ordinary round-robin load balancer, with no sticky routing and no shared session store.

2. Cross-era traffic fails hard, with no fallback.

Per the spec's compatibility matrix, a modern client talking to a legacy server fails outright — legacy clients have no fall-forward mechanism and modern clients have no automatic downgrade. A gateway sitting between them is exactly where this breaks first: whichever side upgrades first, MCPX becomes the blocker unless it can serve both eras. Dual-era support (accept both initialize and server/discover; connect to both legacy and modern upstreams) is likely the practical target rather than a hard cutover.

Gateway-specific work items in this revision

Beyond the usual protocol updates, these land squarely on a proxy:

  • MRTR (SEP-2322) — server-initiated requests (sampling/createMessage, elicitation/create, roots/list) are gone. Servers now return an InputRequiredResult carrying inputRequests + an opaque requestState, and the client retries with inputResponses and a new JSON-RPC id. A gateway must wrap the upstream's requestState in its own envelope so the retry routes back to the same upstream, and the spec requires treating incoming requestState as attacker-controlled (integrity protection, principal binding, TTL, originating-request digest).
  • subscriptions/listen replaces the HTTP GET stream and resources/subscribe/unsubscribe. A gateway needs to fan out to N upstreams and multiplex their notifications onto one downstream stream, re-stamping io.modelcontextprotocol/subscriptionId.
  • resultType on every result ("complete" / "input_required"), with absent-means-"complete" for older upstreams.
  • Required request headers Mcp-Method and Mcp-Name on Streamable HTTP POSTs, plus mandatory header/body consistency validation (-32020 HeaderMismatch). Relevant to MCPX both as a server and as a client. Also x-mcp-headerMcp-Param-* mirroring, which clients MUST support.
  • server/discover — servers MUST implement it; useful for MCPX to expose aggregated capabilities in one call.
  • Caching fieldsttlMs and cacheScope are now required on tools/list, prompts/list, resources/list, resources/read, resources/templates/list. For an aggregating gateway the natural merge is min-ttlMs and private if any upstream is private.
  • Deterministic tools/list ordering (SHOULD) — the spec calls this out explicitly to keep client caches and LLM prompt-prefix caches warm. For an aggregator this matters more than for a single server, since fan-out order is non-deterministic by default.
  • Deprecations — Roots, Sampling and Logging are now Deprecated (12-month minimum window), as is resources/subscribe, DCR, and the HTTP+SSE transport. ping and logging/setLevel are removed.

Suggested phasing

  1. Track the TypeScript SDK's 2026-07-28 support and pin to it when available.
  2. Dual-era on the downstream side first (keep serving initialize clients, additionally accept per-request _meta + server/discover).
  3. Dual-era on the upstream side (probe server/discover, fall back to initialize on any non-modern error — the spec's stdio backward-compatibility rules).
  4. MRTR requestState wrapping/routing and subscriptions/listen multiplexing — these are the two genuinely new pieces of gateway logic.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions