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.

Page history

Subscriptions

specification/2026-07-28/basic/patterns/subscriptions

2 recorded changes 164 lines First seen Last changed Upstream

History

specification/2026-07-28/basic/patterns/subscriptions Changed · +7 / -6 lines

from line 117
 
 * 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 the
-  empty `subscriptions/listen` response to signal a graceful end (see
+* 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).
from line 127
 
 When the server ends a subscription on its own initiative (for example, during
 shutdown), it **SHOULD** respond to the original `subscriptions/listen` request
-with an empty result before closing the stream. 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.
+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}
 {

specification/2026-07-28/basic/patterns/subscriptions First recorded · 163 lines, first recorded

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

The first capture of this source. The page was already there, and this is what it said.

# 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 the
  empty `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 an empty result before closing the stream. 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/2026-07-28/basic/patterns/cancellation