Fork resource subscriptions by protocol era: legacy keeps resources/subscribe; modern (2026-07-28) models subscriptions as a filter over one long-lived subscriptions/listen stream with reconnect-by-re-listen (capped backoff), an optimistic Connecting→Listening header badge, and a fix so the browser proxy no longer blocks listen() ~60s. Closes #1630.
61 lines
3.4 KiB
Markdown
61 lines
3.4 KiB
Markdown
# Resource subscriptions era fork (#1630) — proof screenshots
|
|
|
|
End-to-end verification of the era fork against two real test servers
|
|
(`test-servers/configs/subscriptions-modern-http.json` on port 3220 and
|
|
`subscriptions-legacy-http.json` on 3221), driven in a real browser.
|
|
|
|
## Modern era (2026-07-28)
|
|
|
|

|
|
|
|
**`subscriptions-modern-header-badge.png`** — on the modern era the Subscriptions
|
|
section shows a single **stream-status badge in its accordion header** (next to the
|
|
count, so it stays visible while the section is collapsed): `● Listening` when the
|
|
`subscriptions/listen` stream is acknowledged, `● Reconnecting…` while it re-lists
|
|
after a drop, `● Stream ended` on graceful close — each explained in a tooltip.
|
|
Legacy connections show no badge.
|
|
|
|

|
|
|
|
**`subscriptions-modern-listen-acknowledged.png`** — subscribing on a
|
|
**Modern**-negotiated connection sends **`subscriptions/listen`** (long-lived →
|
|
`PENDING`) and the server answers with **`notifications/subscriptions/acknowledged`**.
|
|
No `resources/subscribe` is sent — the defining era-fork behavior. Two other
|
|
details: the connection era is shown once in the panel header (`Messages · MODERN`),
|
|
not per entry; and the `sub ⧉ listen:0` subscription-id tag rides the notification's
|
|
top line (beside the direction) so the method badge below gets the full column width
|
|
instead of truncating against the pin control.
|
|
|
|
## Legacy era (contrast)
|
|
|
|

|
|
|
|
**`subscriptions-legacy-resources-subscribe.png`** — the same subscribe on a
|
|
**Legacy** connection sends **`resources/subscribe`** (Protocol view, LEGACY) and the
|
|
Subscriptions section shows **no stream badge and no header dot** (there is no
|
|
persistent stream on the legacy era). Legacy behavior is unchanged.
|
|
|
|

|
|
|
|
**`subscriptions-legacy-live-update.png`** — calling the `update_resource` tool emits
|
|
**`notifications/resources/updated`** (server → client, Protocol view), and the
|
|
subscribed `resource_1` tile stamps its **last-updated time** (`2:53:17 PM`) — the
|
|
full subscribe → update → notify round-trip on the legacy era.
|
|
|
|
## Notes
|
|
|
|
- Modern subscribe in the browser is now prompt (`Connecting…` → `Listening`) and
|
|
stable: the web backend's `/api/mcp/send` and the browser remote transport used
|
|
to hold the `subscriptions/listen` request waiting for a JSON-RPC response that a
|
|
long-lived stream never sends, blocking `listen()` ~60s and then spuriously
|
|
driving the reconnect loop. Both sides now exempt `subscriptions/listen` from the
|
|
response-wait (its ack + notifications ride the SSE event channel), so the badge
|
|
no longer oscillates. (Some of the older screenshots here were captured before
|
|
that fix and show the transient `Reconnecting…`/`RECONNECTING…` state.)
|
|
- A tool-triggered `resources/updated` does **not** reach the modern
|
|
`subscriptions/listen` stream on the SDK's stateless modern leg (a tool call and
|
|
the listen stream are separate connections; `server.notification()` rides the
|
|
tool call's connection). This is an SDK server-side gap — the same class as the
|
|
logging showcase's stateless-notification caveat — independent of this PR's
|
|
client-side work. Hence the live-update proof is shown on the legacy era, where
|
|
the round-trip completes.
|