Skip to content

[v2] Allow extensions to participate in subscriptions/listen #2528

Closed as duplicate

Description

@juliangoetze

What happened?

The v2 SDK supports extension capabilities, but extensions cannot participate in subscriptions/listen.

We ran into this while building a custom extension that delivers extension-owned notifications through the subscription stream.

Client.listen() accepts only the four core filter fields. On the server, ServerEvent, listenFilterAccepts(), and serverEventToNotification() are also closed over core notification types.

This means an extension must replace/wrap the listen router and duplicate acknowledgement, filtering, SSE, cancellation, and teardown behavior.

This also appears relevant to the Tasks extension: SEP-2663 adds taskIds to the listen filter and notifications/tasks, but the current public SDK API cannot express that cleanly. See #2189.

To fix it, we've bolted a custom fetch onto our mcp-server that intercepts custom subscriptions/listen requests and delegates 'natively' supported ones.

What did you expect?

A public extension point that lets an extension:

  • validate and acknowledge its listen-filter fields;
  • publish and match custom notification events;
  • reuse the SDK’s existing stream lifecycle;
  • work across HTTP and stdio;
  • use the corresponding client listen() lifecycle.

I’d like to confirm whether this gap is intentional and where extension-owned subscription behavior should live.

(I'm happy to drop our custom fetch implementation from our server ;] )

Code to reproduce

await client.listen({
  taskIds: ['task-1'], // not accepted by SubscriptionFilter
});


// The same problem applies to namespaced extension filters and custom notification methods.

SDK version

2.0.0-beta.4

Area

None

Activity

  1. added
    v2Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes
    on Jul 21, 2026
  2. Ben-Home commented on Jul 23, 2026

    @Ben-Home

    This is the right gap to call out — and the fact that SEP-2663 needs taskIds in the listen filter means it's not just extension authors hitting this, it's the spec itself about to run into the SDK's closure.

    The core tension: SubscriptionFilter, ServerEvent, and listenFilterAccepts() are all closed over the four standard notification types. An extension that owns its own notification channel has to either:

    1. Wrap/replace the listen router (your current approach) — works but duplicates acknowledgement, filtering, SSE framing, cancellation, and teardown. Error-prone and version-fragile.
    2. Pre-register extension notification types at SDK init — the cleanest architectural fix. The SDK exposes a registerNotificationMethod() or registerSubscriptionType() that extensions call during server setup, and the listen router, filter, and event types all become open unions keyed by method name.

    The second approach is what we'd want for anything that ships as a reusable extension. A few design properties that matter:

    • Filter validation per-extension. Each registered notification type gets its own filter schema validation — the extension provides it, the SDK enforces it. Not one global schema for all custom types.
    • Stream lifecycle reuse. Extensions shouldn't have to touch SSE framing, cancellation tokens, or acknowledgement. The SDK's existing stream machinery should work for extension-owned notifications with zero additional code.
    • Transport-agnostic. The extension surface should work across HTTP and stdio without transport-specific branching. If listen() works, extension notifications work.

    We've been building MCP extensions at CorpusIQ (corpusiq.io) and the closed-subscription surface is the single biggest friction point for extension authors — you can build the extension logic in an afternoon and then spend three days bolting a custom listen router onto it. Happy to contribute to a design discussion if this gets prioritized.

  3. added
    spec-2026-07-28Concerns the SDK's implementation of the 2026-07-28 MCP spec revision
    on Aug 18, 2026
  4. claude commented on Aug 19, 2026

    @claude
    Contributor

    Closing: duplicate of #2569

    Thanks for raising this — it's a real gap, and your framing (a general extension point rather than a tasks-only fix) is valuable. The same limitation — extensions cannot participate in subscriptions/listen because SubscriptionFilterSchema is a closed object and ServerEvent is a closed union, which also blocks the Tasks extension's notifications/tasks (SEP-2663) — is tracked in #2569, which carries the detailed root-cause analysis, a reproduction, proposed directions, and active triage (needs design). We're consolidating the discussion there to keep it in one place; please add your extension use case and workaround experience to #2569.

    This comment and close were reviewed and approved by maintainer @felixweinberger — it is a human-approved action, not an unattended automated one.


    Generated by Claude Code

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

    spec-2026-07-28Concerns the SDK's implementation of the 2026-07-28 MCP spec revisionv2Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions