What does MCP's subscriptions/listen request do, and what can it filter?
answer
- one stream, opted into explicitly
- the client names what it wants
- four filter fields, one is a URI list
- replaced the GET channel
- and replaced resources/subscribe
basics
~20 ssubscriptions/listen is one long-lived request whose response stream carries server-to-client change notifications. The client names what it wants in a SubscriptionFilter: toolsListChanged, promptsListChanged, resourcesListChanged, and resourceSubscriptions (a list of resource URIs). Nothing is pushed unless the client opted in.
solid answer
~40 sIn MCP revision 2026-07-28 there is no standing push channel: server-to-client change notifications only flow on a stream the client explicitly opened. The client issues `subscriptions/listen` — over Streamable HTTP that is a single long-lived POST whose response is streamed — and supplies a `SubscriptionFilter` with four opt-ins: `toolsListChanged`, `promptsListChanged`, `resourcesListChanged`, and `resourceSubscriptions`, an array of resource URIs to watch individually. The server then delivers only the matching notifications on that stream: `notifications/tools/list_changed`, `notifications/prompts/list_changed`, `notifications/resources/list_changed`, and `notifications/resources/updated`. This one mechanism replaced both the standalone HTTP GET listening stream and the removed `resources/subscribe` / `resources/unsubscribe` calls. Request-scoped traffic such as progress updates is unaffected — it still flows on the originating request's own response stream.
code
json · 6 lines{
"toolsListChanged": true,
"promptsListChanged": false,
"resourcesListChanged": true,
"resourceSubscriptions": ["file:///project/README.md"]
}go deeper
Know the name subscriptions/listen and the one-line idea: the client opens a stream and says which changes it wants, and the server pushes only those.
Be ready to name all four SubscriptionFilter fields, say which notification each unlocks, and state that a list_changed notification is a signal that triggers a re-list rather than a payload.
Show that you know what it replaced in 2026-07-28 — the GET listening stream and resources/subscribe — and that progress and message notifications still ride their originating request's stream, not this one.
Own the cost side: one held-open request per client-server pair across a fleet, and the call on whether a product needs live catalogue updates at all versus re-listing on a cache expiry.
## What subscriptions/listen is `subscriptions/listen` is the single channel over which an MCP server pushes change notifications to a client, introduced in protocol revision **2026-07-28**. The client sends it like any other JSON-RPC request, but instead of a prompt reply-and-close, the response is a stream held open for as long as the client wants notifications. Over the Streamable HTTP transport that means one long-lived POST to the server's single MCP endpoint, whose response the server upgrades to a streamed body. Over stdio it means one outstanding request on the shared stdin/stdout channel. The crucial property is that it is **opt-in and explicit**. A 2026-07-28 server does not push anything to a client that has not asked; there is no ambient channel it can use. If your client never calls `subscriptions/listen`, it will simply never see `notifications/tools/list_changed`, and must re-list when it wants fresh data. ## The SubscriptionFilter The request carries a `SubscriptionFilter` with four fields: - `toolsListChanged` — deliver `notifications/tools/list_changed` when the server's tool set changes. - `promptsListChanged` — deliver `notifications/prompts/list_changed`. - `resourcesListChanged` — deliver `notifications/resources/list_changed`. - `resourceSubscriptions` — an array of resource URIs; the server delivers `notifications/resources/updated` for those specific resources. The first three are coarse "the catalogue moved" signals; the fourth is per-resource watching. Note the asymmetry: you can watch individual resources by URI, but there is no per-tool or per-prompt watch — tools and prompts are all-or-nothing at list granularity. Because the filter is stated in the request, the client's interests are self-describing and need no prior state on the server. That fits the era's framing: MCP 2026-07-28 is a stateless protocol in which every request is self-contained, and servers must not rely on earlier requests over the same connection to establish context. ## What it replaced Two older mechanisms collapsed into this one. First, the **standalone HTTP GET listening stream**. In revisions up to 2025-11-25, a Streamable HTTP client could issue a GET to the MCP endpoint and hold open an SSE stream for unsolicited server messages. That was removed in 2026-07-28; the endpoint is POST-only, and a modern-only server should answer a GET with `405 Method Not Allowed`. Second, **`resources/subscribe` and `resources/unsubscribe`**. Those RPCs were removed; watching a resource is now expressed as a URI in `resourceSubscriptions` on the listen filter, and un-watching means re-issuing the listen request with a different filter or ending the stream. A candidate who reaches for either of the old mechanisms is exactly what an interviewer asking this question is trying to detect, since a great deal of pre-2026 writing about MCP still describes them. ## What does not flow on this stream Request-scoped notifications — `notifications/progress` and `notifications/message` — do **not** move to the listen stream. They still travel on the response stream of the request that caused them, so a long-running `tools/call` reports its own progress on its own stream. This keeps correlation trivial: a progress update belongs to the request whose stream carried it. The listen stream carries only the fleet-level change notifications the filter opted into (plus, when the `io.modelcontextprotocol/tasks` extension is in play, its optional task pushes). ## Practical consequences A client that shows a live tool palette will typically open one listen stream per connected server with `toolsListChanged` set, and re-call `tools/list` when the notification arrives — the notification is a signal, not a payload, so no diff travels on it. A client that never renders a live catalogue can skip the stream entirely and rely on re-listing, which is cheaper: an open listen stream is one HTTP request occupying a connection for the whole session's lifetime, multiplied by every client-server pair. A server implementer must remember two obligations that come with the stream: it must send `notifications/subscriptions/acknowledged` as the first message before any change notification, and every notification it sends over the stream must carry `io.modelcontextprotocol/subscriptionId` in `_meta` so a client with several streams can tell them apart. ## Interview framing Say plainly: "nothing is pushed unless the client opened a `subscriptions/listen` stream and named the change classes in its filter." Then name the four filter fields, note that it replaced the GET channel and `resources/subscribe` in 2026-07-28, and add that progress still rides its own request's stream. That answer dates your knowledge to the current revision and shows you know where the boundary between the two kinds of notification sits.
- If the tool list changes, does the notification carry the new tools?No. `notifications/tools/list_changed` is a signal that the catalogue moved, not a payload. The client re-calls `tools/list` to get the new set. The same holds for the prompts and resources list-changed notifications; only `notifications/resources/updated` names a URI, and even then the client must read the resource to see the new content.
- Can a client watch one specific tool the way it watches one resource?No. Watching is per-resource only, through the `resourceSubscriptions` URI array. Tools and prompts are watched at list granularity via `toolsListChanged` and `promptsListChanged`, so any change to the server's tool set produces the same single notification and the client re-lists to find out what actually changed.
- Does a long-running tools/call report its progress on the listen stream?No. Request-scoped notifications — `notifications/progress` and `notifications/message` — flow on the response stream of the request that produced them, not on the listen stream. That keeps correlation trivial and means a client that never opens a listen stream still sees progress for its own calls.
saying these in an interview costs you the question
- Claiming the server pushes notifications without any client opt-in
- Reaching for resources/subscribe, removed in 2026-07-28
- Describing a standalone HTTP GET stream for server messages
- Saying progress notifications arrive on the listen stream
- Expecting list_changed to carry the new tool definitions