Skip to content

Support MCP protocol version 2025-11-25 (v4) #6706

Closed

Description

@guillempuche

What is the problem this feature would solve?

Re-filing #6157 against v4 — that issue was auto-closed by the v3 feature-freeze sweep, and reopening it is rejected by GitHub (422), so this is a fresh copy with the ask narrowed to where v4 actually stands.

McpServer in v4 main now routes through a pluggable protocol registry: multiple adapters, per-session protocol selection, and mcp-protocol-version header negotiation. But McpProtocol.ts still exports exactly one adapter:

export const v2025_06_18: ProtocolAdapter = Internal.make({
  protocolVersion: "2025-06-18",
  clientRpcs: McpSchema.ClientRpcs,
  clientNotificationRpcs: McpSchema.ClientNotificationRpcs,
  serverRequestRpcs: McpSchema.ServerRequestRpcs,
  serverNotificationRpcs: McpSchema.ServerNotificationRpcs
})

export type ProtocolVersion = ProtocolAdapter["protocolVersion"]

So a server can't advertise 2025-11-25, and none of that spec's additions are reachable.

The concrete ask: add a McpProtocol.v2025_11_25 adapter alongside the existing one, widen ProtocolVersion to the union, and add the McpSchema shapes it needs.

From the 2025-11-25 changelog, the pieces that matter most for a server implementation:

  • Tasks (experimental) — durable async requests with polling and deferred result retrieval (SEP-1686)
  • Icons for tools, resources, resource templates, and prompts (SEP-973)
  • Input validation errors as tool execution errors, so the model can self-correct instead of the request failing at the protocol level (SEP-1303)
  • Tool calling in sampling via tools and toolChoice (SEP-1577)
  • Elicitation enhancements — default values (SEP-1034), titled/multi-select enums (SEP-1330), URL mode (SEP-1036)
  • Protocol-level — payloads decoupled from RPC method definitions (SEP-1319), JSON Schema 2020-12 as the default dialect (SEP-1613)

The OAuth changes (SEP-991, SEP-1046, SEP-985, SEP-835, OIDC Discovery) are a larger, separable chunk — happy for those to be their own issue if that's cleaner.

How this helps my use case

I run a CRM exposed entirely over MCP — ~89 tools across several toolkits, plus resources and prompts.

  • Tasks — my company-research tools run for minutes against external providers. Today the client has to hold the request open; I've had to build my own poll-a-handle convention on top because the protocol has no primitive for it. Tasks is exactly that primitive.
  • Input validation as tool errors — handlers currently turn bad input into protocol-level failures, which reads to the model as a crash rather than "you passed a bad id, try again". SEP-1303 makes the retry loop work.
  • Icons — with that many tools grouped into toolkits, icons are a real navigability win in clients.
  • Elicitation defaults and titled enums — my create/update tools have many optional fields; basic elicitation works on 2025-06-18 but is clumsy without defaults.

What alternatives have you considered?

Staying on 2025-06-18 — clients negotiate down, so nothing is broken today. But as clients adopt 2025-11-25, Effect servers can't advertise the new capabilities, and workarounds like a hand-rolled polling convention for long-running tools stay necessary.

The registry refactor already landed the hard part; the remaining work is a second adapter plus schema additions. Happy to take a first pass at it if that direction is welcome.

Activity

  1. lloydrichards commented on Aug 1, 2026

    @lloydrichards
    Contributor

    With the new #6829 it should now be easier to add another dated ProtocolAdapter, following the existing v2025-06-18 shape:

    • add frozen v2025-11-25 wire schemas under internal/mcpSchema/v2025_11_25.ts
    • add internal/mcpProtocol/v2025_11_25.ts, built with McpProtocol.make(...)
    • export McpProtocol.v2025_11_25 and extend the public adapter/version unions
    • let the adapter own its RPC groups, capability and content projection, reverse-client transcoding, notification projection, and transport policy
    • keep adapter selection before payload decoding, so a request is decoded only against the negotiated dated schema
    • extend the shared public model only for stable, revision-neutral additions needed by this protocol (for example icons and implementation metadata); older adapters must omit fields they cannot represent
    • add a dedicated v2025-11-25 conformance entrypoint and cover negotiation, transport, schema projection, sampling, and elicitation deltas

    This should not add version conditionals throughout McpServer or turn the canonical McpSchema into a permissive union of every dated wire contract.

    Something important to separate would be in v2025-11-25 introduced Tasks experimentally, but that API was subsequently redesigned as the io.modelcontextprotocol/tasks extension. The two are not wire-compatible: the extension uses per-request capability negotiation, server-directed task creation, and tasks/get, tasks/update, and tasks/cancel, rather than the legacy tasks/result / tasks/list flow.

    I suggest we defer first-class task support to #6834.

    If this issue implements the historical v2025-11-25 task wire surface, it should remain strictly adapter-local. It should not add Task, task-store, or tasks/* APIs to the version-neutral public McpSchema / McpServer surface, and must not treat the later extension capability as enabling the
    legacy behavior.

    References:

  2. guillempuche commented on Aug 1, 2026

    @guillempuche
    Author

    #6829 is great!

  3. lloydrichards commented on Aug 4, 2026

    @lloydrichards
    Contributor

    Getting ahead of myself since I can stack the commits -> https://github.com/lloydrichards/open_effect/blob/feat/v2025-11-25-adapter/packages/effect/src/unstable/ai/internal/mcpProtocol/v2025_11_25.ts

    But was pretty simple to implement though it introduces some changes to McpSchema which are interesting like Icons. It got me thinking how Task should be handled where it should either only be an extension or if it should be treated differently or only add the v2025_11_25 experimental implementation (should makes the McpServer more complex)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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