Skip to content

T17 - client subscriptions/listen #255

Description

@kubinio123

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.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions