You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[v2] Allow extensions to participate in subscriptions/listen #2528
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
awaitclient.listen({taskIds: ['task-1'],// not accepted by SubscriptionFilter});// The same problem applies to namespaced extension filters and custom notification methods.
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:
Wrap/replace the listen router (your current approach) — works but duplicates acknowledgement, filtering, SSE framing, cancellation, and teardown. Error-prone and version-fragile.
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.
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.
Activity
Ben-Home commentedon Jul 23, 2026
This is the right gap to call out — and the fact that SEP-2663 needs
taskIdsin 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, andlistenFilterAccepts()are all closed over the four standard notification types. An extension that owns its own notification channel has to either:registerNotificationMethod()orregisterSubscriptionType()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:
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.
claude commentedon Aug 19, 2026
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/listenbecauseSubscriptionFilterSchemais a closed object andServerEventis a closed union, which also blocks the Tasks extension'snotifications/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