( mcpUrl: string, bearer: string, label: string, recordSession: (sessionId: string) => void, )
| 68 | * orphaning a real session on the target isolate. |
| 69 | */ |
| 70 | const openSession = async ( |
| 71 | mcpUrl: string, |
| 72 | bearer: string, |
| 73 | label: string, |
| 74 | recordSession: (sessionId: string) => void, |
| 75 | ): Promise<string> => { |
| 76 | const initialized = await postJson(mcpUrl, bearer, { |
| 77 | jsonrpc: "2.0" as const, |
| 78 | id: "initialize", |
| 79 | method: "initialize", |
| 80 | params: { |
| 81 | protocolVersion: PROTOCOL_VERSION, |
| 82 | capabilities: {}, |
| 83 | clientInfo: { name: `executor-e2e-cap-eviction-${label}`, version: "0.0.1" }, |
| 84 | }, |
| 85 | }); |
| 86 | const sessionId = initialized.headers.get("mcp-session-id"); |
| 87 | if (!sessionId) { |
| 88 | // oxlint-disable-next-line executor/no-error-constructor -- boundary: e2e setup precondition. |
| 89 | throw new Error(`openSession (${label}): no mcp-session-id header`); |
| 90 | } |
| 91 | // Recorded the moment the id exists — BEFORE the body read and status |
| 92 | // assertion below, either of which can throw with the session already live |
| 93 | // on the server. The cleanup finalizer needs the id on every one of those |
| 94 | // paths, not just a fully successful return. |
| 95 | recordSession(sessionId); |
| 96 | await initialized.text(); |
| 97 | expect(initialized.status, `initialize (${label}) opens a session`).toBe(200); |
| 98 | const notification = await postJson( |
| 99 | mcpUrl, |
| 100 | bearer, |
| 101 | { jsonrpc: "2.0" as const, method: "notifications/initialized" }, |
| 102 | sessionId, |
| 103 | ); |
| 104 | await notification.text(); |
| 105 | expect(notification.status, `(${label}) completes the handshake`).toBe(202); |
| 106 | return sessionId; |
| 107 | }; |
| 108 | |
| 109 | const executeBody = (id: string, code: string) => ({ |
| 110 | jsonrpc: "2.0" as const, |
no test coverage detected