ruby-sdk/docs/_server/subscriptions.md
Koichi ITO c9d36b04bf [Doc] Align the Docs Page Names With the MCP Specification
Three pages carried names the 2026-07-28 specification does not use: "Multi-Round-Trip Results" for
the pattern the specification titles Multi Round-Trip Requests (MRTR) and serves at basic/patterns/mrtr -
the results are the `InputRequiredResult` wire type, not the feature - plus "Completions" for the utility
the specification titles Completion, and "Notification Subscriptions" for the pattern it titles Subscriptions.
Retitle the three pages to the specification's names, move them to /server/mrtr/ and /client/mrtr/,
/server/completion/, and /server/subscriptions/ following the specification's slugs, update every internal reference,
and keep the URLs published with v1.3.0 working via jekyll-redirect-from.
The Discovery page keeps its title but moves from /server/discovery/ to /server/discover/, matching
the specification's slug and the `server/discover` RPC, with its published URL redirected the same way.
2026-08-22 18:07:38 +09:00

2.5 KiB

layout title nav_order redirect_from
default Subscriptions 12
/server/notification-subscriptions/

Subscriptions

subscriptions/listen is the long-lived notification subscription stream of MCP 2026-07-28 (SEP-2575), replacing the legacy HTTP GET listening stream.

Subscribing

The client opts in via the notifications filter (toolsListChanged / promptsListChanged / resourcesListChanged / resourceSubscriptions), the server acknowledges the honored subset with notifications/subscriptions/acknowledged as the first stream message, and every delivered notification carries the correlating io.modelcontextprotocol/subscriptionId in _meta. The honored subset follows the capabilities the server declares (listChanged and subscribe flags).

The client opens the stream with a subscriptions/listen request:

{
  "jsonrpc": "2.0",
  "id": "listen-1",
  "method": "subscriptions/listen",
  "params": {
    "notifications": { "toolsListChanged": true, "resourceSubscriptions": ["file:///a.txt"] },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "my_client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

The first SSE event on the stream is the acknowledgement:

{
  "jsonrpc": "2.0",
  "method": "notifications/subscriptions/acknowledged",
  "params": {
    "notifications": { "toolsListChanged": true, "resourceSubscriptions": ["file:///a.txt"] },
    "_meta": { "io.modelcontextprotocol/subscriptionId": "listen-1" }
  }
}

Transport Support

The stream is served on the Streamable HTTP modern path; stdio answers -32601.

Limits and Keepalives

Concurrent streams are capped by max_listen_subscriptions: (default 1000; pass nil to remove the cap), and each stream receives an SSE keepalive comment frame every listen_keepalive_interval: seconds (default 15) so a dropped connection frees its slot; pass listen_keepalive_interval: nil when an upstream proxy already keeps the stream alive.

transport = MCP::Server::Transports::StreamableHTTPTransport.new(
  server,
  max_listen_subscriptions: 500,
  listen_keepalive_interval: 30,
)

A stream stays open until the client closes the connection; on graceful shutdown via transport.close, each open stream receives its subscriptions/listen response before closing.

See Notifications for the notification types themselves and their session scoping.