Target branch: 2026-07-28-protocol-support
Requires:
Goal
A chimp client on the 2026-07-28 wire receives list-change and resource-update notifications through subscriptions/listen. The application sees them through the same notification listener it uses today, and can tell which subscription delivered them.
Opening a subscription
- The application can open a subscription with a filter that names the notification types it wants: tools list changed, prompts list changed, resources list changed, and updates for a given set of resource URIs.
- The client sends
subscriptions/listen and keeps the response stream open. The first message is the server's acknowledgement. The application can read the acknowledged filter and see which types the server declined.
- Several subscriptions can be open at once. Each one is identified by the id of its listen request.
Receiving
- Every notification that arrives on a subscription reaches the
onServerNotification listeners, together with its subscription id. Notifications are attributed by _meta["io.modelcontextprotocol/subscriptionId"], on stdio where all subscriptions share one channel and on HTTP alike.
- Progress and log notifications for an in-flight request keep arriving as today, with that request. They never come through a subscription.
Ending a subscription
- The application can close a subscription. Over HTTP the client closes the stream. Over stdio it sends
notifications/cancelled with the id of the listen request.
- A successful
subscriptions/listen result from the server means the server ended the subscription cleanly. The application is told, and the client does not reopen it.
- A stream that ends without that result is an unexpected disconnect. The client reopens the subscription with the same filter, with the backoff the streaming transports already use. The new subscription has a new id, and the application keeps receiving notifications. If the transport cannot be re-established, the failure surfaces to the application.
Transports and eras
- Subscriptions need a transport that can deliver messages outside a request's own response: the streaming HTTP transports and the stdio transports. On the sync HTTP transport the operation fails with
McpProtocolException.
- On the stateless wire the client does not open the GET stream any more. Resource updates come through a subscription with
resourceSubscriptions, so subscribeResource and unsubscribeResource stay legacy-only as decided in T10.
- Against a legacy server nothing changes: the GET listener and
resources/subscribe work as today.
Coverage
- The rules above hold for the streaming HTTP and stdio clients on ZIO, Ox and Pekko.
- Shared tests run against an in-process chimp server from T16 on both wires: subscriptions on the stateless wire, the GET stream on the legacy wire.
Spec:
Conformance scenarios that must pass after this task: none, the shared streaming tests against the in-process chimp server are the acceptance tests.
Docs: yes.
docs/client/capabilities.md, notifications section: how to open a subscription, the filter, the acknowledgement, the subscription id on notifications, and how to close it.
docs/client/transport.md: no GET stream and no resumability on the 2026-07-28 wire, and what a dropped subscription stream means.
Target branch: 2026-07-28-protocol-support
Requires:
Goal
A chimp client on the 2026-07-28 wire receives list-change and resource-update notifications through
subscriptions/listen. The application sees them through the same notification listener it uses today, and can tell which subscription delivered them.Opening a subscription
subscriptions/listenand keeps the response stream open. The first message is the server's acknowledgement. The application can read the acknowledged filter and see which types the server declined.Receiving
onServerNotificationlisteners, together with its subscription id. Notifications are attributed by_meta["io.modelcontextprotocol/subscriptionId"], on stdio where all subscriptions share one channel and on HTTP alike.Ending a subscription
notifications/cancelledwith the id of the listen request.subscriptions/listenresult from the server means the server ended the subscription cleanly. The application is told, and the client does not reopen it.Transports and eras
McpProtocolException.resourceSubscriptions, sosubscribeResourceandunsubscribeResourcestay legacy-only as decided in T10.resources/subscribework as today.Coverage
Spec:
Conformance scenarios that must pass after this task: none, the shared streaming tests against the in-process chimp server are the acceptance tests.
Docs: yes.
docs/client/capabilities.md, notifications section: how to open a subscription, the filter, the acknowledgement, the subscription id on notifications, and how to close it.docs/client/transport.md: no GET stream and no resumability on the 2026-07-28 wire, and what a dropped subscription stream means.