| 133 | ): LocalMcpRequestHandlerConfig => ("defaultConfig" in input ? input : { defaultConfig: input }); |
| 134 | |
| 135 | export const createMcpRequestHandler = ( |
| 136 | input: ExecutorMcpToolConfig | LocalMcpRequestHandlerConfig, |
| 137 | ): McpRequestHandler => { |
| 138 | const handlerConfig = normalizeHandlerConfig(input); |
| 139 | const transports = new Map<string, WebStandardStreamableHTTPServerTransport>(); |
| 140 | const servers = new Map<string, McpServer>(); |
| 141 | const resources = new Map<string, McpResource>(); |
| 142 | const sessionEngines = new Map<string, AnyExecutionEngine>(); |
| 143 | const sessionClosers = new Map<string, () => Promise<void>>(); |
| 144 | const modernHandlers = new Map<string, McpHttpHandler>(); |
| 145 | const modernRequestBodies = new WeakMap<Request, unknown>(); |
| 146 | const approvals = makeInProcessBrowserApprovalStore(); |
| 147 | const defaultEngine = engineFromConfig(handlerConfig.defaultConfig); |
| 148 | let requestStateSigningKey: Uint8Array | undefined; |
| 149 | |
| 150 | const signingKey = (): Uint8Array => |
| 151 | (requestStateSigningKey ??= crypto.getRandomValues(new Uint8Array(32))); |
| 152 | |
| 153 | const pausedDetail = ( |
| 154 | sessionId: string, |
| 155 | executionId: string, |
| 156 | ): Promise<ReturnType<typeof formatPausedExecution> | null> => |
| 157 | (sessionEngines.get(sessionId) ?? defaultEngine) |
| 158 | ? Effect.runPromise( |
| 159 | (sessionEngines.get(sessionId) ?? defaultEngine)!.getPausedExecution(executionId).pipe( |
| 160 | Effect.map((paused) => (paused ? formatPausedExecution(paused) : null)), |
| 161 | Effect.orElseSucceed(() => null), |
| 162 | ), |
| 163 | ) |
| 164 | : Promise.resolve(null); |
| 165 | |
| 166 | const configForResource = async (resource: McpResource): Promise<LocalMcpServerConfig> => { |
| 167 | if (!handlerConfig.createConfigForResource) return { config: handlerConfig.defaultConfig }; |
| 168 | return handlerConfig.createConfigForResource(resource); |
| 169 | }; |
| 170 | |
| 171 | const dispose = async (id: string, opts: { transport?: boolean; server?: boolean } = {}) => { |
| 172 | const t = transports.get(id); |
| 173 | const s = servers.get(id); |
| 174 | const close = sessionClosers.get(id); |
| 175 | transports.delete(id); |
| 176 | servers.delete(id); |
| 177 | resources.delete(id); |
| 178 | sessionEngines.delete(id); |
| 179 | sessionClosers.delete(id); |
| 180 | if (opts.transport) await ignoreClose(t ? () => t.close() : undefined); |
| 181 | if (opts.server) await ignoreClose(s ? () => s.close() : undefined); |
| 182 | await ignoreClose(close); |
| 183 | }; |
| 184 | |
| 185 | const modernHandlerFor = (resource: McpResource): McpHttpHandler => { |
| 186 | const key = mcpResourceKey(resource); |
| 187 | const cached = modernHandlers.get(key); |
| 188 | if (cached) return cached; |
| 189 | |
| 190 | const handler = createMcpHandler( |
| 191 | (context) => { |
| 192 | const request = context.requestInfo; |