@@ -15,6 +15,28 @@ import type { HostProbeSnapshot } from "./host-probe-types";
1515const RESOURCE_URI = "ui://mcp-demo/mcp-app.html" ;
1616const RESOURCE_URI_PROBE = "ui://mcp-demo/host-probe.html" ;
1717
18+ type RawInitializeParams = {
19+ protocolVersion ?: unknown ;
20+ capabilities ?: unknown ;
21+ clientInfo ?: unknown ;
22+ } ;
23+
24+ async function getInitializeParamsFromStorage (
25+ agent : unknown ,
26+ ) : Promise < RawInitializeParams | undefined > {
27+ const a = agent as {
28+ getInitializeRequest ?: ( ) => Promise <
29+ { params ?: RawInitializeParams } | undefined
30+ > ;
31+ } ;
32+ try {
33+ const req = await a . getInitializeRequest ?.( ) ;
34+ return req ?. params ;
35+ } catch {
36+ return undefined ;
37+ }
38+ }
39+
1840export class MyMCP extends McpAgent {
1941 server = new McpServer ( {
2042 name : "MCP App Demo" ,
@@ -127,19 +149,14 @@ export class MyMCP extends McpAgent {
127149 _meta : { ui : { visibility : [ "app" ] } } ,
128150 } ,
129151 async ( snapshot ) => {
130- // Merge server-side MCP-level info that the View can't see.
131- // Read from the raw initializeParams on the transport — the SDK's
132- // ClientCapabilitiesSchema strips non-standard keys via Zod.
133- const transport = ( this as unknown as {
134- _transport ?: {
135- initializeParams ?: {
136- capabilities ?: unknown ;
137- clientInfo ?: unknown ;
138- protocolVersion ?: unknown ;
139- } ;
140- } ;
141- } ) . _transport ;
142- const raw = transport ?. initializeParams ;
152+ // Read from the persisted JSON-RPC initialize request stored by
153+ // McpAgent. The transport-level `initializeParams` is only set on
154+ // cold-start `handlePostRequest`; after a Durable Object eviction
155+ // it stays undefined, so the raw params survive only via storage.
156+ // The SDK's ClientCapabilitiesSchema is also strict z.object — it
157+ // strips non-standard keys (e.g. `extensions.*`) — so we cannot
158+ // rely on getClientCapabilities() for raw payloads.
159+ const raw = await getInitializeParamsFromStorage ( this ) ;
143160 const underlying = ( this . server as { server ?: unknown } ) . server as
144161 | {
145162 getClientVersion ?: ( ) => unknown ;
@@ -189,20 +206,14 @@ export class MyMCP extends McpAgent {
189206 _meta : { } ,
190207 } ,
191208 async ( ) => {
192- // Prefer the raw initializeParams captured by the WorkerTransport
193- // before Zod validation — the SDK's ClientCapabilitiesSchema is a
194- // strict z.object, so getClientCapabilities() silently drops any
195- // non-standard keys (e.g. `extensions.io.modelcontextprotocol/ui`).
196- const transport = ( this as unknown as {
197- _transport ?: {
198- initializeParams ?: {
199- capabilities ?: unknown ;
200- clientInfo ?: unknown ;
201- protocolVersion ?: unknown ;
202- } ;
203- } ;
204- } ) . _transport ;
205- const raw = transport ?. initializeParams ;
209+ // Read from the persisted JSON-RPC initialize request stored by
210+ // McpAgent. The transport-level `initializeParams` is only set on
211+ // cold-start `handlePostRequest`; after a Durable Object eviction
212+ // it stays undefined, so the raw params survive only via storage.
213+ // The SDK's ClientCapabilitiesSchema is also strict z.object — it
214+ // strips non-standard keys (e.g. `extensions.io.modelcontextprotocol/ui`)
215+ // — so we cannot rely on getClientCapabilities() for raw payloads.
216+ const raw = await getInitializeParamsFromStorage ( this ) ;
206217
207218 const underlying = ( this . server as { server ?: unknown } ) . server as
208219 | {
0 commit comments