Resources: subscriptions/listen model on modern servers (era fork) (#1630) (#1730)

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.
This commit is contained in:
Cliff Hall 2026-07-20 19:33:40 -04:00 • committed by GitHub
commit 320daf2f67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -0,0 +1,53 @@
import type { ResourceSubscriptionStreamStatus } from "../../../../../../core/mcp/types.js";
export interface StreamPresentation {
/** Mantine palette color name conveying the status. */
color: string;
/** Short label shown on the panel badge. */
label: string;
/** Full explanation shown in the tooltip (both variants). */
tooltip: string;
}
const STREAM_INTRO =
"On modern (2026-07-28) servers, resource subscriptions are a filter over one long-lived subscriptions/listen stream.";
// Keyed by status so it's exhaustive at compile time: a new
// `ResourceSubscriptionStreamStatus` that isn't handled here is a type error
// (no unreachable `default` needed, so it stays fully covered).
const PRESENTATION: Record<
ResourceSubscriptionStreamStatus,
StreamPresentation
> = {
connecting: {
color: "blue",
label: "Connecting…",
tooltip: `${STREAM_INTRO} Opening the stream — waiting for the server to acknowledge the subscription.`,
},
acknowledged: {
color: "green",
label: "Listening",
tooltip: `${STREAM_INTRO} The server acknowledged the subscription and the stream is open, carrying resources/updated notifications.`,
},
reconnecting: {
color: "yellow",
label: "Reconnecting…",
tooltip: `${STREAM_INTRO} The stream dropped unexpectedly; re-listening to re-establish it (there is no resumability, so the full filter is re-sent).`,
},
ended: {
color: "gray",
label: "Stream ended",
tooltip: `${STREAM_INTRO} The stream is closed and won't reconnect on its own — either the server ended it (for example, on shutdown) or reconnection was abandoned after repeated failures. Re-subscribe to try again.`,
},
};
/**
* Maps a modern listen-stream status to its badge color, label, and tooltip
* copy (#1630). Kept in its own module so the badge component file exports only
* a component (react-refresh rule).
*/
export function subscriptionStreamPresentation(
status: ResourceSubscriptionStreamStatus,
): StreamPresentation {
return PRESENTATION[status];
}