{"version":3,"file":"index.mjs","names":["#definition","#handler","#shutdownTimeoutMs","#stdioHandles","#fetchTasks","#buildTasks","#principals","#requestPipeline","#reportError","#observe","#assertOpen","#buildServer","#resolvePrincipal","McpServer","#serveHttp","#createRequestOperation","#closePromise","#closing","#performClose","#runtimes","#assertOpen","#closePromise","#closing","#performClose"],"sources":["../src/mcp-server.runtime.ts","../src/mcp-server.registry.ts"],"sourcesContent":["import { toNodeHandler } from \"@modelcontextprotocol/node\";\nimport {\n\tcomposeMcpMiddleware,\n\tcreateMcpLifecycleMiddleware,\n\tcreateMcpOperation,\n\tcreateMcpOperationContext,\n} from \"@nestm/mcp-core\";\nimport type { NodeMcpRequestHandler, ToNodeHandlerOptions } from \"@modelcontextprotocol/node\";\nimport { createMcpHandler, McpServer } from \"@modelcontextprotocol/server\";\nimport type {\n\tAuthInfo,\n\tMcpHandlerRequestOptions,\n\tMcpHttpHandler,\n\tMcpRequestContext,\n\tServerEventBus,\n\tServerNotifier,\n} from \"@modelcontextprotocol/server\";\nimport { serveStdio } from \"@modelcontextprotocol/server/stdio\";\nimport type { ServeStdioOptions, StdioServerHandle } from \"@modelcontextprotocol/server/stdio\";\nimport { McpServerRuntimeError } from \"./mcp-server.errors.ts\";\nimport {\n\tapplyMcpCorsHeaders,\n\tisMcpRequestSecured,\n\tlimitMcpRequestBody,\n\tmcpHttpSecurityRejection,\n\tresolveMcpHttpSecurity,\n} from \"./security/mcp-http-security.ts\";\nimport type { McpHttpSecurityPolicy } from \"./security/mcp-http-security.ts\";\nimport { withMcpNodeBodyLimit } from \"./security/mcp-node-body-limit.ts\";\nimport type {\n\tMcpServerBuildContext,\n\tMcpServerDefinition,\n\tMcpServerOperationInput,\n\tMcpServerOperationContext,\n\tMcpServerPrincipal,\n\tMcpServerPrincipalClaimsResolver,\n\tMcpServerRuntimeEvent,\n} from \"./mcp-server.types.ts\";\n\nconst DEFAULT_SHUTDOWN_TIMEOUT_MS = 30_000;\n\n/** Owns one named MCP server definition and every HTTP/stdio serving lifecycle. */\nexport class McpServerRuntime implements AsyncDisposable {\n\treadonly name: string;\n\treadonly notify: ServerNotifier;\n\treadonly bus: ServerEventBus;\n\t/** Resolved HTTP security posture applied ahead of every HTTP dispatch. */\n\treadonly httpSecurity: McpHttpSecurityPolicy;\n\n\treadonly #definition: McpServerDefinition;\n\treadonly #handler: McpHttpHandler;\n\treadonly #shutdownTimeoutMs: number;\n\treadonly #stdioHandles = new Set<StdioServerHandle>();\n\treadonly #fetchTasks = new Set<Promise<Response>>();\n\treadonly #buildTasks = new Set<Promise<McpServer>>();\n\treadonly #principals = new WeakMap<AuthInfo, Promise<McpServerPrincipal>>();\n\treadonly #requestPipeline: (\n\t\toperation: ReturnType<typeof createServerRequestOperation>,\n\t) => Promise<Response>;\n\t#closePromise: Promise<void> | undefined;\n\t#closing = false;\n\n\tconstructor(definition: McpServerDefinition) {\n\t\tassertDefinition(definition);\n\t\tthis.#definition = {\n\t\t\t...definition,\n\t\t\tfeatures: [...(definition.features ?? [])],\n\t\t};\n\t\tthis.#shutdownTimeoutMs = definition.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;\n\t\tthis.name = definition.name;\n\t\tthis.httpSecurity = resolveMcpHttpSecurity(definition.httpSecurity);\n\t\tthis.#handler = createMcpHandler((context) => this.createServer(context), {\n\t\t\t...definition.http,\n\t\t\tonerror: (error) => {\n\t\t\t\tthis.#reportError(error);\n\t\t\t\tthis.#observe({ phase: \"handler:error\", error });\n\t\t\t},\n\t\t});\n\t\tthis.notify = this.#handler.notify;\n\t\tthis.bus = this.#handler.bus;\n\t\tconst middleware = [...(definition.middleware ?? [])];\n\t\tif (definition.lifecycleObserver !== undefined) {\n\t\t\tmiddleware.unshift(\n\t\t\t\tcreateMcpLifecycleMiddleware<McpServerOperationInput, Response, McpServerOperationContext>(\n\t\t\t\t\tdefinition.lifecycleObserver,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tthis.#requestPipeline = composeMcpMiddleware(middleware, (operation) => {\n\t\t\tthis.#assertOpen();\n\t\t\treturn this.#handler.fetch(operation.input.request, operation.input.options);\n\t\t});\n\t}\n\n\t/** Build the same server factory used by HTTP and stdio serving. */\n\tcreateServer(context: McpRequestContext): Promise<McpServer> {\n\t\tthis.#assertOpen();\n\t\tconst task = this.#buildServer(context);\n\t\treturn trackTask(this.#buildTasks, task);\n\t}\n\n\tasync #buildServer(context: McpRequestContext): Promise<McpServer> {\n\t\tconst startedAt = performance.now();\n\t\tthis.#observe({ phase: \"build:start\", era: context.era });\n\t\tlet server: McpServer | undefined;\n\t\ttry {\n\t\t\tconst principal =\n\t\t\t\tcontext.authInfo === undefined ? undefined : await this.#resolvePrincipal(context.authInfo);\n\t\t\t// Principal projection may be asynchronous. Do not construct a new SDK\n\t\t\t// server after shutdown won that race.\n\t\t\tthis.#assertOpen();\n\t\t\tserver = new McpServer(this.#definition.serverInfo, this.#definition.serverOptions);\n\t\t\tconst buildContext: McpServerBuildContext = {\n\t\t\t\t...context,\n\t\t\t\truntimeName: this.name,\n\t\t\t\t...(principal === undefined ? {} : { principal }),\n\t\t\t};\n\t\t\tfor (const feature of this.#definition.features ?? []) {\n\t\t\t\tawait feature(server, buildContext);\n\t\t\t\t// A feature may await application work. Shutdown winning during that\n\t\t\t\t// await must roll the partially built SDK server back below.\n\t\t\t\tthis.#assertOpen();\n\t\t\t}\n\t\t\tthis.#assertOpen();\n\t\t\tthis.#observe({\n\t\t\t\tphase: \"build:success\",\n\t\t\t\tera: context.era,\n\t\t\t\tdurationMs: performance.now() - startedAt,\n\t\t\t});\n\t\t\t// Observers are isolated from protocol results, but they may synchronously\n\t\t\t// re-enter close(). Never hand a newly built SDK server out after that\n\t\t\t// ownership transition.\n\t\t\tthis.#assertOpen();\n\t\t\treturn server;\n\t\t} catch (cause) {\n\t\t\tlet error = toError(cause);\n\t\t\tif (server !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tawait server.close();\n\t\t\t\t} catch (closeError) {\n\t\t\t\t\terror = new AggregateError(\n\t\t\t\t\t\t[error, closeError],\n\t\t\t\t\t\t`MCP server runtime \"${this.name}\" failed to build and close its partial SDK server.`,\n\t\t\t\t\t\t{ cause: error },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.#reportError(error);\n\t\t\tthis.#observe({\n\t\t\t\tphase: \"build:error\",\n\t\t\t\tera: context.era,\n\t\t\t\tdurationMs: performance.now() - startedAt,\n\t\t\t\terror,\n\t\t\t});\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tfetch(request: Request, options?: McpHandlerRequestOptions): Promise<Response> {\n\t\tthis.#assertOpen();\n\t\tconst task = this.#serveHttp(request, options);\n\t\treturn trackTask(this.#fetchTasks, task);\n\t}\n\n\tasync #serveHttp(request: Request, options?: McpHandlerRequestOptions): Promise<Response> {\n\t\t// An outer hardened facade (controller seam, hardenMcpFetch) already\n\t\t// gated this request under its own policy; defer to it entirely.\n\t\tif (isMcpRequestSecured(request)) {\n\t\t\tconst operation = await this.#createRequestOperation(request, options);\n\t\t\treturn this.#requestPipeline(operation);\n\t\t}\n\t\t// Security gating runs outside definition middleware and lifecycle\n\t\t// observation: a rejected request never reaches application composition.\n\t\tconst rejection = mcpHttpSecurityRejection(request, this.httpSecurity);\n\t\tif (rejection !== undefined) {\n\t\t\tif (rejection.status >= 400) {\n\t\t\t\tthis.#observe({ phase: \"request:rejected\", status: rejection.status });\n\t\t\t}\n\t\t\treturn rejection;\n\t\t}\n\t\tconst limited = await limitMcpRequestBody(request, this.httpSecurity);\n\t\tif (limited instanceof Response) {\n\t\t\tthis.#observe({ phase: \"request:rejected\", status: limited.status });\n\t\t\treturn applyMcpCorsHeaders(request, limited, this.httpSecurity);\n\t\t}\n\t\tconst operation = await this.#createRequestOperation(limited, options);\n\t\tconst response = await this.#requestPipeline(operation);\n\t\treturn applyMcpCorsHeaders(request, response, this.httpSecurity);\n\t}\n\n\ttoNodeHandler(options?: ToNodeHandlerOptions): NodeMcpRequestHandler {\n\t\tthis.#assertOpen();\n\t\t// Adapt the runtime fetch face, not the raw SDK handler. This preserves\n\t\t// operation middleware, authorization, and lifecycle observation for\n\t\t// Express, Fastify, and plain Node hosts as well as web-standard hosts.\n\t\t// The Node-level body cap runs before the SDK converts the request,\n\t\t// where an unbounded stream would otherwise be buffered in full.\n\t\treturn withMcpNodeBodyLimit(\n\t\t\ttoNodeHandler(\n\t\t\t\t{\n\t\t\t\t\tfetch: (request, requestOptions) => this.fetch(request, requestOptions),\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t),\n\t\t\tthis.httpSecurity,\n\t\t\t{ onRejected: (status) => this.reportRequestRejected(status) },\n\t\t);\n\t}\n\n\t/**\n\t * Reports a pre-dispatch security rejection detected by an outer hardened\n\t * layer (a Nest controller seam, a hand-composed facade) so it still surfaces\n\t * as a `request:rejected` runtime observer event.\n\t */\n\treportRequestRejected(status: number): void {\n\t\tif (status >= 400) this.#observe({ phase: \"request:rejected\", status });\n\t}\n\n\t/** Start a stdio connection backed by this runtime's feature factory. */\n\tserveStdio(options?: Omit<ServeStdioOptions, \"onerror\">): StdioServerHandle {\n\t\tthis.#assertOpen();\n\t\tconst sdkHandle = serveStdio((context) => this.createServer(context), {\n\t\t\t...options,\n\t\t\tonerror: (error) => {\n\t\t\t\tthis.#reportError(error);\n\t\t\t\tthis.#observe({ phase: \"handler:error\", error });\n\t\t\t},\n\t\t});\n\t\tlet closePromise: Promise<void> | undefined;\n\t\tlet managedHandle: StdioServerHandle;\n\t\tmanagedHandle = Object.freeze({\n\t\t\tclose: () => {\n\t\t\t\tclosePromise ??= Promise.resolve()\n\t\t\t\t\t.then(() => sdkHandle.close())\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tthis.#stdioHandles.delete(managedHandle);\n\t\t\t\t\t});\n\t\t\t\treturn closePromise;\n\t\t\t},\n\t\t});\n\t\tthis.#stdioHandles.add(managedHandle);\n\t\treturn managedHandle;\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (this.#closePromise !== undefined) return this.#closePromise;\n\t\t// Publish the closing state and promise before observers, middleware, or\n\t\t// child handles can re-enter close().\n\t\tthis.#closing = true;\n\t\tthis.#closePromise = Promise.resolve().then(() => this.#performClose());\n\t\treturn this.#closePromise;\n\t}\n\n\tasync [Symbol.asyncDispose](): Promise<void> {\n\t\tawait this.close();\n\t}\n\n\tasync #performClose(): Promise<void> {\n\t\tconst startedAt = performance.now();\n\t\tthis.#observe({ phase: \"close:start\" });\n\t\tconst servingTasks = [\n\t\t\t...[...this.#stdioHandles].map(async (handle) => handle.close()),\n\t\t\tthis.#handler.close(),\n\t\t];\n\t\tconst acceptedTasks = [...this.#fetchTasks, ...this.#buildTasks];\n\t\tconst shutdownResult = await settleShutdownWithin(\n\t\t\tservingTasks,\n\t\t\tacceptedTasks,\n\t\t\tthis.#shutdownTimeoutMs,\n\t\t);\n\t\tconst failures = shutdownResult.servingSettled\n\t\t\t.filter((result): result is PromiseRejectedResult => result.status === \"rejected\")\n\t\t\t.map((result) => result.reason as unknown);\n\t\tif (shutdownResult.timeoutError !== undefined) failures.push(shutdownResult.timeoutError);\n\t\tif (failures.length === 0) {\n\t\t\tthis.#observe({\n\t\t\t\tphase: \"close:success\",\n\t\t\t\tdurationMs: performance.now() - startedAt,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst error = new AggregateError(\n\t\t\tfailures,\n\t\t\t`MCP server runtime \"${this.name}\" failed to shut down cleanly.`,\n\t\t);\n\t\tthis.#reportError(error);\n\t\tthis.#observe({\n\t\t\tphase: \"close:error\",\n\t\t\tdurationMs: performance.now() - startedAt,\n\t\t\terror,\n\t\t});\n\t\tthrow error;\n\t}\n\n\tasync #createRequestOperation(request: Request, options?: McpHandlerRequestOptions) {\n\t\tconst principal =\n\t\t\toptions?.authInfo === undefined ? undefined : await this.#resolvePrincipal(options.authInfo);\n\t\t// A slow claims resolver must not revive request dispatch after close().\n\t\tthis.#assertOpen();\n\t\treturn createServerRequestOperation(this.name, request, options, principal);\n\t}\n\n\t#resolvePrincipal(authInfo: AuthInfo): Promise<McpServerPrincipal> {\n\t\tconst existing = this.#principals.get(authInfo);\n\t\tif (existing !== undefined) return existing;\n\t\tconst pending = resolveMcpServerPrincipal(authInfo, this.#definition.principalClaims);\n\t\tthis.#principals.set(authInfo, pending);\n\t\tvoid pending.catch(() => this.#principals.delete(authInfo));\n\t\treturn pending;\n\t}\n\n\t#assertOpen(): void {\n\t\tif (this.#closing) {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"RUNTIME_CLOSED\",\n\t\t\t\t`MCP server runtime \"${this.name}\" is closed.`,\n\t\t\t);\n\t\t}\n\t}\n\n\t#reportError(error: Error): void {\n\t\ttry {\n\t\t\tconst result = this.#definition.onError?.(error);\n\t\t\tvoid Promise.resolve(result).catch(() => undefined);\n\t\t} catch {\n\t\t\t// Reporting must never change protocol behavior.\n\t\t}\n\t}\n\n\t#observe(event: Omit<McpServerRuntimeEvent, \"runtimeName\" | \"timestamp\">): void {\n\t\ttry {\n\t\t\tconst result = this.#definition.observer?.({\n\t\t\t\t...event,\n\t\t\t\truntimeName: this.name,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\t\t\tvoid Promise.resolve(result).catch(() => undefined);\n\t\t} catch {\n\t\t\t// Observability is deliberately isolated from the request path.\n\t\t}\n\t}\n}\n\nfunction assertDefinition(definition: McpServerDefinition): void {\n\tif (typeof definition !== \"object\" || definition === null) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"MCP server definition must be an object.\",\n\t\t);\n\t}\n\tif (typeof definition.name !== \"string\" || definition.name.trim().length === 0) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"MCP server name must be a non-empty string.\",\n\t\t);\n\t}\n\tif (typeof definition.serverInfo !== \"object\" || definition.serverInfo === null) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"MCP wire-level server info must be an object.\",\n\t\t);\n\t}\n\tif (\n\t\ttypeof definition.serverInfo.name !== \"string\" ||\n\t\tdefinition.serverInfo.name.trim().length === 0\n\t) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"MCP wire-level server name must be a non-empty string.\",\n\t\t);\n\t}\n\tif (\n\t\ttypeof definition.serverInfo.version !== \"string\" ||\n\t\tdefinition.serverInfo.version.trim().length === 0\n\t) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"MCP wire-level server version must be a non-empty string.\",\n\t\t);\n\t}\n\tif (\n\t\tdefinition.shutdownTimeoutMs !== undefined &&\n\t\t(!Number.isFinite(definition.shutdownTimeoutMs) || definition.shutdownTimeoutMs <= 0)\n\t) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"MCP server shutdownTimeoutMs must be a positive finite number.\",\n\t\t);\n\t}\n}\n\nfunction trackTask<Value>(tasks: Set<Promise<Value>>, task: Promise<Value>): Promise<Value> {\n\ttasks.add(task);\n\tvoid task.then(\n\t\t() => {\n\t\t\ttasks.delete(task);\n\t\t},\n\t\t() => {\n\t\t\ttasks.delete(task);\n\t\t},\n\t);\n\treturn task;\n}\n\nasync function settleShutdownWithin(\n\tservingTasks: readonly Promise<unknown>[],\n\tacceptedTasks: readonly Promise<unknown>[],\n\ttimeoutMs: number,\n): Promise<{\n\treadonly servingSettled: readonly PromiseSettledResult<unknown>[];\n\treadonly timeoutError?: Error;\n}> {\n\tconst observedServing: PromiseSettledResult<unknown>[] = [];\n\tconst servingSettled = Promise.all(\n\t\tservingTasks.map(async (task) => {\n\t\t\ttry {\n\t\t\t\tconst value = await task;\n\t\t\t\tconst result = { status: \"fulfilled\", value } as const;\n\t\t\t\tobservedServing.push(result);\n\t\t\t\treturn result;\n\t\t\t} catch (reason) {\n\t\t\t\tconst result = { status: \"rejected\", reason } as const;\n\t\t\t\tobservedServing.push(result);\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}),\n\t);\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tconst expired = new Promise<\"timeout\">((resolve) => {\n\t\ttimeout = setTimeout(resolve, timeoutMs, \"timeout\");\n\t});\n\ttry {\n\t\tconst result = await Promise.race([\n\t\t\tPromise.all([servingSettled, Promise.allSettled(acceptedTasks)]).then(([settled]) => ({\n\t\t\t\tkind: \"settled\" as const,\n\t\t\t\tservingSettled: settled,\n\t\t\t})),\n\t\t\texpired,\n\t\t]);\n\t\tif (result === \"timeout\") {\n\t\t\treturn {\n\t\t\t\tservingSettled: observedServing,\n\t\t\t\ttimeoutError: new Error(`MCP server shutdown timed out after ${String(timeoutMs)}ms.`),\n\t\t\t};\n\t\t}\n\t\treturn { servingSettled: result.servingSettled };\n\t} finally {\n\t\tif (timeout !== undefined) clearTimeout(timeout);\n\t}\n}\n\nfunction toError(value: unknown): Error {\n\treturn value instanceof Error ? value : new Error(String(value));\n}\n\nfunction createServerRequestOperation(\n\truntimeName: string,\n\trequest: Request,\n\toptions?: McpHandlerRequestOptions,\n\tprincipal?: McpServerPrincipal,\n) {\n\tconst requestId = request.headers.get(\"x-request-id\") ?? undefined;\n\tconst sessionId = request.headers.get(\"mcp-session-id\") ?? undefined;\n\tconst context = createMcpOperationContext({\n\t\toperationId: requestId ?? crypto.randomUUID(),\n\t\trole: \"server\",\n\t\toperation: {\n\t\t\tname: \"mcp.http\",\n\t\t\tkind: \"request\",\n\t\t\ttarget: runtimeName,\n\t\t\tattributes: { \"http.method\": request.method },\n\t\t},\n\t\tsignal: request.signal,\n\t\t...(requestId === undefined ? {} : { requestId }),\n\t\t...(sessionId === undefined ? {} : { sessionId }),\n\t\t...(principal === undefined ? {} : { principal }),\n\t});\n\treturn createMcpOperation(\n\t\t{\n\t\t\trequest,\n\t\t\t...(options === undefined ? {} : { options }),\n\t\t},\n\t\tcontext,\n\t);\n}\n\n/** Projects verified auth data onto the deliberately narrow token-free principal contract. */\nexport async function resolveMcpServerPrincipal(\n\tauthInfo: AuthInfo,\n\tresolveClaims?: McpServerPrincipalClaimsResolver,\n): Promise<McpServerPrincipal> {\n\tconst claims = resolveClaims === undefined ? undefined : await resolveClaims(authInfo);\n\tassertPrincipalClaims(claims);\n\treturn Object.freeze({\n\t\tclientId: authInfo.clientId,\n\t\tscopes: Object.freeze([...authInfo.scopes]),\n\t\t...(authInfo.expiresAt === undefined ? {} : { expiresAt: authInfo.expiresAt }),\n\t\t...(authInfo.resource === undefined ? {} : { resource: authInfo.resource.href }),\n\t\t...(claims?.subject === undefined ? {} : { subject: claims.subject }),\n\t\t...(claims?.tenantId === undefined ? {} : { tenantId: claims.tenantId }),\n\t});\n}\n\nfunction assertPrincipalClaims(\n\tvalue: unknown,\n): asserts value is { readonly subject?: string; readonly tenantId?: string } | undefined {\n\tif (value === undefined) return;\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"principalClaims must resolve to a claims object.\",\n\t\t);\n\t}\n\tfor (const key of [\"subject\", \"tenantId\"] as const) {\n\t\tconst claim = Reflect.get(value, key);\n\t\tif (claim !== undefined && (typeof claim !== \"string\" || claim.trim().length === 0)) {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\t`principalClaims.${key} must be a non-empty string when present.`,\n\t\t\t);\n\t\t}\n\t}\n}\n","import { McpServerRuntimeError } from \"./mcp-server.errors.ts\";\nimport { McpServerRuntime } from \"./mcp-server.runtime.ts\";\nimport type { McpServerDefinition } from \"./mcp-server.types.ts\";\n\n/** Mutable registry of named server runtimes with deterministic reverse-order shutdown. */\nexport class McpServerRegistry implements AsyncDisposable {\n\treadonly #runtimes = new Map<string, McpServerRuntime>();\n\t#closePromise: Promise<void> | undefined;\n\t#closing = false;\n\n\tconstructor(definitions: readonly McpServerDefinition[] = []) {\n\t\tfor (const definition of definitions) this.register(definition);\n\t}\n\n\tregister(definition: McpServerDefinition): McpServerRuntime {\n\t\tthis.#assertOpen();\n\t\tif (this.#runtimes.has(definition.name)) {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"DUPLICATE_SERVER\",\n\t\t\t\t`An MCP server named \"${definition.name}\" is already registered.`,\n\t\t\t);\n\t\t}\n\t\tconst runtime = new McpServerRuntime(definition);\n\t\tthis.#runtimes.set(runtime.name, runtime);\n\t\treturn runtime;\n\t}\n\n\tregisterRuntime(runtime: McpServerRuntime): McpServerRuntime {\n\t\tthis.#assertOpen();\n\t\tif (this.#runtimes.has(runtime.name)) {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"DUPLICATE_SERVER\",\n\t\t\t\t`An MCP server named \"${runtime.name}\" is already registered.`,\n\t\t\t);\n\t\t}\n\t\tthis.#runtimes.set(runtime.name, runtime);\n\t\treturn runtime;\n\t}\n\n\thas(name: string): boolean {\n\t\treturn this.#runtimes.has(name);\n\t}\n\n\tget(name: string): McpServerRuntime {\n\t\tconst runtime = this.#runtimes.get(name);\n\t\tif (runtime === undefined) {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"UNKNOWN_SERVER\",\n\t\t\t\t`No MCP server named \"${name}\" is registered.`,\n\t\t\t);\n\t\t}\n\t\treturn runtime;\n\t}\n\n\tlist(): readonly McpServerRuntime[] {\n\t\treturn [...this.#runtimes.values()];\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (this.#closePromise !== undefined) return this.#closePromise;\n\t\tthis.#closing = true;\n\t\tthis.#closePromise = Promise.resolve().then(() => this.#performClose());\n\t\treturn this.#closePromise;\n\t}\n\n\tasync [Symbol.asyncDispose](): Promise<void> {\n\t\tawait this.close();\n\t}\n\n\tasync #performClose(): Promise<void> {\n\t\tconst runtimes = [...this.#runtimes.values()].toReversed();\n\t\tthis.#runtimes.clear();\n\t\tconst settled = await Promise.allSettled(runtimes.map((runtime) => runtime.close()));\n\t\tconst errors = settled.flatMap((result) =>\n\t\t\tresult.status === \"rejected\" ? [result.reason] : [],\n\t\t);\n\t\tif (errors.length > 0) {\n\t\t\tthrow new AggregateError(errors, \"One or more MCP server runtimes failed to close.\");\n\t\t}\n\t}\n\n\t#assertOpen(): void {\n\t\tif (this.#closing) {\n\t\t\tthrow new McpServerRuntimeError(\"RUNTIME_CLOSED\", \"The MCP server registry is closed.\");\n\t\t}\n\t}\n}\n"],"mappings":"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"}