Skip to content

Commit d3eb5d0

Browse files
authored
Merge pull request #7 from MCPJam/fix/probe-init-storage
fix(probe): read initializeParams from DO storage, not transport
2 parents 61171d5 + e1a0ccf commit d3eb5d0

1 file changed

Lines changed: 38 additions & 27 deletions

File tree

src/index.ts

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,28 @@ import type { HostProbeSnapshot } from "./host-probe-types";
1515
const RESOURCE_URI = "ui://mcp-demo/mcp-app.html";
1616
const 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+
1840
export 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

Comments
 (0)