examples/stories/subscriptions/README.md
Server-originated change notifications on the 2026-07-28 protocol. A client
opens one subscriptions/listen request whose response is the stream; the
server publishes with ctx.notify_resource_updated(uri) /
ctx.notify_tools_changed() and the SDK does the wire work (ack-first,
per-stream filtering, subscription-id tagging). Replaces the handshake-era
resources/subscribe + standalone-GET notification path.
The client opens the stream with client.listen(...), edits a note it did
not subscribe to (silence), edits the one it did (a typed ResourceUpdated),
registers a tool at runtime (a typed ToolsListChanged, then re-lists and
calls it), and finally leaves the async with block, which ends the
subscription while the connection lives on.
# HTTP: the client self-hosts the server on a free port, runs, then tears it
# down (subscriptions/listen is 2026-era only)
uv run python -m stories.subscriptions.client --http
# same, against the lowlevel-API server variant
uv run python -m stories.subscriptions.client --http --server server_lowlevel
client.py: the whole subscription is one context manager,
async with client.listen(...) as sub. Entering waits for the server's
acknowledgment, so sub.honored is already in hand on the first line of the
block. Events arrive as typed values from anext(sub); the edit to the
unsubscribed note never shows up, because the filter is enforced
server-side. Leaving the block ends the subscription (over HTTP the SDK
closes that request's response stream) and the session carries on, which the
final search call proves.server.py: publishing is one await ctx.notify_*() line per change; the
filter, the tagging, and the ack ordering are the SDK's job. Publishing with
no subscribers is a no-op.server_lowlevel.py: the same machinery held by hand: an
InMemorySubscriptionBus, handlers that await bus.publish(...), and
ListenHandler(bus) passed as on_subscriptions_listen=. A multi-replica
deployment swaps the bus for one backed by its own pub/sub
(MCPServer(subscriptions=...) on the high-level server).resources/subscribe and unsolicited notifications instead), so the
story pins the modern era and has no legacy leg.Subscriptions, basic utilities
streaming/ (request-scoped notifications), events/ (the events extension
on top of this channel, deferred), and the narrative versions:
docs/handlers/subscriptions.md (server) and docs/client/subscriptions.md
(client).