new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

MCP · Specification · all subjects

subscriptions

46 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Subscriptions use subscriptions/listen and subscriptionId-tagged notifications

In MCP 2026-07-28, a client opens a stream with `subscriptions/listen` naming the desired subscription kinds (e.g. toolsListChanged, resourceSubscriptions) or resource URIs. The server replies with `notifications/subscriptions/acknowledged`, then streams `notifications/*` messages each tagged with a `subscriptionId`. Receiving resource update notifications requires opening such a `subscriptions/listen` stream.

subscriptionId must be included on subscription stream notifications

On notifications delivered via a `subscriptions/listen` stream, the server MUST include `io.modelcontextprotocol/subscriptionId` in `_meta` so the client can correlate the notification with the originating subscription request.

Server-sent notifications/cancelled restricted to subscriptions/listen

A server MUST send `notifications/cancelled` referencing a `subscriptions/listen` request ID when it tears down that subscription stream. Servers MUST NOT send `notifications/cancelled` for any other purpose. Server-sent cancellation notifications MUST reference a `subscriptions/listen` request, to terminate that subscription stream.

subscriptions/listen long-lived stream and acknowledgement

To receive change notifications (list changes, resource updates), the client sends a `subscriptions/listen` request; the reply is a long-lived stream of the requested notification types. The server replies with `notifications/subscriptions/acknowledged`, then the stream stays open and subsequent `notifications/*` are tagged with a `subscriptionId`.

Subscription stream state is scoped to the request; re-issue on channel loss

Stream state for `subscriptions/listen` is scoped to the request: if the underlying channel is lost, the client re-issues the `subscriptions/listen` request.

Client SHOULD verify acknowledged filter

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

subscriptionId in _meta identifies the stream

All notifications delivered on a subscription stream carry `io.modelcontextprotocol/subscriptionId` in `_meta`. Its value is the JSON-RPC ID of the `subscriptions/listen` request that opened the stream (e.g. a request with "id": 1 yields subscription ID 1 on the acknowledgment and all subsequent notifications). On stdio, where all messages share a single channel, clients MUST use this field to correlate notifications with their originating subscription.

notifications/resources/updated payload on a subscription

An example resource-update notification on a subscription: {"jsonrpc":"2.0","method":"notifications/resources/updated","params":{"_meta":{"io.modelcontextprotocol/subscriptionId":1},"uri":"file:///project/config.json"}}.

Multiple concurrent subscriptions allowed

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 carries that ID in `io.modelcontextprotocol/subscriptionId` so clients can demultiplex them.

How a subscription ends (cancellation paths)

A subscription ends when: (1) the client cancels it — closing the SSE stream over HTTP, or sending `notifications/cancelled` referencing the `subscriptions/listen` request ID on stdio; (2) the server tears it down (e.g. during shutdown), in which case it SHOULD send the empty `subscriptions/listen` response to signal a graceful end before closing the stream; or (3) the underlying transport closes (HTTP timeout, TCP disconnect, stdio process exit).

Graceful closure response for subscriptions/listen

When the server ends a subscription on its own initiative, it SHOULD respond to the original `subscriptions/listen` request with an empty result before closing the stream: {"jsonrpc":"2.0","id":1,"result":{"resultType":"complete","_meta":{"io.modelcontextprotocol/subscriptionId":1}}}. This JSON-RPC response is correlated by `id` and signals the subscription ended gracefully, as opposed to an abrupt transport drop which carries no response.

Missing close response means unexpected disconnect

A client that receives the empty `subscriptions/listen` result 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.

stdio reconnect requires re-sending subscriptions/listen

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.

subscriptions/listen replaces resources/subscribe and HTTP GET endpoint

In MCP spec version 2026-07-28, the `subscriptions/listen` request opens a long-lived notification stream from server to client. The stream stays open and delivers notifications until the client cancels it. It replaces the former `resources/subscribe` RPC and the HTTP GET endpoint.

subscriptions/listen request shape with notifications filter

A `subscriptions/listen` request is a normal JSON-RPC request, e.g. {"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 fields for subscriptions/listen

The `notifications` filter object in `subscriptions/listen` params supports: `toolsListChanged` (boolean) to receive `notifications/tools/list_changed`; `promptsListChanged` (boolean) to receive `notifications/prompts/list_changed`; `resourcesListChanged` (boolean) to receive `notifications/resources/list_changed`; and `resourceSubscriptions` (string[] of resource URIs) to receive `notifications/resources/updated` for those URIs. All fields are optional; omitting a field is equivalent to not subscribing to that notification type.

notifications/subscriptions/acknowledged message shape

The acknowledgment looks like {"jsonrpc":"2.0","method":"notifications/subscriptions/acknowledged","params":{"_meta":{"io.modelcontextprotocol/subscriptionId":1},"notifications":{"toolsListChanged":true,"resourceSubscriptions":["file:///project/config.json"]}}}. The `notifications` field reflects the subset the server agreed to honor; notification types the server does not support are omitted.

Correlating subscription notifications via _meta subscriptionId

For notifications delivered for an active subscriptions/listen request over stdio, clients MUST correlate them using the `io.modelcontextprotocol/subscriptionId` field in `_meta` (see SubscriptionsListenRequest).

subscriptions/listen replaces HTTP GET and resources/subscribe

Revision 2026-07-28 replaces the HTTP GET endpoint and the `resources/subscribe`/`resources/unsubscribe` methods with a single `subscriptions/listen` method: a long-lived POST-response stream for opted-in server-to-client change notifications. Clients opt in to specific notification types: `toolsListChanged`, `promptsListChanged`, `resourcesListChanged`, and `resourceSubscriptions`. The server acknowledges and tags notifications with the `_meta` key `io.modelcontextprotocol/subscriptionId`.

notifications/prompts/list_changed via subscriptions/listen

When the list of available prompts changes, servers that declared the `listChanged` capability SHOULD send `{"jsonrpc":"2.0","method":"notifications/prompts/list_changed"}` to clients that have opened a `subscriptions/listen` stream with `promptsListChanged: true`. The flow is: client sends subscriptions/listen (promptsListChanged: true), server sends notifications/subscriptions/acknowledged, then notifications/prompts/list_changed on change, then the client re-lists with prompts/list.

Resource subscriptions via subscriptions/listen

Clients subscribe to change notifications for specific resources by sending a `subscriptions/listen` request with the resource URIs listed in `notifications.resourceSubscriptions`. The server then delivers `notifications/resources/updated` on the resulting stream whenever a watched resource changes. Example notification: {"jsonrpc":"2.0","method":"notifications/resources/updated","params":{"_meta":{"io.modelcontextprotocol/subscriptionId":4},"uri":"file:///project/src/main.rs"}}. Acknowledgment, subscriptionId correlation, and cancellation are defined by the general Subscriptions pattern.

Resource message flow order

Typical resource message flow: client sends resources/list and server returns the list; client sends resources/templates/list and server returns templates; client sends resources/read and server returns contents; client sends subscriptions/listen with resourceSubscriptions and server streams notifications/subscriptions/acknowledged; on change the server sends notifications/resources/updated and the client re-issues resources/read to get updated contents.

notifications/tools/list_changed requires subscriptions/listen

When the list of available tools changes, servers that declared the `listChanged` capability SHOULD send `{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}` to clients that have opened a `subscriptions/listen` stream with `toolsListChanged: true`. The server acknowledges the listen with `notifications/subscriptions/acknowledged`.

Caching interacts with listChanged notifications

TTL and server-push notifications are complementary. A server MAY provide `ttlMs` without advertising `listChanged: true` in its capabilities, in which case the client relies entirely on TTL freshness. A server MAY advertise `listChanged: true` and also provide `ttlMs`. When a relevant notification (e.g. `notifications/tools/list_changed`) arrives while a cached response is still fresh, the notification invalidates the cached response and it should be considered immediately stale.

notifications/message is request-scoped only

`notifications/message` is request-scoped: the server MUST NOT deliver it on a `subscriptions/listen` stream or on any stream other than the one carrying the response to the request that set the log level via `_meta`.

subscriptions/listen provides the long-lived notification stream

Long-lived change notifications (list changes, resource updates) are delivered on the SSE response stream of a subscriptions/listen request, which stays open and carries only the notification types the client opted into (e.g. notifications/subscriptions/acknowledged first, then notifications/tools/list_changed, notifications/resources/updated). Request-scoped notifications such as notifications/progress and notifications/message are NOT delivered on the listen stream; they flow only on the response stream of the request they relate to.

SSE keep-alive comment lines on long-lived streams

For long-lived streams, in particular the subscriptions/listen response stream, servers are encouraged to periodically emit an SSE comment line (a line beginning with a colon, e.g. ':\r\n') as a keep-alive. Per the SSE specification any line beginning with a colon is a comment carrying no event data; clients must ignore such lines and must not treat them as malformed input.

notifications/resources/updated requires resourceSubscriptions opt-in

ResourceUpdatedNotification is {"jsonrpc":"2.0","method":"notifications/resources/updated","params": ResourceUpdatedNotificationParams} and tells the client a resource changed and may need re-reading. It is only sent for resources the client opted in to via the `resourceSubscriptions` field of a subscriptions/listen request. Example: params contain `_meta` with "io.modelcontextprotocol/subscriptionId": "listen-1" and "uri": "file:///project/src/main.rs".

Subscription notifications carry io.modelcontextprotocol/subscriptionId in _meta

Notifications delivered on a subscriptions/listen stream (prompts/list_changed, resources/list_changed, resources/updated) include a `_meta` object in params with the key "io.modelcontextprotocol/subscriptionId" whose value identifies the listen stream, e.g. "listen-1".

ResourceUpdatedNotificationParams shape (notifications/resources/updated)

The params of a `notifications/resources/updated` notification (interface ResourceUpdatedNotificationParams) contain an optional `_meta?: NotificationMetaObject` and a required `uri: string`. The `uri` is the URI of the resource that has been updated and might be a sub-resource of the one the client actually subscribed to. Example params: {"uri": "file:///project/src/main.rs"}.

notifications/subscriptions/acknowledged notification shape

SubscriptionsAcknowledgedNotification is a JSON-RPC notification with jsonrpc: "2.0", method: "notifications/subscriptions/acknowledged", and required params of type SubscriptionsAcknowledgedNotificationParams (optional `_meta?: NotificationMetaObject` plus required `notifications: SubscriptionFilter`). It is sent by the server to acknowledge that a subscriptions/listen subscription has been established and to report which notification types it agreed to honor.

MUST: acknowledgement is the first message on a subscription

The notifications/subscriptions/acknowledged notification MUST be the first message the server sends carrying the subscription's ID in `io.modelcontextprotocol/subscriptionId`. The server MUST NOT send any notification on the subscription before acknowledging 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.

Example: subscriptions/acknowledged payload

Example acknowledgement message: {"jsonrpc": "2.0", "method": "notifications/subscriptions/acknowledged", "params": {"_meta": {"io.modelcontextprotocol/subscriptionId": "listen-1"}, "notifications": {"toolsListChanged": true, "resourceSubscriptions": ["file:///project/config.json"]}}}.

notifications/tools/list_changed shape and delivery condition

ToolListChangedNotification has jsonrpc: "2.0", method: "notifications/tools/list_changed", and optional `params?: NotificationParams`. It is an optional notification from server to client that the tool list changed, and is only delivered on a subscriptions/listen stream when the client requested it via the `toolsListChanged` filter field. Example: {"jsonrpc": "2.0", "method": "notifications/tools/list_changed", "params": {"_meta": {"io.modelcontextprotocol/subscriptionId": "listen-1"}}}.

SubscriptionsListenResultResponse envelope

SubscriptionsListenResultResponse is {jsonrpc: "2.0"; id: RequestId; result: SubscriptionsListenResult}. Example: {"jsonrpc":"2.0","id":"listen-1","result":{"resultType":"complete","_meta":{"io.modelcontextprotocol/subscriptionId":"listen-1"}}}.

subscriptions/listen request shape

SubscriptionsListenRequest is a JSON-RPC request with `jsonrpc: "2.0"`, `id: RequestId`, `method: "subscriptions/listen"`, and required `params: SubscriptionsListenRequestParams`. It is sent from the client to open a long-lived channel for receiving notifications outside the context of a specific request, replacing the previous HTTP GET endpoint and ensuring consistent behavior between HTTP and STDIO.

SubscriptionsListenRequestParams fields

SubscriptionsListenRequestParams has required `_meta: RequestMetaObject` (inherited from RequestParams) and required `notifications: SubscriptionFilter`, which lists the notifications the client opts in to on this stream.

Server MUST NOT send unrequested notification types on a listen stream

On a subscriptions/listen stream the server MUST NOT send notification types that the client has not explicitly requested in the `notifications` (SubscriptionFilter) parameter.

subscriptions/listen example request JSON

Example: {"jsonrpc": "2.0", "id": "listen-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"]}}}.

SubscriptionsListenResult shape and graceful close

SubscriptionsListenResult is the response to a `subscriptions/listen` request. It has `resultType: string` and `_meta: SubscriptionsListenResultMetaObject` plus arbitrary extra keys. It signals the subscription ended gracefully (e.g. during server shutdown). Because the listen stream is long-lived, this result is sent only when the server tears the subscription down; an abrupt transport close carries no response. The result body is otherwise empty. Example: {"resultType": "complete", "_meta": {"io.modelcontextprotocol/subscriptionId": "listen-1"}}.

subscriptionId meta key on listen result

SubscriptionsListenResultMetaObject extends ResultMetaObject with a required key "io.modelcontextprotocol/subscriptionId" of type RequestId, identifying the subscription stream the response closes. Its value is the JSON-RPC ID of the `subscriptions/listen` request that opened the stream and equals the response's own `id`. The optional "io.modelcontextprotocol/serverInfo" (an Implementation with required `name` and `version`) is inherited; servers SHOULD include it on every response unless configured otherwise, and clients SHOULD NOT use it to change behaviour or for security decisions.

Acknowledged `notifications` filter omits unsupported types

In SubscriptionsAcknowledgedNotificationParams, the `notifications` field (a SubscriptionFilter) carries only the subset of requested notification types the server agreed to honor. It only includes notification types the server actually supports; if the client requested an unsupported type (for example `promptsListChanged` when the server has no prompts), it is omitted from that set.

SubscriptionFilter fields are opt-in (MUST NOT send unrequested)

SubscriptionFilter, used on a `subscriptions/listen` request, has optional fields: toolsListChanged?: boolean (receive notifications/tools/list_changed), promptsListChanged?: boolean (notifications/prompts/list_changed), resourcesListChanged?: boolean (notifications/resources/list_changed), and resourceSubscriptions?: string[] (receive notifications/resources/updated for those resource URIs, replacing the former `resources/subscribe` RPC). Each notification type is opt-in; the server MUST NOT send notification types the client has not explicitly requested.

Subscription notifications MUST carry io.modelcontextprotocol/subscriptionId

`NotificationMetaObject` extends `MetaObject` with `"io.modelcontextprotocol/subscriptionId"?: RequestId`. The server MUST include this key on every notification delivered via a `subscriptions/listen` stream so the client can correlate the notification with the originating subscription. Its value is the JSON-RPC ID of the `subscriptions/listen` request that opened the stream. The key is absent on notifications not delivered via a subscription stream (e.g. progress notifications for an in-flight request), which is why it is optional.

notifications/prompts/list_changed requires promptsListChanged filter

PromptListChangedNotification is {"jsonrpc":"2.0","method":"notifications/prompts/list_changed","params"?: NotificationParams}. It is an optional server-to-client notification that the prompt list changed, and is only delivered on a subscriptions/listen stream when the client requested it via the `promptsListChanged` filter field. Example params carry `_meta` with "io.modelcontextprotocol/subscriptionId": "listen-1".

notifications/resources/list_changed requires resourcesListChanged filter

ResourceListChangedNotification is {"jsonrpc":"2.0","method":"notifications/resources/list_changed","params"?: NotificationParams}. It informs the client the list of readable resources changed and is only delivered on a subscriptions/listen stream when the client requested it via the `resourcesListChanged` filter field. Example params include `_meta` with "io.modelcontextprotocol/subscriptionId": "listen-1".

Give your agent this brain