barrel_mcp_subscriptions (barrel_mcp v3.0.0)
View SourceLong-lived notification streams (MCP 2026-07-28).
subscriptions/listen replaced the standalone GET SSE stream and the resources/subscribe RPC. A client opens one by POSTing a request whose response stream stays open, naming the notification types it wants; the server sends those and nothing else.
This module is the registry behind that. Each entry belongs to the request process holding the stream, and is keyed by that process together with the JSON-RPC id of the subscriptions/listen request, which is the subscription id on the wire. That id is only unique per connection, hence the pid in the key.
Entries are monitored, so a stream whose process dies without cleaning up does not leak.
Fan-out reads the table directly rather than going through the gen_server: a notification broadcast must not queue behind a registration.
Summary
Functions
Ask every open stream to end gracefully, so a client can tell a clean shutdown from a dropped connection.
Fan a list-changed notification out to every subscriber that asked for that kind.
Read a client's notification filter off the wire.
Fan a resource update out to the subscribers watching that URI.
Register the calling process as the holder of a subscription.
Fan a task status change out to the streams that asked for that task by id.
Types
-type handler_type() :: tool | resource | prompt | resource_template | completion.
Functions
-spec close_all() -> ok.
Ask every open stream to end gracefully, so a client can tell a clean shutdown from a dropped connection.
-spec count() -> non_neg_integer().
-spec list_changed(handler_type()) -> ok.
Fan a list-changed notification out to every subscriber that asked for that kind.
Read a client's notification filter off the wire.
Unknown keys are dropped rather than rejected: the acknowledgment tells the client what was actually honoured, which is the mechanism the spec gives for a server that does not support a type.
Fan a resource update out to the subscribers watching that URI.
Register the calling process as the holder of a subscription.
Called from the request process that owns the response stream, so the monitor established here is what cleans up on disconnect.
Fan a task status change out to the streams that asked for that task by id.
-spec unsubscribe(term()) -> ok.