You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Proposal: Allow Views to subscribe to server resource updates via resources/subscribe
Summary
Add resources/subscribe and resources/unsubscribe to the set of standard MCP messages that Views (UI iframes) can send through the host, and define notifications/resources/updated forwarding from host to View. This enables real-time, server-pushed data updates for interactive UIs without polling via repeated resources/read.
Motivation
The current MCP Apps spec (2026-01-26) allows Views to read server resources via resources/read but not subscribe to changes. For UIs that display live data — dashboards, monitors, collaborative editors, multiplayer games, streaming feeds — the only option today is polling via resources/read on a timer. This is:
Wasteful — generates unnecessary server load and API traffic when nothing has changed
Laggy — minimum latency is bounded by poll interval, not by actual data availability
Inconsistent — the core MCP spec already supports resources/subscribe + notifications/resources/updated between client and server, but the MCP Apps extension blocks Views from using it
The gap is already visible in the ecosystem. UI libraries building on MCP Apps have independently implemented subscription mechanisms with automatic polling fallbacks for hosts that don't support subscriptions. The native subscription path cannot be exercised because no host currently advertises subscription support — only the polling fallback runs in practice.
Proposed Changes
1. Add to Standard MCP Messages (View → Host)
Add to the allowed message list in "Standard MCP Messages":
resources/subscribe — Subscribe to updates for a resource URI
resources/unsubscribe — Unsubscribe from a previously subscribed resource URI
2. Add to Notifications (Host → View)
notifications/resources/updated — Host forwards this notification to the View when the server signals a subscribed resource has changed
// Host → View notification{jsonrpc: "2.0",method: "notifications/resources/updated",params: {uri: string// URI of the updated resource}}
The View would then typically call resources/read to fetch the updated content — same pattern as the core MCP spec.
3. Host Capabilities
Add subscribe?: boolean to HostCapabilities.serverResources:
Views MUST check hostCapabilities.serverResources.subscribe before sending resources/subscribe. If absent or false, Views SHOULD fall back to polling via resources/read.
4. Subscription Limits
Add optional maxSubscriptions to host capabilities:
Note: -32002 is already used by the core MCP spec for "Resource not found." A new application-level error code should be defined for subscription limits. -32001 is used here as a placeholder — the final code should be coordinated with the core spec maintainers.
5. Lifecycle & Cleanup
Add to the existing Cleanup section:
When a View is torn down (via ui/resource-teardown or iframe removal), the Host MUST send resources/unsubscribe to the MCP server for every active subscription that was proxied on behalf of that View. The Host MUST track all subscriptions per View.
6. Security Requirements
Requirement
Details
Per-View subscription cap
Host MUST enforce maxSubscriptions (default: 10 if unspecified)
Scoping
Subscriptions MUST be scoped to the originating server connection. A View MUST NOT receive notifications from a different server's resources
Rate limiting
Host SHOULD rate-limit forwarded notifications/resources/updated to the View (e.g., max 10/sec per URI) to prevent amplification
Cleanup on teardown
Host MUST unsubscribe all on View teardown — no orphaned server-side state
URI validation
Host SHOULD validate that subscribed URIs match resources previously returned by resources/list or resources/read from the same server
Message Flow
sequenceDiagram
participant V as View (iframe)
participant H as Host
participant S as MCP Server
V->>H: resources/subscribe { uri: "data://metrics/live" }
H->>S: resources/subscribe { uri: "data://metrics/live" }
S-->>H: subscription confirmed
H-->>V: subscription confirmed
Note over S: Data changes
S--)H: notifications/resources/updated { uri: "data://metrics/live" }
H--)V: notifications/resources/updated { uri: "data://metrics/live" }
V->>H: resources/read { uri: "data://metrics/live" }
H->>S: resources/read { uri: "data://metrics/live" }
S-->>H: updated contents
H-->>V: updated contents
Note over V: View teardown
H->>S: resources/unsubscribe { uri: "data://metrics/live" }
Loading
Graceful Degradation
Views that want real-time updates SHOULD implement a dual-path pattern:
consthostCaps=awaitgetHostCapabilities();if(hostCaps.serverResources?.subscribe){// Real-time pathawaitclient.request("resources/subscribe",{ uri });client.onNotification("notifications/resources/updated",async({ uri })=>{constdata=awaitclient.request("resources/read",{ uri });updateUI(data);});}else{// Polling fallbacksetInterval(async()=>{constdata=awaitclient.request("resources/read",{ uri });updateUI(data);},5000);}
Why Not Just Poll?
Polling (resources/read loop)
Subscription
Latency
Bounded by interval (seconds)
Near-instant
Server load
O(n) per interval regardless of changes
O(1) per actual change
Complexity for View developer
Timer management, dedup, cleanup
Subscribe once, handle events
Works today
Yes
Requires host support
Scope
This proposal does NOT introduce:
New subscription semantics beyond what core MCP already defines
View-to-View communication
Cross-server subscriptions
Any change to the server-side resources/subscribe spec
It only allows Views to access an existing core MCP capability through the host proxy, with appropriate security controls.
Prior Art
Core MCP spec (2025-03-26 and 2025-11-25): resources/subscribe + notifications/resources/updated fully specified for client↔server
HostCapabilities.serverResources.listChanged already exists in the MCP Apps spec — subscribe is the natural companion field
@maxhealth.tech/prefab (Max-Health-Inc/prefab): Working reference implementation of this proposal's dual-path pattern. The bridge (src/renderer/bridge.ts) sends resources/subscribe via JSON-RPC when the host supports it, listens for both notifications/resources/updated and ui/notifications/resource-updated, and returns a cleanup function that sends resources/unsubscribe. Host capability is detected from hostCapabilities.resources.subscribe during the ui/initialize handshake. When no host advertises support, the Subscribe action falls back to SetInterval + CallTool polling automatically. The native subscription path exists and is fully wired but has never been exercised on a real host — only the polling fallback runs today.
PrefectHQ/fastmcp (#3641): FastMCP doesn't yet support resources/subscribe / resources/unsubscribe (both listed as expected failures in the MCP conformance suite). A design proposal for per-server subscription tracking with deterministic cleanup is under review. Once shipped, servers will handle subscriptions — but Views still can't use them without this spec change. CC @jlowin@syhstanley
PrefectHQ/prefab (repo): Prefect's own UI framework has no subscription support — it uses SetInterval + CallTool polling for live data, illustrating the gap even for the team building both the server framework and the UI framework.
Proposal: Allow Views to subscribe to server resource updates via
resources/subscribeSummary
Add
resources/subscribeandresources/unsubscribeto the set of standard MCP messages that Views (UI iframes) can send through the host, and definenotifications/resources/updatedforwarding from host to View. This enables real-time, server-pushed data updates for interactive UIs without polling via repeatedresources/read.Motivation
The current MCP Apps spec (2026-01-26) allows Views to read server resources via
resources/readbut not subscribe to changes. For UIs that display live data — dashboards, monitors, collaborative editors, multiplayer games, streaming feeds — the only option today is polling viaresources/readon a timer. This is:resources/subscribe+notifications/resources/updatedbetween client and server, but the MCP Apps extension blocks Views from using itThe gap is already visible in the ecosystem. UI libraries building on MCP Apps have independently implemented subscription mechanisms with automatic polling fallbacks for hosts that don't support subscriptions. The native subscription path cannot be exercised because no host currently advertises subscription support — only the polling fallback runs in practice.
Proposed Changes
1. Add to Standard MCP Messages (View → Host)
Add to the allowed message list in "Standard MCP Messages":
resources/subscribe— Subscribe to updates for a resource URIresources/unsubscribe— Unsubscribe from a previously subscribed resource URI2. Add to Notifications (Host → View)
notifications/resources/updated— Host forwards this notification to the View when the server signals a subscribed resource has changedThe View would then typically call
resources/readto fetch the updated content — same pattern as the core MCP spec.3. Host Capabilities
Add
subscribe?: booleantoHostCapabilities.serverResources:Views MUST check
hostCapabilities.serverResources.subscribebefore sendingresources/subscribe. If absent or false, Views SHOULD fall back to polling viaresources/read.4. Subscription Limits
Add optional
maxSubscriptionsto host capabilities:Host MUST reject
resources/subscribewith a JSON-RPC error when the limit is reached:{ "jsonrpc": "2.0", "id": 5, "error": { "code": -32001, "message": "Subscription limit reached", "data": { "uri": "data://metrics/live", "maxSubscriptions": 10 } } }Note:
-32002is already used by the core MCP spec for "Resource not found." A new application-level error code should be defined for subscription limits.-32001is used here as a placeholder — the final code should be coordinated with the core spec maintainers.5. Lifecycle & Cleanup
Add to the existing Cleanup section:
6. Security Requirements
maxSubscriptions(default: 10 if unspecified)notifications/resources/updatedto the View (e.g., max 10/sec per URI) to prevent amplificationresources/listorresources/readfrom the same serverMessage Flow
sequenceDiagram participant V as View (iframe) participant H as Host participant S as MCP Server V->>H: resources/subscribe { uri: "data://metrics/live" } H->>S: resources/subscribe { uri: "data://metrics/live" } S-->>H: subscription confirmed H-->>V: subscription confirmed Note over S: Data changes S--)H: notifications/resources/updated { uri: "data://metrics/live" } H--)V: notifications/resources/updated { uri: "data://metrics/live" } V->>H: resources/read { uri: "data://metrics/live" } H->>S: resources/read { uri: "data://metrics/live" } S-->>H: updated contents H-->>V: updated contents Note over V: View teardown H->>S: resources/unsubscribe { uri: "data://metrics/live" }Graceful Degradation
Views that want real-time updates SHOULD implement a dual-path pattern:
Why Not Just Poll?
resources/readloop)Scope
This proposal does NOT introduce:
resources/subscribespecIt only allows Views to access an existing core MCP capability through the host proxy, with appropriate security controls.
Prior Art
resources/subscribe+notifications/resources/updatedfully specified for client↔serverHostCapabilities.serverResources.listChangedalready exists in the MCP Apps spec —subscribeis the natural companion field@maxhealth.tech/prefab(Max-Health-Inc/prefab): Working reference implementation of this proposal's dual-path pattern. The bridge (src/renderer/bridge.ts) sendsresources/subscribevia JSON-RPC when the host supports it, listens for bothnotifications/resources/updatedandui/notifications/resource-updated, and returns a cleanup function that sendsresources/unsubscribe. Host capability is detected fromhostCapabilities.resources.subscribeduring theui/initializehandshake. When no host advertises support, theSubscribeaction falls back toSetInterval+CallToolpolling automatically. The native subscription path exists and is fully wired but has never been exercised on a real host — only the polling fallback runs today.resources/subscribe/resources/unsubscribe(both listed as expected failures in the MCP conformance suite). A design proposal for per-server subscription tracking with deterministic cleanup is under review. Once shipped, servers will handle subscriptions — but Views still can't use them without this spec change. CC @jlowin @syhstanleySetInterval+CallToolpolling for live data, illustrating the gap even for the team building both the server framework and the UI framework.