History

Keep MCP-Apps rendering across a cold session restore

The negotiated MCP-Apps capability lived only in the tool server instance, set from the client at initialize. A session whose Durable Object was evicted (deploy, idle) and cold-restored on the same mcp-session-id was rebuilt with no initialize to replay, so apps support read back as false and create-artifact/show-artifact answered with the deep-link fallback instead of the inline widget, mid-conversation. Persist the negotiated bit in SessionMeta and seed the rebuilt server from it. A real initialize still overrules the restored value in both directions, and init carries the stored bit through its re-resolve so restoring a session no longer erases it.

Rhys Sullivan committed 3 months ago

Commit ed7bf081 parent a7c46896 files · +325 −4Browse files

Showing the changes to apps/cloud/src (1 of 6 files). Show all

Unified · Split

apps/cloud/src/mcp/session-durable-object.ts+4−0
@@ -280,6 +280,10 @@ export class McpSessionDOSqlite extends McpAgentSessionDOBase<Env, CloudSessionD · 279 unmodified lines
280 // flag existed carry no value; absent now means off, same as a fresh280 // flag existed carry no value; absent now means off, same as a fresh
281 // connection that did not ask for `?artifacts=true`.281 // connection that did not ask for `?artifacts=true`.
282 artifactsEnabled: sessionMeta.artifactsEnabled ?? false,282 artifactsEnabled: sessionMeta.artifactsEnabled ?? false,
283 // Cold restores rebuild this server with no `initialize` to replay, so
284 // the negotiated apps support comes back from storage instead.
285 restoredAppsEnabled: sessionMeta.appsEnabled ?? false,
286 onAppsEnabledChange: (appsEnabled) => self.persistAppsEnabled(appsEnabled),
283 loadAppShellHtml,287 loadAppShellHtml,
284 smokeRenderArtifact,288 smokeRenderArtifact,
285 artifactUrl: artifactUrlFor(289 artifactUrl: artifactUrlFor(