Source Intelligence
Sweep 28 Aug 2026 · 00:00Z Build v2.1.250 478 read Stable v2.1.236 Latest v2.1.250 Next v2.1.250 Feeds RSS JSON llms.txt

DisclaimerUnofficial, and not affiliated with Anthropic. Nearly all of this is read straight out of what ships: npm bundles, captured prompts, published docs. Anthropic's own notes go in verbatim, marked as theirs. The rest is my reading, and every entry carries the strings behind it. If one looks wrong, vote it down and say why.

One change

Subscriptions

specification/draft/basic/patterns/subscriptions

The page's own history The capture it came from

Nearest release: v2.1.246, published 8 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

specification/draft/basic/patterns/subscriptions New page · 164 lines, new page

# Subscriptions ## Opening a Stream ### Notification Filter ## Acknowledgment ## Receiving Notifications ## Multiple Concurrent Subscriptions ## Cancellation ### Graceful Closure

A whole new page. There's nothing to diff it against, so here is what it says.

# Subscriptions

<div id="enable-section-numbers" />

`subscriptions/listen` opens a long-lived notification stream from the server to the
client. Unlike one-off requests, the stream stays open and delivers notifications until
the client cancels it. It replaces the former `resources/subscribe` RPC and the HTTP GET
endpoint.

## Opening a Stream

The client sends a `subscriptions/listen` request with a `notifications` filter
specifying which event types it wants to receive. The server **MUST NOT** send
notification types the client has not explicitly requested.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "subscriptions/listen",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {
        "name": "ExampleClient",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    },
    "notifications": {
      "toolsListChanged": true,
      "resourceSubscriptions": ["file:///project/config.json"]
    }
  }
}
```

### Notification Filter

| Field                   | Type       | Description                                                       |
| ----------------------- | ---------- | ----------------------------------------------------------------- |
| `toolsListChanged`      | `boolean`  | Receive `notifications/tools/list_changed` when tools change      |
| `promptsListChanged`    | `boolean`  | Receive `notifications/prompts/list_changed` when prompts change  |
| `resourcesListChanged`  | `boolean`  | Receive `notifications/resources/list_changed` when list changes  |
| `resourceSubscriptions` | `string[]` | Receive `notifications/resources/updated` for these resource URIs |

All fields are optional. Omitting a field is equivalent to not subscribing to that
notification type.

## Acknowledgment

The server **MUST** send `notifications/subscriptions/acknowledged` as the first message
carrying the subscription's ID in `_meta` under `io.modelcontextprotocol/subscriptionId`,
and **MUST NOT** send any notification on the
subscription before it. On stdio, where every subscription shares one channel, this
ordering is defined per subscription ID and not per channel: messages belonging to other
subscriptions **MAY** be interleaved before it.

The `notifications` field in the acknowledgment reflects the subset the server agreed to
honor. Notification types the server does not support are omitted.

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "notifications/subscriptions/acknowledged",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 1
    },
    "notifications": {
      "toolsListChanged": true,
      "resourceSubscriptions": ["file:///project/config.json"]
    }
  }
}
```

The client **SHOULD** check the acknowledged filter against what it requested and handle
any unsupported types gracefully.

## Receiving Notifications

All notifications delivered on the stream carry
`io.modelcontextprotocol/subscriptionId` in `_meta`, identifying the
`subscriptions/listen` request that opened the stream. The value is the JSON-RPC ID of
the `subscriptions/listen` request. In the examples above, the request used `"id": 1`,
so the acknowledgment and all subsequent notifications carry the subscription ID `1`.
On stdio, where all messages
share a single channel, clients **MUST** use this field to correlate notifications
with their originating subscription.

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "notifications/resources/updated",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 1
    },
    "uri": "file:///project/config.json"
  }
}
```

## Multiple Concurrent Subscriptions

A client **MAY** have multiple active subscriptions concurrently — for example,
one listening for tools-list changes and another for resource updates. Each
subscription is identified by the JSON-RPC request ID of its
`subscriptions/listen` request, and every notification on the stream carries
that ID in
`io.modelcontextprotocol/subscriptionId` so clients can demultiplex them.

## Cancellation

A subscription ends when:

* The **client** cancels it — close the SSE stream (HTTP) or send
  `notifications/cancelled` referencing the `subscriptions/listen` request ID (stdio).
* The **server** tears it down (e.g., during shutdown) — it **SHOULD** send a
  successful `subscriptions/listen` response to signal a graceful end (see
  [Graceful Closure](#graceful-closure)), then close the stream.
* The underlying transport closes (HTTP timeout, TCP disconnect, stdio process
  exit).

### Graceful Closure

When the server ends a subscription on its own initiative (for example, during
shutdown), it **SHOULD** respond to the original `subscriptions/listen` request
with a completion result before closing the stream. The result carries no
method-specific data beyond the standard result fields and subscription
metadata. This is the JSON-RPC response to the long-lived request, correlated by
its `id`, and signals that the subscription ended gracefully — as opposed to an
abrupt transport drop, which carries no response.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 1
    }
  }
}
```

Like every other message on the stream, the response carries
`io.modelcontextprotocol/subscriptionId` in `_meta`, identifying which
subscription it closes. The value matches the JSON-RPC `id` of the originating
`subscriptions/listen` request.

A client that receives this response knows the subscription closed cleanly; a
transport that closes without it indicates an unexpected disconnect, which the
client **MAY** treat as a trigger to reconnect.

On **stdio**, if the connection is terminated and then re-established, the
client **MUST** re-send `subscriptions/listen` to re-establish its
subscriptions — the server holds no subscription state across reconnections.

See [Cancellation][cancellation] for the full rules.

[cancellation]: /specification/draft/basic/patterns/cancellation