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
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(), andserverEventToNotification()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
taskIdsto the listen filter andnotifications/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/listenrequests and delegates 'natively' supported ones.What did you expect?
A public extension point that lets an extension:
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
fetchimplementation from our server ;] )Code to reproduce
SDK version
2.0.0-beta.4
Area
None