MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / openSession

Function openSession

e2e/cloud/mcp-session-cap-eviction.test.ts:132–190  ·  view source on GitHub ↗
(
  mcpUrl: string,
  bearer: string,
  label: string,
  recordSession: (sessionId: string) => void,
)

Source from the content-addressed store, hash-verified

130 * orphaning a real session on the target isolate.
131 */
132const openSession = async (
133 mcpUrl: string,
134 bearer: string,
135 label: string,
136 recordSession: (sessionId: string) => void,
137): Promise<string> => {
138 // The platform can reset a session Durable Object while its initialize
139 // is in flight, and the server answers that with the documented restart
140 // envelope (503, -32001, "MCP session is restarting, please retry") — the
141 // same contract a streamable-http client follows: same request, after the
142 // advertised delay. Treat it as transient here instead of failing the
143 // scenario on a retryable platform blip.
144 const RESTART_ATTEMPTS = 8;
145 const RESTART_DELAY_MS = 2_000; // The host advertises Retry-After: 2.
146 let minted: { readonly response: Response; readonly sessionId: string } | undefined;
147 for (let attempt = 0; attempt < RESTART_ATTEMPTS; attempt += 1) {
148 const response = await postJson(mcpUrl, bearer, {
149 jsonrpc: "2.0" as const,
150 id: "initialize",
151 method: "initialize",
152 params: {
153 protocolVersion: PROTOCOL_VERSION,
154 capabilities: {},
155 clientInfo: { name: `executor-e2e-cap-eviction-${label}`, version: "0.0.1" },
156 },
157 });
158 const candidate = response.headers.get("mcp-session-id");
159 if (candidate !== null && candidate.length > 0) {
160 minted = { response, sessionId: candidate };
161 break;
162 }
163 const body = await response.text();
164 const isRestart = isRestartResponse(response.status, body);
165 if (!isRestart) break;
166 if (attempt === RESTART_ATTEMPTS - 1) break;
167 await new Promise((resolve) => setTimeout(resolve, RESTART_DELAY_MS));
168 }
169 if (!minted) {
170 // oxlint-disable-next-line executor/no-error-constructor -- boundary: e2e setup precondition.
171 throw new Error(`openSession (${label}): no mcp-session-id header`);
172 }
173 const { response: initialized, sessionId } = minted;
174 // Recorded the moment the id exists — BEFORE the body read and status
175 // assertion below, either of which can throw with the session already live
176 // on the server. The cleanup finalizer needs the id on every one of those
177 // paths, not just a fully successful return.
178 recordSession(sessionId);
179 await initialized.text();
180 expect(initialized.status, `initialize (${label}) opens a session`).toBe(200);
181 const notification = await postJson(
182 mcpUrl,
183 bearer,
184 { jsonrpc: "2.0" as const, method: "notifications/initialized" },
185 sessionId,
186 );
187 await notification.text();
188 expect(notification.status, `(${label}) completes the handshake`).toBe(202);
189 return sessionId;

Calls 4

isRestartResponseFunction · 0.85
postJsonFunction · 0.70
getMethod · 0.65
textMethod · 0.65

Tested by

no test coverage detected