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

Function makeCloudMcpAgentHandler

apps/cloud/src/mcp/agent-handler.ts:222–378  ·  view source on GitHub ↗
(options: CloudMcpAgentHandlerOptions)

Source from the content-addressed store, hash-verified

220
221/** Build the cloud worker's authenticated legacy/modern MCP request handler. */
222export const makeCloudMcpAgentHandler = (options: CloudMcpAgentHandlerOptions) => {
223 const authProvider = options.authProvider ?? cloudMcpAuth;
224 const traceRequest = options.traceRequest ?? ((request, _env, _ctx, handle) => handle(request));
225 const modern = makeMcpModernRequestRouter();
226 const ALLOWED_METHODS = new Set(["GET", "POST", "DELETE", "OPTIONS"]);
227
228 const handle = async (request: Request, env: Env, ctx: ExecutionContext): Promise<Response> => {
229 if (request.method === "OPTIONS") {
230 return mcpCorsPreflightResponse(request.headers.get("access-control-request-headers"));
231 }
232 // Preserve the old envelope's JSON-RPC 405 before authenticating, so
233 // unsupported methods never reach the session engine.
234 if (!ALLOWED_METHODS.has(request.method)) {
235 return jsonRpcResponse(405, -32001, "Method not allowed");
236 }
237 const sessionId = request.headers.get("mcp-session-id");
238
239 const { auth, outcome } = await runTraced(request, authenticate(request, authProvider));
240 if (!Predicate.isTagged(outcome, "Authenticated")) {
241 // Destroying a live session on auth grounds requires a POSITIVE
242 // determination that access is genuinely gone — only `Forbidden` carries
243 // that (valid bearer, org absent/revoked). `Unavailable` (transient WorkOS
244 // / JWKS failure) and `Unauthorized` (retry with a fresh token) must leave
245 // the session intact, so the condemn path is gated on `Forbidden` alone.
246 if (Predicate.isTagged(outcome, "Forbidden") && sessionId) {
247 const session = mcpSessionStub(env.MCP_SESSION, sessionId);
248 await Effect.runPromise(
249 Effect.ignore(
250 session ? Effect.tryPromise(() => session._cf_scheduleDestroy()) : Effect.void,
251 ),
252 );
253 }
254 return renderAuthError(auth, request, outcome);
255 }
256
257 const parsedBody = await Effect.runPromise(requestBodyFromRequest(request));
258 const era = await classifyMcpProtocolEra(request, parsedBody);
259 if (era === "modern") {
260 if (env.MCP_2026_07_28_ENABLED === "false") {
261 return mcpModernDisabledResponse();
262 }
263 const resource = resourceFromPath(request);
264 const props = await runTraced(
265 request,
266 propsForPrincipal(request, outcome.principal, resource),
267 );
268 (ctx as ExecutionContext & { props?: McpSessionProps }).props = props;
269 const forwarded = withVerifiedIdentityHeaders(
270 request,
271 {
272 accountId: outcome.principal.accountId,
273 organizationId: outcome.principal.organizationId,
274 },
275 resource,
276 );
277 return modern.fetch({
278 request: forwarded,
279 parsedBody,

Callers 2

server.tsFile · 0.90
makeHarnessFunction · 0.90

Calls 8

handleFunction · 0.70
isDeadSessionCachedFunction · 0.70
authenticateFunction · 0.70
deadSessionResponseFunction · 0.70
cachedDeadSessionMessageFunction · 0.70
renderAuthErrorFunction · 0.70
getMethod · 0.65

Tested by 1

makeHarnessFunction · 0.72