@modelcontextprotocol/server 2.0.0-alpha.3 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/dist/{ajvProvider-Birb50r-.mjs → ajvProvider-BQMcjynJ.mjs} +952 -154
- package/dist/ajvProvider-BQMcjynJ.mjs.map +1 -0
- package/dist/{ajvProvider-DZ_siXcF.d.mts → ajvProvider-Dzgk80kq.d.mts} +58 -11
- package/dist/ajvProvider-Dzgk80kq.d.mts.map +1 -0
- package/dist/{cfWorkerProvider-BrJKpSFH.mjs → cfWorkerProvider-BDC2rVl3.mjs} +21 -5
- package/dist/cfWorkerProvider-BDC2rVl3.mjs.map +1 -0
- package/dist/{cfWorkerProvider-DUhk5Ewx.d.mts → cfWorkerProvider-DmvjVsvQ.d.mts} +13 -6
- package/dist/cfWorkerProvider-DmvjVsvQ.d.mts.map +1 -0
- package/dist/{transport-DMKhEchd.d.mts → createMcpHandler-Du3hjXvf.d.mts} +5283 -1559
- package/dist/createMcpHandler-Du3hjXvf.d.mts.map +1 -0
- package/dist/index.d.mts +167 -2015
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1238 -1281
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-JttQJlI9.mjs +9998 -0
- package/dist/mcp-JttQJlI9.mjs.map +1 -0
- package/dist/shimsNode.d.mts +1 -1
- package/dist/shimsNode.mjs +1 -1
- package/dist/shimsWorkerd.d.mts +1 -1
- package/dist/shimsWorkerd.mjs +1 -1
- package/dist/stdio.d.mts +61 -3
- package/dist/stdio.d.mts.map +1 -1
- package/dist/stdio.mjs +457 -2
- package/dist/stdio.mjs.map +1 -1
- package/dist/types-DBYdVs-n.d.mts +1099 -0
- package/dist/types-DBYdVs-n.d.mts.map +1 -0
- package/dist/validators/ajv.d.mts +1 -1
- package/dist/validators/ajv.mjs +1 -1
- package/dist/validators/cfWorker.d.mts +1 -1
- package/dist/validators/cfWorker.mjs +1 -1
- package/package.json +3 -6
- package/dist/ajvProvider-Birb50r-.mjs.map +0 -1
- package/dist/ajvProvider-DZ_siXcF.d.mts.map +0 -1
- package/dist/cfWorkerProvider-BrJKpSFH.mjs.map +0 -1
- package/dist/cfWorkerProvider-DUhk5Ewx.d.mts.map +0 -1
- package/dist/src-Pa1iAvsj.mjs +0 -3386
- package/dist/src-Pa1iAvsj.mjs.map +0 -1
- package/dist/transport-DMKhEchd.d.mts.map +0 -1
- package/dist/types-R2RTIcjk.d.mts +0 -66
- package/dist/types-R2RTIcjk.d.mts.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["COMPLETABLE_SYMBOL: unique symbol","_serverInfo: Implementation","transportSessionId: string | undefined","formParams: ElicitRequestFormParams","toolDefinition: Tool","templateResources: Resource[]","registeredResource: RegisteredResource","registeredResourceTemplate: RegisteredResourceTemplate","registeredPrompt: RegisteredPrompt","registeredTool: RegisteredTool","_callbacks: {\n /**\n * A callback to list all resources matching this template. This is required to be specified, even if `undefined`, to avoid accidentally forgetting resource listing.\n */\n list: ListResourcesCallback | undefined;\n\n /**\n * An optional callback to autocomplete variables within the URI template. Useful for clients and users to discover possible values.\n */\n complete?: {\n [variable: string]: CompleteResourceTemplateCallback;\n };\n }","callback","EMPTY_COMPLETION_RESULT: CompleteResult","hostname: string","error: { code: number; message: string; data?: string }","streamController: ReadableStreamDefaultController<Uint8Array>","headers: Record<string, string>","streamId: string | undefined","messages: JSONRPCMessage[]","closeSSEStream: (() => void) | undefined","closeStandaloneSSEStream: (() => void) | undefined","eventId: string | undefined","_defaultValidator: jsonSchemaValidator | undefined","coreFromJsonSchema"],"sources":["../src/server/completable.ts","../src/server/server.ts","../src/server/mcp.ts","../src/server/middleware/hostHeaderValidation.ts","../src/server/streamableHttp.ts","../src/fromJsonSchema.ts"],"sourcesContent":["import type { StandardSchemaV1 } from '@modelcontextprotocol/core-internal';\n\nexport const COMPLETABLE_SYMBOL: unique symbol = Symbol.for('mcp.completable');\n\nexport type CompleteCallback<T extends StandardSchemaV1 = StandardSchemaV1> = (\n value: StandardSchemaV1.InferInput<T>,\n context?: {\n arguments?: Record<string, string>;\n }\n) => StandardSchemaV1.InferInput<T>[] | Promise<StandardSchemaV1.InferInput<T>[]>;\n\nexport type CompletableMeta<T extends StandardSchemaV1 = StandardSchemaV1> = {\n complete: CompleteCallback<T>;\n};\n\nexport type CompletableSchema<T extends StandardSchemaV1> = T & {\n [COMPLETABLE_SYMBOL]: CompletableMeta<T>;\n};\n\n/**\n * Wraps a schema to provide autocompletion capabilities. Useful for, e.g., prompt arguments in MCP.\n *\n * @example\n * ```ts source=\"./completable.examples.ts#completable_basicUsage\"\n * server.registerPrompt(\n * 'review-code',\n * {\n * title: 'Code Review',\n * argsSchema: z.object({\n * language: completable(z.string().describe('Programming language'), value =>\n * ['typescript', 'javascript', 'python', 'rust', 'go'].filter(lang => lang.startsWith(value))\n * )\n * })\n * },\n * ({ language }) => ({\n * messages: [\n * {\n * role: 'user' as const,\n * content: {\n * type: 'text' as const,\n * text: `Review this ${language} code.`\n * }\n * }\n * ]\n * })\n * );\n * ```\n *\n * @see {@linkcode server/mcp.McpServer.registerPrompt | McpServer.registerPrompt} for using completable schemas in prompt argument definitions\n */\nexport function completable<T extends StandardSchemaV1>(schema: T, complete: CompleteCallback<T>): CompletableSchema<T> {\n Object.defineProperty(schema as object, COMPLETABLE_SYMBOL, {\n value: { complete } as CompletableMeta<T>,\n enumerable: false,\n writable: false,\n configurable: false\n });\n return schema as CompletableSchema<T>;\n}\n\n/**\n * Checks if a schema is completable (has completion metadata).\n */\nexport function isCompletable(schema: unknown): schema is CompletableSchema<StandardSchemaV1> {\n return !!schema && typeof schema === 'object' && COMPLETABLE_SYMBOL in (schema as object);\n}\n\n/**\n * Gets the completer callback from a completable schema, if it exists.\n */\nexport function getCompleter<T extends StandardSchemaV1>(schema: T): CompleteCallback<T> | undefined {\n const meta = (schema as unknown as { [COMPLETABLE_SYMBOL]?: CompletableMeta<T> })[COMPLETABLE_SYMBOL];\n return meta?.complete as CompleteCallback<T> | undefined;\n}\n","import type {\n BaseContext,\n ClientCapabilities,\n CreateMessageRequest,\n CreateMessageRequestParamsBase,\n CreateMessageRequestParamsWithTools,\n CreateMessageResult,\n CreateMessageResultWithTools,\n ElicitRequestFormParams,\n ElicitRequestURLParams,\n ElicitResult,\n Implementation,\n InitializeRequest,\n InitializeResult,\n JSONRPCRequest,\n JsonSchemaType,\n jsonSchemaValidator,\n ListRootsRequest,\n LoggingLevel,\n LoggingMessageNotification,\n MessageExtraInfo,\n NotificationMethod,\n NotificationOptions,\n ProtocolOptions,\n RequestMethod,\n RequestOptions,\n ResourceUpdatedNotification,\n Result,\n ServerCapabilities,\n ServerContext,\n ToolResultContent,\n ToolUseContent\n} from '@modelcontextprotocol/core-internal';\nimport {\n CallToolRequestSchema,\n CallToolResultSchema,\n CreateMessageResultSchema,\n CreateMessageResultWithToolsSchema,\n ElicitResultSchema,\n EmptyResultSchema,\n LATEST_PROTOCOL_VERSION,\n ListRootsResultSchema,\n LoggingLevelSchema,\n mergeCapabilities,\n parseSchema,\n Protocol,\n ProtocolError,\n ProtocolErrorCode,\n SdkError,\n SdkErrorCode\n} from '@modelcontextprotocol/core-internal';\nimport { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims';\n\nexport type ServerOptions = ProtocolOptions & {\n /**\n * Capabilities to advertise as being supported by this server.\n *\n * Note: per the MCP spec, a server that declares a capability MUST respond to that\n * capability's requests (e.g. `tools/list` for `tools`) — potentially with an empty\n * result — rather than with a \"Method not found\" error. {@linkcode server/mcp.McpServer | McpServer}\n * handles this automatically for capabilities declared here; when using the low-level\n * {@linkcode Server} directly, you are responsible for registering a request handler for\n * every capability you declare.\n */\n capabilities?: ServerCapabilities;\n\n /**\n * Optional instructions describing how to use the server and its features.\n */\n instructions?: string;\n\n /**\n * JSON Schema validator for elicitation response validation.\n *\n * The validator is used to validate user input returned from elicitation\n * requests against the requested schema.\n *\n * @default Runtime-selected validator (AJV-backed on Node.js, `@cfworker/json-schema`-backed on browser/workerd runtimes)\n */\n jsonSchemaValidator?: jsonSchemaValidator;\n};\n\n/**\n * An MCP server on top of a pluggable transport.\n *\n * This server will automatically respond to the initialization flow as initiated from the client.\n *\n * @deprecated Use {@linkcode server/mcp.McpServer | McpServer} instead for the high-level API. Only use `Server` for advanced use cases.\n */\nexport class Server extends Protocol<ServerContext> {\n private _clientCapabilities?: ClientCapabilities;\n private _clientVersion?: Implementation;\n private _negotiatedProtocolVersion?: string;\n private _capabilities: ServerCapabilities;\n private _instructions?: string;\n private _jsonSchemaValidator: jsonSchemaValidator;\n\n /**\n * Callback for when initialization has fully completed (i.e., the client has sent an `notifications/initialized` notification).\n */\n oninitialized?: () => void;\n\n /**\n * Initializes this server with the given name and version information.\n */\n constructor(\n private _serverInfo: Implementation,\n options?: ServerOptions\n ) {\n super(options);\n this._capabilities = options?.capabilities ? { ...options.capabilities } : {};\n this._instructions = options?.instructions;\n this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new DefaultJsonSchemaValidator();\n\n this.setRequestHandler('initialize', request => this._oninitialize(request));\n this.setNotificationHandler('notifications/initialized', () => this.oninitialized?.());\n\n if (this._capabilities.logging) {\n this._registerLoggingHandler();\n }\n }\n\n /**\n * Registers the built-in `logging/setLevel` request handler.\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to stderr logging (STDIO servers) or OpenTelemetry.\n */\n private _registerLoggingHandler(): void {\n this.setRequestHandler('logging/setLevel', async (request, ctx) => {\n const transportSessionId: string | undefined =\n ctx.sessionId || (ctx.http?.req?.headers.get('mcp-session-id') as string) || undefined;\n const { level } = request.params;\n const parseResult = parseSchema(LoggingLevelSchema, level);\n if (parseResult.success) {\n this._loggingLevels.set(transportSessionId, parseResult.data);\n }\n return {};\n });\n }\n\n protected override buildContext(ctx: BaseContext, transportInfo?: MessageExtraInfo): ServerContext {\n // Only create http when there's actual HTTP transport info or auth info\n const hasHttpInfo = ctx.http || transportInfo?.request || transportInfo?.closeSSEStream || transportInfo?.closeStandaloneSSEStream;\n return {\n ...ctx,\n mcpReq: {\n ...ctx.mcpReq,\n // Deprecated as of protocol version 2026-07-28 (SEP-2577): `log` and\n // `requestSampling` remain functional during the deprecation window\n // (at least twelve months). See ServerContext for migration guidance.\n log: (level, data, logger) => this.sendLoggingMessage({ level, data, logger }),\n elicitInput: (params, options) => this.elicitInput(params, options),\n requestSampling: (params, options) => this.createMessage(params, options)\n },\n http: hasHttpInfo\n ? {\n ...ctx.http,\n req: transportInfo?.request,\n closeSSE: transportInfo?.closeSSEStream,\n closeStandaloneSSE: transportInfo?.closeStandaloneSSEStream\n }\n : undefined\n };\n }\n\n // Map log levels by session id\n private _loggingLevels = new Map<string | undefined, LoggingLevel>();\n\n // Map LogLevelSchema to severity index\n private readonly LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));\n\n // Is a message with the given level ignored in the log level set for the given session id?\n private isMessageIgnored = (level: LoggingLevel, sessionId?: string): boolean => {\n const currentLevel = this._loggingLevels.get(sessionId);\n return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level)! < this.LOG_LEVEL_SEVERITY.get(currentLevel)! : false;\n };\n\n /**\n * Registers new capabilities. This can only be called before connecting to a transport.\n *\n * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).\n */\n public registerCapabilities(capabilities: ServerCapabilities): void {\n if (this.transport) {\n throw new SdkError(SdkErrorCode.AlreadyConnected, 'Cannot register capabilities after connecting to transport');\n }\n const hadLogging = !!this._capabilities.logging;\n this._capabilities = mergeCapabilities(this._capabilities, capabilities);\n if (!hadLogging && this._capabilities.logging) {\n this._registerLoggingHandler();\n }\n }\n\n /**\n * Enforces server-side validation for `tools/call` results regardless of how the\n * handler was registered.\n */\n protected override _wrapHandler(\n method: string,\n handler: (request: JSONRPCRequest, ctx: ServerContext) => Promise<Result>\n ): (request: JSONRPCRequest, ctx: ServerContext) => Promise<Result> {\n if (method !== 'tools/call') {\n return handler;\n }\n return async (request, ctx) => {\n const validatedRequest = parseSchema(CallToolRequestSchema, request);\n if (!validatedRequest.success) {\n const errorMessage =\n validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`);\n }\n\n const result = await handler(request, ctx);\n\n const validationResult = parseSchema(CallToolResultSchema, result);\n if (!validationResult.success) {\n const errorMessage =\n validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage}`);\n }\n\n return validationResult.data;\n };\n }\n\n protected assertCapabilityForMethod(method: RequestMethod | string): void {\n switch (method) {\n case 'sampling/createMessage': {\n if (!this._clientCapabilities?.sampling) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Client does not support sampling (required for ${method})`);\n }\n break;\n }\n\n case 'elicitation/create': {\n if (!this._clientCapabilities?.elicitation) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Client does not support elicitation (required for ${method})`);\n }\n break;\n }\n\n case 'roots/list': {\n if (!this._clientCapabilities?.roots) {\n throw new SdkError(\n SdkErrorCode.CapabilityNotSupported,\n `Client does not support listing roots (required for ${method})`\n );\n }\n break;\n }\n\n case 'ping': {\n // No specific capability required for ping\n break;\n }\n }\n }\n\n protected assertNotificationCapability(method: NotificationMethod | string): void {\n switch (method) {\n case 'notifications/message': {\n if (!this._capabilities.logging) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`);\n }\n break;\n }\n\n case 'notifications/resources/updated':\n case 'notifications/resources/list_changed': {\n if (!this._capabilities.resources) {\n throw new SdkError(\n SdkErrorCode.CapabilityNotSupported,\n `Server does not support notifying about resources (required for ${method})`\n );\n }\n break;\n }\n\n case 'notifications/tools/list_changed': {\n if (!this._capabilities.tools) {\n throw new SdkError(\n SdkErrorCode.CapabilityNotSupported,\n `Server does not support notifying of tool list changes (required for ${method})`\n );\n }\n break;\n }\n\n case 'notifications/prompts/list_changed': {\n if (!this._capabilities.prompts) {\n throw new SdkError(\n SdkErrorCode.CapabilityNotSupported,\n `Server does not support notifying of prompt list changes (required for ${method})`\n );\n }\n break;\n }\n\n case 'notifications/elicitation/complete': {\n if (!this._clientCapabilities?.elicitation?.url) {\n throw new SdkError(\n SdkErrorCode.CapabilityNotSupported,\n `Client does not support URL elicitation (required for ${method})`\n );\n }\n break;\n }\n\n case 'notifications/cancelled': {\n // Cancellation notifications are always allowed\n break;\n }\n\n case 'notifications/progress': {\n // Progress notifications are always allowed\n break;\n }\n }\n }\n\n protected assertRequestHandlerCapability(method: string): void {\n switch (method) {\n case 'completion/complete': {\n if (!this._capabilities.completions) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support completions (required for ${method})`);\n }\n break;\n }\n\n case 'logging/setLevel': {\n if (!this._capabilities.logging) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`);\n }\n break;\n }\n\n case 'prompts/get':\n case 'prompts/list': {\n if (!this._capabilities.prompts) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support prompts (required for ${method})`);\n }\n break;\n }\n\n case 'resources/list':\n case 'resources/templates/list':\n case 'resources/read': {\n if (!this._capabilities.resources) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support resources (required for ${method})`);\n }\n break;\n }\n\n case 'tools/call':\n case 'tools/list': {\n if (!this._capabilities.tools) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support tools (required for ${method})`);\n }\n break;\n }\n\n case 'ping':\n case 'initialize': {\n // No specific capability required for these methods\n break;\n }\n }\n }\n\n private async _oninitialize(request: InitializeRequest): Promise<InitializeResult> {\n const requestedVersion = request.params.protocolVersion;\n\n this._clientCapabilities = request.params.capabilities;\n this._clientVersion = request.params.clientInfo;\n\n const protocolVersion = this._supportedProtocolVersions.includes(requestedVersion)\n ? requestedVersion\n : (this._supportedProtocolVersions[0] ?? LATEST_PROTOCOL_VERSION);\n\n this._negotiatedProtocolVersion = protocolVersion;\n this.transport?.setProtocolVersion?.(protocolVersion);\n\n return {\n protocolVersion,\n capabilities: this.getCapabilities(),\n serverInfo: this._serverInfo,\n ...(this._instructions && { instructions: this._instructions })\n };\n }\n\n /**\n * After initialization has completed, this will be populated with the client's reported capabilities.\n */\n getClientCapabilities(): ClientCapabilities | undefined {\n return this._clientCapabilities;\n }\n\n /**\n * After initialization has completed, this will be populated with information about the client's name and version.\n */\n getClientVersion(): Implementation | undefined {\n return this._clientVersion;\n }\n\n /**\n * After initialization has completed, this will be populated with the protocol version negotiated\n * with the client (the version the server responded with during the initialize handshake), or\n * `undefined` before initialization.\n */\n getNegotiatedProtocolVersion(): string | undefined {\n return this._negotiatedProtocolVersion;\n }\n\n /**\n * Returns the current server capabilities.\n */\n public getCapabilities(): ServerCapabilities {\n return this._capabilities;\n }\n\n async ping() {\n return this._requestWithSchema({ method: 'ping' }, EmptyResultSchema);\n }\n\n /**\n * Request LLM sampling from the client (without tools).\n * Returns single content block for backwards compatibility.\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to calling LLM provider APIs directly.\n */\n async createMessage(params: CreateMessageRequestParamsBase, options?: RequestOptions): Promise<CreateMessageResult>;\n\n /**\n * Request LLM sampling from the client with tool support.\n * Returns content that may be a single block or array (for parallel tool calls).\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to calling LLM provider APIs directly.\n */\n async createMessage(params: CreateMessageRequestParamsWithTools, options?: RequestOptions): Promise<CreateMessageResultWithTools>;\n\n /**\n * Request LLM sampling from the client.\n * When tools may or may not be present, returns the union type.\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to calling LLM provider APIs directly.\n */\n async createMessage(\n params: CreateMessageRequest['params'],\n options?: RequestOptions\n ): Promise<CreateMessageResult | CreateMessageResultWithTools>;\n\n // Implementation\n async createMessage(\n params: CreateMessageRequest['params'],\n options?: RequestOptions\n ): Promise<CreateMessageResult | CreateMessageResultWithTools> {\n // Capability check - only required when tools/toolChoice are provided\n if ((params.tools || params.toolChoice) && !this._clientCapabilities?.sampling?.tools) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, 'Client does not support sampling tools capability.');\n }\n\n // Message structure validation - always validate tool_use/tool_result pairs.\n // These may appear even without tools/toolChoice in the current request when\n // a previous sampling request returned tool_use and this is a follow-up with results.\n if (params.messages.length > 0) {\n const lastMessage = params.messages.at(-1)!;\n const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];\n const hasToolResults = lastContent.some(c => c.type === 'tool_result');\n\n const previousMessage = params.messages.length > 1 ? params.messages.at(-2) : undefined;\n const previousContent = previousMessage\n ? Array.isArray(previousMessage.content)\n ? previousMessage.content\n : [previousMessage.content]\n : [];\n const hasPreviousToolUse = previousContent.some(c => c.type === 'tool_use');\n\n if (hasToolResults) {\n if (lastContent.some(c => c.type !== 'tool_result')) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n 'The last message must contain only tool_result content if any is present'\n );\n }\n if (!hasPreviousToolUse) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n 'tool_result blocks are not matching any tool_use from the previous message'\n );\n }\n }\n if (hasPreviousToolUse) {\n const toolUseIds = new Set(previousContent.filter(c => c.type === 'tool_use').map(c => (c as ToolUseContent).id));\n const toolResultIds = new Set(\n lastContent.filter(c => c.type === 'tool_result').map(c => (c as ToolResultContent).toolUseId)\n );\n if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every(id => toolResultIds.has(id))) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n 'ids of tool_result blocks and tool_use blocks from previous message do not match'\n );\n }\n }\n }\n\n // Use different schemas based on whether tools are provided\n if (params.tools) {\n return this._requestWithSchema({ method: 'sampling/createMessage', params }, CreateMessageResultWithToolsSchema, options);\n }\n return this._requestWithSchema({ method: 'sampling/createMessage', params }, CreateMessageResultSchema, options);\n }\n\n /**\n * Creates an elicitation request for the given parameters.\n * For backwards compatibility, `mode` may be omitted for form requests and will default to `\"form\"`.\n * @param params The parameters for the elicitation request.\n * @param options Optional request options.\n * @returns The result of the elicitation request.\n */\n async elicitInput(params: ElicitRequestFormParams | ElicitRequestURLParams, options?: RequestOptions): Promise<ElicitResult> {\n const mode = (params.mode ?? 'form') as 'form' | 'url';\n\n switch (mode) {\n case 'url': {\n if (!this._clientCapabilities?.elicitation?.url) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, 'Client does not support url elicitation.');\n }\n\n const urlParams = params as ElicitRequestURLParams;\n return this._requestWithSchema({ method: 'elicitation/create', params: urlParams }, ElicitResultSchema, options);\n }\n case 'form': {\n if (!this._clientCapabilities?.elicitation?.form) {\n throw new SdkError(SdkErrorCode.CapabilityNotSupported, 'Client does not support form elicitation.');\n }\n\n const formParams: ElicitRequestFormParams =\n params.mode === 'form' ? (params as ElicitRequestFormParams) : { ...(params as ElicitRequestFormParams), mode: 'form' };\n\n const result = await this._requestWithSchema(\n { method: 'elicitation/create', params: formParams },\n ElicitResultSchema,\n options\n );\n\n if (result.action === 'accept' && result.content && formParams.requestedSchema) {\n try {\n const validator = this._jsonSchemaValidator.getValidator(formParams.requestedSchema as JsonSchemaType);\n const validationResult = validator(result.content);\n\n if (!validationResult.valid) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n `Elicitation response content does not match requested schema: ${validationResult.errorMessage}`\n );\n }\n } catch (error) {\n if (error instanceof ProtocolError) {\n throw error;\n }\n throw new ProtocolError(\n ProtocolErrorCode.InternalError,\n `Error validating elicitation response: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n return result;\n }\n }\n }\n\n /**\n * Creates a reusable callback that, when invoked, will send a `notifications/elicitation/complete`\n * notification for the specified elicitation ID.\n *\n * @param elicitationId The ID of the elicitation to mark as complete.\n * @param options Optional notification options. Useful when the completion notification should be related to a prior request.\n * @returns A function that emits the completion notification when awaited.\n */\n createElicitationCompletionNotifier(elicitationId: string, options?: NotificationOptions): () => Promise<void> {\n if (!this._clientCapabilities?.elicitation?.url) {\n throw new SdkError(\n SdkErrorCode.CapabilityNotSupported,\n 'Client does not support URL elicitation (required for notifications/elicitation/complete)'\n );\n }\n\n return () =>\n this.notification(\n {\n method: 'notifications/elicitation/complete',\n params: {\n elicitationId\n }\n },\n options\n );\n }\n\n /**\n * Requests the list of roots from the client.\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to passing paths via tool parameters, resource URIs, or configuration.\n */\n async listRoots(params?: ListRootsRequest['params'], options?: RequestOptions) {\n return this._requestWithSchema({ method: 'roots/list', params }, ListRootsResultSchema, options);\n }\n\n /**\n * Sends a logging message to the client, if connected.\n * Note: You only need to send the parameters object, not the entire JSON-RPC message.\n * @see {@linkcode LoggingMessageNotification}\n * @param params\n * @param sessionId Optional for stateless transports and backward compatibility.\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to stderr logging (STDIO servers) or OpenTelemetry.\n */\n async sendLoggingMessage(params: LoggingMessageNotification['params'], sessionId?: string) {\n if (this._capabilities.logging && !this.isMessageIgnored(params.level, sessionId)) {\n return this.notification({ method: 'notifications/message', params });\n }\n }\n\n async sendResourceUpdated(params: ResourceUpdatedNotification['params']) {\n return this.notification({\n method: 'notifications/resources/updated',\n params\n });\n }\n\n async sendResourceListChanged() {\n return this.notification({\n method: 'notifications/resources/list_changed'\n });\n }\n\n async sendToolListChanged() {\n return this.notification({ method: 'notifications/tools/list_changed' });\n }\n\n async sendPromptListChanged() {\n return this.notification({ method: 'notifications/prompts/list_changed' });\n }\n}\n","import type {\n BaseMetadata,\n CallToolResult,\n CompleteRequestPrompt,\n CompleteRequestResourceTemplate,\n CompleteResult,\n GetPromptResult,\n Icon,\n Implementation,\n ListPromptsResult,\n ListResourcesResult,\n ListToolsResult,\n LoggingMessageNotification,\n Prompt,\n PromptReference,\n ReadResourceResult,\n Resource,\n ResourceTemplateReference,\n Result,\n ServerContext,\n StandardSchemaWithJSON,\n Tool,\n ToolAnnotations,\n ToolExecution,\n Transport,\n Variables\n} from '@modelcontextprotocol/core-internal';\nimport {\n assertCompleteRequestPrompt,\n assertCompleteRequestResourceTemplate,\n normalizeRawShapeSchema,\n promptArgumentsFromStandardSchema,\n ProtocolError,\n ProtocolErrorCode,\n standardSchemaToJsonSchema,\n UriTemplate,\n validateAndWarnToolName,\n validateStandardSchema\n} from '@modelcontextprotocol/core-internal';\nimport type * as z from 'zod/v4';\n\nimport { getCompleter, isCompletable } from './completable';\nimport type { ServerOptions } from './server';\nimport { Server } from './server';\n\n/**\n * High-level MCP server that provides a simpler API for working with resources, tools, and prompts.\n * For advanced usage (like sending notifications or setting custom request handlers), use the underlying\n * {@linkcode Server} instance available via the {@linkcode McpServer.server | server} property.\n *\n * @example\n * ```ts source=\"./mcp.examples.ts#McpServer_basicUsage\"\n * const server = new McpServer({\n * name: 'my-server',\n * version: '1.0.0'\n * });\n * ```\n */\nexport class McpServer {\n /**\n * The underlying {@linkcode Server} instance, useful for advanced operations like sending notifications.\n */\n public readonly server: Server;\n\n private _registeredResources: { [uri: string]: RegisteredResource } = {};\n private _registeredResourceTemplates: {\n [name: string]: RegisteredResourceTemplate;\n } = {};\n private _registeredTools: { [name: string]: RegisteredTool } = {};\n private _registeredPrompts: { [name: string]: RegisteredPrompt } = {};\n\n constructor(serverInfo: Implementation, options?: ServerOptions) {\n this.server = new Server(serverInfo, options);\n\n // Per the MCP spec, a server that declares a primitive capability MUST respond to its\n // list method (potentially with an empty result) rather than \"Method not found\" — even\n // if nothing has been registered yet. Handlers are normally installed lazily on first\n // registration, so eagerly install them here for any capability declared up front.\n // (Users of the low-level `Server` class remain responsible for their own handlers.)\n if (options?.capabilities?.tools) {\n this.setToolRequestHandlers();\n }\n if (options?.capabilities?.resources) {\n this.setResourceRequestHandlers();\n }\n if (options?.capabilities?.prompts) {\n this.setPromptRequestHandlers();\n }\n }\n\n /**\n * Attaches to the given transport, starts it, and starts listening for messages.\n *\n * The `server` object assumes ownership of the {@linkcode Transport}, replacing any callbacks that have already been set, and expects that it is the only user of the {@linkcode Transport} instance going forward.\n *\n * @example\n * ```ts source=\"./mcp.examples.ts#McpServer_connect_stdio\"\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n * const transport = new StdioServerTransport();\n * await server.connect(transport);\n * ```\n */\n async connect(transport: Transport): Promise<void> {\n return await this.server.connect(transport);\n }\n\n /**\n * Closes the connection.\n */\n async close(): Promise<void> {\n await this.server.close();\n }\n\n private _toolHandlersInitialized = false;\n\n private setToolRequestHandlers() {\n if (this._toolHandlersInitialized) {\n return;\n }\n\n this.server.assertCanSetRequestHandler('tools/list');\n this.server.assertCanSetRequestHandler('tools/call');\n\n this.server.registerCapabilities({\n tools: {\n listChanged: this.server.getCapabilities().tools?.listChanged ?? true\n }\n });\n\n // Note: tools are listed in registration (insertion) order, which keeps the ordering\n // deterministic across requests when the underlying tool set has not changed, as\n // recommended by the spec.\n this.server.setRequestHandler(\n 'tools/list',\n (): ListToolsResult => ({\n tools: Object.entries(this._registeredTools)\n .filter(([, tool]) => tool.enabled)\n .map(([name, tool]): Tool => {\n const toolDefinition: Tool = {\n name,\n title: tool.title,\n description: tool.description,\n inputSchema: tool.inputSchema\n ? (standardSchemaToJsonSchema(tool.inputSchema, 'input') as Tool['inputSchema'])\n : EMPTY_OBJECT_JSON_SCHEMA,\n annotations: tool.annotations,\n icons: tool.icons,\n execution: tool.execution,\n _meta: tool._meta\n };\n\n if (tool.outputSchema) {\n toolDefinition.outputSchema = standardSchemaToJsonSchema(tool.outputSchema, 'output') as Tool['outputSchema'];\n }\n\n return toolDefinition;\n })\n })\n );\n\n this.server.setRequestHandler('tools/call', async (request, ctx): Promise<CallToolResult> => {\n const tool = this._registeredTools[request.params.name];\n if (!tool) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Tool ${request.params.name} not found`);\n }\n if (!tool.enabled) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Tool ${request.params.name} disabled`);\n }\n\n try {\n const args = await this.validateToolInput(tool, request.params.arguments, request.params.name);\n const result = await this.executeToolHandler(tool, args, ctx);\n await this.validateToolOutput(tool, result, request.params.name);\n return result;\n } catch (error) {\n if (error instanceof ProtocolError && error.code === ProtocolErrorCode.UrlElicitationRequired) {\n throw error; // Return the error to the caller without wrapping in CallToolResult\n }\n return this.createToolError(error instanceof Error ? error.message : String(error));\n }\n });\n\n this._toolHandlersInitialized = true;\n }\n\n /**\n * Creates a tool error result.\n *\n * @param errorMessage - The error message.\n * @returns The tool error result.\n */\n private createToolError(errorMessage: string): CallToolResult {\n return {\n content: [\n {\n type: 'text',\n text: errorMessage\n }\n ],\n isError: true\n };\n }\n\n /**\n * Validates tool input arguments against the tool's input schema.\n */\n private async validateToolInput<\n ToolType extends RegisteredTool,\n Args extends ToolType['inputSchema'] extends infer InputSchema\n ? InputSchema extends StandardSchemaWithJSON\n ? StandardSchemaWithJSON.InferOutput<InputSchema>\n : undefined\n : undefined\n >(tool: ToolType, args: Args, toolName: string): Promise<Args> {\n if (!tool.inputSchema) {\n return undefined as Args;\n }\n\n const parseResult = await validateStandardSchema(tool.inputSchema, args ?? {});\n if (!parseResult.success) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n `Input validation error: Invalid arguments for tool ${toolName}: ${parseResult.error}`\n );\n }\n\n return parseResult.data as unknown as Args;\n }\n\n /**\n * Validates tool output against the tool's output schema.\n */\n private async validateToolOutput(tool: RegisteredTool, result: CallToolResult, toolName: string): Promise<void> {\n if (!tool.outputSchema) {\n return;\n }\n\n if (result.isError) {\n return;\n }\n\n if (!result.structuredContent) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n `Output validation error: Tool ${toolName} has an output schema but no structured content was provided`\n );\n }\n\n // if the tool has an output schema, validate structured content\n const parseResult = await validateStandardSchema(tool.outputSchema, result.structuredContent);\n if (!parseResult.success) {\n throw new ProtocolError(\n ProtocolErrorCode.InvalidParams,\n `Output validation error: Invalid structured content for tool ${toolName}: ${parseResult.error}`\n );\n }\n }\n\n /**\n * Executes a tool handler.\n */\n private async executeToolHandler(tool: RegisteredTool, args: unknown, ctx: ServerContext): Promise<CallToolResult> {\n // Executor encapsulates handler invocation with proper types\n return tool.executor(args, ctx);\n }\n\n private _completionHandlerInitialized = false;\n\n private setCompletionRequestHandler() {\n if (this._completionHandlerInitialized) {\n return;\n }\n\n this.server.assertCanSetRequestHandler('completion/complete');\n\n this.server.registerCapabilities({\n completions: {}\n });\n\n this.server.setRequestHandler('completion/complete', async (request): Promise<CompleteResult> => {\n switch (request.params.ref.type) {\n case 'ref/prompt': {\n assertCompleteRequestPrompt(request);\n return this.handlePromptCompletion(request, request.params.ref);\n }\n\n case 'ref/resource': {\n assertCompleteRequestResourceTemplate(request);\n return this.handleResourceCompletion(request, request.params.ref);\n }\n\n default: {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid completion reference: ${request.params.ref}`);\n }\n }\n });\n\n this._completionHandlerInitialized = true;\n }\n\n private async handlePromptCompletion(request: CompleteRequestPrompt, ref: PromptReference): Promise<CompleteResult> {\n const prompt = this._registeredPrompts[ref.name];\n if (!prompt) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${ref.name} not found`);\n }\n\n if (!prompt.enabled) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${ref.name} disabled`);\n }\n\n if (!prompt.argsSchema) {\n return EMPTY_COMPLETION_RESULT;\n }\n\n const promptShape = getSchemaShape(prompt.argsSchema);\n const field = unwrapOptionalSchema(promptShape?.[request.params.argument.name]);\n if (!isCompletable(field)) {\n return EMPTY_COMPLETION_RESULT;\n }\n\n const completer = getCompleter(field);\n if (!completer) {\n return EMPTY_COMPLETION_RESULT;\n }\n\n const suggestions = await completer(request.params.argument.value, request.params.context);\n return createCompletionResult(suggestions);\n }\n\n private async handleResourceCompletion(\n request: CompleteRequestResourceTemplate,\n ref: ResourceTemplateReference\n ): Promise<CompleteResult> {\n const template = Object.values(this._registeredResourceTemplates).find(t => t.resourceTemplate.uriTemplate.toString() === ref.uri);\n\n if (!template) {\n if (this._registeredResources[ref.uri]) {\n // Attempting to autocomplete a fixed resource URI is not an error in the spec (but probably should be).\n return EMPTY_COMPLETION_RESULT;\n }\n\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource template ${request.params.ref.uri} not found`);\n }\n\n const completer = template.resourceTemplate.completeCallback(request.params.argument.name);\n if (!completer) {\n return EMPTY_COMPLETION_RESULT;\n }\n\n const suggestions = await completer(request.params.argument.value, request.params.context);\n return createCompletionResult(suggestions);\n }\n\n private _resourceHandlersInitialized = false;\n\n private setResourceRequestHandlers() {\n if (this._resourceHandlersInitialized) {\n return;\n }\n\n this.server.assertCanSetRequestHandler('resources/list');\n this.server.assertCanSetRequestHandler('resources/templates/list');\n this.server.assertCanSetRequestHandler('resources/read');\n\n this.server.registerCapabilities({\n resources: {\n listChanged: this.server.getCapabilities().resources?.listChanged ?? true\n }\n });\n\n this.server.setRequestHandler('resources/list', async (_request, ctx) => {\n const resources = Object.entries(this._registeredResources)\n .filter(([_, resource]) => resource.enabled)\n .map(([uri, resource]) => ({\n uri,\n name: resource.name,\n ...resource.metadata\n }));\n\n const templateResources: Resource[] = [];\n for (const template of Object.values(this._registeredResourceTemplates)) {\n if (!template.resourceTemplate.listCallback) {\n continue;\n }\n\n const result = await template.resourceTemplate.listCallback(ctx);\n for (const resource of result.resources) {\n templateResources.push({\n ...template.metadata,\n // the defined resource metadata should override the template metadata if present\n ...resource\n });\n }\n }\n\n return { resources: [...resources, ...templateResources] };\n });\n\n this.server.setRequestHandler('resources/templates/list', async () => {\n const resourceTemplates = Object.entries(this._registeredResourceTemplates).map(([name, template]) => ({\n name,\n uriTemplate: template.resourceTemplate.uriTemplate.toString(),\n ...template.metadata\n }));\n\n return { resourceTemplates };\n });\n\n this.server.setRequestHandler('resources/read', async (request, ctx) => {\n const uri = new URL(request.params.uri);\n\n // First check for exact resource match\n const resource = this._registeredResources[uri.toString()];\n if (resource) {\n if (!resource.enabled) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource ${uri} disabled`);\n }\n return resource.readCallback(uri, ctx);\n }\n\n // Then check templates\n for (const template of Object.values(this._registeredResourceTemplates)) {\n const variables = template.resourceTemplate.uriTemplate.match(uri.toString());\n if (variables) {\n return template.readCallback(uri, variables, ctx);\n }\n }\n\n throw new ProtocolError(ProtocolErrorCode.ResourceNotFound, `Resource ${uri} not found`);\n });\n\n this._resourceHandlersInitialized = true;\n }\n\n private _promptHandlersInitialized = false;\n\n private setPromptRequestHandlers() {\n if (this._promptHandlersInitialized) {\n return;\n }\n\n this.server.assertCanSetRequestHandler('prompts/list');\n this.server.assertCanSetRequestHandler('prompts/get');\n\n this.server.registerCapabilities({\n prompts: {\n listChanged: this.server.getCapabilities().prompts?.listChanged ?? true\n }\n });\n\n this.server.setRequestHandler(\n 'prompts/list',\n (): ListPromptsResult => ({\n prompts: Object.entries(this._registeredPrompts)\n .filter(([, prompt]) => prompt.enabled)\n .map(([name, prompt]): Prompt => {\n return {\n name,\n title: prompt.title,\n description: prompt.description,\n arguments: prompt.argsSchema ? promptArgumentsFromStandardSchema(prompt.argsSchema) : undefined,\n icons: prompt.icons,\n _meta: prompt._meta\n };\n })\n })\n );\n\n this.server.setRequestHandler('prompts/get', async (request, ctx): Promise<GetPromptResult> => {\n const prompt = this._registeredPrompts[request.params.name];\n if (!prompt) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${request.params.name} not found`);\n }\n\n if (!prompt.enabled) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${request.params.name} disabled`);\n }\n\n // Handler encapsulates parsing and callback invocation with proper types\n return prompt.handler(request.params.arguments, ctx);\n });\n\n this._promptHandlersInitialized = true;\n }\n\n /**\n * Registers a resource with a config object and callback.\n * For static resources, use a URI string. For dynamic resources, use a {@linkcode ResourceTemplate}.\n *\n * @example\n * ```ts source=\"./mcp.examples.ts#McpServer_registerResource_static\"\n * server.registerResource(\n * 'config',\n * 'config://app',\n * {\n * title: 'Application Config',\n * mimeType: 'text/plain'\n * },\n * async uri => ({\n * contents: [{ uri: uri.href, text: 'App configuration here' }]\n * })\n * );\n * ```\n */\n registerResource(name: string, uriOrTemplate: string, config: ResourceMetadata, readCallback: ReadResourceCallback): RegisteredResource;\n registerResource(\n name: string,\n uriOrTemplate: ResourceTemplate,\n config: ResourceMetadata,\n readCallback: ReadResourceTemplateCallback\n ): RegisteredResourceTemplate;\n registerResource(\n name: string,\n uriOrTemplate: string | ResourceTemplate,\n config: ResourceMetadata,\n readCallback: ReadResourceCallback | ReadResourceTemplateCallback\n ): RegisteredResource | RegisteredResourceTemplate {\n if (typeof uriOrTemplate === 'string') {\n if (this._registeredResources[uriOrTemplate]) {\n throw new Error(`Resource ${uriOrTemplate} is already registered`);\n }\n\n const registeredResource = this._createRegisteredResource(\n name,\n (config as BaseMetadata).title,\n uriOrTemplate,\n config,\n readCallback as ReadResourceCallback\n );\n\n this.setResourceRequestHandlers();\n this.sendResourceListChanged();\n return registeredResource;\n } else {\n if (this._registeredResourceTemplates[name]) {\n throw new Error(`Resource template ${name} is already registered`);\n }\n\n const registeredResourceTemplate = this._createRegisteredResourceTemplate(\n name,\n (config as BaseMetadata).title,\n uriOrTemplate,\n config,\n readCallback as ReadResourceTemplateCallback\n );\n\n this.setResourceRequestHandlers();\n this.sendResourceListChanged();\n return registeredResourceTemplate;\n }\n }\n\n private _createRegisteredResource(\n name: string,\n title: string | undefined,\n uri: string,\n metadata: ResourceMetadata | undefined,\n readCallback: ReadResourceCallback\n ): RegisteredResource {\n const registeredResource: RegisteredResource = {\n name,\n title,\n metadata,\n readCallback,\n enabled: true,\n disable: () => registeredResource.update({ enabled: false }),\n enable: () => registeredResource.update({ enabled: true }),\n remove: () => registeredResource.update({ uri: null }),\n update: updates => {\n if (updates.uri !== undefined && updates.uri !== uri) {\n delete this._registeredResources[uri];\n if (updates.uri) this._registeredResources[updates.uri] = registeredResource;\n }\n if (updates.name !== undefined) registeredResource.name = updates.name;\n if (updates.title !== undefined) registeredResource.title = updates.title;\n if (updates.metadata !== undefined) registeredResource.metadata = updates.metadata;\n if (updates.callback !== undefined) registeredResource.readCallback = updates.callback;\n if (updates.enabled !== undefined) registeredResource.enabled = updates.enabled;\n this.sendResourceListChanged();\n }\n };\n this._registeredResources[uri] = registeredResource;\n return registeredResource;\n }\n\n private _createRegisteredResourceTemplate(\n name: string,\n title: string | undefined,\n template: ResourceTemplate,\n metadata: ResourceMetadata | undefined,\n readCallback: ReadResourceTemplateCallback\n ): RegisteredResourceTemplate {\n const registeredResourceTemplate: RegisteredResourceTemplate = {\n resourceTemplate: template,\n title,\n metadata,\n readCallback,\n enabled: true,\n disable: () => registeredResourceTemplate.update({ enabled: false }),\n enable: () => registeredResourceTemplate.update({ enabled: true }),\n remove: () => registeredResourceTemplate.update({ name: null }),\n update: updates => {\n if (updates.name !== undefined && updates.name !== name) {\n delete this._registeredResourceTemplates[name];\n if (updates.name) this._registeredResourceTemplates[updates.name] = registeredResourceTemplate;\n }\n if (updates.title !== undefined) registeredResourceTemplate.title = updates.title;\n if (updates.template !== undefined) registeredResourceTemplate.resourceTemplate = updates.template;\n if (updates.metadata !== undefined) registeredResourceTemplate.metadata = updates.metadata;\n if (updates.callback !== undefined) registeredResourceTemplate.readCallback = updates.callback;\n if (updates.enabled !== undefined) registeredResourceTemplate.enabled = updates.enabled;\n this.sendResourceListChanged();\n }\n };\n this._registeredResourceTemplates[name] = registeredResourceTemplate;\n\n // If the resource template has any completion callbacks, enable completions capability\n const variableNames = template.uriTemplate.variableNames;\n const hasCompleter = Array.isArray(variableNames) && variableNames.some(v => !!template.completeCallback(v));\n if (hasCompleter) {\n this.setCompletionRequestHandler();\n }\n\n return registeredResourceTemplate;\n }\n\n private _createRegisteredPrompt(\n name: string,\n title: string | undefined,\n description: string | undefined,\n argsSchema: StandardSchemaWithJSON | undefined,\n callback: PromptCallback<StandardSchemaWithJSON | undefined>,\n icons: Icon[] | undefined,\n _meta: Record<string, unknown> | undefined\n ): RegisteredPrompt {\n // Track current schema and callback for handler regeneration\n let currentArgsSchema = argsSchema;\n let currentCallback = callback;\n\n const registeredPrompt: RegisteredPrompt = {\n title,\n description,\n argsSchema,\n icons,\n _meta,\n handler: createPromptHandler(name, argsSchema, callback),\n enabled: true,\n disable: () => registeredPrompt.update({ enabled: false }),\n enable: () => registeredPrompt.update({ enabled: true }),\n remove: () => registeredPrompt.update({ name: null }),\n update: updates => {\n if (updates.name !== undefined && updates.name !== name) {\n delete this._registeredPrompts[name];\n if (updates.name) this._registeredPrompts[updates.name] = registeredPrompt;\n }\n if (updates.title !== undefined) registeredPrompt.title = updates.title;\n if (updates.description !== undefined) registeredPrompt.description = updates.description;\n if (updates.icons !== undefined) registeredPrompt.icons = updates.icons;\n if (updates._meta !== undefined) registeredPrompt._meta = updates._meta;\n\n // Track if we need to regenerate the handler\n let needsHandlerRegen = false;\n if (updates.argsSchema !== undefined) {\n registeredPrompt.argsSchema = updates.argsSchema;\n currentArgsSchema = updates.argsSchema;\n needsHandlerRegen = true;\n }\n if (updates.callback !== undefined) {\n currentCallback = updates.callback as PromptCallback<StandardSchemaWithJSON | undefined>;\n needsHandlerRegen = true;\n }\n if (needsHandlerRegen) {\n registeredPrompt.handler = createPromptHandler(name, currentArgsSchema, currentCallback);\n }\n\n if (updates.enabled !== undefined) registeredPrompt.enabled = updates.enabled;\n this.sendPromptListChanged();\n }\n };\n this._registeredPrompts[name] = registeredPrompt;\n\n // If any argument uses a Completable schema, enable completions capability\n if (argsSchema) {\n const shape = getSchemaShape(argsSchema);\n if (shape) {\n const hasCompletable = Object.values(shape).some(field => {\n const inner = unwrapOptionalSchema(field);\n return isCompletable(inner);\n });\n if (hasCompletable) {\n this.setCompletionRequestHandler();\n }\n }\n }\n\n return registeredPrompt;\n }\n\n private _createRegisteredTool(\n name: string,\n title: string | undefined,\n description: string | undefined,\n inputSchema: StandardSchemaWithJSON | undefined,\n outputSchema: StandardSchemaWithJSON | undefined,\n annotations: ToolAnnotations | undefined,\n icons: Icon[] | undefined,\n execution: ToolExecution | undefined,\n _meta: Record<string, unknown> | undefined,\n handler: AnyToolHandler<StandardSchemaWithJSON | undefined>\n ): RegisteredTool {\n // Validate tool name according to SEP specification\n validateAndWarnToolName(name);\n\n // Track current handler for executor regeneration\n let currentHandler = handler;\n\n const registeredTool: RegisteredTool = {\n title,\n description,\n inputSchema,\n outputSchema,\n annotations,\n icons,\n execution,\n _meta,\n handler: handler,\n executor: createToolExecutor(inputSchema, handler),\n enabled: true,\n disable: () => registeredTool.update({ enabled: false }),\n enable: () => registeredTool.update({ enabled: true }),\n remove: () => registeredTool.update({ name: null }),\n update: updates => {\n if (updates.name !== undefined && updates.name !== name) {\n if (typeof updates.name === 'string') {\n validateAndWarnToolName(updates.name);\n }\n delete this._registeredTools[name];\n if (updates.name) this._registeredTools[updates.name] = registeredTool;\n }\n if (updates.title !== undefined) registeredTool.title = updates.title;\n if (updates.description !== undefined) registeredTool.description = updates.description;\n\n // Track if we need to regenerate the executor\n let needsExecutorRegen = false;\n if (updates.paramsSchema !== undefined) {\n registeredTool.inputSchema = updates.paramsSchema;\n needsExecutorRegen = true;\n }\n if (updates.callback !== undefined) {\n registeredTool.handler = updates.callback;\n currentHandler = updates.callback as AnyToolHandler<StandardSchemaWithJSON | undefined>;\n needsExecutorRegen = true;\n }\n if (needsExecutorRegen) {\n registeredTool.executor = createToolExecutor(registeredTool.inputSchema, currentHandler);\n }\n\n if (updates.outputSchema !== undefined) registeredTool.outputSchema = updates.outputSchema;\n if (updates.annotations !== undefined) registeredTool.annotations = updates.annotations;\n if (updates.icons !== undefined) registeredTool.icons = updates.icons;\n if (updates._meta !== undefined) registeredTool._meta = updates._meta;\n if (updates.enabled !== undefined) registeredTool.enabled = updates.enabled;\n this.sendToolListChanged();\n }\n };\n this._registeredTools[name] = registeredTool;\n\n this.setToolRequestHandlers();\n this.sendToolListChanged();\n\n return registeredTool;\n }\n\n /**\n * Registers a tool with a config object and callback.\n *\n * @example\n * ```ts source=\"./mcp.examples.ts#McpServer_registerTool_basic\"\n * server.registerTool(\n * 'calculate-bmi',\n * {\n * title: 'BMI Calculator',\n * description: 'Calculate Body Mass Index',\n * inputSchema: z.object({\n * weightKg: z.number(),\n * heightM: z.number()\n * }),\n * outputSchema: z.object({ bmi: z.number() })\n * },\n * async ({ weightKg, heightM }) => {\n * const output = { bmi: weightKg / (heightM * heightM) };\n * return {\n * content: [{ type: 'text', text: JSON.stringify(output) }],\n * structuredContent: output\n * };\n * }\n * );\n * ```\n */\n registerTool<OutputArgs extends StandardSchemaWithJSON, InputArgs extends StandardSchemaWithJSON | undefined = undefined>(\n name: string,\n config: {\n title?: string;\n description?: string;\n inputSchema?: InputArgs;\n outputSchema?: OutputArgs;\n annotations?: ToolAnnotations;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n },\n cb: ToolCallback<InputArgs>\n ): RegisteredTool;\n /** @deprecated Wrap with `z.object({...})` instead. Raw-shape form: `inputSchema`/`outputSchema` may be a plain `{ field: z.string() }` record; it is auto-wrapped with `z.object()`. */\n registerTool<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape | StandardSchemaWithJSON | undefined = undefined>(\n name: string,\n config: {\n title?: string;\n description?: string;\n inputSchema?: InputArgs;\n outputSchema?: OutputArgs;\n annotations?: ToolAnnotations;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n },\n cb: LegacyToolCallback<InputArgs>\n ): RegisteredTool;\n registerTool(\n name: string,\n config: {\n title?: string;\n description?: string;\n inputSchema?: StandardSchemaWithJSON | ZodRawShape;\n outputSchema?: StandardSchemaWithJSON | ZodRawShape;\n annotations?: ToolAnnotations;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n },\n cb: ToolCallback<StandardSchemaWithJSON | undefined> | LegacyToolCallback<ZodRawShape>\n ): RegisteredTool {\n if (this._registeredTools[name]) {\n throw new Error(`Tool ${name} is already registered`);\n }\n\n const { title, description, inputSchema, outputSchema, annotations, icons, _meta } = config;\n\n return this._createRegisteredTool(\n name,\n title,\n description,\n normalizeRawShapeSchema(inputSchema),\n normalizeRawShapeSchema(outputSchema),\n annotations,\n icons,\n undefined,\n _meta,\n cb as ToolCallback<StandardSchemaWithJSON | undefined>\n );\n }\n\n /**\n * Registers a prompt with a config object and callback.\n *\n * @example\n * ```ts source=\"./mcp.examples.ts#McpServer_registerPrompt_basic\"\n * server.registerPrompt(\n * 'review-code',\n * {\n * title: 'Code Review',\n * description: 'Review code for best practices',\n * argsSchema: z.object({ code: z.string() })\n * },\n * ({ code }) => ({\n * messages: [\n * {\n * role: 'user' as const,\n * content: {\n * type: 'text' as const,\n * text: `Please review this code:\\n\\n${code}`\n * }\n * }\n * ]\n * })\n * );\n * ```\n */\n registerPrompt<Args extends StandardSchemaWithJSON>(\n name: string,\n config: {\n title?: string;\n description?: string;\n argsSchema?: Args;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n },\n cb: PromptCallback<Args>\n ): RegisteredPrompt;\n /** @deprecated Wrap with `z.object({...})` instead. Raw-shape form: `argsSchema` may be a plain `{ field: z.string() }` record; it is auto-wrapped with `z.object()`. */\n registerPrompt<Args extends ZodRawShape>(\n name: string,\n config: {\n title?: string;\n description?: string;\n argsSchema?: Args;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n },\n cb: LegacyPromptCallback<Args>\n ): RegisteredPrompt;\n registerPrompt(\n name: string,\n config: {\n title?: string;\n description?: string;\n argsSchema?: StandardSchemaWithJSON | ZodRawShape;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n },\n cb: PromptCallback<StandardSchemaWithJSON> | LegacyPromptCallback<ZodRawShape>\n ): RegisteredPrompt {\n if (this._registeredPrompts[name]) {\n throw new Error(`Prompt ${name} is already registered`);\n }\n\n const { title, description, argsSchema, icons, _meta } = config;\n\n const registeredPrompt = this._createRegisteredPrompt(\n name,\n title,\n description,\n normalizeRawShapeSchema(argsSchema),\n cb as PromptCallback<StandardSchemaWithJSON | undefined>,\n icons,\n _meta\n );\n\n this.setPromptRequestHandlers();\n this.sendPromptListChanged();\n\n return registeredPrompt;\n }\n\n /**\n * Checks if the server is connected to a transport.\n * @returns `true` if the server is connected\n */\n isConnected() {\n return this.server.transport !== undefined;\n }\n\n /**\n * Sends a logging message to the client, if connected.\n * Note: You only need to send the parameters object, not the entire JSON-RPC message.\n * @see {@linkcode LoggingMessageNotification}\n * @param params\n * @param sessionId Optional for stateless transports and backward compatibility.\n *\n * @example\n * ```ts source=\"./mcp.examples.ts#McpServer_sendLoggingMessage_basic\"\n * await server.sendLoggingMessage({\n * level: 'info',\n * data: 'Processing complete'\n * });\n * ```\n *\n * @deprecated Deprecated as of protocol version 2026-07-28 (SEP-2577).\n * Remains functional during the deprecation window (at least twelve months).\n * Migrate to stderr logging (STDIO servers) or OpenTelemetry.\n */\n async sendLoggingMessage(params: LoggingMessageNotification['params'], sessionId?: string) {\n return this.server.sendLoggingMessage(params, sessionId);\n }\n /**\n * Sends a resource list changed event to the client, if connected.\n */\n sendResourceListChanged() {\n if (this.isConnected()) {\n this.server.sendResourceListChanged();\n }\n }\n\n /**\n * Sends a tool list changed event to the client, if connected.\n */\n sendToolListChanged() {\n if (this.isConnected()) {\n this.server.sendToolListChanged();\n }\n }\n\n /**\n * Sends a prompt list changed event to the client, if connected.\n */\n sendPromptListChanged() {\n if (this.isConnected()) {\n this.server.sendPromptListChanged();\n }\n }\n}\n\n/**\n * A callback to complete one variable within a resource template's URI template.\n */\nexport type CompleteResourceTemplateCallback = (\n value: string,\n context?: {\n arguments?: Record<string, string>;\n }\n) => string[] | Promise<string[]>;\n\n/**\n * A resource template combines a URI pattern with optional functionality to enumerate\n * all resources matching that pattern.\n */\nexport class ResourceTemplate {\n private _uriTemplate: UriTemplate;\n\n constructor(\n uriTemplate: string | UriTemplate,\n private _callbacks: {\n /**\n * A callback to list all resources matching this template. This is required to be specified, even if `undefined`, to avoid accidentally forgetting resource listing.\n */\n list: ListResourcesCallback | undefined;\n\n /**\n * An optional callback to autocomplete variables within the URI template. Useful for clients and users to discover possible values.\n */\n complete?: {\n [variable: string]: CompleteResourceTemplateCallback;\n };\n }\n ) {\n this._uriTemplate = typeof uriTemplate === 'string' ? new UriTemplate(uriTemplate) : uriTemplate;\n }\n\n /**\n * Gets the URI template pattern.\n */\n get uriTemplate(): UriTemplate {\n return this._uriTemplate;\n }\n\n /**\n * Gets the list callback, if one was provided.\n */\n get listCallback(): ListResourcesCallback | undefined {\n return this._callbacks.list;\n }\n\n /**\n * Gets the callback for completing a specific URI template variable, if one was provided.\n */\n completeCallback(variable: string): CompleteResourceTemplateCallback | undefined {\n return this._callbacks.complete?.[variable];\n }\n}\n\n/**\n * A plain record of Zod field schemas, e.g. `{ name: z.string() }`. Accepted by\n * `registerTool`/`registerPrompt` as a shorthand; auto-wrapped with `z.object()`.\n * Zod schemas only — `z.object()` cannot wrap other Standard Schema libraries.\n */\nexport type ZodRawShape = Record<string, z.ZodType>;\n\n/** Infers the parsed-output type of a {@linkcode ZodRawShape}. */\nexport type InferRawShape<S extends ZodRawShape> = z.infer<z.ZodObject<S>>;\n\n/** {@linkcode ToolCallback} variant used when `inputSchema` is a {@linkcode ZodRawShape}. */\nexport type LegacyToolCallback<Args extends ZodRawShape | undefined> = Args extends ZodRawShape\n ? (args: InferRawShape<Args>, ctx: ServerContext) => CallToolResult | Promise<CallToolResult>\n : (ctx: ServerContext) => CallToolResult | Promise<CallToolResult>;\n\n/** {@linkcode PromptCallback} variant used when `argsSchema` is a {@linkcode ZodRawShape}. */\nexport type LegacyPromptCallback<Args extends ZodRawShape | undefined> = Args extends ZodRawShape\n ? (args: InferRawShape<Args>, ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>\n : (ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>;\n\nexport type BaseToolCallback<\n SendResultT extends Result,\n Ctx extends ServerContext,\n Args extends StandardSchemaWithJSON | undefined\n> = Args extends StandardSchemaWithJSON\n ? (args: StandardSchemaWithJSON.InferOutput<Args>, ctx: Ctx) => SendResultT | Promise<SendResultT>\n : (ctx: Ctx) => SendResultT | Promise<SendResultT>;\n\n/**\n * Callback for a tool handler registered with {@linkcode McpServer.registerTool}.\n */\nexport type ToolCallback<Args extends StandardSchemaWithJSON | undefined = undefined> = BaseToolCallback<\n CallToolResult,\n ServerContext,\n Args\n>;\n\n/**\n * Tool handler callback type.\n */\nexport type AnyToolHandler<Args extends StandardSchemaWithJSON | undefined = undefined> = ToolCallback<Args>;\n\n/**\n * Internal executor type that encapsulates handler invocation with proper types.\n */\ntype ToolExecutor = (args: unknown, ctx: ServerContext) => Promise<CallToolResult>;\n\nexport type RegisteredTool = {\n title?: string;\n description?: string;\n inputSchema?: StandardSchemaWithJSON;\n outputSchema?: StandardSchemaWithJSON;\n annotations?: ToolAnnotations;\n icons?: Icon[];\n execution?: ToolExecution;\n _meta?: Record<string, unknown>;\n handler: AnyToolHandler<StandardSchemaWithJSON | undefined>;\n /** @hidden */\n executor: ToolExecutor;\n enabled: boolean;\n enable(): void;\n disable(): void;\n update(updates: {\n name?: string | null;\n title?: string;\n description?: string;\n paramsSchema?: StandardSchemaWithJSON;\n outputSchema?: StandardSchemaWithJSON;\n annotations?: ToolAnnotations;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n callback?: ToolCallback<StandardSchemaWithJSON>;\n enabled?: boolean;\n }): void;\n remove(): void;\n};\n\n/**\n * Creates an executor that invokes the handler with the appropriate arguments.\n * When `inputSchema` is defined, the handler is called with `(args, ctx)`.\n * When `inputSchema` is undefined, the handler is called with just `(ctx)`.\n */\nfunction createToolExecutor(\n inputSchema: StandardSchemaWithJSON | undefined,\n handler: AnyToolHandler<StandardSchemaWithJSON | undefined>\n): ToolExecutor {\n if (inputSchema) {\n const callback = handler as ToolCallbackInternal;\n return async (args, ctx) => callback(args, ctx);\n }\n\n // When no inputSchema, call with just ctx (the handler expects (ctx) signature)\n const callback = handler as (ctx: ServerContext) => CallToolResult | Promise<CallToolResult>;\n return async (_args, ctx) => callback(ctx);\n}\n\nconst EMPTY_OBJECT_JSON_SCHEMA = {\n type: 'object' as const,\n properties: {}\n};\n\n/**\n * Additional, optional information for annotating a resource.\n */\nexport type ResourceMetadata = Omit<Resource, 'uri' | 'name'>;\n\n/**\n * Callback to list all resources matching a given template.\n */\nexport type ListResourcesCallback = (ctx: ServerContext) => ListResourcesResult | Promise<ListResourcesResult>;\n\n/**\n * Callback to read a resource at a given URI.\n */\nexport type ReadResourceCallback = (uri: URL, ctx: ServerContext) => ReadResourceResult | Promise<ReadResourceResult>;\n\nexport type RegisteredResource = {\n name: string;\n title?: string;\n metadata?: ResourceMetadata;\n readCallback: ReadResourceCallback;\n enabled: boolean;\n enable(): void;\n disable(): void;\n update(updates: {\n name?: string;\n title?: string;\n uri?: string | null;\n metadata?: ResourceMetadata;\n callback?: ReadResourceCallback;\n enabled?: boolean;\n }): void;\n remove(): void;\n};\n\n/**\n * Callback to read a resource at a given URI, following a filled-in URI template.\n */\nexport type ReadResourceTemplateCallback = (\n uri: URL,\n variables: Variables,\n ctx: ServerContext\n) => ReadResourceResult | Promise<ReadResourceResult>;\n\nexport type RegisteredResourceTemplate = {\n resourceTemplate: ResourceTemplate;\n title?: string;\n metadata?: ResourceMetadata;\n readCallback: ReadResourceTemplateCallback;\n enabled: boolean;\n enable(): void;\n disable(): void;\n update(updates: {\n name?: string | null;\n title?: string;\n template?: ResourceTemplate;\n metadata?: ResourceMetadata;\n callback?: ReadResourceTemplateCallback;\n enabled?: boolean;\n }): void;\n remove(): void;\n};\n\nexport type PromptCallback<Args extends StandardSchemaWithJSON | undefined = undefined> = Args extends StandardSchemaWithJSON\n ? (args: StandardSchemaWithJSON.InferOutput<Args>, ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>\n : (ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>;\n\n/**\n * Internal handler type that encapsulates parsing and callback invocation.\n * This allows type-safe handling without runtime type assertions.\n */\ntype PromptHandler = (args: Record<string, unknown> | undefined, ctx: ServerContext) => Promise<GetPromptResult>;\n\ntype ToolCallbackInternal = (args: unknown, ctx: ServerContext) => CallToolResult | Promise<CallToolResult>;\n\nexport type RegisteredPrompt = {\n title?: string;\n description?: string;\n argsSchema?: StandardSchemaWithJSON;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n /** @hidden */\n handler: PromptHandler;\n enabled: boolean;\n enable(): void;\n disable(): void;\n update<Args extends StandardSchemaWithJSON>(updates: {\n name?: string | null;\n title?: string;\n description?: string;\n argsSchema?: Args;\n icons?: Icon[];\n _meta?: Record<string, unknown>;\n callback?: PromptCallback<Args>;\n enabled?: boolean;\n }): void;\n remove(): void;\n};\n\n/**\n * Creates a type-safe prompt handler that captures the schema and callback in a closure.\n * This eliminates the need for type assertions at the call site.\n */\nfunction createPromptHandler(\n name: string,\n argsSchema: StandardSchemaWithJSON | undefined,\n callback: PromptCallback<StandardSchemaWithJSON | undefined>\n): PromptHandler {\n if (argsSchema) {\n const typedCallback = callback as (args: unknown, ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>;\n\n return async (args, ctx) => {\n const parseResult = await validateStandardSchema(argsSchema, args);\n if (!parseResult.success) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parseResult.error}`);\n }\n return typedCallback(parseResult.data, ctx);\n };\n } else {\n const typedCallback = callback as (ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>;\n\n return async (_args, ctx) => {\n return typedCallback(ctx);\n };\n }\n}\n\nfunction createCompletionResult(suggestions: readonly unknown[]): CompleteResult {\n const values = suggestions.map(String).slice(0, 100);\n return {\n completion: {\n values,\n total: suggestions.length,\n hasMore: suggestions.length > 100\n }\n };\n}\n\nconst EMPTY_COMPLETION_RESULT: CompleteResult = {\n completion: {\n values: [],\n hasMore: false\n }\n};\n\n/** @internal Gets the shape of a Zod object schema */\nfunction getSchemaShape(schema: unknown): Record<string, unknown> | undefined {\n const candidate = schema as { shape?: unknown };\n if (candidate.shape && typeof candidate.shape === 'object') {\n return candidate.shape as Record<string, unknown>;\n }\n return undefined;\n}\n\n/** @internal Checks if a Zod schema is optional */\nfunction isOptionalSchema(schema: unknown): boolean {\n const candidate = schema as { type?: string } | null | undefined;\n return candidate?.type === 'optional';\n}\n\n/** @internal Unwraps an optional Zod schema */\nfunction unwrapOptionalSchema(schema: unknown): unknown {\n if (!isOptionalSchema(schema)) {\n return schema;\n }\n const candidate = schema as { def?: { innerType?: unknown } };\n return candidate.def?.innerType ?? schema;\n}\n","export type HostHeaderValidationResult =\n | { ok: true; hostname: string }\n | {\n ok: false;\n errorCode: 'missing_host' | 'invalid_host_header' | 'invalid_host';\n message: string;\n hostHeader?: string;\n hostname?: string;\n };\n\n/**\n * Parse and validate a `Host` header against an allowlist of hostnames (port-agnostic).\n *\n * - Input host header may include a port (e.g. `localhost:3000`) or IPv6 brackets (e.g. `[::1]:3000`).\n * - Allowlist items should be hostnames only (no ports). For IPv6, include brackets (e.g. `[::1]`).\n */\nexport function validateHostHeader(hostHeader: string | null | undefined, allowedHostnames: string[]): HostHeaderValidationResult {\n if (!hostHeader) {\n return { ok: false, errorCode: 'missing_host', message: 'Missing Host header' };\n }\n\n // Use URL API to parse hostname (handles IPv4, IPv6, and regular hostnames)\n let hostname: string;\n try {\n hostname = new URL(`http://${hostHeader}`).hostname;\n } catch {\n return { ok: false, errorCode: 'invalid_host_header', message: `Invalid Host header: ${hostHeader}`, hostHeader };\n }\n\n if (!allowedHostnames.includes(hostname)) {\n return { ok: false, errorCode: 'invalid_host', message: `Invalid Host: ${hostname}`, hostHeader, hostname };\n }\n\n return { ok: true, hostname };\n}\n\n/**\n * Convenience allowlist for `localhost` DNS rebinding protection.\n */\nexport function localhostAllowedHostnames(): string[] {\n return ['localhost', '127.0.0.1', '[::1]'];\n}\n\n/**\n * Web-standard `Request` helper for DNS rebinding protection.\n * @example\n * ```ts source=\"./hostHeaderValidation.examples.ts#hostHeaderValidationResponse_basicUsage\"\n * const result = validateHostHeader(req.headers.get('host'), ['localhost']);\n * ```\n */\nexport function hostHeaderValidationResponse(req: Request, allowedHostnames: string[]): Response | undefined {\n const result = validateHostHeader(req.headers.get('host'), allowedHostnames);\n if (result.ok) return undefined;\n\n return Response.json(\n {\n jsonrpc: '2.0',\n error: {\n code: -32_000,\n message: result.message\n },\n id: null\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n}\n","/**\n * Web Standards Streamable HTTP Server Transport\n *\n * This is the core transport implementation using Web Standard APIs (`Request`, `Response`, `ReadableStream`).\n * It can run on any runtime that supports Web Standards: Node.js 18+, Cloudflare Workers, Deno, Bun, etc.\n *\n * For Node.js Express/HTTP compatibility, use {@linkcode @modelcontextprotocol/node!NodeStreamableHTTPServerTransport | NodeStreamableHTTPServerTransport} which wraps this transport.\n */\n\nimport type { AuthInfo, JSONRPCMessage, MessageExtraInfo, RequestId, Transport } from '@modelcontextprotocol/core-internal';\nimport {\n DEFAULT_NEGOTIATED_PROTOCOL_VERSION,\n isInitializeRequest,\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n JSONRPCMessageSchema,\n SUPPORTED_PROTOCOL_VERSIONS\n} from '@modelcontextprotocol/core-internal';\n\nexport type StreamId = string;\nexport type EventId = string;\n\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n /**\n * Stores an event for later retrieval\n * @param streamId ID of the stream the event belongs to\n * @param message The JSON-RPC message to store\n * @returns The generated event ID for the stored event\n */\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n\n /**\n * Get the stream ID associated with a given event ID.\n * @param eventId The event ID to look up\n * @returns The stream ID, or `undefined` if not found\n *\n * Optional: If not provided, the SDK will use the `streamId` returned by\n * {@linkcode replayEventsAfter} for stream mapping.\n */\n getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;\n\n replayEventsAfter(\n lastEventId: EventId,\n {\n send\n }: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n }\n ): Promise<StreamId>;\n}\n\n/**\n * Internal stream mapping for managing SSE connections\n */\ninterface StreamMapping {\n /** Stream controller for pushing SSE data - only used with `ReadableStream` approach */\n controller?: ReadableStreamDefaultController<Uint8Array>;\n /** Text encoder for SSE formatting */\n encoder?: InstanceType<typeof TextEncoder>;\n /** Promise resolver for JSON response mode */\n resolveJson?: (response: Response) => void;\n /** Cleanup function to close stream and remove mapping */\n cleanup: () => void;\n}\n\n/**\n * Configuration options for {@linkcode WebStandardStreamableHTTPServerTransport}\n */\nexport interface WebStandardStreamableHTTPServerTransportOptions {\n /**\n * Function that generates a session ID for the transport.\n * The session ID SHOULD be globally unique and cryptographically secure (e.g., a securely generated UUID, a JWT, or a cryptographic hash)\n *\n * If not provided, session management is disabled (stateless mode).\n */\n sessionIdGenerator?: (() => string) | undefined;\n\n /**\n * A callback for session initialization events\n * This is called when the server initializes a new session.\n * Useful in cases when you need to register multiple mcp sessions\n * and need to keep track of them.\n * @param sessionId The generated session ID\n */\n onsessioninitialized?: ((sessionId: string) => void | Promise<void>) | undefined;\n\n /**\n * A callback for session close events\n * This is called when the server closes a session due to a `DELETE` request.\n * Useful in cases when you need to clean up resources associated with the session.\n * Note that this is different from the transport closing, if you are handling\n * HTTP requests from multiple nodes you might want to close each\n * {@linkcode WebStandardStreamableHTTPServerTransport} after a request is completed while still keeping the\n * session open/running.\n * @param sessionId The session ID that was closed\n */\n onsessionclosed?: ((sessionId: string) => void | Promise<void>) | undefined;\n\n /**\n * If `true`, the server will return JSON responses instead of starting an SSE stream.\n * This can be useful for simple request/response scenarios without streaming.\n * Default is `false` (SSE streams are preferred).\n */\n enableJsonResponse?: boolean;\n\n /**\n * Event store for resumability support\n * If provided, resumability will be enabled, allowing clients to reconnect and resume messages\n */\n eventStore?: EventStore;\n\n /**\n * List of allowed `Host` header values for DNS rebinding protection.\n * If not specified, host validation is disabled.\n * @deprecated Use external middleware for host validation instead.\n */\n allowedHosts?: string[];\n\n /**\n * List of allowed `Origin` header values for DNS rebinding protection.\n * If not specified, origin validation is disabled.\n * @deprecated Use external middleware for origin validation instead.\n */\n allowedOrigins?: string[];\n\n /**\n * Enable DNS rebinding protection (requires `allowedHosts` and/or `allowedOrigins` to be configured).\n * Default is `false` for backwards compatibility.\n * @deprecated Use external middleware for DNS rebinding protection instead.\n */\n enableDnsRebindingProtection?: boolean;\n\n /**\n * Retry interval in milliseconds to suggest to clients in SSE `retry` field.\n * When set, the server will send a `retry` field in SSE priming events to control\n * client reconnection timing for polling behavior.\n */\n retryInterval?: number;\n\n /**\n * List of protocol versions that this transport will accept.\n * Used to validate the `mcp-protocol-version` header in incoming requests.\n *\n * Note: When using {@linkcode server/server.Server.connect | Server.connect()}, the server automatically passes its\n * `supportedProtocolVersions` to the transport, so you typically don't need\n * to set this option directly.\n *\n * @default {@linkcode SUPPORTED_PROTOCOL_VERSIONS}\n */\n supportedProtocolVersions?: string[];\n}\n\n/**\n * Options for handling a request\n */\nexport interface HandleRequestOptions {\n /**\n * Pre-parsed request body. If provided, the transport will use this instead of parsing `req.json()`.\n * Useful when using body-parser middleware that has already parsed the body.\n */\n parsedBody?: unknown;\n\n /**\n * Authentication info from middleware. If provided, will be passed to message handlers.\n */\n authInfo?: AuthInfo;\n}\n\n/**\n * Server transport for Web Standards Streamable HTTP: this implements the MCP Streamable HTTP transport specification\n * using Web Standard APIs (`Request`, `Response`, `ReadableStream`).\n *\n * This transport works on any runtime that supports Web Standards: Node.js 18+, Cloudflare Workers, Deno, Bun, etc.\n *\n * In stateful mode:\n * - Session ID is generated and included in response headers\n * - Session ID is always included in initialization responses\n * - Requests with invalid session IDs are rejected with `404 Not Found`\n * - Non-initialization requests without a session ID are rejected with `400 Bad Request`\n * - State is maintained in-memory (connections, message history)\n *\n * In stateless mode:\n * - No Session ID is included in any responses\n * - No session validation is performed\n *\n * @example Stateful setup\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_stateful\"\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n *\n * const transport = new WebStandardStreamableHTTPServerTransport({\n * sessionIdGenerator: () => crypto.randomUUID()\n * });\n *\n * await server.connect(transport);\n * ```\n *\n * @example Stateless setup\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_stateless\"\n * const transport = new WebStandardStreamableHTTPServerTransport({\n * sessionIdGenerator: undefined\n * });\n * ```\n *\n * @example Hono.js\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_hono\"\n * app.all('/mcp', async c => {\n * return transport.handleRequest(c.req.raw);\n * });\n * ```\n *\n * @example Cloudflare Workers\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_workers\"\n * const worker = {\n * async fetch(request: Request): Promise<Response> {\n * return transport.handleRequest(request);\n * }\n * };\n * ```\n */\nexport class WebStandardStreamableHTTPServerTransport implements Transport {\n // when sessionId is not set (undefined), it means the transport is in stateless mode\n private sessionIdGenerator: (() => string) | undefined;\n private _started: boolean = false;\n private _closed: boolean = false;\n private _streamMapping: Map<string, StreamMapping> = new Map();\n private _requestToStreamMapping: Map<RequestId, string> = new Map();\n private _requestResponseMap: Map<RequestId, JSONRPCMessage> = new Map();\n private _initialized: boolean = false;\n private _enableJsonResponse: boolean = false;\n private _standaloneSseStreamId: string = '_GET_stream';\n private _eventStore?: EventStore;\n private _onsessioninitialized?: ((sessionId: string) => void | Promise<void>) | undefined;\n private _onsessionclosed?: ((sessionId: string) => void | Promise<void>) | undefined;\n private _allowedHosts?: string[];\n private _allowedOrigins?: string[];\n private _enableDnsRebindingProtection: boolean;\n private _retryInterval?: number;\n private _supportedProtocolVersions: string[];\n\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n constructor(options: WebStandardStreamableHTTPServerTransportOptions = {}) {\n this.sessionIdGenerator = options.sessionIdGenerator;\n this._enableJsonResponse = options.enableJsonResponse ?? false;\n this._eventStore = options.eventStore;\n this._onsessioninitialized = options.onsessioninitialized;\n this._onsessionclosed = options.onsessionclosed;\n this._allowedHosts = options.allowedHosts;\n this._allowedOrigins = options.allowedOrigins;\n this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;\n this._retryInterval = options.retryInterval;\n this._supportedProtocolVersions = options.supportedProtocolVersions ?? SUPPORTED_PROTOCOL_VERSIONS;\n }\n\n /**\n * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op\n * for the Streamable HTTP transport as connections are managed per-request.\n */\n async start(): Promise<void> {\n if (this._started) {\n throw new Error('Transport already started');\n }\n this._started = true;\n }\n\n /**\n * Sets the supported protocol versions for header validation.\n * Called by the server during {@linkcode server/server.Server.connect | connect()} to pass its supported versions.\n */\n setSupportedProtocolVersions(versions: string[]): void {\n this._supportedProtocolVersions = versions;\n }\n\n /**\n * Helper to create a JSON error response\n */\n private createJsonErrorResponse(\n status: number,\n code: number,\n message: string,\n options?: { headers?: Record<string, string>; data?: string }\n ): Response {\n const error: { code: number; message: string; data?: string } = { code, message };\n if (options?.data !== undefined) {\n error.data = options.data;\n }\n return Response.json(\n {\n jsonrpc: '2.0',\n error,\n id: null\n },\n {\n status,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n }\n );\n }\n\n /**\n * Validates request headers for DNS rebinding protection.\n * @returns Error response if validation fails, `undefined` if validation passes.\n */\n private validateRequestHeaders(req: Request): Response | undefined {\n // Skip validation if protection is not enabled\n if (!this._enableDnsRebindingProtection) {\n return undefined;\n }\n\n // Validate Host header if allowedHosts is configured\n if (this._allowedHosts && this._allowedHosts.length > 0) {\n const hostHeader = req.headers.get('host');\n if (!hostHeader || !this._allowedHosts.includes(hostHeader)) {\n const error = `Invalid Host header: ${hostHeader}`;\n this.onerror?.(new Error(error));\n return this.createJsonErrorResponse(403, -32_000, error);\n }\n }\n\n // Validate Origin header if allowedOrigins is configured\n if (this._allowedOrigins && this._allowedOrigins.length > 0) {\n const originHeader = req.headers.get('origin');\n if (originHeader && !this._allowedOrigins.includes(originHeader)) {\n const error = `Invalid Origin header: ${originHeader}`;\n this.onerror?.(new Error(error));\n return this.createJsonErrorResponse(403, -32_000, error);\n }\n }\n\n return undefined;\n }\n\n /**\n * Handles an incoming HTTP request, whether `GET`, `POST`, or `DELETE`\n * Returns a `Response` object (Web Standard)\n */\n async handleRequest(req: Request, options?: HandleRequestOptions): Promise<Response> {\n // Validate request headers for DNS rebinding protection\n const validationError = this.validateRequestHeaders(req);\n if (validationError) {\n return validationError;\n }\n\n switch (req.method) {\n case 'POST': {\n return this.handlePostRequest(req, options);\n }\n case 'GET': {\n return this.handleGetRequest(req);\n }\n case 'DELETE': {\n return this.handleDeleteRequest(req);\n }\n default: {\n return this.handleUnsupportedRequest();\n }\n }\n }\n\n /**\n * Returns true if the client's protocol version supports empty SSE data in\n * priming events (the fix shipped with protocol version `2025-11-25`).\n *\n * The version is checked for membership in this transport instance's\n * supported protocol versions rather than with an open-ended\n * `>= '2025-11-25'` comparison: the value may come from an `initialize`\n * request body, which (unlike the `MCP-Protocol-Version` header) is not\n * validated against `supportedProtocolVersions` before reaching this\n * check. An unknown future version string must not silently enable\n * behavior reserved for versions this transport actually supports.\n */\n private supportsEmptySSEData(protocolVersion: string): boolean {\n return this._supportedProtocolVersions.includes(protocolVersion) && protocolVersion >= '2025-11-25';\n }\n\n /**\n * Writes a priming event to establish resumption capability.\n * Only sends if `eventStore` is configured (opt-in for resumability) and\n * the client's protocol version supports empty SSE data (a supported\n * version that is >= `2025-11-25`).\n */\n private async writePrimingEvent(\n controller: ReadableStreamDefaultController<Uint8Array>,\n encoder: InstanceType<typeof TextEncoder>,\n streamId: string,\n protocolVersion: string\n ): Promise<void> {\n if (!this._eventStore) {\n return;\n }\n\n // Priming events have empty data which older clients cannot handle.\n // Only send priming events to clients whose protocol version includes\n // the fix for handling empty SSE data.\n if (!this.supportsEmptySSEData(protocolVersion)) {\n return;\n }\n\n const primingEventId = await this._eventStore.storeEvent(streamId, {} as JSONRPCMessage);\n\n let primingEvent = `id: ${primingEventId}\\ndata: \\n\\n`;\n if (this._retryInterval !== undefined) {\n primingEvent = `id: ${primingEventId}\\nretry: ${this._retryInterval}\\ndata: \\n\\n`;\n }\n controller.enqueue(encoder.encode(primingEvent));\n }\n\n /**\n * Handles `GET` requests for SSE stream\n */\n private async handleGetRequest(req: Request): Promise<Response> {\n // The client MUST include an Accept header, listing text/event-stream as a supported content type.\n const acceptHeader = req.headers.get('accept');\n if (!acceptHeader?.includes('text/event-stream')) {\n this.onerror?.(new Error('Not Acceptable: Client must accept text/event-stream'));\n return this.createJsonErrorResponse(406, -32_000, 'Not Acceptable: Client must accept text/event-stream');\n }\n\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n const sessionError = this.validateSession(req);\n if (sessionError) {\n return sessionError;\n }\n const protocolError = this.validateProtocolVersion(req);\n if (protocolError) {\n return protocolError;\n }\n\n // Handle resumability: check for Last-Event-ID header\n if (this._eventStore) {\n const lastEventId = req.headers.get('last-event-id');\n if (lastEventId) {\n return this.replayEvents(lastEventId);\n }\n }\n\n // Check if there's already an active standalone SSE stream for this session\n if (this._streamMapping.get(this._standaloneSseStreamId) !== undefined) {\n // Only one GET SSE stream is allowed per session\n this.onerror?.(new Error('Conflict: Only one SSE stream is allowed per session'));\n return this.createJsonErrorResponse(409, -32_000, 'Conflict: Only one SSE stream is allowed per session');\n }\n\n const encoder = new TextEncoder();\n let streamController: ReadableStreamDefaultController<Uint8Array>;\n\n // Create a ReadableStream with a controller we can use to push SSE events\n const readable = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n cancel: () => {\n // Stream was cancelled by client\n this._streamMapping.delete(this._standaloneSseStreamId);\n }\n });\n\n const headers: Record<string, string> = {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive'\n };\n\n // After initialization, always include the session ID if we have one\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n // Store the stream mapping with the controller for pushing data\n this._streamMapping.set(this._standaloneSseStreamId, {\n controller: streamController!,\n encoder,\n cleanup: () => {\n this._streamMapping.delete(this._standaloneSseStreamId);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n });\n\n return new Response(readable, { headers });\n }\n\n /**\n * Replays events that would have been sent after the specified event ID\n * Only used when resumability is enabled\n */\n private async replayEvents(lastEventId: string): Promise<Response> {\n if (!this._eventStore) {\n this.onerror?.(new Error('Event store not configured'));\n return this.createJsonErrorResponse(400, -32_000, 'Event store not configured');\n }\n\n try {\n // If getStreamIdForEventId is available, use it for conflict checking\n let streamId: string | undefined;\n if (this._eventStore.getStreamIdForEventId) {\n streamId = await this._eventStore.getStreamIdForEventId(lastEventId);\n\n if (!streamId) {\n this.onerror?.(new Error('Invalid event ID format'));\n return this.createJsonErrorResponse(400, -32_000, 'Invalid event ID format');\n }\n\n // Check conflict with the SAME streamId we'll use for mapping\n if (this._streamMapping.get(streamId) !== undefined) {\n this.onerror?.(new Error('Conflict: Stream already has an active connection'));\n return this.createJsonErrorResponse(409, -32_000, 'Conflict: Stream already has an active connection');\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive'\n };\n\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n // Create a ReadableStream with controller for SSE\n const encoder = new TextEncoder();\n let streamController: ReadableStreamDefaultController<Uint8Array>;\n\n const readable = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n cancel: () => {\n // Stream was cancelled by client\n // Cleanup will be handled by the mapping\n }\n });\n\n // Replay events - returns the streamId for backwards compatibility\n const replayedStreamId = await this._eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId: string, message: JSONRPCMessage) => {\n const success = this.writeSSEEvent(streamController!, encoder, message, eventId);\n if (!success) {\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n }\n });\n\n this._streamMapping.set(replayedStreamId, {\n controller: streamController!,\n encoder,\n cleanup: () => {\n this._streamMapping.delete(replayedStreamId);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n });\n\n return new Response(readable, { headers });\n } catch (error) {\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(500, -32_000, 'Error replaying events');\n }\n }\n\n /**\n * Writes an event to an SSE stream via controller with proper formatting\n */\n private writeSSEEvent(\n controller: ReadableStreamDefaultController<Uint8Array>,\n encoder: InstanceType<typeof TextEncoder>,\n message: JSONRPCMessage,\n eventId?: string\n ): boolean {\n try {\n let eventData = `event: message\\n`;\n // Include event ID if provided - this is important for resumability\n if (eventId) {\n eventData += `id: ${eventId}\\n`;\n }\n eventData += `data: ${JSON.stringify(message)}\\n\\n`;\n controller.enqueue(encoder.encode(eventData));\n return true;\n } catch (error) {\n this.onerror?.(error as Error);\n return false;\n }\n }\n\n /**\n * Handles unsupported requests (`PUT`, `PATCH`, etc.)\n */\n private handleUnsupportedRequest(): Response {\n this.onerror?.(new Error('Method not allowed.'));\n return Response.json(\n {\n jsonrpc: '2.0',\n error: {\n code: -32_000,\n message: 'Method not allowed.'\n },\n id: null\n },\n {\n status: 405,\n headers: {\n Allow: 'GET, POST, DELETE',\n 'Content-Type': 'application/json'\n }\n }\n );\n }\n\n /**\n * Handles `POST` requests containing JSON-RPC messages\n */\n private async handlePostRequest(req: Request, options?: HandleRequestOptions): Promise<Response> {\n try {\n // Validate the Accept header\n const acceptHeader = req.headers.get('accept');\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (!acceptHeader?.includes('application/json') || !acceptHeader.includes('text/event-stream')) {\n this.onerror?.(new Error('Not Acceptable: Client must accept both application/json and text/event-stream'));\n return this.createJsonErrorResponse(\n 406,\n -32_000,\n 'Not Acceptable: Client must accept both application/json and text/event-stream'\n );\n }\n\n const ct = req.headers.get('content-type');\n if (!ct || !ct.includes('application/json')) {\n this.onerror?.(new Error('Unsupported Media Type: Content-Type must be application/json'));\n return this.createJsonErrorResponse(415, -32_000, 'Unsupported Media Type: Content-Type must be application/json');\n }\n\n const request = req;\n\n let rawMessage;\n if (options?.parsedBody === undefined) {\n try {\n rawMessage = await req.json();\n } catch (error) {\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON');\n }\n } else {\n rawMessage = options.parsedBody;\n }\n\n let messages: JSONRPCMessage[];\n\n // handle batch and single messages\n try {\n messages = Array.isArray(rawMessage)\n ? rawMessage.map(msg => JSONRPCMessageSchema.parse(msg))\n : [JSONRPCMessageSchema.parse(rawMessage)];\n } catch (error) {\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON-RPC message');\n }\n\n // Check if this is an initialization request\n // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/\n const isInitializationRequest = messages.some(element => isInitializeRequest(element));\n if (isInitializationRequest) {\n // If it's a server with session management and the session ID is already set we should reject the request\n // to avoid re-initialization.\n if (this._initialized && this.sessionId !== undefined) {\n this.onerror?.(new Error('Invalid Request: Server already initialized'));\n return this.createJsonErrorResponse(400, -32_600, 'Invalid Request: Server already initialized');\n }\n if (messages.length > 1) {\n this.onerror?.(new Error('Invalid Request: Only one initialization request is allowed'));\n return this.createJsonErrorResponse(400, -32_600, 'Invalid Request: Only one initialization request is allowed');\n }\n this.sessionId = this.sessionIdGenerator?.();\n this._initialized = true;\n\n // If we have a session ID and an onsessioninitialized handler, call it immediately\n // This is needed in cases where the server needs to keep track of multiple sessions\n if (this.sessionId && this._onsessioninitialized) {\n await Promise.resolve(this._onsessioninitialized(this.sessionId));\n }\n }\n if (!isInitializationRequest) {\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n const sessionError = this.validateSession(req);\n if (sessionError) {\n return sessionError;\n }\n // Mcp-Protocol-Version header is required for all requests after initialization.\n const protocolError = this.validateProtocolVersion(req);\n if (protocolError) {\n return protocolError;\n }\n }\n\n // check if it contains requests\n const hasRequests = messages.some(element => isJSONRPCRequest(element));\n\n if (!hasRequests) {\n // if it only contains notifications or responses, return 202\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: options?.authInfo, request });\n }\n return new Response(null, { status: 202 });\n }\n\n // The default behavior is to use SSE streaming\n // but in some cases server will return JSON responses\n const streamId = crypto.randomUUID();\n\n // Extract protocol version for priming event decision.\n // For initialize requests, get from request params.\n // For other requests, get from header (already validated).\n const initRequest = messages.find(m => isInitializeRequest(m));\n const clientProtocolVersion = initRequest\n ? initRequest.params.protocolVersion\n : (req.headers.get('mcp-protocol-version') ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION);\n\n if (this._enableJsonResponse) {\n // For JSON response mode, return a Promise that resolves when all responses are ready\n return new Promise<Response>(resolve => {\n this._streamMapping.set(streamId, {\n resolveJson: resolve,\n cleanup: () => {\n this._streamMapping.delete(streamId);\n }\n });\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this._requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: options?.authInfo, request });\n }\n });\n }\n\n // SSE streaming mode - use ReadableStream with controller for more reliable data pushing\n const encoder = new TextEncoder();\n let streamController: ReadableStreamDefaultController<Uint8Array>;\n\n const readable = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n cancel: () => {\n // Stream was cancelled by client\n this._streamMapping.delete(streamId);\n }\n });\n\n const headers: Record<string, string> = {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive'\n };\n\n // After initialization, always include the session ID if we have one\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n // Store the response for this request to send messages back through this connection\n // We need to track by request ID to maintain the connection\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this._streamMapping.set(streamId, {\n controller: streamController!,\n encoder,\n cleanup: () => {\n this._streamMapping.delete(streamId);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n });\n this._requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n // Write priming event if event store is configured (after mapping is set up)\n await this.writePrimingEvent(streamController!, encoder, streamId, clientProtocolVersion);\n\n // handle each message\n for (const message of messages) {\n // Build closeSSEStream callback for requests when eventStore is configured\n // AND client supports resumability (a supported protocol version >= 2025-11-25).\n // Old clients can't resume if the stream is closed early because they\n // didn't receive a priming event with an event ID.\n let closeSSEStream: (() => void) | undefined;\n let closeStandaloneSSEStream: (() => void) | undefined;\n if (isJSONRPCRequest(message) && this._eventStore && this.supportsEmptySSEData(clientProtocolVersion)) {\n closeSSEStream = () => {\n this.closeSSEStream(message.id);\n };\n closeStandaloneSSEStream = () => {\n this.closeStandaloneSSEStream();\n };\n }\n\n this.onmessage?.(message, { authInfo: options?.authInfo, request, closeSSEStream, closeStandaloneSSEStream });\n }\n // The server SHOULD NOT close the SSE stream before sending all JSON-RPC responses\n // This will be handled by the send() method when responses are ready\n\n return new Response(readable, { status: 200, headers });\n } catch (error) {\n // return JSON-RPC formatted error\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(400, -32_700, 'Parse error', { data: String(error) });\n }\n }\n\n /**\n * Handles `DELETE` requests to terminate sessions\n */\n private async handleDeleteRequest(req: Request): Promise<Response> {\n const sessionError = this.validateSession(req);\n if (sessionError) {\n return sessionError;\n }\n const protocolError = this.validateProtocolVersion(req);\n if (protocolError) {\n return protocolError;\n }\n\n await Promise.resolve(this._onsessionclosed?.(this.sessionId!));\n await this.close();\n return new Response(null, { status: 200 });\n }\n\n /**\n * Validates session ID for non-initialization requests.\n * Returns `Response` error if invalid, `undefined` otherwise\n */\n private validateSession(req: Request): Response | undefined {\n if (this.sessionIdGenerator === undefined) {\n // If the sessionIdGenerator ID is not set, the session management is disabled\n // and we don't need to validate the session ID\n return undefined;\n }\n if (!this._initialized) {\n // If the server has not been initialized yet, reject all requests\n this.onerror?.(new Error('Bad Request: Server not initialized'));\n return this.createJsonErrorResponse(400, -32_000, 'Bad Request: Server not initialized');\n }\n\n const sessionId = req.headers.get('mcp-session-id');\n\n if (!sessionId) {\n // Non-initialization requests without a session ID should return 400 Bad Request\n this.onerror?.(new Error('Bad Request: Mcp-Session-Id header is required'));\n return this.createJsonErrorResponse(400, -32_000, 'Bad Request: Mcp-Session-Id header is required');\n }\n\n if (sessionId !== this.sessionId) {\n // Reject requests with invalid session ID with 404 Not Found\n this.onerror?.(new Error('Session not found'));\n return this.createJsonErrorResponse(404, -32_001, 'Session not found');\n }\n\n return undefined;\n }\n\n /**\n * Validates the `MCP-Protocol-Version` header on incoming requests.\n *\n * For initialization: Version negotiation handles unknown versions gracefully\n * (server responds with its supported version).\n *\n * For subsequent requests with `MCP-Protocol-Version` header:\n * - Accept if in supported list\n * - 400 if unsupported\n *\n * For HTTP requests without the `MCP-Protocol-Version` header:\n * - Accept and default to the version negotiated at initialization\n */\n private validateProtocolVersion(req: Request): Response | undefined {\n const protocolVersion = req.headers.get('mcp-protocol-version');\n\n if (protocolVersion !== null && !this._supportedProtocolVersions.includes(protocolVersion)) {\n const error = `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${this._supportedProtocolVersions.join(', ')})`;\n this.onerror?.(new Error(error));\n return this.createJsonErrorResponse(400, -32_000, error);\n }\n return undefined;\n }\n\n async close(): Promise<void> {\n if (this._closed) {\n return;\n }\n this._closed = true;\n\n // Close all SSE connections\n for (const { cleanup } of this._streamMapping.values()) {\n cleanup();\n }\n this._streamMapping.clear();\n\n // Clear any pending responses\n this._requestResponseMap.clear();\n this.onclose?.();\n }\n\n /**\n * Close an SSE stream for a specific request, triggering client reconnection.\n * Use this to implement polling behavior during long-running operations -\n * client will reconnect after the retry interval specified in the priming event.\n */\n closeSSEStream(requestId: RequestId): void {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (!streamId) return;\n\n const stream = this._streamMapping.get(streamId);\n if (stream) {\n stream.cleanup();\n }\n }\n\n /**\n * Close the standalone `GET` SSE stream, triggering client reconnection.\n * Use this to implement polling behavior for server-initiated notifications.\n */\n closeStandaloneSSEStream(): void {\n const stream = this._streamMapping.get(this._standaloneSseStreamId);\n if (stream) {\n stream.cleanup();\n }\n }\n\n async send(message: JSONRPCMessage, options?: { relatedRequestId?: RequestId }): Promise<void> {\n let requestId = options?.relatedRequestId;\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n // If the message is a response, use the request ID from the message\n requestId = message.id;\n }\n\n // Check if this message should be sent on the standalone SSE stream (no request ID)\n // Ignore notifications from tools (which have relatedRequestId set)\n // Those will be sent via dedicated response SSE streams\n if (requestId === undefined) {\n // For standalone SSE streams, we can only send requests and notifications\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n throw new Error('Cannot send a response on a standalone SSE stream unless resuming a previous client request');\n }\n\n // Generate and store event ID if event store is provided\n // Store even if stream is disconnected so events can be replayed on reconnect\n let eventId: string | undefined;\n if (this._eventStore) {\n // Stores the event and gets the generated event ID\n eventId = await this._eventStore.storeEvent(this._standaloneSseStreamId, message);\n }\n\n const standaloneSse = this._streamMapping.get(this._standaloneSseStreamId);\n if (standaloneSse === undefined) {\n // Stream is disconnected - event is stored for replay, nothing more to do\n return;\n }\n\n // Send the message to the standalone SSE stream\n if (standaloneSse.controller && standaloneSse.encoder) {\n this.writeSSEEvent(standaloneSse.controller, standaloneSse.encoder, message, eventId);\n }\n return;\n }\n\n // Get the response for this request\n const streamId = this._requestToStreamMapping.get(requestId);\n if (!streamId) {\n throw new Error(`No connection established for request ID: ${String(requestId)}`);\n }\n\n const stream = this._streamMapping.get(streamId);\n\n if (!this._enableJsonResponse && stream?.controller && stream?.encoder) {\n // For SSE responses, generate event ID if event store is provided\n let eventId: string | undefined;\n\n if (this._eventStore) {\n eventId = await this._eventStore.storeEvent(streamId, message);\n }\n // Write the event to the response stream\n this.writeSSEEvent(stream.controller, stream.encoder, message, eventId);\n }\n\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n this._requestResponseMap.set(requestId, message);\n const relatedIds = [...this._requestToStreamMapping.entries()].filter(([_, sid]) => sid === streamId).map(([id]) => id);\n\n // Check if we have responses for all requests using this connection\n const allResponsesReady = relatedIds.every(id => this._requestResponseMap.has(id));\n\n if (allResponsesReady) {\n if (!stream) {\n throw new Error(`No connection established for request ID: ${String(requestId)}`);\n }\n if (this._enableJsonResponse && stream.resolveJson) {\n // All responses ready, send as JSON\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json'\n };\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n const responses = relatedIds.map(id => this._requestResponseMap.get(id)!);\n\n if (responses.length === 1) {\n stream.resolveJson(Response.json(responses[0], { status: 200, headers }));\n } else {\n stream.resolveJson(Response.json(responses, { status: 200, headers }));\n }\n } else {\n // End the SSE stream\n stream.cleanup();\n }\n // Clean up\n for (const id of relatedIds) {\n this._requestResponseMap.delete(id);\n this._requestToStreamMapping.delete(id);\n }\n }\n }\n }\n}\n","import type { JsonSchemaType, jsonSchemaValidator, StandardSchemaWithJSON } from '@modelcontextprotocol/core-internal';\nimport { fromJsonSchema as coreFromJsonSchema } from '@modelcontextprotocol/core-internal';\nimport { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims';\n\nlet _defaultValidator: jsonSchemaValidator | undefined;\n\nexport function fromJsonSchema<T = unknown>(schema: JsonSchemaType, validator?: jsonSchemaValidator): StandardSchemaWithJSON<T, T> {\n return coreFromJsonSchema<T>(schema, validator ?? (_defaultValidator ??= new DefaultJsonSchemaValidator()));\n}\n"],"mappings":";;;;AAEA,MAAaA,qBAAoC,OAAO,IAAI,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgD9E,SAAgB,YAAwC,QAAW,UAAqD;AACpH,QAAO,eAAe,QAAkB,oBAAoB;EACxD,OAAO,EAAE,UAAU;EACnB,YAAY;EACZ,UAAU;EACV,cAAc;EACjB,CAAC;AACF,QAAO;;;;;AAMX,SAAgB,cAAc,QAAgE;AAC1F,QAAO,CAAC,CAAC,UAAU,OAAO,WAAW,YAAY,sBAAuB;;;;;AAM5E,SAAgB,aAAyC,QAA4C;AAEjG,QADc,OAAoE,qBACrE;;;;;;;;;;;;ACiBjB,IAAa,SAAb,cAA4B,SAAwB;CAChD,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;;;;CAKR;;;;CAKA,YACI,AAAQC,aACR,SACF;AACE,QAAM,QAAQ;EAHN;AAIR,OAAK,gBAAgB,SAAS,eAAe,EAAE,GAAG,QAAQ,cAAc,GAAG,EAAE;AAC7E,OAAK,gBAAgB,SAAS;AAC9B,OAAK,uBAAuB,SAAS,uBAAuB,IAAI,4BAA4B;AAE5F,OAAK,kBAAkB,eAAc,YAAW,KAAK,cAAc,QAAQ,CAAC;AAC5E,OAAK,uBAAuB,mCAAmC,KAAK,iBAAiB,CAAC;AAEtF,MAAI,KAAK,cAAc,QACnB,MAAK,yBAAyB;;;;;;;;;CAWtC,AAAQ,0BAAgC;AACpC,OAAK,kBAAkB,oBAAoB,OAAO,SAAS,QAAQ;GAC/D,MAAMC,qBACF,IAAI,aAAc,IAAI,MAAM,KAAK,QAAQ,IAAI,iBAAiB,IAAe;GACjF,MAAM,EAAE,UAAU,QAAQ;GAC1B,MAAM,cAAc,YAAY,oBAAoB,MAAM;AAC1D,OAAI,YAAY,QACZ,MAAK,eAAe,IAAI,oBAAoB,YAAY,KAAK;AAEjE,UAAO,EAAE;IACX;;CAGN,AAAmB,aAAa,KAAkB,eAAiD;EAE/F,MAAM,cAAc,IAAI,QAAQ,eAAe,WAAW,eAAe,kBAAkB,eAAe;AAC1G,SAAO;GACH,GAAG;GACH,QAAQ;IACJ,GAAG,IAAI;IAIP,MAAM,OAAO,MAAM,WAAW,KAAK,mBAAmB;KAAE;KAAO;KAAM;KAAQ,CAAC;IAC9E,cAAc,QAAQ,YAAY,KAAK,YAAY,QAAQ,QAAQ;IACnE,kBAAkB,QAAQ,YAAY,KAAK,cAAc,QAAQ,QAAQ;IAC5E;GACD,MAAM,cACA;IACI,GAAG,IAAI;IACP,KAAK,eAAe;IACpB,UAAU,eAAe;IACzB,oBAAoB,eAAe;IACtC,GACD;GACT;;CAIL,AAAQ,iCAAiB,IAAI,KAAuC;CAGpE,AAAiB,qBAAqB,IAAI,IAAI,mBAAmB,QAAQ,KAAK,OAAO,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;CAG/G,AAAQ,oBAAoB,OAAqB,cAAgC;EAC7E,MAAM,eAAe,KAAK,eAAe,IAAI,UAAU;AACvD,SAAO,eAAe,KAAK,mBAAmB,IAAI,MAAM,GAAI,KAAK,mBAAmB,IAAI,aAAa,GAAI;;;;;;;CAQ7G,AAAO,qBAAqB,cAAwC;AAChE,MAAI,KAAK,UACL,OAAM,IAAI,SAAS,aAAa,kBAAkB,6DAA6D;EAEnH,MAAM,aAAa,CAAC,CAAC,KAAK,cAAc;AACxC,OAAK,gBAAgB,kBAAkB,KAAK,eAAe,aAAa;AACxE,MAAI,CAAC,cAAc,KAAK,cAAc,QAClC,MAAK,yBAAyB;;;;;;CAQtC,AAAmB,aACf,QACA,SACgE;AAChE,MAAI,WAAW,aACX,QAAO;AAEX,SAAO,OAAO,SAAS,QAAQ;GAC3B,MAAM,mBAAmB,YAAY,uBAAuB,QAAQ;AACpE,OAAI,CAAC,iBAAiB,SAAS;IAC3B,MAAM,eACF,iBAAiB,iBAAiB,QAAQ,iBAAiB,MAAM,UAAU,OAAO,iBAAiB,MAAM;AAC7G,UAAM,IAAI,cAAc,kBAAkB,eAAe,+BAA+B,eAAe;;GAK3G,MAAM,mBAAmB,YAAY,sBAFtB,MAAM,QAAQ,SAAS,IAAI,CAEwB;AAClE,OAAI,CAAC,iBAAiB,SAAS;IAC3B,MAAM,eACF,iBAAiB,iBAAiB,QAAQ,iBAAiB,MAAM,UAAU,OAAO,iBAAiB,MAAM;AAC7G,UAAM,IAAI,cAAc,kBAAkB,eAAe,8BAA8B,eAAe;;AAG1G,UAAO,iBAAiB;;;CAIhC,AAAU,0BAA0B,QAAsC;AACtE,UAAQ,QAAR;GACI,KAAK;AACD,QAAI,CAAC,KAAK,qBAAqB,SAC3B,OAAM,IAAI,SAAS,aAAa,wBAAwB,kDAAkD,OAAO,GAAG;AAExH;GAGJ,KAAK;AACD,QAAI,CAAC,KAAK,qBAAqB,YAC3B,OAAM,IAAI,SAAS,aAAa,wBAAwB,qDAAqD,OAAO,GAAG;AAE3H;GAGJ,KAAK;AACD,QAAI,CAAC,KAAK,qBAAqB,MAC3B,OAAM,IAAI,SACN,aAAa,wBACb,uDAAuD,OAAO,GACjE;AAEL;GAGJ,KAAK,OAED;;;CAKZ,AAAU,6BAA6B,QAA2C;AAC9E,UAAQ,QAAR;GACI,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,QACpB,OAAM,IAAI,SAAS,aAAa,wBAAwB,iDAAiD,OAAO,GAAG;AAEvH;GAGJ,KAAK;GACL,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,UACpB,OAAM,IAAI,SACN,aAAa,wBACb,mEAAmE,OAAO,GAC7E;AAEL;GAGJ,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,MACpB,OAAM,IAAI,SACN,aAAa,wBACb,wEAAwE,OAAO,GAClF;AAEL;GAGJ,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,QACpB,OAAM,IAAI,SACN,aAAa,wBACb,0EAA0E,OAAO,GACpF;AAEL;GAGJ,KAAK;AACD,QAAI,CAAC,KAAK,qBAAqB,aAAa,IACxC,OAAM,IAAI,SACN,aAAa,wBACb,yDAAyD,OAAO,GACnE;AAEL;GAGJ,KAAK,0BAED;GAGJ,KAAK,yBAED;;;CAKZ,AAAU,+BAA+B,QAAsB;AAC3D,UAAQ,QAAR;GACI,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,YACpB,OAAM,IAAI,SAAS,aAAa,wBAAwB,qDAAqD,OAAO,GAAG;AAE3H;GAGJ,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,QACpB,OAAM,IAAI,SAAS,aAAa,wBAAwB,iDAAiD,OAAO,GAAG;AAEvH;GAGJ,KAAK;GACL,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,QACpB,OAAM,IAAI,SAAS,aAAa,wBAAwB,iDAAiD,OAAO,GAAG;AAEvH;GAGJ,KAAK;GACL,KAAK;GACL,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,UACpB,OAAM,IAAI,SAAS,aAAa,wBAAwB,mDAAmD,OAAO,GAAG;AAEzH;GAGJ,KAAK;GACL,KAAK;AACD,QAAI,CAAC,KAAK,cAAc,MACpB,OAAM,IAAI,SAAS,aAAa,wBAAwB,+CAA+C,OAAO,GAAG;AAErH;GAGJ,KAAK;GACL,KAAK,aAED;;;CAKZ,MAAc,cAAc,SAAuD;EAC/E,MAAM,mBAAmB,QAAQ,OAAO;AAExC,OAAK,sBAAsB,QAAQ,OAAO;AAC1C,OAAK,iBAAiB,QAAQ,OAAO;EAErC,MAAM,kBAAkB,KAAK,2BAA2B,SAAS,iBAAiB,GAC5E,mBACC,KAAK,2BAA2B,MAAM;AAE7C,OAAK,6BAA6B;AAClC,OAAK,WAAW,qBAAqB,gBAAgB;AAErD,SAAO;GACH;GACA,cAAc,KAAK,iBAAiB;GACpC,YAAY,KAAK;GACjB,GAAI,KAAK,iBAAiB,EAAE,cAAc,KAAK,eAAe;GACjE;;;;;CAML,wBAAwD;AACpD,SAAO,KAAK;;;;;CAMhB,mBAA+C;AAC3C,SAAO,KAAK;;;;;;;CAQhB,+BAAmD;AAC/C,SAAO,KAAK;;;;;CAMhB,AAAO,kBAAsC;AACzC,SAAO,KAAK;;CAGhB,MAAM,OAAO;AACT,SAAO,KAAK,mBAAmB,EAAE,QAAQ,QAAQ,EAAE,kBAAkB;;CAqCzE,MAAM,cACF,QACA,SAC2D;AAE3D,OAAK,OAAO,SAAS,OAAO,eAAe,CAAC,KAAK,qBAAqB,UAAU,MAC5E,OAAM,IAAI,SAAS,aAAa,wBAAwB,qDAAqD;AAMjH,MAAI,OAAO,SAAS,SAAS,GAAG;GAC5B,MAAM,cAAc,OAAO,SAAS,GAAG,GAAG;GAC1C,MAAM,cAAc,MAAM,QAAQ,YAAY,QAAQ,GAAG,YAAY,UAAU,CAAC,YAAY,QAAQ;GACpG,MAAM,iBAAiB,YAAY,MAAK,MAAK,EAAE,SAAS,cAAc;GAEtE,MAAM,kBAAkB,OAAO,SAAS,SAAS,IAAI,OAAO,SAAS,GAAG,GAAG,GAAG;GAC9E,MAAM,kBAAkB,kBAClB,MAAM,QAAQ,gBAAgB,QAAQ,GAClC,gBAAgB,UAChB,CAAC,gBAAgB,QAAQ,GAC7B,EAAE;GACR,MAAM,qBAAqB,gBAAgB,MAAK,MAAK,EAAE,SAAS,WAAW;AAE3E,OAAI,gBAAgB;AAChB,QAAI,YAAY,MAAK,MAAK,EAAE,SAAS,cAAc,CAC/C,OAAM,IAAI,cACN,kBAAkB,eAClB,2EACH;AAEL,QAAI,CAAC,mBACD,OAAM,IAAI,cACN,kBAAkB,eAClB,6EACH;;AAGT,OAAI,oBAAoB;IACpB,MAAM,aAAa,IAAI,IAAI,gBAAgB,QAAO,MAAK,EAAE,SAAS,WAAW,CAAC,KAAI,MAAM,EAAqB,GAAG,CAAC;IACjH,MAAM,gBAAgB,IAAI,IACtB,YAAY,QAAO,MAAK,EAAE,SAAS,cAAc,CAAC,KAAI,MAAM,EAAwB,UAAU,CACjG;AACD,QAAI,WAAW,SAAS,cAAc,QAAQ,CAAC,CAAC,GAAG,WAAW,CAAC,OAAM,OAAM,cAAc,IAAI,GAAG,CAAC,CAC7F,OAAM,IAAI,cACN,kBAAkB,eAClB,mFACH;;;AAMb,MAAI,OAAO,MACP,QAAO,KAAK,mBAAmB;GAAE,QAAQ;GAA0B;GAAQ,EAAE,oCAAoC,QAAQ;AAE7H,SAAO,KAAK,mBAAmB;GAAE,QAAQ;GAA0B;GAAQ,EAAE,2BAA2B,QAAQ;;;;;;;;;CAUpH,MAAM,YAAY,QAA0D,SAAiD;AAGzH,UAFc,OAAO,QAAQ,QAE7B;GACI,KAAK,OAAO;AACR,QAAI,CAAC,KAAK,qBAAqB,aAAa,IACxC,OAAM,IAAI,SAAS,aAAa,wBAAwB,2CAA2C;IAGvG,MAAM,YAAY;AAClB,WAAO,KAAK,mBAAmB;KAAE,QAAQ;KAAsB,QAAQ;KAAW,EAAE,oBAAoB,QAAQ;;GAEpH,KAAK,QAAQ;AACT,QAAI,CAAC,KAAK,qBAAqB,aAAa,KACxC,OAAM,IAAI,SAAS,aAAa,wBAAwB,4CAA4C;IAGxG,MAAMC,aACF,OAAO,SAAS,SAAU,SAAqC;KAAE,GAAI;KAAoC,MAAM;KAAQ;IAE3H,MAAM,SAAS,MAAM,KAAK,mBACtB;KAAE,QAAQ;KAAsB,QAAQ;KAAY,EACpD,oBACA,QACH;AAED,QAAI,OAAO,WAAW,YAAY,OAAO,WAAW,WAAW,gBAC3D,KAAI;KAEA,MAAM,mBADY,KAAK,qBAAqB,aAAa,WAAW,gBAAkC,CACnE,OAAO,QAAQ;AAElD,SAAI,CAAC,iBAAiB,MAClB,OAAM,IAAI,cACN,kBAAkB,eAClB,iEAAiE,iBAAiB,eACrF;aAEA,OAAO;AACZ,SAAI,iBAAiB,cACjB,OAAM;AAEV,WAAM,IAAI,cACN,kBAAkB,eAClB,0CAA0C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACnG;;AAGT,WAAO;;;;;;;;;;;;CAanB,oCAAoC,eAAuB,SAAoD;AAC3G,MAAI,CAAC,KAAK,qBAAqB,aAAa,IACxC,OAAM,IAAI,SACN,aAAa,wBACb,4FACH;AAGL,eACI,KAAK,aACD;GACI,QAAQ;GACR,QAAQ,EACJ,eACH;GACJ,EACD,QACH;;;;;;;;;CAUT,MAAM,UAAU,QAAqC,SAA0B;AAC3E,SAAO,KAAK,mBAAmB;GAAE,QAAQ;GAAc;GAAQ,EAAE,uBAAuB,QAAQ;;;;;;;;;;;;;CAcpG,MAAM,mBAAmB,QAA8C,WAAoB;AACvF,MAAI,KAAK,cAAc,WAAW,CAAC,KAAK,iBAAiB,OAAO,OAAO,UAAU,CAC7E,QAAO,KAAK,aAAa;GAAE,QAAQ;GAAyB;GAAQ,CAAC;;CAI7E,MAAM,oBAAoB,QAA+C;AACrE,SAAO,KAAK,aAAa;GACrB,QAAQ;GACR;GACH,CAAC;;CAGN,MAAM,0BAA0B;AAC5B,SAAO,KAAK,aAAa,EACrB,QAAQ,wCACX,CAAC;;CAGN,MAAM,sBAAsB;AACxB,SAAO,KAAK,aAAa,EAAE,QAAQ,oCAAoC,CAAC;;CAG5E,MAAM,wBAAwB;AAC1B,SAAO,KAAK,aAAa,EAAE,QAAQ,sCAAsC,CAAC;;;;;;;;;;;;;;;;;;;ACnlBlF,IAAa,YAAb,MAAuB;;;;CAInB,AAAgB;CAEhB,AAAQ,uBAA8D,EAAE;CACxE,AAAQ,+BAEJ,EAAE;CACN,AAAQ,mBAAuD,EAAE;CACjE,AAAQ,qBAA2D,EAAE;CAErE,YAAY,YAA4B,SAAyB;AAC7D,OAAK,SAAS,IAAI,OAAO,YAAY,QAAQ;AAO7C,MAAI,SAAS,cAAc,MACvB,MAAK,wBAAwB;AAEjC,MAAI,SAAS,cAAc,UACvB,MAAK,4BAA4B;AAErC,MAAI,SAAS,cAAc,QACvB,MAAK,0BAA0B;;;;;;;;;;;;;;CAgBvC,MAAM,QAAQ,WAAqC;AAC/C,SAAO,MAAM,KAAK,OAAO,QAAQ,UAAU;;;;;CAM/C,MAAM,QAAuB;AACzB,QAAM,KAAK,OAAO,OAAO;;CAG7B,AAAQ,2BAA2B;CAEnC,AAAQ,yBAAyB;AAC7B,MAAI,KAAK,yBACL;AAGJ,OAAK,OAAO,2BAA2B,aAAa;AACpD,OAAK,OAAO,2BAA2B,aAAa;AAEpD,OAAK,OAAO,qBAAqB,EAC7B,OAAO,EACH,aAAa,KAAK,OAAO,iBAAiB,CAAC,OAAO,eAAe,MACpE,EACJ,CAAC;AAKF,OAAK,OAAO,kBACR,qBACwB,EACpB,OAAO,OAAO,QAAQ,KAAK,iBAAiB,CACvC,QAAQ,GAAG,UAAU,KAAK,QAAQ,CAClC,KAAK,CAAC,MAAM,UAAgB;GACzB,MAAMC,iBAAuB;IACzB;IACA,OAAO,KAAK;IACZ,aAAa,KAAK;IAClB,aAAa,KAAK,cACX,2BAA2B,KAAK,aAAa,QAAQ,GACtD;IACN,aAAa,KAAK;IAClB,OAAO,KAAK;IACZ,WAAW,KAAK;IAChB,OAAO,KAAK;IACf;AAED,OAAI,KAAK,aACL,gBAAe,eAAe,2BAA2B,KAAK,cAAc,SAAS;AAGzF,UAAO;IACT,EACT,EACJ;AAED,OAAK,OAAO,kBAAkB,cAAc,OAAO,SAAS,QAAiC;GACzF,MAAM,OAAO,KAAK,iBAAiB,QAAQ,OAAO;AAClD,OAAI,CAAC,KACD,OAAM,IAAI,cAAc,kBAAkB,eAAe,QAAQ,QAAQ,OAAO,KAAK,YAAY;AAErG,OAAI,CAAC,KAAK,QACN,OAAM,IAAI,cAAc,kBAAkB,eAAe,QAAQ,QAAQ,OAAO,KAAK,WAAW;AAGpG,OAAI;IACA,MAAM,OAAO,MAAM,KAAK,kBAAkB,MAAM,QAAQ,OAAO,WAAW,QAAQ,OAAO,KAAK;IAC9F,MAAM,SAAS,MAAM,KAAK,mBAAmB,MAAM,MAAM,IAAI;AAC7D,UAAM,KAAK,mBAAmB,MAAM,QAAQ,QAAQ,OAAO,KAAK;AAChE,WAAO;YACF,OAAO;AACZ,QAAI,iBAAiB,iBAAiB,MAAM,SAAS,kBAAkB,uBACnE,OAAM;AAEV,WAAO,KAAK,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;;IAEzF;AAEF,OAAK,2BAA2B;;;;;;;;CASpC,AAAQ,gBAAgB,cAAsC;AAC1D,SAAO;GACH,SAAS,CACL;IACI,MAAM;IACN,MAAM;IACT,CACJ;GACD,SAAS;GACZ;;;;;CAML,MAAc,kBAOZ,MAAgB,MAAY,UAAiC;AAC3D,MAAI,CAAC,KAAK,YACN;EAGJ,MAAM,cAAc,MAAM,uBAAuB,KAAK,aAAa,QAAQ,EAAE,CAAC;AAC9E,MAAI,CAAC,YAAY,QACb,OAAM,IAAI,cACN,kBAAkB,eAClB,sDAAsD,SAAS,IAAI,YAAY,QAClF;AAGL,SAAO,YAAY;;;;;CAMvB,MAAc,mBAAmB,MAAsB,QAAwB,UAAiC;AAC5G,MAAI,CAAC,KAAK,aACN;AAGJ,MAAI,OAAO,QACP;AAGJ,MAAI,CAAC,OAAO,kBACR,OAAM,IAAI,cACN,kBAAkB,eAClB,iCAAiC,SAAS,8DAC7C;EAIL,MAAM,cAAc,MAAM,uBAAuB,KAAK,cAAc,OAAO,kBAAkB;AAC7F,MAAI,CAAC,YAAY,QACb,OAAM,IAAI,cACN,kBAAkB,eAClB,gEAAgE,SAAS,IAAI,YAAY,QAC5F;;;;;CAOT,MAAc,mBAAmB,MAAsB,MAAe,KAA6C;AAE/G,SAAO,KAAK,SAAS,MAAM,IAAI;;CAGnC,AAAQ,gCAAgC;CAExC,AAAQ,8BAA8B;AAClC,MAAI,KAAK,8BACL;AAGJ,OAAK,OAAO,2BAA2B,sBAAsB;AAE7D,OAAK,OAAO,qBAAqB,EAC7B,aAAa,EAAE,EAClB,CAAC;AAEF,OAAK,OAAO,kBAAkB,uBAAuB,OAAO,YAAqC;AAC7F,WAAQ,QAAQ,OAAO,IAAI,MAA3B;IACI,KAAK;AACD,iCAA4B,QAAQ;AACpC,YAAO,KAAK,uBAAuB,SAAS,QAAQ,OAAO,IAAI;IAGnE,KAAK;AACD,2CAAsC,QAAQ;AAC9C,YAAO,KAAK,yBAAyB,SAAS,QAAQ,OAAO,IAAI;IAGrE,QACI,OAAM,IAAI,cAAc,kBAAkB,eAAe,iCAAiC,QAAQ,OAAO,MAAM;;IAGzH;AAEF,OAAK,gCAAgC;;CAGzC,MAAc,uBAAuB,SAAgC,KAA+C;EAChH,MAAM,SAAS,KAAK,mBAAmB,IAAI;AAC3C,MAAI,CAAC,OACD,OAAM,IAAI,cAAc,kBAAkB,eAAe,UAAU,IAAI,KAAK,YAAY;AAG5F,MAAI,CAAC,OAAO,QACR,OAAM,IAAI,cAAc,kBAAkB,eAAe,UAAU,IAAI,KAAK,WAAW;AAG3F,MAAI,CAAC,OAAO,WACR,QAAO;EAIX,MAAM,QAAQ,qBADM,eAAe,OAAO,WAAW,GACJ,QAAQ,OAAO,SAAS,MAAM;AAC/E,MAAI,CAAC,cAAc,MAAM,CACrB,QAAO;EAGX,MAAM,YAAY,aAAa,MAAM;AACrC,MAAI,CAAC,UACD,QAAO;AAIX,SAAO,uBADa,MAAM,UAAU,QAAQ,OAAO,SAAS,OAAO,QAAQ,OAAO,QAAQ,CAChD;;CAG9C,MAAc,yBACV,SACA,KACuB;EACvB,MAAM,WAAW,OAAO,OAAO,KAAK,6BAA6B,CAAC,MAAK,MAAK,EAAE,iBAAiB,YAAY,UAAU,KAAK,IAAI,IAAI;AAElI,MAAI,CAAC,UAAU;AACX,OAAI,KAAK,qBAAqB,IAAI,KAE9B,QAAO;AAGX,SAAM,IAAI,cAAc,kBAAkB,eAAe,qBAAqB,QAAQ,OAAO,IAAI,IAAI,YAAY;;EAGrH,MAAM,YAAY,SAAS,iBAAiB,iBAAiB,QAAQ,OAAO,SAAS,KAAK;AAC1F,MAAI,CAAC,UACD,QAAO;AAIX,SAAO,uBADa,MAAM,UAAU,QAAQ,OAAO,SAAS,OAAO,QAAQ,OAAO,QAAQ,CAChD;;CAG9C,AAAQ,+BAA+B;CAEvC,AAAQ,6BAA6B;AACjC,MAAI,KAAK,6BACL;AAGJ,OAAK,OAAO,2BAA2B,iBAAiB;AACxD,OAAK,OAAO,2BAA2B,2BAA2B;AAClE,OAAK,OAAO,2BAA2B,iBAAiB;AAExD,OAAK,OAAO,qBAAqB,EAC7B,WAAW,EACP,aAAa,KAAK,OAAO,iBAAiB,CAAC,WAAW,eAAe,MACxE,EACJ,CAAC;AAEF,OAAK,OAAO,kBAAkB,kBAAkB,OAAO,UAAU,QAAQ;GACrE,MAAM,YAAY,OAAO,QAAQ,KAAK,qBAAqB,CACtD,QAAQ,CAAC,GAAG,cAAc,SAAS,QAAQ,CAC3C,KAAK,CAAC,KAAK,eAAe;IACvB;IACA,MAAM,SAAS;IACf,GAAG,SAAS;IACf,EAAE;GAEP,MAAMC,oBAAgC,EAAE;AACxC,QAAK,MAAM,YAAY,OAAO,OAAO,KAAK,6BAA6B,EAAE;AACrE,QAAI,CAAC,SAAS,iBAAiB,aAC3B;IAGJ,MAAM,SAAS,MAAM,SAAS,iBAAiB,aAAa,IAAI;AAChE,SAAK,MAAM,YAAY,OAAO,UAC1B,mBAAkB,KAAK;KACnB,GAAG,SAAS;KAEZ,GAAG;KACN,CAAC;;AAIV,UAAO,EAAE,WAAW,CAAC,GAAG,WAAW,GAAG,kBAAkB,EAAE;IAC5D;AAEF,OAAK,OAAO,kBAAkB,4BAA4B,YAAY;AAOlE,UAAO,EAAE,mBANiB,OAAO,QAAQ,KAAK,6BAA6B,CAAC,KAAK,CAAC,MAAM,eAAe;IACnG;IACA,aAAa,SAAS,iBAAiB,YAAY,UAAU;IAC7D,GAAG,SAAS;IACf,EAAE,EAEyB;IAC9B;AAEF,OAAK,OAAO,kBAAkB,kBAAkB,OAAO,SAAS,QAAQ;GACpE,MAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,IAAI;GAGvC,MAAM,WAAW,KAAK,qBAAqB,IAAI,UAAU;AACzD,OAAI,UAAU;AACV,QAAI,CAAC,SAAS,QACV,OAAM,IAAI,cAAc,kBAAkB,eAAe,YAAY,IAAI,WAAW;AAExF,WAAO,SAAS,aAAa,KAAK,IAAI;;AAI1C,QAAK,MAAM,YAAY,OAAO,OAAO,KAAK,6BAA6B,EAAE;IACrE,MAAM,YAAY,SAAS,iBAAiB,YAAY,MAAM,IAAI,UAAU,CAAC;AAC7E,QAAI,UACA,QAAO,SAAS,aAAa,KAAK,WAAW,IAAI;;AAIzD,SAAM,IAAI,cAAc,kBAAkB,kBAAkB,YAAY,IAAI,YAAY;IAC1F;AAEF,OAAK,+BAA+B;;CAGxC,AAAQ,6BAA6B;CAErC,AAAQ,2BAA2B;AAC/B,MAAI,KAAK,2BACL;AAGJ,OAAK,OAAO,2BAA2B,eAAe;AACtD,OAAK,OAAO,2BAA2B,cAAc;AAErD,OAAK,OAAO,qBAAqB,EAC7B,SAAS,EACL,aAAa,KAAK,OAAO,iBAAiB,CAAC,SAAS,eAAe,MACtE,EACJ,CAAC;AAEF,OAAK,OAAO,kBACR,uBAC0B,EACtB,SAAS,OAAO,QAAQ,KAAK,mBAAmB,CAC3C,QAAQ,GAAG,YAAY,OAAO,QAAQ,CACtC,KAAK,CAAC,MAAM,YAAoB;AAC7B,UAAO;IACH;IACA,OAAO,OAAO;IACd,aAAa,OAAO;IACpB,WAAW,OAAO,aAAa,kCAAkC,OAAO,WAAW,GAAG;IACtF,OAAO,OAAO;IACd,OAAO,OAAO;IACjB;IACH,EACT,EACJ;AAED,OAAK,OAAO,kBAAkB,eAAe,OAAO,SAAS,QAAkC;GAC3F,MAAM,SAAS,KAAK,mBAAmB,QAAQ,OAAO;AACtD,OAAI,CAAC,OACD,OAAM,IAAI,cAAc,kBAAkB,eAAe,UAAU,QAAQ,OAAO,KAAK,YAAY;AAGvG,OAAI,CAAC,OAAO,QACR,OAAM,IAAI,cAAc,kBAAkB,eAAe,UAAU,QAAQ,OAAO,KAAK,WAAW;AAItG,UAAO,OAAO,QAAQ,QAAQ,OAAO,WAAW,IAAI;IACtD;AAEF,OAAK,6BAA6B;;CA6BtC,iBACI,MACA,eACA,QACA,cAC+C;AAC/C,MAAI,OAAO,kBAAkB,UAAU;AACnC,OAAI,KAAK,qBAAqB,eAC1B,OAAM,IAAI,MAAM,YAAY,cAAc,wBAAwB;GAGtE,MAAM,qBAAqB,KAAK,0BAC5B,MACC,OAAwB,OACzB,eACA,QACA,aACH;AAED,QAAK,4BAA4B;AACjC,QAAK,yBAAyB;AAC9B,UAAO;SACJ;AACH,OAAI,KAAK,6BAA6B,MAClC,OAAM,IAAI,MAAM,qBAAqB,KAAK,wBAAwB;GAGtE,MAAM,6BAA6B,KAAK,kCACpC,MACC,OAAwB,OACzB,eACA,QACA,aACH;AAED,QAAK,4BAA4B;AACjC,QAAK,yBAAyB;AAC9B,UAAO;;;CAIf,AAAQ,0BACJ,MACA,OACA,KACA,UACA,cACkB;EAClB,MAAMC,qBAAyC;GAC3C;GACA;GACA;GACA;GACA,SAAS;GACT,eAAe,mBAAmB,OAAO,EAAE,SAAS,OAAO,CAAC;GAC5D,cAAc,mBAAmB,OAAO,EAAE,SAAS,MAAM,CAAC;GAC1D,cAAc,mBAAmB,OAAO,EAAE,KAAK,MAAM,CAAC;GACtD,SAAQ,YAAW;AACf,QAAI,QAAQ,QAAQ,UAAa,QAAQ,QAAQ,KAAK;AAClD,YAAO,KAAK,qBAAqB;AACjC,SAAI,QAAQ,IAAK,MAAK,qBAAqB,QAAQ,OAAO;;AAE9D,QAAI,QAAQ,SAAS,OAAW,oBAAmB,OAAO,QAAQ;AAClE,QAAI,QAAQ,UAAU,OAAW,oBAAmB,QAAQ,QAAQ;AACpE,QAAI,QAAQ,aAAa,OAAW,oBAAmB,WAAW,QAAQ;AAC1E,QAAI,QAAQ,aAAa,OAAW,oBAAmB,eAAe,QAAQ;AAC9E,QAAI,QAAQ,YAAY,OAAW,oBAAmB,UAAU,QAAQ;AACxE,SAAK,yBAAyB;;GAErC;AACD,OAAK,qBAAqB,OAAO;AACjC,SAAO;;CAGX,AAAQ,kCACJ,MACA,OACA,UACA,UACA,cAC0B;EAC1B,MAAMC,6BAAyD;GAC3D,kBAAkB;GAClB;GACA;GACA;GACA,SAAS;GACT,eAAe,2BAA2B,OAAO,EAAE,SAAS,OAAO,CAAC;GACpE,cAAc,2BAA2B,OAAO,EAAE,SAAS,MAAM,CAAC;GAClE,cAAc,2BAA2B,OAAO,EAAE,MAAM,MAAM,CAAC;GAC/D,SAAQ,YAAW;AACf,QAAI,QAAQ,SAAS,UAAa,QAAQ,SAAS,MAAM;AACrD,YAAO,KAAK,6BAA6B;AACzC,SAAI,QAAQ,KAAM,MAAK,6BAA6B,QAAQ,QAAQ;;AAExE,QAAI,QAAQ,UAAU,OAAW,4BAA2B,QAAQ,QAAQ;AAC5E,QAAI,QAAQ,aAAa,OAAW,4BAA2B,mBAAmB,QAAQ;AAC1F,QAAI,QAAQ,aAAa,OAAW,4BAA2B,WAAW,QAAQ;AAClF,QAAI,QAAQ,aAAa,OAAW,4BAA2B,eAAe,QAAQ;AACtF,QAAI,QAAQ,YAAY,OAAW,4BAA2B,UAAU,QAAQ;AAChF,SAAK,yBAAyB;;GAErC;AACD,OAAK,6BAA6B,QAAQ;EAG1C,MAAM,gBAAgB,SAAS,YAAY;AAE3C,MADqB,MAAM,QAAQ,cAAc,IAAI,cAAc,MAAK,MAAK,CAAC,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAExG,MAAK,6BAA6B;AAGtC,SAAO;;CAGX,AAAQ,wBACJ,MACA,OACA,aACA,YACA,UACA,OACA,OACgB;EAEhB,IAAI,oBAAoB;EACxB,IAAI,kBAAkB;EAEtB,MAAMC,mBAAqC;GACvC;GACA;GACA;GACA;GACA;GACA,SAAS,oBAAoB,MAAM,YAAY,SAAS;GACxD,SAAS;GACT,eAAe,iBAAiB,OAAO,EAAE,SAAS,OAAO,CAAC;GAC1D,cAAc,iBAAiB,OAAO,EAAE,SAAS,MAAM,CAAC;GACxD,cAAc,iBAAiB,OAAO,EAAE,MAAM,MAAM,CAAC;GACrD,SAAQ,YAAW;AACf,QAAI,QAAQ,SAAS,UAAa,QAAQ,SAAS,MAAM;AACrD,YAAO,KAAK,mBAAmB;AAC/B,SAAI,QAAQ,KAAM,MAAK,mBAAmB,QAAQ,QAAQ;;AAE9D,QAAI,QAAQ,UAAU,OAAW,kBAAiB,QAAQ,QAAQ;AAClE,QAAI,QAAQ,gBAAgB,OAAW,kBAAiB,cAAc,QAAQ;AAC9E,QAAI,QAAQ,UAAU,OAAW,kBAAiB,QAAQ,QAAQ;AAClE,QAAI,QAAQ,UAAU,OAAW,kBAAiB,QAAQ,QAAQ;IAGlE,IAAI,oBAAoB;AACxB,QAAI,QAAQ,eAAe,QAAW;AAClC,sBAAiB,aAAa,QAAQ;AACtC,yBAAoB,QAAQ;AAC5B,yBAAoB;;AAExB,QAAI,QAAQ,aAAa,QAAW;AAChC,uBAAkB,QAAQ;AAC1B,yBAAoB;;AAExB,QAAI,kBACA,kBAAiB,UAAU,oBAAoB,MAAM,mBAAmB,gBAAgB;AAG5F,QAAI,QAAQ,YAAY,OAAW,kBAAiB,UAAU,QAAQ;AACtE,SAAK,uBAAuB;;GAEnC;AACD,OAAK,mBAAmB,QAAQ;AAGhC,MAAI,YAAY;GACZ,MAAM,QAAQ,eAAe,WAAW;AACxC,OAAI,OAKA;QAJuB,OAAO,OAAO,MAAM,CAAC,MAAK,UAAS;AAEtD,YAAO,cADO,qBAAqB,MAAM,CACd;MAC7B,CAEE,MAAK,6BAA6B;;;AAK9C,SAAO;;CAGX,AAAQ,sBACJ,MACA,OACA,aACA,aACA,cACA,aACA,OACA,WACA,OACA,SACc;AAEd,0BAAwB,KAAK;EAG7B,IAAI,iBAAiB;EAErB,MAAMC,iBAAiC;GACnC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACS;GACT,UAAU,mBAAmB,aAAa,QAAQ;GAClD,SAAS;GACT,eAAe,eAAe,OAAO,EAAE,SAAS,OAAO,CAAC;GACxD,cAAc,eAAe,OAAO,EAAE,SAAS,MAAM,CAAC;GACtD,cAAc,eAAe,OAAO,EAAE,MAAM,MAAM,CAAC;GACnD,SAAQ,YAAW;AACf,QAAI,QAAQ,SAAS,UAAa,QAAQ,SAAS,MAAM;AACrD,SAAI,OAAO,QAAQ,SAAS,SACxB,yBAAwB,QAAQ,KAAK;AAEzC,YAAO,KAAK,iBAAiB;AAC7B,SAAI,QAAQ,KAAM,MAAK,iBAAiB,QAAQ,QAAQ;;AAE5D,QAAI,QAAQ,UAAU,OAAW,gBAAe,QAAQ,QAAQ;AAChE,QAAI,QAAQ,gBAAgB,OAAW,gBAAe,cAAc,QAAQ;IAG5E,IAAI,qBAAqB;AACzB,QAAI,QAAQ,iBAAiB,QAAW;AACpC,oBAAe,cAAc,QAAQ;AACrC,0BAAqB;;AAEzB,QAAI,QAAQ,aAAa,QAAW;AAChC,oBAAe,UAAU,QAAQ;AACjC,sBAAiB,QAAQ;AACzB,0BAAqB;;AAEzB,QAAI,mBACA,gBAAe,WAAW,mBAAmB,eAAe,aAAa,eAAe;AAG5F,QAAI,QAAQ,iBAAiB,OAAW,gBAAe,eAAe,QAAQ;AAC9E,QAAI,QAAQ,gBAAgB,OAAW,gBAAe,cAAc,QAAQ;AAC5E,QAAI,QAAQ,UAAU,OAAW,gBAAe,QAAQ,QAAQ;AAChE,QAAI,QAAQ,UAAU,OAAW,gBAAe,QAAQ,QAAQ;AAChE,QAAI,QAAQ,YAAY,OAAW,gBAAe,UAAU,QAAQ;AACpE,SAAK,qBAAqB;;GAEjC;AACD,OAAK,iBAAiB,QAAQ;AAE9B,OAAK,wBAAwB;AAC7B,OAAK,qBAAqB;AAE1B,SAAO;;CAwDX,aACI,MACA,QASA,IACc;AACd,MAAI,KAAK,iBAAiB,MACtB,OAAM,IAAI,MAAM,QAAQ,KAAK,wBAAwB;EAGzD,MAAM,EAAE,OAAO,aAAa,aAAa,cAAc,aAAa,OAAO,UAAU;AAErF,SAAO,KAAK,sBACR,MACA,OACA,aACA,wBAAwB,YAAY,EACpC,wBAAwB,aAAa,EACrC,aACA,OACA,QACA,OACA,GACH;;CAoDL,eACI,MACA,QAOA,IACgB;AAChB,MAAI,KAAK,mBAAmB,MACxB,OAAM,IAAI,MAAM,UAAU,KAAK,wBAAwB;EAG3D,MAAM,EAAE,OAAO,aAAa,YAAY,OAAO,UAAU;EAEzD,MAAM,mBAAmB,KAAK,wBAC1B,MACA,OACA,aACA,wBAAwB,WAAW,EACnC,IACA,OACA,MACH;AAED,OAAK,0BAA0B;AAC/B,OAAK,uBAAuB;AAE5B,SAAO;;;;;;CAOX,cAAc;AACV,SAAO,KAAK,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;CAsBrC,MAAM,mBAAmB,QAA8C,WAAoB;AACvF,SAAO,KAAK,OAAO,mBAAmB,QAAQ,UAAU;;;;;CAK5D,0BAA0B;AACtB,MAAI,KAAK,aAAa,CAClB,MAAK,OAAO,yBAAyB;;;;;CAO7C,sBAAsB;AAClB,MAAI,KAAK,aAAa,CAClB,MAAK,OAAO,qBAAqB;;;;;CAOzC,wBAAwB;AACpB,MAAI,KAAK,aAAa,CAClB,MAAK,OAAO,uBAAuB;;;;;;;AAmB/C,IAAa,mBAAb,MAA8B;CAC1B,AAAQ;CAER,YACI,aACA,AAAQC,YAaV;EAbU;AAcR,OAAK,eAAe,OAAO,gBAAgB,WAAW,IAAI,YAAY,YAAY,GAAG;;;;;CAMzF,IAAI,cAA2B;AAC3B,SAAO,KAAK;;;;;CAMhB,IAAI,eAAkD;AAClD,SAAO,KAAK,WAAW;;;;;CAM3B,iBAAiB,UAAgE;AAC7E,SAAO,KAAK,WAAW,WAAW;;;;;;;;AAsF1C,SAAS,mBACL,aACA,SACY;AACZ,KAAI,aAAa;EACb,MAAMC,aAAW;AACjB,SAAO,OAAO,MAAM,QAAQA,WAAS,MAAM,IAAI;;CAInD,MAAM,WAAW;AACjB,QAAO,OAAO,OAAO,QAAQ,SAAS,IAAI;;AAG9C,MAAM,2BAA2B;CAC7B,MAAM;CACN,YAAY,EAAE;CACjB;;;;;AAwGD,SAAS,oBACL,MACA,YACA,UACa;AACb,KAAI,YAAY;EACZ,MAAM,gBAAgB;AAEtB,SAAO,OAAO,MAAM,QAAQ;GACxB,MAAM,cAAc,MAAM,uBAAuB,YAAY,KAAK;AAClE,OAAI,CAAC,YAAY,QACb,OAAM,IAAI,cAAc,kBAAkB,eAAe,gCAAgC,KAAK,IAAI,YAAY,QAAQ;AAE1H,UAAO,cAAc,YAAY,MAAM,IAAI;;QAE5C;EACH,MAAM,gBAAgB;AAEtB,SAAO,OAAO,OAAO,QAAQ;AACzB,UAAO,cAAc,IAAI;;;;AAKrC,SAAS,uBAAuB,aAAiD;AAE7E,QAAO,EACH,YAAY;EACR,QAHO,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI;EAI5C,OAAO,YAAY;EACnB,SAAS,YAAY,SAAS;EACjC,EACJ;;AAGL,MAAMC,0BAA0C,EAC5C,YAAY;CACR,QAAQ,EAAE;CACV,SAAS;CACZ,EACJ;;AAGD,SAAS,eAAe,QAAsD;CAC1E,MAAM,YAAY;AAClB,KAAI,UAAU,SAAS,OAAO,UAAU,UAAU,SAC9C,QAAO,UAAU;;;AAMzB,SAAS,iBAAiB,QAA0B;AAEhD,QADkB,QACA,SAAS;;;AAI/B,SAAS,qBAAqB,QAA0B;AACpD,KAAI,CAAC,iBAAiB,OAAO,CACzB,QAAO;AAGX,QADkB,OACD,KAAK,aAAa;;;;;;;;;;;AC3xCvC,SAAgB,mBAAmB,YAAuC,kBAAwD;AAC9H,KAAI,CAAC,WACD,QAAO;EAAE,IAAI;EAAO,WAAW;EAAgB,SAAS;EAAuB;CAInF,IAAIC;AACJ,KAAI;AACA,aAAW,IAAI,IAAI,UAAU,aAAa,CAAC;SACvC;AACJ,SAAO;GAAE,IAAI;GAAO,WAAW;GAAuB,SAAS,wBAAwB;GAAc;GAAY;;AAGrH,KAAI,CAAC,iBAAiB,SAAS,SAAS,CACpC,QAAO;EAAE,IAAI;EAAO,WAAW;EAAgB,SAAS,iBAAiB;EAAY;EAAY;EAAU;AAG/G,QAAO;EAAE,IAAI;EAAM;EAAU;;;;;AAMjC,SAAgB,4BAAsC;AAClD,QAAO;EAAC;EAAa;EAAa;EAAQ;;;;;;;;;AAU9C,SAAgB,6BAA6B,KAAc,kBAAkD;CACzG,MAAM,SAAS,mBAAmB,IAAI,QAAQ,IAAI,OAAO,EAAE,iBAAiB;AAC5E,KAAI,OAAO,GAAI,QAAO;AAEtB,QAAO,SAAS,KACZ;EACI,SAAS;EACT,OAAO;GACH,MAAM;GACN,SAAS,OAAO;GACnB;EACD,IAAI;EACP,EACD;EACI,QAAQ;EACR,SAAS,EAAE,gBAAgB,oBAAoB;EAClD,CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC4JL,IAAa,2CAAb,MAA2E;CAEvE,AAAQ;CACR,AAAQ,WAAoB;CAC5B,AAAQ,UAAmB;CAC3B,AAAQ,iCAA6C,IAAI,KAAK;CAC9D,AAAQ,0CAAkD,IAAI,KAAK;CACnE,AAAQ,sCAAsD,IAAI,KAAK;CACvE,AAAQ,eAAwB;CAChC,AAAQ,sBAA+B;CACvC,AAAQ,yBAAiC;CACzC,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER;CACA;CACA;CACA;CAEA,YAAY,UAA2D,EAAE,EAAE;AACvE,OAAK,qBAAqB,QAAQ;AAClC,OAAK,sBAAsB,QAAQ,sBAAsB;AACzD,OAAK,cAAc,QAAQ;AAC3B,OAAK,wBAAwB,QAAQ;AACrC,OAAK,mBAAmB,QAAQ;AAChC,OAAK,gBAAgB,QAAQ;AAC7B,OAAK,kBAAkB,QAAQ;AAC/B,OAAK,gCAAgC,QAAQ,gCAAgC;AAC7E,OAAK,iBAAiB,QAAQ;AAC9B,OAAK,6BAA6B,QAAQ,6BAA6B;;;;;;CAO3E,MAAM,QAAuB;AACzB,MAAI,KAAK,SACL,OAAM,IAAI,MAAM,4BAA4B;AAEhD,OAAK,WAAW;;;;;;CAOpB,6BAA6B,UAA0B;AACnD,OAAK,6BAA6B;;;;;CAMtC,AAAQ,wBACJ,QACA,MACA,SACA,SACQ;EACR,MAAMC,QAA0D;GAAE;GAAM;GAAS;AACjF,MAAI,SAAS,SAAS,OAClB,OAAM,OAAO,QAAQ;AAEzB,SAAO,SAAS,KACZ;GACI,SAAS;GACT;GACA,IAAI;GACP,EACD;GACI;GACA,SAAS;IACL,gBAAgB;IAChB,GAAG,SAAS;IACf;GACJ,CACJ;;;;;;CAOL,AAAQ,uBAAuB,KAAoC;AAE/D,MAAI,CAAC,KAAK,8BACN;AAIJ,MAAI,KAAK,iBAAiB,KAAK,cAAc,SAAS,GAAG;GACrD,MAAM,aAAa,IAAI,QAAQ,IAAI,OAAO;AAC1C,OAAI,CAAC,cAAc,CAAC,KAAK,cAAc,SAAS,WAAW,EAAE;IACzD,MAAM,QAAQ,wBAAwB;AACtC,SAAK,UAAU,IAAI,MAAM,MAAM,CAAC;AAChC,WAAO,KAAK,wBAAwB,KAAK,OAAS,MAAM;;;AAKhE,MAAI,KAAK,mBAAmB,KAAK,gBAAgB,SAAS,GAAG;GACzD,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,OAAI,gBAAgB,CAAC,KAAK,gBAAgB,SAAS,aAAa,EAAE;IAC9D,MAAM,QAAQ,0BAA0B;AACxC,SAAK,UAAU,IAAI,MAAM,MAAM,CAAC;AAChC,WAAO,KAAK,wBAAwB,KAAK,OAAS,MAAM;;;;;;;;CAWpE,MAAM,cAAc,KAAc,SAAmD;EAEjF,MAAM,kBAAkB,KAAK,uBAAuB,IAAI;AACxD,MAAI,gBACA,QAAO;AAGX,UAAQ,IAAI,QAAZ;GACI,KAAK,OACD,QAAO,KAAK,kBAAkB,KAAK,QAAQ;GAE/C,KAAK,MACD,QAAO,KAAK,iBAAiB,IAAI;GAErC,KAAK,SACD,QAAO,KAAK,oBAAoB,IAAI;GAExC,QACI,QAAO,KAAK,0BAA0B;;;;;;;;;;;;;;;CAiBlD,AAAQ,qBAAqB,iBAAkC;AAC3D,SAAO,KAAK,2BAA2B,SAAS,gBAAgB,IAAI,mBAAmB;;;;;;;;CAS3F,MAAc,kBACV,YACA,SACA,UACA,iBACa;AACb,MAAI,CAAC,KAAK,YACN;AAMJ,MAAI,CAAC,KAAK,qBAAqB,gBAAgB,CAC3C;EAGJ,MAAM,iBAAiB,MAAM,KAAK,YAAY,WAAW,UAAU,EAAE,CAAmB;EAExF,IAAI,eAAe,OAAO,eAAe;AACzC,MAAI,KAAK,mBAAmB,OACxB,gBAAe,OAAO,eAAe,WAAW,KAAK,eAAe;AAExE,aAAW,QAAQ,QAAQ,OAAO,aAAa,CAAC;;;;;CAMpD,MAAc,iBAAiB,KAAiC;AAG5D,MAAI,CADiB,IAAI,QAAQ,IAAI,SAAS,EAC3B,SAAS,oBAAoB,EAAE;AAC9C,QAAK,0BAAU,IAAI,MAAM,uDAAuD,CAAC;AACjF,UAAO,KAAK,wBAAwB,KAAK,OAAS,uDAAuD;;EAM7G,MAAM,eAAe,KAAK,gBAAgB,IAAI;AAC9C,MAAI,aACA,QAAO;EAEX,MAAM,gBAAgB,KAAK,wBAAwB,IAAI;AACvD,MAAI,cACA,QAAO;AAIX,MAAI,KAAK,aAAa;GAClB,MAAM,cAAc,IAAI,QAAQ,IAAI,gBAAgB;AACpD,OAAI,YACA,QAAO,KAAK,aAAa,YAAY;;AAK7C,MAAI,KAAK,eAAe,IAAI,KAAK,uBAAuB,KAAK,QAAW;AAEpE,QAAK,0BAAU,IAAI,MAAM,uDAAuD,CAAC;AACjF,UAAO,KAAK,wBAAwB,KAAK,OAAS,uDAAuD;;EAG7G,MAAM,UAAU,IAAI,aAAa;EACjC,IAAIC;EAGJ,MAAM,WAAW,IAAI,eAA2B;GAC5C,QAAO,eAAc;AACjB,uBAAmB;;GAEvB,cAAc;AAEV,SAAK,eAAe,OAAO,KAAK,uBAAuB;;GAE9D,CAAC;EAEF,MAAMC,UAAkC;GACpC,gBAAgB;GAChB,iBAAiB;GACjB,YAAY;GACf;AAGD,MAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;AAIrC,OAAK,eAAe,IAAI,KAAK,wBAAwB;GACjD,YAAY;GACZ;GACA,eAAe;AACX,SAAK,eAAe,OAAO,KAAK,uBAAuB;AACvD,QAAI;AACA,sBAAkB,OAAO;YACrB;;GAIf,CAAC;AAEF,SAAO,IAAI,SAAS,UAAU,EAAE,SAAS,CAAC;;;;;;CAO9C,MAAc,aAAa,aAAwC;AAC/D,MAAI,CAAC,KAAK,aAAa;AACnB,QAAK,0BAAU,IAAI,MAAM,6BAA6B,CAAC;AACvD,UAAO,KAAK,wBAAwB,KAAK,OAAS,6BAA6B;;AAGnF,MAAI;GAEA,IAAIC;AACJ,OAAI,KAAK,YAAY,uBAAuB;AACxC,eAAW,MAAM,KAAK,YAAY,sBAAsB,YAAY;AAEpE,QAAI,CAAC,UAAU;AACX,UAAK,0BAAU,IAAI,MAAM,0BAA0B,CAAC;AACpD,YAAO,KAAK,wBAAwB,KAAK,OAAS,0BAA0B;;AAIhF,QAAI,KAAK,eAAe,IAAI,SAAS,KAAK,QAAW;AACjD,UAAK,0BAAU,IAAI,MAAM,oDAAoD,CAAC;AAC9E,YAAO,KAAK,wBAAwB,KAAK,OAAS,oDAAoD;;;GAI9G,MAAMD,UAAkC;IACpC,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IACf;AAED,OAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;GAIrC,MAAM,UAAU,IAAI,aAAa;GACjC,IAAID;GAEJ,MAAM,WAAW,IAAI,eAA2B;IAC5C,QAAO,eAAc;AACjB,wBAAmB;;IAEvB,cAAc;IAIjB,CAAC;GAGF,MAAM,mBAAmB,MAAM,KAAK,YAAY,kBAAkB,aAAa,EAC3E,MAAM,OAAO,SAAiB,YAA4B;AAEtD,QAAI,CADY,KAAK,cAAc,kBAAmB,SAAS,SAAS,QAAQ,CAE5E,KAAI;AACA,sBAAkB,OAAO;YACrB;MAKnB,CAAC;AAEF,QAAK,eAAe,IAAI,kBAAkB;IACtC,YAAY;IACZ;IACA,eAAe;AACX,UAAK,eAAe,OAAO,iBAAiB;AAC5C,SAAI;AACA,uBAAkB,OAAO;aACrB;;IAIf,CAAC;AAEF,UAAO,IAAI,SAAS,UAAU,EAAE,SAAS,CAAC;WACrC,OAAO;AACZ,QAAK,UAAU,MAAe;AAC9B,UAAO,KAAK,wBAAwB,KAAK,OAAS,yBAAyB;;;;;;CAOnF,AAAQ,cACJ,YACA,SACA,SACA,SACO;AACP,MAAI;GACA,IAAI,YAAY;AAEhB,OAAI,QACA,cAAa,OAAO,QAAQ;AAEhC,gBAAa,SAAS,KAAK,UAAU,QAAQ,CAAC;AAC9C,cAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;AAC7C,UAAO;WACF,OAAO;AACZ,QAAK,UAAU,MAAe;AAC9B,UAAO;;;;;;CAOf,AAAQ,2BAAqC;AACzC,OAAK,0BAAU,IAAI,MAAM,sBAAsB,CAAC;AAChD,SAAO,SAAS,KACZ;GACI,SAAS;GACT,OAAO;IACH,MAAM;IACN,SAAS;IACZ;GACD,IAAI;GACP,EACD;GACI,QAAQ;GACR,SAAS;IACL,OAAO;IACP,gBAAgB;IACnB;GACJ,CACJ;;;;;CAML,MAAc,kBAAkB,KAAc,SAAmD;AAC7F,MAAI;GAEA,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAE9C,OAAI,CAAC,cAAc,SAAS,mBAAmB,IAAI,CAAC,aAAa,SAAS,oBAAoB,EAAE;AAC5F,SAAK,0BAAU,IAAI,MAAM,iFAAiF,CAAC;AAC3G,WAAO,KAAK,wBACR,KACA,OACA,iFACH;;GAGL,MAAM,KAAK,IAAI,QAAQ,IAAI,eAAe;AAC1C,OAAI,CAAC,MAAM,CAAC,GAAG,SAAS,mBAAmB,EAAE;AACzC,SAAK,0BAAU,IAAI,MAAM,gEAAgE,CAAC;AAC1F,WAAO,KAAK,wBAAwB,KAAK,OAAS,gEAAgE;;GAGtH,MAAM,UAAU;GAEhB,IAAI;AACJ,OAAI,SAAS,eAAe,OACxB,KAAI;AACA,iBAAa,MAAM,IAAI,MAAM;YACxB,OAAO;AACZ,SAAK,UAAU,MAAe;AAC9B,WAAO,KAAK,wBAAwB,KAAK,QAAS,4BAA4B;;OAGlF,cAAa,QAAQ;GAGzB,IAAIG;AAGJ,OAAI;AACA,eAAW,MAAM,QAAQ,WAAW,GAC9B,WAAW,KAAI,QAAO,qBAAqB,MAAM,IAAI,CAAC,GACtD,CAAC,qBAAqB,MAAM,WAAW,CAAC;YACzC,OAAO;AACZ,SAAK,UAAU,MAAe;AAC9B,WAAO,KAAK,wBAAwB,KAAK,QAAS,wCAAwC;;GAK9F,MAAM,0BAA0B,SAAS,MAAK,YAAW,oBAAoB,QAAQ,CAAC;AACtF,OAAI,yBAAyB;AAGzB,QAAI,KAAK,gBAAgB,KAAK,cAAc,QAAW;AACnD,UAAK,0BAAU,IAAI,MAAM,8CAA8C,CAAC;AACxE,YAAO,KAAK,wBAAwB,KAAK,QAAS,8CAA8C;;AAEpG,QAAI,SAAS,SAAS,GAAG;AACrB,UAAK,0BAAU,IAAI,MAAM,8DAA8D,CAAC;AACxF,YAAO,KAAK,wBAAwB,KAAK,QAAS,8DAA8D;;AAEpH,SAAK,YAAY,KAAK,sBAAsB;AAC5C,SAAK,eAAe;AAIpB,QAAI,KAAK,aAAa,KAAK,sBACvB,OAAM,QAAQ,QAAQ,KAAK,sBAAsB,KAAK,UAAU,CAAC;;AAGzE,OAAI,CAAC,yBAAyB;IAI1B,MAAM,eAAe,KAAK,gBAAgB,IAAI;AAC9C,QAAI,aACA,QAAO;IAGX,MAAM,gBAAgB,KAAK,wBAAwB,IAAI;AACvD,QAAI,cACA,QAAO;;AAOf,OAAI,CAFgB,SAAS,MAAK,YAAW,iBAAiB,QAAQ,CAAC,EAErD;AAEd,SAAK,MAAM,WAAW,SAClB,MAAK,YAAY,SAAS;KAAE,UAAU,SAAS;KAAU;KAAS,CAAC;AAEvE,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;GAK9C,MAAM,WAAW,OAAO,YAAY;GAKpC,MAAM,cAAc,SAAS,MAAK,MAAK,oBAAoB,EAAE,CAAC;GAC9D,MAAM,wBAAwB,cACxB,YAAY,OAAO,kBAClB,IAAI,QAAQ,IAAI,uBAAuB,IAAI;AAElD,OAAI,KAAK,oBAEL,QAAO,IAAI,SAAkB,YAAW;AACpC,SAAK,eAAe,IAAI,UAAU;KAC9B,aAAa;KACb,eAAe;AACX,WAAK,eAAe,OAAO,SAAS;;KAE3C,CAAC;AAEF,SAAK,MAAM,WAAW,SAClB,KAAI,iBAAiB,QAAQ,CACzB,MAAK,wBAAwB,IAAI,QAAQ,IAAI,SAAS;AAI9D,SAAK,MAAM,WAAW,SAClB,MAAK,YAAY,SAAS;KAAE,UAAU,SAAS;KAAU;KAAS,CAAC;KAEzE;GAIN,MAAM,UAAU,IAAI,aAAa;GACjC,IAAIH;GAEJ,MAAM,WAAW,IAAI,eAA2B;IAC5C,QAAO,eAAc;AACjB,wBAAmB;;IAEvB,cAAc;AAEV,UAAK,eAAe,OAAO,SAAS;;IAE3C,CAAC;GAEF,MAAMC,UAAkC;IACpC,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IACf;AAGD,OAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;AAKrC,QAAK,MAAM,WAAW,SAClB,KAAI,iBAAiB,QAAQ,EAAE;AAC3B,SAAK,eAAe,IAAI,UAAU;KAC9B,YAAY;KACZ;KACA,eAAe;AACX,WAAK,eAAe,OAAO,SAAS;AACpC,UAAI;AACA,wBAAkB,OAAO;cACrB;;KAIf,CAAC;AACF,SAAK,wBAAwB,IAAI,QAAQ,IAAI,SAAS;;AAK9D,SAAM,KAAK,kBAAkB,kBAAmB,SAAS,UAAU,sBAAsB;AAGzF,QAAK,MAAM,WAAW,UAAU;IAK5B,IAAIG;IACJ,IAAIC;AACJ,QAAI,iBAAiB,QAAQ,IAAI,KAAK,eAAe,KAAK,qBAAqB,sBAAsB,EAAE;AACnG,4BAAuB;AACnB,WAAK,eAAe,QAAQ,GAAG;;AAEnC,sCAAiC;AAC7B,WAAK,0BAA0B;;;AAIvC,SAAK,YAAY,SAAS;KAAE,UAAU,SAAS;KAAU;KAAS;KAAgB;KAA0B,CAAC;;AAKjH,UAAO,IAAI,SAAS,UAAU;IAAE,QAAQ;IAAK;IAAS,CAAC;WAClD,OAAO;AAEZ,QAAK,UAAU,MAAe;AAC9B,UAAO,KAAK,wBAAwB,KAAK,QAAS,eAAe,EAAE,MAAM,OAAO,MAAM,EAAE,CAAC;;;;;;CAOjG,MAAc,oBAAoB,KAAiC;EAC/D,MAAM,eAAe,KAAK,gBAAgB,IAAI;AAC9C,MAAI,aACA,QAAO;EAEX,MAAM,gBAAgB,KAAK,wBAAwB,IAAI;AACvD,MAAI,cACA,QAAO;AAGX,QAAM,QAAQ,QAAQ,KAAK,mBAAmB,KAAK,UAAW,CAAC;AAC/D,QAAM,KAAK,OAAO;AAClB,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;;;;;CAO9C,AAAQ,gBAAgB,KAAoC;AACxD,MAAI,KAAK,uBAAuB,OAG5B;AAEJ,MAAI,CAAC,KAAK,cAAc;AAEpB,QAAK,0BAAU,IAAI,MAAM,sCAAsC,CAAC;AAChE,UAAO,KAAK,wBAAwB,KAAK,OAAS,sCAAsC;;EAG5F,MAAM,YAAY,IAAI,QAAQ,IAAI,iBAAiB;AAEnD,MAAI,CAAC,WAAW;AAEZ,QAAK,0BAAU,IAAI,MAAM,iDAAiD,CAAC;AAC3E,UAAO,KAAK,wBAAwB,KAAK,OAAS,iDAAiD;;AAGvG,MAAI,cAAc,KAAK,WAAW;AAE9B,QAAK,0BAAU,IAAI,MAAM,oBAAoB,CAAC;AAC9C,UAAO,KAAK,wBAAwB,KAAK,QAAS,oBAAoB;;;;;;;;;;;;;;;;CAmB9E,AAAQ,wBAAwB,KAAoC;EAChE,MAAM,kBAAkB,IAAI,QAAQ,IAAI,uBAAuB;AAE/D,MAAI,oBAAoB,QAAQ,CAAC,KAAK,2BAA2B,SAAS,gBAAgB,EAAE;GACxF,MAAM,QAAQ,8CAA8C,gBAAgB,wBAAwB,KAAK,2BAA2B,KAAK,KAAK,CAAC;AAC/I,QAAK,UAAU,IAAI,MAAM,MAAM,CAAC;AAChC,UAAO,KAAK,wBAAwB,KAAK,OAAS,MAAM;;;CAKhE,MAAM,QAAuB;AACzB,MAAI,KAAK,QACL;AAEJ,OAAK,UAAU;AAGf,OAAK,MAAM,EAAE,aAAa,KAAK,eAAe,QAAQ,CAClD,UAAS;AAEb,OAAK,eAAe,OAAO;AAG3B,OAAK,oBAAoB,OAAO;AAChC,OAAK,WAAW;;;;;;;CAQpB,eAAe,WAA4B;EACvC,MAAM,WAAW,KAAK,wBAAwB,IAAI,UAAU;AAC5D,MAAI,CAAC,SAAU;EAEf,MAAM,SAAS,KAAK,eAAe,IAAI,SAAS;AAChD,MAAI,OACA,QAAO,SAAS;;;;;;CAQxB,2BAAiC;EAC7B,MAAM,SAAS,KAAK,eAAe,IAAI,KAAK,uBAAuB;AACnE,MAAI,OACA,QAAO,SAAS;;CAIxB,MAAM,KAAK,SAAyB,SAA2D;EAC3F,IAAI,YAAY,SAAS;AACzB,MAAI,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ,CAEnE,aAAY,QAAQ;AAMxB,MAAI,cAAc,QAAW;AAEzB,OAAI,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ,CACnE,OAAM,IAAI,MAAM,8FAA8F;GAKlH,IAAIC;AACJ,OAAI,KAAK,YAEL,WAAU,MAAM,KAAK,YAAY,WAAW,KAAK,wBAAwB,QAAQ;GAGrF,MAAM,gBAAgB,KAAK,eAAe,IAAI,KAAK,uBAAuB;AAC1E,OAAI,kBAAkB,OAElB;AAIJ,OAAI,cAAc,cAAc,cAAc,QAC1C,MAAK,cAAc,cAAc,YAAY,cAAc,SAAS,SAAS,QAAQ;AAEzF;;EAIJ,MAAM,WAAW,KAAK,wBAAwB,IAAI,UAAU;AAC5D,MAAI,CAAC,SACD,OAAM,IAAI,MAAM,6CAA6C,OAAO,UAAU,GAAG;EAGrF,MAAM,SAAS,KAAK,eAAe,IAAI,SAAS;AAEhD,MAAI,CAAC,KAAK,uBAAuB,QAAQ,cAAc,QAAQ,SAAS;GAEpE,IAAIA;AAEJ,OAAI,KAAK,YACL,WAAU,MAAM,KAAK,YAAY,WAAW,UAAU,QAAQ;AAGlE,QAAK,cAAc,OAAO,YAAY,OAAO,SAAS,SAAS,QAAQ;;AAG3E,MAAI,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ,EAAE;AACrE,QAAK,oBAAoB,IAAI,WAAW,QAAQ;GAChD,MAAM,aAAa,CAAC,GAAG,KAAK,wBAAwB,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,QAAQ,SAAS,CAAC,KAAK,CAAC,QAAQ,GAAG;AAKvH,OAF0B,WAAW,OAAM,OAAM,KAAK,oBAAoB,IAAI,GAAG,CAAC,EAE3D;AACnB,QAAI,CAAC,OACD,OAAM,IAAI,MAAM,6CAA6C,OAAO,UAAU,GAAG;AAErF,QAAI,KAAK,uBAAuB,OAAO,aAAa;KAEhD,MAAML,UAAkC,EACpC,gBAAgB,oBACnB;AACD,SAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;KAGrC,MAAM,YAAY,WAAW,KAAI,OAAM,KAAK,oBAAoB,IAAI,GAAG,CAAE;AAEzE,SAAI,UAAU,WAAW,EACrB,QAAO,YAAY,SAAS,KAAK,UAAU,IAAI;MAAE,QAAQ;MAAK;MAAS,CAAC,CAAC;SAEzE,QAAO,YAAY,SAAS,KAAK,WAAW;MAAE,QAAQ;MAAK;MAAS,CAAC,CAAC;UAI1E,QAAO,SAAS;AAGpB,SAAK,MAAM,MAAM,YAAY;AACzB,UAAK,oBAAoB,OAAO,GAAG;AACnC,UAAK,wBAAwB,OAAO,GAAG;;;;;;;;;ACrhC3D,IAAIM;AAEJ,SAAgB,eAA4B,QAAwB,WAA+D;AAC/H,QAAOC,iBAAsB,QAAQ,cAAc,sBAAsB,IAAI,4BAA4B,EAAE"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["messageExtra: MessageExtraInfo","resolve!: (response: Response) => void","reject!: (error: Error) => void","controller!: ReadableStreamDefaultController<Uint8Array>","error: { code: number; message: string; data?: string }","streamController: ReadableStreamDefaultController<Uint8Array>","headers: Record<string, string>","streamId: string | undefined","replayedStreamId: string | undefined","messages: JSONRPCMessage[]","closeSSEStream: (() => void) | undefined","closeStandaloneSSEStream: (() => void) | undefined","eventId: string | undefined","body: unknown","bodyText: string","bus: ServerEventBus","legacyHandler: LegacyHttpHandler | undefined","hostname: string","hostname: string","cryptoKey: ReturnType<typeof subtle.importKey> | undefined","envelope: { p: T; exp: number; b?: string }","macBytes: Uint8Array<ArrayBuffer>","_defaultValidator: jsonSchemaValidator | undefined","coreFromJsonSchema"],"sources":["../src/server/perRequestTransport.ts","../src/server/invoke.ts","../src/server/streamableHttp.ts","../src/server/createMcpHandler.ts","../src/server/middleware/hostHeaderValidation.ts","../src/server/middleware/originValidation.ts","../src/server/requestStateCodec.ts","../src/fromJsonSchema.ts"],"sourcesContent":["/**\n * A single-exchange, per-request HTTP server transport for modern-era\n * (protocol revision 2026-07-28) serving.\n *\n * One transport instance serves exactly one already-classified inbound\n * JSON-RPC message and produces exactly one HTTP `Response`:\n *\n * - a `202` with no body for notifications,\n * - a single JSON body for requests whose handler produces no streamed\n * output, or\n * - a lazily-opened SSE stream when the handler emits related messages\n * (notifications or server-to-client requests) before its result — the\n * stream carries those messages and finally the terminal result, then\n * closes.\n *\n * The transport is constructed already-classified: the entry parses and\n * classifies the request body exactly once and hands the classification in via\n * the constructor; the transport attaches it (together with the original\n * request and any caller-provided auth info) to every message it delivers, and\n * the protocol layer validates it against the serving instance's negotiated\n * era. `authInfo` is strictly pass-through — it is never derived from the\n * inbound request's headers here.\n *\n * Deliberately NOT carried over from the session-oriented streamable HTTP\n * transport: session ids and session headers, resumability (event ids,\n * priming events, `Last-Event-ID` replay, retry hints), the standalone GET\n * stream, and request-header validation (which belongs to middleware). The\n * exchange is single-use; serving another request requires a new transport\n * (and, in the per-request serving model, a fresh server instance).\n */\nimport type {\n AuthInfo,\n JSONRPCErrorResponse,\n JSONRPCMessage,\n JSONRPCNotification,\n JSONRPCRequest,\n MessageClassification,\n MessageExtraInfo,\n RequestId,\n Transport,\n TransportSendOptions\n} from '@modelcontextprotocol/core-internal';\nimport {\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n LADDER_ERROR_HTTP_STATUS,\n SdkError,\n SdkErrorCode\n} from '@modelcontextprotocol/core-internal';\n\n/**\n * How the transport shapes its HTTP response for a request:\n *\n * - `auto` (default): answer with a single JSON body unless the handler emits\n * a related message before its result, in which case the response upgrades\n * to an SSE stream.\n * - `sse`: always answer handler output over an SSE stream. The stream opens\n * once the request has passed the pre-dispatch validation gates, so ladder\n * rejections keep their mapped HTTP status instead of being framed onto a\n * 200 stream.\n * - `json`: never stream; related messages other than the terminal response\n * are dropped.\n */\nexport type PerRequestResponseMode = 'auto' | 'sse' | 'json';\n\n/** Constructor options for {@linkcode PerRequestHTTPServerTransport}. */\nexport interface PerRequestHTTPServerTransportOptions {\n /** The edge classification of the message this transport will serve. */\n classification: MessageClassification;\n /** Response shaping for the exchange; defaults to `auto`. */\n responseMode?: PerRequestResponseMode;\n}\n\n/** Per-exchange context handed to {@linkcode PerRequestHTTPServerTransport.handleMessage}. */\nexport interface PerRequestMessageExtra {\n /**\n * The original HTTP request. Used for handler context and, when the\n * runtime provides an abort signal on it, to cancel the exchange when the\n * client disconnects.\n */\n request?: globalThis.Request;\n /**\n * Validated authentication information supplied by the caller. Strictly\n * pass-through: the transport never populates this from request headers.\n */\n authInfo?: AuthInfo;\n}\n\ninterface DeferredResponse {\n promise: Promise<Response>;\n resolve: (response: Response) => void;\n reject: (error: Error) => void;\n settled: boolean;\n}\n\ninterface SseSink {\n controller: ReadableStreamDefaultController<Uint8Array>;\n encoder: InstanceType<typeof TextEncoder>;\n closed: boolean;\n}\n\n/**\n * The per-request micro-transport: a real, connected `Transport` whose whole\n * lifetime is one HTTP exchange. See the module documentation for the\n * response shapes it produces.\n */\nexport class PerRequestHTTPServerTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: <T extends JSONRPCMessage>(message: T, extra?: MessageExtraInfo) => void;\n\n private readonly _classification: MessageClassification;\n private readonly _responseMode: PerRequestResponseMode;\n\n private _started = false;\n private _used = false;\n private _closed = false;\n private _terminalDelivered = false;\n /**\n * `true` only while the inbound message is being delivered synchronously\n * to the connected protocol layer. The pre-handler gates (the era\n * registry gate, the edge→instance handoff check, the missing-handler\n * rejection) answer inside this window; request handlers always run\n * after it (the protocol layer defers them to a microtask). An error\n * sent inside the window is therefore ladder-originated, and an error\n * sent after it is handler-produced.\n */\n private _dispatchWindowOpen = false;\n private _requestId?: RequestId;\n private _deferredResponse?: DeferredResponse;\n private _sse?: SseSink;\n private _abortCleanup?: () => void;\n\n constructor(options: PerRequestHTTPServerTransportOptions) {\n this._classification = options.classification;\n this._responseMode = options.responseMode ?? 'auto';\n }\n\n async start(): Promise<void> {\n if (this._started) {\n throw new Error('PerRequestHTTPServerTransport is already started');\n }\n this._started = true;\n }\n\n /**\n * Serves the single exchange: delivers the classified message to the\n * connected server instance and resolves with the HTTP response.\n *\n * Throws when called a second time (the transport is strictly\n * single-use), or before a server has been connected to the transport.\n * The returned promise rejects with a connection-closed error when the\n * transport is closed before a response was produced (for example because\n * the client disconnected).\n */\n async handleMessage(message: JSONRPCRequest | JSONRPCNotification, extra?: PerRequestMessageExtra): Promise<Response> {\n if (this._used) {\n throw new Error('PerRequestHTTPServerTransport serves exactly one exchange; construct a new transport per request');\n }\n if (!this._started || this.onmessage === undefined) {\n throw new Error('PerRequestHTTPServerTransport is not connected: connect a server to this transport before handling a message');\n }\n if (this._closed) {\n throw new Error('PerRequestHTTPServerTransport is closed');\n }\n this._used = true;\n\n const signal = extra?.request?.signal;\n if (signal?.aborted) {\n await this.close();\n throw new SdkError(SdkErrorCode.ConnectionClosed, 'The request was aborted before it could be handled');\n }\n\n // authInfo is strictly pass-through from the caller; it is never\n // derived from the inbound request's headers.\n const messageExtra: MessageExtraInfo = {\n classification: this._classification,\n ...(extra?.request !== undefined && { request: extra.request }),\n ...(extra?.authInfo !== undefined && { authInfo: extra.authInfo })\n };\n\n if (isJSONRPCRequest(message)) {\n this._requestId = message.id;\n\n let resolve!: (response: Response) => void;\n let reject!: (error: Error) => void;\n const promise = new Promise<Response>((promiseResolve, promiseReject) => {\n resolve = promiseResolve;\n reject = promiseReject;\n });\n this._deferredResponse = { promise, resolve, reject, settled: false };\n\n if (signal !== undefined) {\n const onAbort = () => void this.close();\n signal.addEventListener('abort', onAbort, { once: true });\n this._abortCleanup = () => signal.removeEventListener('abort', onAbort);\n }\n\n this._dispatchWindowOpen = true;\n try {\n this.onmessage(message, messageExtra);\n } finally {\n this._dispatchWindowOpen = false;\n }\n\n if (this._responseMode === 'sse' && !this._closed && !this._deferredResponse.settled) {\n // Forced-SSE exchanges open their stream as soon as the\n // request has passed the pre-dispatch gates: a ladder\n // rejection settles inside the dispatch window with its\n // mapped HTTP status, while handler output — including\n // comment frames written before the first message — streams\n // as before.\n this.upgradeToSse();\n }\n return promise;\n }\n\n // Notifications never get a JSON-RPC response: deliver the message and\n // acknowledge the POST with 202 and no body.\n this.onmessage(message, messageExtra);\n return new Response(null, { status: 202 });\n }\n\n async send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void> {\n if (this._closed) {\n // The exchange is over; late writes are dropped.\n return;\n }\n\n const isResponse = isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message);\n const relatedId = isResponse ? (message as { id: RequestId }).id : options?.relatedRequestId;\n\n if (this._requestId === undefined || relatedId === undefined || relatedId !== this._requestId) {\n if (isResponse) {\n this.onerror?.(new Error(`Received a response for an unknown request id: ${String((message as { id?: unknown }).id)}`));\n }\n // Messages unrelated to the single in-flight request have nowhere\n // to go on a per-request exchange (there is no session-wide\n // stream); they are dropped.\n return;\n }\n\n if (isResponse) {\n if (this._terminalDelivered) {\n return;\n }\n this._terminalDelivered = true;\n\n // The HTTP status is keyed on the error's origin, not on its bare\n // code: only errors produced inside the dispatch window — the\n // validation ladder, the era registry gate and handoff check, a\n // missing handler — are answered with the mapped HTTP status from\n // the ladder table. Handler-produced errors, whatever their code,\n // stay in-band on HTTP 200. Ladder rejections keep that mapped\n // status in every response mode (the SSE upgrade is deferred to\n // the first actual send), so a forced-`sse` exchange still\n // answers pre-dispatch rejections as plain HTTP errors.\n const ladderStatus =\n this._dispatchWindowOpen && isJSONRPCErrorResponse(message)\n ? LADDER_ERROR_HTTP_STATUS[(message as JSONRPCErrorResponse).error.code]\n : undefined;\n if (ladderStatus !== undefined && this._sse === undefined) {\n this.settleResponse(Response.json(message, { status: ladderStatus, headers: { 'Content-Type': 'application/json' } }));\n queueMicrotask(() => void this.close());\n return;\n }\n\n if (this._sse !== undefined || this._responseMode === 'sse') {\n // Finalize the stream: serialize the terminal result onto it\n // after everything already enqueued, then close.\n if (this._sse === undefined) {\n this.upgradeToSse();\n }\n this.writeMessageFrame(message);\n this.finalizeStream();\n return;\n }\n\n // Single JSON body.\n this.settleResponse(Response.json(message, { status: 200, headers: { 'Content-Type': 'application/json' } }));\n queueMicrotask(() => void this.close());\n return;\n }\n\n // A message related to the in-flight request that is not its terminal\n // response: a mid-call notification or a server-to-client request\n // emitted by the handler.\n if (this._responseMode === 'json') {\n // JSON responses cannot carry mid-call messages; they are dropped.\n return;\n }\n if (this._sse === undefined) {\n this.upgradeToSse();\n }\n this.writeMessageFrame(message);\n }\n\n /**\n * Writes an SSE comment frame (a keep-alive heartbeat). Dropped when the\n * exchange is not currently streaming.\n */\n writeCommentFrame(comment: string): void {\n if (this._closed || this._sse === undefined || this._sse.closed) {\n return;\n }\n const frame = comment\n .split('\\n')\n .map(line => `: ${line}`)\n .join('\\n');\n this.writeFrame(`${frame}\\n\\n`);\n }\n\n async close(): Promise<void> {\n if (this._closed) {\n return;\n }\n this._closed = true;\n\n this._abortCleanup?.();\n this._abortCleanup = undefined;\n\n if (this._sse !== undefined && !this._sse.closed) {\n this._sse.closed = true;\n try {\n this._sse.controller.close();\n } catch {\n // The stream was already closed or cancelled by the consumer.\n }\n }\n\n if (this._deferredResponse !== undefined && !this._deferredResponse.settled) {\n this._deferredResponse.settled = true;\n this._deferredResponse.reject(new SdkError(SdkErrorCode.ConnectionClosed, 'Connection closed before a response was produced'));\n }\n\n this.onclose?.();\n }\n\n private settleResponse(response: Response): void {\n if (this._deferredResponse === undefined || this._deferredResponse.settled) {\n return;\n }\n this._deferredResponse.settled = true;\n this._deferredResponse.resolve(response);\n }\n\n private upgradeToSse(): void {\n let controller!: ReadableStreamDefaultController<Uint8Array>;\n const readable = new ReadableStream<Uint8Array>({\n start: streamController => {\n controller = streamController;\n },\n cancel: () => {\n // The client went away mid-stream: tear the exchange down,\n // which aborts the in-flight handler through the connected\n // server's close chain.\n void this.close();\n }\n });\n this._sse = { controller, encoder: new TextEncoder(), closed: false };\n\n this.settleResponse(\n new Response(readable, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n // Disable proxy buffering so streamed messages are\n // delivered as they are written.\n 'X-Accel-Buffering': 'no'\n }\n })\n );\n }\n\n private finalizeStream(): void {\n if (this._sse !== undefined && !this._sse.closed) {\n this._sse.closed = true;\n try {\n this._sse.controller.close();\n } catch {\n // The stream was already cancelled by the consumer.\n }\n }\n queueMicrotask(() => void this.close());\n }\n\n private writeMessageFrame(message: JSONRPCMessage): void {\n this.writeFrame(`event: message\\ndata: ${JSON.stringify(message)}\\n\\n`);\n }\n\n private writeFrame(frame: string): void {\n if (this._sse === undefined || this._sse.closed) {\n return;\n }\n try {\n this._sse.controller.enqueue(this._sse.encoder.encode(frame));\n } catch (error) {\n this.onerror?.(new Error(`Failed to write to the response stream: ${error}`));\n }\n }\n}\n","/**\n * The internal per-request invoke seam for modern-era HTTP serving.\n *\n * One classified inbound message is served by composing existing pieces, with\n * no changes to the protocol dispatch layer:\n *\n * server instance (from the consumer's factory)\n * → `connect(per-request transport)`\n * → inject the classified message through the transport's message callback\n * → capture the value (a single JSON body or an SSE stream) via the\n * transport's send path.\n *\n * The seam is value-returning and independently testable: it resolves with the\n * HTTP `Response` for the exchange. Marking factory instances as modern-era\n * (and installing modern-only handlers) is the calling entry's responsibility\n * and happens before this seam runs; the seam itself never writes era state.\n */\nimport type { AuthInfo, JSONRPCNotification, JSONRPCRequest, MessageClassification } from '@modelcontextprotocol/core-internal';\n\nimport type { McpServer } from './mcp';\nimport type { PerRequestResponseMode } from './perRequestTransport';\nimport { PerRequestHTTPServerTransport } from './perRequestTransport';\nimport type { Server } from './server';\n\n/** Per-exchange context for {@linkcode invoke}. */\nexport interface InvokeContext {\n /** The edge classification of the message (computed once, at the entry boundary). */\n classification: MessageClassification;\n /** The original HTTP request, when serving HTTP traffic. */\n request?: globalThis.Request;\n /**\n * Validated authentication information supplied by the caller. Strictly\n * pass-through — never derived from request headers by this seam.\n */\n authInfo?: AuthInfo;\n /** Response shaping for the exchange; defaults to `auto` (lazy SSE upgrade). */\n responseMode?: PerRequestResponseMode;\n}\n\n/**\n * Serves one classified inbound message on the given server instance and\n * returns the HTTP response for the exchange.\n *\n * The instance is connected to a fresh single-exchange transport, the message\n * is injected through the normal transport message path, and whatever the\n * dispatch layer produces (the handler result, a protocol-level rejection, or\n * streamed related messages followed by the result) is captured as the\n * returned `Response`. For request exchanges, teardown rides the transport's\n * close chain once the terminal response has been delivered; notification\n * exchanges resolve with the 202 response immediately and do NOT run the\n * close chain — the transport stays connected until the caller closes it or\n * drops the per-request instance, which is the caller's choice either way.\n */\nexport async function invoke(\n server: Server | McpServer,\n message: JSONRPCRequest | JSONRPCNotification,\n ctx: InvokeContext\n): Promise<Response> {\n const transport = new PerRequestHTTPServerTransport({\n classification: ctx.classification,\n ...(ctx.responseMode !== undefined && { responseMode: ctx.responseMode })\n });\n await server.connect(transport);\n return transport.handleMessage(message, {\n ...(ctx.request !== undefined && { request: ctx.request }),\n ...(ctx.authInfo !== undefined && { authInfo: ctx.authInfo })\n });\n}\n","/**\n * Web Standards Streamable HTTP Server Transport\n *\n * This is the core transport implementation using Web Standard APIs (`Request`, `Response`, `ReadableStream`).\n * It can run on any runtime that supports Web Standards: Node.js 18+, Cloudflare Workers, Deno, Bun, etc.\n *\n * For Node.js Express/HTTP compatibility, use {@linkcode @modelcontextprotocol/node!NodeStreamableHTTPServerTransport | NodeStreamableHTTPServerTransport} which wraps this transport.\n */\n\nimport type { AuthInfo, JSONRPCMessage, MessageExtraInfo, RequestId, Transport } from '@modelcontextprotocol/core-internal';\nimport {\n DEFAULT_NEGOTIATED_PROTOCOL_VERSION,\n isInitializeRequest,\n isJSONRPCErrorResponse,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n JSONRPCMessageSchema,\n SUPPORTED_PROTOCOL_VERSIONS\n} from '@modelcontextprotocol/core-internal';\n\nexport type StreamId = string;\nexport type EventId = string;\n\n/**\n * Interface for resumability support via event storage\n */\nexport interface EventStore {\n /**\n * Stores an event for later retrieval\n * @param streamId ID of the stream the event belongs to\n * @param message The JSON-RPC message to store\n * @returns The generated event ID for the stored event\n */\n storeEvent(streamId: StreamId, message: JSONRPCMessage): Promise<EventId>;\n\n /**\n * Get the stream ID associated with a given event ID.\n * @param eventId The event ID to look up\n * @returns The stream ID, or `undefined` if not found\n *\n * Optional: If not provided, the SDK will use the `streamId` returned by\n * {@linkcode replayEventsAfter} for stream mapping.\n */\n getStreamIdForEventId?(eventId: EventId): Promise<StreamId | undefined>;\n\n replayEventsAfter(\n lastEventId: EventId,\n {\n send\n }: {\n send: (eventId: EventId, message: JSONRPCMessage) => Promise<void>;\n }\n ): Promise<StreamId>;\n}\n\n/**\n * Internal stream mapping for managing SSE connections\n */\ninterface StreamMapping {\n /** Stream controller for pushing SSE data - only used with `ReadableStream` approach */\n controller?: ReadableStreamDefaultController<Uint8Array>;\n /** Text encoder for SSE formatting */\n encoder?: InstanceType<typeof TextEncoder>;\n /** Promise resolver for JSON response mode */\n resolveJson?: (response: Response) => void;\n /**\n * Event ids already written to this stream by `replayEventsAfter` — lets\n * `send()` skip a duplicate write when the resumed stream registered\n * during the `storeEvent()` await and replay already delivered the event.\n */\n replayedEventIds?: Set<string>;\n /** Cleanup function to close stream and remove mapping */\n cleanup: () => void;\n}\n\n/**\n * Configuration options for {@linkcode WebStandardStreamableHTTPServerTransport}\n */\nexport interface WebStandardStreamableHTTPServerTransportOptions {\n /**\n * Function that generates a session ID for the transport.\n * The session ID SHOULD be globally unique and cryptographically secure (e.g., a securely generated UUID, a JWT, or a cryptographic hash)\n *\n * If not provided, session management is disabled (stateless mode).\n */\n sessionIdGenerator?: (() => string) | undefined;\n\n /**\n * A callback for session initialization events\n * This is called when the server initializes a new session.\n * Useful in cases when you need to register multiple mcp sessions\n * and need to keep track of them.\n * @param sessionId The generated session ID\n */\n onsessioninitialized?: ((sessionId: string) => void | Promise<void>) | undefined;\n\n /**\n * A callback for session close events\n * This is called when the server closes a session due to a `DELETE` request.\n * Useful in cases when you need to clean up resources associated with the session.\n * Note that this is different from the transport closing, if you are handling\n * HTTP requests from multiple nodes you might want to close each\n * {@linkcode WebStandardStreamableHTTPServerTransport} after a request is completed while still keeping the\n * session open/running.\n * @param sessionId The session ID that was closed\n */\n onsessionclosed?: ((sessionId: string) => void | Promise<void>) | undefined;\n\n /**\n * If `true`, the server will return JSON responses instead of starting an SSE stream.\n * This can be useful for simple request/response scenarios without streaming.\n * Default is `false` (SSE streams are preferred).\n */\n enableJsonResponse?: boolean;\n\n /**\n * Event store for resumability support\n * If provided, resumability will be enabled, allowing clients to reconnect and resume messages\n */\n eventStore?: EventStore;\n\n /**\n * List of allowed `Host` header values for DNS rebinding protection.\n * If not specified, host validation is disabled.\n * @deprecated Use external middleware for host validation instead.\n */\n allowedHosts?: string[];\n\n /**\n * List of allowed `Origin` header values for DNS rebinding protection.\n * If not specified, origin validation is disabled.\n * @deprecated Use external middleware for origin validation instead.\n */\n allowedOrigins?: string[];\n\n /**\n * Enable DNS rebinding protection (requires `allowedHosts` and/or `allowedOrigins` to be configured).\n * Default is `false` for backwards compatibility.\n * @deprecated Use external middleware for DNS rebinding protection instead.\n */\n enableDnsRebindingProtection?: boolean;\n\n /**\n * Retry interval in milliseconds to suggest to clients in SSE `retry` field.\n * When set, the server will send a `retry` field in SSE priming events to control\n * client reconnection timing for polling behavior.\n */\n retryInterval?: number;\n\n /**\n * List of protocol versions that this transport will accept.\n * Used to validate the `mcp-protocol-version` header in incoming requests.\n *\n * Note: When using {@linkcode server/server.Server.connect | Server.connect()}, the server automatically passes its\n * `supportedProtocolVersions` to the transport, so you typically don't need\n * to set this option directly.\n *\n * @default {@linkcode SUPPORTED_PROTOCOL_VERSIONS}\n */\n supportedProtocolVersions?: string[];\n}\n\n/**\n * Options for handling a request\n */\nexport interface HandleRequestOptions {\n /**\n * Pre-parsed request body. If provided, the transport will use this instead of parsing `req.json()`.\n * Useful when using body-parser middleware that has already parsed the body.\n */\n parsedBody?: unknown;\n\n /**\n * Authentication info from middleware. If provided, will be passed to message handlers.\n */\n authInfo?: AuthInfo;\n}\n\n/**\n * Server transport for Web Standards Streamable HTTP: this implements the MCP Streamable HTTP transport specification\n * using Web Standard APIs (`Request`, `Response`, `ReadableStream`).\n *\n * This transport works on any runtime that supports Web Standards: Node.js 18+, Cloudflare Workers, Deno, Bun, etc.\n *\n * In stateful mode:\n * - Session ID is generated and included in response headers\n * - Session ID is always included in initialization responses\n * - Requests with invalid session IDs are rejected with `404 Not Found`\n * - Non-initialization requests without a session ID are rejected with `400 Bad Request`\n * - State is maintained in-memory (connections, message history)\n *\n * In stateless mode:\n * - No Session ID is included in any responses\n * - No session validation is performed\n *\n * @example Stateful setup\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_stateful\"\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n *\n * const transport = new WebStandardStreamableHTTPServerTransport({\n * sessionIdGenerator: () => crypto.randomUUID()\n * });\n *\n * await server.connect(transport);\n * ```\n *\n * @example Stateless setup\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_stateless\"\n * const transport = new WebStandardStreamableHTTPServerTransport({\n * sessionIdGenerator: undefined\n * });\n * ```\n *\n * @example Hono.js\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_hono\"\n * app.all('/mcp', async c => {\n * return transport.handleRequest(c.req.raw);\n * });\n * ```\n *\n * @example Cloudflare Workers\n * ```ts source=\"./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_workers\"\n * const worker = {\n * async fetch(request: Request): Promise<Response> {\n * return transport.handleRequest(request);\n * }\n * };\n * ```\n */\nexport class WebStandardStreamableHTTPServerTransport implements Transport {\n // when sessionId is not set (undefined), it means the transport is in stateless mode\n private sessionIdGenerator: (() => string) | undefined;\n private _started: boolean = false;\n private _closed: boolean = false;\n private _streamMapping: Map<string, StreamMapping> = new Map();\n private _requestToStreamMapping: Map<RequestId, string> = new Map();\n private _requestResponseMap: Map<RequestId, JSONRPCMessage> = new Map();\n private _initialized: boolean = false;\n private _enableJsonResponse: boolean = false;\n private _standaloneSseStreamId: string = '_GET_stream';\n private _eventStore?: EventStore;\n private _onsessioninitialized?: ((sessionId: string) => void | Promise<void>) | undefined;\n private _onsessionclosed?: ((sessionId: string) => void | Promise<void>) | undefined;\n private _allowedHosts?: string[];\n private _allowedOrigins?: string[];\n private _enableDnsRebindingProtection: boolean;\n private _retryInterval?: number;\n private _supportedProtocolVersions: string[];\n\n sessionId?: string;\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void;\n\n constructor(options: WebStandardStreamableHTTPServerTransportOptions = {}) {\n this.sessionIdGenerator = options.sessionIdGenerator;\n this._enableJsonResponse = options.enableJsonResponse ?? false;\n this._eventStore = options.eventStore;\n this._onsessioninitialized = options.onsessioninitialized;\n this._onsessionclosed = options.onsessionclosed;\n this._allowedHosts = options.allowedHosts;\n this._allowedOrigins = options.allowedOrigins;\n this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;\n this._retryInterval = options.retryInterval;\n this._supportedProtocolVersions = options.supportedProtocolVersions ?? SUPPORTED_PROTOCOL_VERSIONS;\n }\n\n /**\n * Starts the transport. This is required by the {@linkcode Transport} interface but is a no-op\n * for the Streamable HTTP transport as connections are managed per-request.\n */\n async start(): Promise<void> {\n if (this._started) {\n throw new Error('Transport already started');\n }\n this._started = true;\n }\n\n /**\n * Sets the supported protocol versions for header validation.\n * Called by the server during {@linkcode server/server.Server.connect | connect()} to pass its supported versions.\n */\n setSupportedProtocolVersions(versions: string[]): void {\n this._supportedProtocolVersions = versions;\n }\n\n /**\n * Helper to create a JSON error response\n */\n private createJsonErrorResponse(\n status: number,\n code: number,\n message: string,\n options?: { headers?: Record<string, string>; data?: string }\n ): Response {\n const error: { code: number; message: string; data?: string } = { code, message };\n if (options?.data !== undefined) {\n error.data = options.data;\n }\n return Response.json(\n {\n jsonrpc: '2.0',\n error,\n id: null\n },\n {\n status,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n }\n );\n }\n\n /**\n * Validates request headers for DNS rebinding protection.\n * @returns Error response if validation fails, `undefined` if validation passes.\n */\n private validateRequestHeaders(req: Request): Response | undefined {\n // Skip validation if protection is not enabled\n if (!this._enableDnsRebindingProtection) {\n return undefined;\n }\n\n // Validate Host header if allowedHosts is configured\n if (this._allowedHosts && this._allowedHosts.length > 0) {\n const hostHeader = req.headers.get('host');\n if (!hostHeader || !this._allowedHosts.includes(hostHeader)) {\n const error = `Invalid Host header: ${hostHeader}`;\n this.onerror?.(new Error(error));\n return this.createJsonErrorResponse(403, -32_000, error);\n }\n }\n\n // Validate Origin header if allowedOrigins is configured\n if (this._allowedOrigins && this._allowedOrigins.length > 0) {\n const originHeader = req.headers.get('origin');\n if (originHeader && !this._allowedOrigins.includes(originHeader)) {\n const error = `Invalid Origin header: ${originHeader}`;\n this.onerror?.(new Error(error));\n return this.createJsonErrorResponse(403, -32_000, error);\n }\n }\n\n return undefined;\n }\n\n /**\n * Handles an incoming HTTP request, whether `GET`, `POST`, or `DELETE`\n * Returns a `Response` object (Web Standard)\n */\n async handleRequest(req: Request, options?: HandleRequestOptions): Promise<Response> {\n // Validate request headers for DNS rebinding protection\n const validationError = this.validateRequestHeaders(req);\n if (validationError) {\n return validationError;\n }\n\n switch (req.method) {\n case 'POST': {\n return this.handlePostRequest(req, options);\n }\n case 'GET': {\n return this.handleGetRequest(req);\n }\n case 'DELETE': {\n return this.handleDeleteRequest(req);\n }\n default: {\n return this.handleUnsupportedRequest();\n }\n }\n }\n\n /**\n * Returns true if the client's protocol version supports empty SSE data in\n * priming events (the fix shipped with protocol version `2025-11-25`).\n *\n * The version is checked for membership in this transport instance's\n * supported protocol versions rather than with an open-ended\n * `>= '2025-11-25'` comparison: the value may come from an `initialize`\n * request body, which (unlike the `MCP-Protocol-Version` header) is not\n * validated against `supportedProtocolVersions` before reaching this\n * check. An unknown future version string must not silently enable\n * behavior reserved for versions this transport actually supports.\n */\n private supportsEmptySSEData(protocolVersion: string): boolean {\n return this._supportedProtocolVersions.includes(protocolVersion) && protocolVersion >= '2025-11-25';\n }\n\n /**\n * Writes a priming event to establish resumption capability.\n * Only sends if `eventStore` is configured (opt-in for resumability) and\n * the client's protocol version supports empty SSE data (a supported\n * version that is >= `2025-11-25`).\n */\n private async writePrimingEvent(\n controller: ReadableStreamDefaultController<Uint8Array>,\n encoder: InstanceType<typeof TextEncoder>,\n streamId: string,\n protocolVersion: string\n ): Promise<void> {\n if (!this._eventStore) {\n return;\n }\n\n // Priming events have empty data which older clients cannot handle.\n // Only send priming events to clients whose protocol version includes\n // the fix for handling empty SSE data.\n if (!this.supportsEmptySSEData(protocolVersion)) {\n return;\n }\n\n const primingEventId = await this._eventStore.storeEvent(streamId, {} as JSONRPCMessage);\n\n let primingEvent = `id: ${primingEventId}\\ndata: \\n\\n`;\n if (this._retryInterval !== undefined) {\n primingEvent = `id: ${primingEventId}\\nretry: ${this._retryInterval}\\ndata: \\n\\n`;\n }\n controller.enqueue(encoder.encode(primingEvent));\n }\n\n /**\n * Handles `GET` requests for SSE stream\n */\n private async handleGetRequest(req: Request): Promise<Response> {\n // The client MUST include an Accept header, listing text/event-stream as a supported content type.\n const acceptHeader = req.headers.get('accept');\n if (!acceptHeader?.includes('text/event-stream')) {\n this.onerror?.(new Error('Not Acceptable: Client must accept text/event-stream'));\n return this.createJsonErrorResponse(406, -32_000, 'Not Acceptable: Client must accept text/event-stream');\n }\n\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n const sessionError = this.validateSession(req);\n if (sessionError) {\n return sessionError;\n }\n const protocolError = this.validateProtocolVersion(req);\n if (protocolError) {\n return protocolError;\n }\n\n // Handle resumability: check for Last-Event-ID header\n if (this._eventStore) {\n const lastEventId = req.headers.get('last-event-id');\n if (lastEventId) {\n return this.replayEvents(lastEventId);\n }\n }\n\n // Check if there's already an active standalone SSE stream for this session\n if (this._streamMapping.get(this._standaloneSseStreamId) !== undefined) {\n // Only one GET SSE stream is allowed per session\n this.onerror?.(new Error('Conflict: Only one SSE stream is allowed per session'));\n return this.createJsonErrorResponse(409, -32_000, 'Conflict: Only one SSE stream is allowed per session');\n }\n\n const encoder = new TextEncoder();\n let streamController: ReadableStreamDefaultController<Uint8Array>;\n\n // Create a ReadableStream with a controller we can use to push SSE events\n const readable = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n cancel: () => {\n // Stream was cancelled by client. Only drop the mapping when\n // it still points at THIS controller — a stale cancel must not\n // delete a successor stream registered by a later GET/resume.\n if (this._streamMapping.get(this._standaloneSseStreamId)?.controller === streamController) {\n this._streamMapping.delete(this._standaloneSseStreamId);\n }\n }\n });\n\n const headers: Record<string, string> = {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive'\n };\n\n // After initialization, always include the session ID if we have one\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n // Store the stream mapping with the controller for pushing data\n this._streamMapping.set(this._standaloneSseStreamId, {\n controller: streamController!,\n encoder,\n cleanup: () => {\n this._streamMapping.delete(this._standaloneSseStreamId);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n });\n\n return new Response(readable, { headers });\n }\n\n /**\n * Replays events that would have been sent after the specified event ID\n * Only used when resumability is enabled\n */\n private async replayEvents(lastEventId: string): Promise<Response> {\n if (!this._eventStore) {\n this.onerror?.(new Error('Event store not configured'));\n return this.createJsonErrorResponse(400, -32_000, 'Event store not configured');\n }\n\n try {\n // If getStreamIdForEventId is available, use it for conflict checking\n let streamId: string | undefined;\n if (this._eventStore.getStreamIdForEventId) {\n streamId = await this._eventStore.getStreamIdForEventId(lastEventId);\n\n if (!streamId) {\n this.onerror?.(new Error('Invalid event ID format'));\n return this.createJsonErrorResponse(400, -32_000, 'Invalid event ID format');\n }\n\n // Check conflict with the SAME streamId we'll use for mapping\n if (this._streamMapping.get(streamId) !== undefined) {\n this.onerror?.(new Error('Conflict: Stream already has an active connection'));\n return this.createJsonErrorResponse(409, -32_000, 'Conflict: Stream already has an active connection');\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive'\n };\n\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n // Create a ReadableStream with controller for SSE\n const encoder = new TextEncoder();\n let streamController: ReadableStreamDefaultController<Uint8Array>;\n // Captured by the cancel closure below before it's assigned (after\n // replayEventsAfter resolves) — must be `let`.\n // eslint-disable-next-line prefer-const\n let replayedStreamId: string | undefined;\n\n const readable = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n cancel: () => {\n // Stream was cancelled by client — drop the mapping so a\n // subsequent reconnect with the same Last-Event-ID is not\n // refused with 409 by the conflict check above. Only delete\n // when the mapped entry is still THIS closure's controller:\n // a stale cancel from an earlier resume must not delete a\n // successor resumed stream a re-poll has since registered.\n if (replayedStreamId !== undefined && this._streamMapping.get(replayedStreamId)?.controller === streamController) {\n this._streamMapping.delete(replayedStreamId);\n }\n }\n });\n\n // Replay events - returns the streamId for backwards compatibility\n const replayedEventIds = new Set<string>();\n replayedStreamId = await this._eventStore.replayEventsAfter(lastEventId, {\n send: async (eventId: string, message: JSONRPCMessage) => {\n replayedEventIds.add(eventId);\n const success = this.writeSSEEvent(streamController!, encoder, message, eventId);\n if (!success) {\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n }\n });\n\n this._streamMapping.set(replayedStreamId, {\n controller: streamController!,\n encoder,\n replayedEventIds,\n cleanup: () => {\n this._streamMapping.delete(replayedStreamId!);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n });\n\n // If this is a per-request stream and no in-flight request still\n // targets this streamId, the request was already retired by the\n // clean-return path while disconnected and the replay above just\n // delivered the final response. Per the spec the server SHOULD\n // close the SSE stream after the JSON-RPC response — close and\n // unregister so a later reconnect isn't refused with 409. The\n // standalone GET stream is never request-scoped and stays open.\n if (replayedStreamId !== this._standaloneSseStreamId) {\n const hasInFlightRequest = [...this._requestToStreamMapping.values()].includes(replayedStreamId);\n if (!hasInFlightRequest) {\n this._streamMapping.delete(replayedStreamId);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n }\n\n return new Response(readable, { headers });\n } catch (error) {\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(500, -32_000, 'Error replaying events');\n }\n }\n\n /**\n * Writes an event to an SSE stream via controller with proper formatting\n */\n private writeSSEEvent(\n controller: ReadableStreamDefaultController<Uint8Array>,\n encoder: InstanceType<typeof TextEncoder>,\n message: JSONRPCMessage,\n eventId?: string\n ): boolean {\n try {\n let eventData = `event: message\\n`;\n // Include event ID if provided - this is important for resumability\n if (eventId) {\n eventData += `id: ${eventId}\\n`;\n }\n eventData += `data: ${JSON.stringify(message)}\\n\\n`;\n controller.enqueue(encoder.encode(eventData));\n return true;\n } catch (error) {\n this.onerror?.(error as Error);\n return false;\n }\n }\n\n /**\n * Handles unsupported requests (`PUT`, `PATCH`, etc.)\n */\n private handleUnsupportedRequest(): Response {\n this.onerror?.(new Error('Method not allowed.'));\n return Response.json(\n {\n jsonrpc: '2.0',\n error: {\n code: -32_000,\n message: 'Method not allowed.'\n },\n id: null\n },\n {\n status: 405,\n headers: {\n Allow: 'GET, POST, DELETE',\n 'Content-Type': 'application/json'\n }\n }\n );\n }\n\n /**\n * Handles `POST` requests containing JSON-RPC messages\n */\n private async handlePostRequest(req: Request, options?: HandleRequestOptions): Promise<Response> {\n try {\n // Validate the Accept header\n const acceptHeader = req.headers.get('accept');\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (!acceptHeader?.includes('application/json') || !acceptHeader.includes('text/event-stream')) {\n this.onerror?.(new Error('Not Acceptable: Client must accept both application/json and text/event-stream'));\n return this.createJsonErrorResponse(\n 406,\n -32_000,\n 'Not Acceptable: Client must accept both application/json and text/event-stream'\n );\n }\n\n const ct = req.headers.get('content-type');\n if (!ct || !ct.includes('application/json')) {\n this.onerror?.(new Error('Unsupported Media Type: Content-Type must be application/json'));\n return this.createJsonErrorResponse(415, -32_000, 'Unsupported Media Type: Content-Type must be application/json');\n }\n\n const request = req;\n\n let rawMessage;\n if (options?.parsedBody === undefined) {\n try {\n rawMessage = await req.json();\n } catch (error) {\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON');\n }\n } else {\n rawMessage = options.parsedBody;\n }\n\n let messages: JSONRPCMessage[];\n\n // handle batch and single messages\n try {\n messages = Array.isArray(rawMessage)\n ? rawMessage.map(msg => JSONRPCMessageSchema.parse(msg))\n : [JSONRPCMessageSchema.parse(rawMessage)];\n } catch (error) {\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON-RPC message');\n }\n\n // Check if this is an initialization request\n // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/\n // The schema-validated guard (types/guards.ts → types/schemas.ts —\n // NOT a wire/rev* import) gates a transport state mutation: a\n // malformed `initialize` must NOT set `_initialized = true` before\n // the protocol layer rejects it.\n const isInitializationRequest = messages.some(element => isInitializeRequest(element));\n if (isInitializationRequest) {\n // If it's a server with session management and the session ID is already set we should reject the request\n // to avoid re-initialization.\n if (this._initialized && this.sessionId !== undefined) {\n this.onerror?.(new Error('Invalid Request: Server already initialized'));\n return this.createJsonErrorResponse(400, -32_600, 'Invalid Request: Server already initialized');\n }\n if (messages.length > 1) {\n this.onerror?.(new Error('Invalid Request: Only one initialization request is allowed'));\n return this.createJsonErrorResponse(400, -32_600, 'Invalid Request: Only one initialization request is allowed');\n }\n this.sessionId = this.sessionIdGenerator?.();\n this._initialized = true;\n\n // If we have a session ID and an onsessioninitialized handler, call it immediately\n // This is needed in cases where the server needs to keep track of multiple sessions\n if (this.sessionId && this._onsessioninitialized) {\n await Promise.resolve(this._onsessioninitialized(this.sessionId));\n }\n }\n if (!isInitializationRequest) {\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n const sessionError = this.validateSession(req);\n if (sessionError) {\n return sessionError;\n }\n // Mcp-Protocol-Version header is required for all requests after initialization.\n const protocolError = this.validateProtocolVersion(req);\n if (protocolError) {\n return protocolError;\n }\n }\n\n // check if it contains requests\n const hasRequests = messages.some(element => isJSONRPCRequest(element));\n\n if (!hasRequests) {\n // if it only contains notifications or responses, return 202\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: options?.authInfo, request });\n }\n return new Response(null, { status: 202 });\n }\n\n // The default behavior is to use SSE streaming\n // but in some cases server will return JSON responses\n const streamId = crypto.randomUUID();\n\n // Extract protocol version for priming event decision.\n // For initialize requests, get from request params.\n // For other requests, get from header (already validated).\n const initRequest = messages.find(m => isInitializeRequest(m));\n const clientProtocolVersion = initRequest\n ? initRequest.params.protocolVersion\n : (req.headers.get('mcp-protocol-version') ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION);\n\n if (this._enableJsonResponse) {\n // For JSON response mode, return a Promise that resolves when all responses are ready\n return new Promise<Response>(resolve => {\n this._streamMapping.set(streamId, {\n resolveJson: resolve,\n cleanup: () => {\n this._streamMapping.delete(streamId);\n }\n });\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this._requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n for (const message of messages) {\n this.onmessage?.(message, { authInfo: options?.authInfo, request });\n }\n });\n }\n\n // SSE streaming mode - use ReadableStream with controller for more reliable data pushing\n const encoder = new TextEncoder();\n let streamController: ReadableStreamDefaultController<Uint8Array>;\n\n const readable = new ReadableStream<Uint8Array>({\n start: controller => {\n streamController = controller;\n },\n cancel: () => {\n // Stream was cancelled by client. Only drop the mapping\n // when it still points at THIS controller — a stale cancel\n // (firing after a Last-Event-ID reconnect registered a\n // resumed stream under the same streamId) must not delete\n // the successor.\n if (this._streamMapping.get(streamId)?.controller === streamController) {\n this._streamMapping.delete(streamId);\n }\n }\n });\n\n const headers: Record<string, string> = {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive'\n };\n\n // After initialization, always include the session ID if we have one\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n // Store the response for this request to send messages back through this connection\n // We need to track by request ID to maintain the connection\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n this._streamMapping.set(streamId, {\n controller: streamController!,\n encoder,\n cleanup: () => {\n this._streamMapping.delete(streamId);\n try {\n streamController!.close();\n } catch {\n // Controller might already be closed\n }\n }\n });\n this._requestToStreamMapping.set(message.id, streamId);\n }\n }\n\n // Write priming event if event store is configured (after mapping is set up)\n await this.writePrimingEvent(streamController!, encoder, streamId, clientProtocolVersion);\n\n // handle each message\n for (const message of messages) {\n // Build closeSSEStream callback for requests when eventStore is configured\n // AND client supports resumability (a supported protocol version >= 2025-11-25).\n // Old clients can't resume if the stream is closed early because they\n // didn't receive a priming event with an event ID.\n let closeSSEStream: (() => void) | undefined;\n let closeStandaloneSSEStream: (() => void) | undefined;\n if (isJSONRPCRequest(message) && this._eventStore && this.supportsEmptySSEData(clientProtocolVersion)) {\n closeSSEStream = () => {\n this.closeSSEStream(message.id);\n };\n closeStandaloneSSEStream = () => {\n this.closeStandaloneSSEStream();\n };\n }\n\n this.onmessage?.(message, { authInfo: options?.authInfo, request, closeSSEStream, closeStandaloneSSEStream });\n }\n // The server SHOULD NOT close the SSE stream before sending all JSON-RPC responses\n // This will be handled by the send() method when responses are ready\n\n return new Response(readable, { status: 200, headers });\n } catch (error) {\n // return JSON-RPC formatted error\n this.onerror?.(error as Error);\n return this.createJsonErrorResponse(400, -32_700, 'Parse error', { data: String(error) });\n }\n }\n\n /**\n * Handles `DELETE` requests to terminate sessions\n */\n private async handleDeleteRequest(req: Request): Promise<Response> {\n const sessionError = this.validateSession(req);\n if (sessionError) {\n return sessionError;\n }\n const protocolError = this.validateProtocolVersion(req);\n if (protocolError) {\n return protocolError;\n }\n\n await Promise.resolve(this._onsessionclosed?.(this.sessionId!));\n await this.close();\n return new Response(null, { status: 200 });\n }\n\n /**\n * Validates session ID for non-initialization requests.\n * Returns `Response` error if invalid, `undefined` otherwise\n */\n private validateSession(req: Request): Response | undefined {\n if (this.sessionIdGenerator === undefined) {\n // If the sessionIdGenerator ID is not set, the session management is disabled\n // and we don't need to validate the session ID\n return undefined;\n }\n if (!this._initialized) {\n // If the server has not been initialized yet, reject all requests\n this.onerror?.(new Error('Bad Request: Server not initialized'));\n return this.createJsonErrorResponse(400, -32_000, 'Bad Request: Server not initialized');\n }\n\n const sessionId = req.headers.get('mcp-session-id');\n\n if (!sessionId) {\n // Non-initialization requests without a session ID should return 400 Bad Request\n this.onerror?.(new Error('Bad Request: Mcp-Session-Id header is required'));\n return this.createJsonErrorResponse(400, -32_000, 'Bad Request: Mcp-Session-Id header is required');\n }\n\n if (sessionId !== this.sessionId) {\n // Reject requests with invalid session ID with 404 Not Found\n this.onerror?.(new Error('Session not found'));\n return this.createJsonErrorResponse(404, -32_001, 'Session not found');\n }\n\n return undefined;\n }\n\n /**\n * Validates the `MCP-Protocol-Version` header on incoming requests.\n *\n * For initialization: Version negotiation handles unknown versions gracefully\n * (server responds with its supported version).\n *\n * For subsequent requests with `MCP-Protocol-Version` header:\n * - Accept if in supported list\n * - 400 if unsupported\n *\n * For HTTP requests without the `MCP-Protocol-Version` header:\n * - Accept and default to the version negotiated at initialization\n */\n private validateProtocolVersion(req: Request): Response | undefined {\n const protocolVersion = req.headers.get('mcp-protocol-version');\n\n if (protocolVersion !== null && !this._supportedProtocolVersions.includes(protocolVersion)) {\n const error = `Bad Request: Unsupported protocol version: ${protocolVersion} (supported versions: ${this._supportedProtocolVersions.join(', ')})`;\n this.onerror?.(new Error(error));\n return this.createJsonErrorResponse(400, -32_000, error);\n }\n return undefined;\n }\n\n async close(): Promise<void> {\n if (this._closed) {\n return;\n }\n this._closed = true;\n\n // Close all SSE connections\n for (const { cleanup } of this._streamMapping.values()) {\n cleanup();\n }\n this._streamMapping.clear();\n\n // Clear any pending responses\n this._requestResponseMap.clear();\n this.onclose?.();\n }\n\n /**\n * Close an SSE stream for a specific request, triggering client reconnection.\n * Use this to implement polling behavior during long-running operations -\n * client will reconnect after the retry interval specified in the priming event.\n */\n closeSSEStream(requestId: RequestId): void {\n const streamId = this._requestToStreamMapping.get(requestId);\n if (!streamId) return;\n\n const stream = this._streamMapping.get(streamId);\n if (stream) {\n stream.cleanup();\n }\n }\n\n /**\n * Close the standalone `GET` SSE stream, triggering client reconnection.\n * Use this to implement polling behavior for server-initiated notifications.\n */\n closeStandaloneSSEStream(): void {\n const stream = this._streamMapping.get(this._standaloneSseStreamId);\n if (stream) {\n stream.cleanup();\n }\n }\n\n async send(message: JSONRPCMessage, options?: { relatedRequestId?: RequestId }): Promise<void> {\n let requestId = options?.relatedRequestId;\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n // If the message is a response, use the request ID from the message\n requestId = message.id;\n }\n\n // Check if this message should be sent on the standalone SSE stream (no request ID)\n // Ignore notifications from tools (which have relatedRequestId set)\n // Those will be sent via dedicated response SSE streams\n if (requestId === undefined) {\n // For standalone SSE streams, we can only send requests and notifications\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n throw new Error('Cannot send a response on a standalone SSE stream unless resuming a previous client request');\n }\n\n // Generate and store event ID if event store is provided\n // Store even if stream is disconnected so events can be replayed on reconnect\n let eventId: string | undefined;\n if (this._eventStore) {\n // Stores the event and gets the generated event ID\n eventId = await this._eventStore.storeEvent(this._standaloneSseStreamId, message);\n }\n\n const standaloneSse = this._streamMapping.get(this._standaloneSseStreamId);\n if (standaloneSse === undefined) {\n // Stream is disconnected - event is stored for replay, nothing more to do\n return;\n }\n\n // Send the message to the standalone SSE stream — unless the\n // resumed stream's replay already delivered this exact eventId\n // (identity dedup; mirrors the per-request path below).\n if (\n standaloneSse.controller &&\n standaloneSse.encoder &&\n (eventId === undefined || !standaloneSse.replayedEventIds?.has(eventId))\n ) {\n this.writeSSEEvent(standaloneSse.controller, standaloneSse.encoder, message, eventId);\n }\n return;\n }\n\n // Get the response for this request\n const streamId = this._requestToStreamMapping.get(requestId);\n if (!streamId) {\n throw new Error(`No connection established for request ID: ${String(requestId)}`);\n }\n\n let stream = this._streamMapping.get(streamId);\n\n if (!this._enableJsonResponse) {\n // Store FIRST so request-related events emitted while the per-request\n // stream is disconnected (e.g. after `closeSSE()` or a transient\n // client drop) are replayed on Last-Event-ID reconnect — same\n // store-first semantics as the standalone path above. Storage is\n // keyed on request-in-flight (`_requestToStreamMapping` resolved\n // `streamId` above), not on whether a live SSE writer currently\n // exists: `_streamMapping` tracks the delivery target only. Per\n // 2025-11-25 transports.mdx, disconnection SHOULD NOT be\n // interpreted as the client cancelling its request.\n let eventId: string | undefined;\n if (this._eventStore) {\n eventId = await this._eventStore.storeEvent(streamId, message);\n // Re-read after the await: a Last-Event-ID reconnect during\n // storeEvent() may have registered a resumed stream under this\n // streamId (mirrors the standalone path's post-await read).\n stream = this._streamMapping.get(streamId);\n }\n // Write the event to the response stream — unless the resumed\n // stream's replay already delivered this exact eventId (the store\n // committed before replay scanned, so replay wrote it; identity\n // dedup only, no ordering assumption).\n if (stream?.controller && stream?.encoder && (eventId === undefined || !stream.replayedEventIds?.has(eventId))) {\n this.writeSSEEvent(stream.controller, stream.encoder, message, eventId);\n }\n }\n\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n this._requestResponseMap.set(requestId, message);\n const relatedIds = [...this._requestToStreamMapping.entries()].filter(([_, sid]) => sid === streamId).map(([id]) => id);\n\n // Check if we have responses for all requests using this connection\n const allResponsesReady = relatedIds.every(id => this._requestResponseMap.has(id));\n\n if (allResponsesReady) {\n if (!stream) {\n if (this._enableJsonResponse) {\n // JSON-mode requires a resolveJson sink; with no stream entry the\n // response is undeliverable.\n throw new Error(`No connection established for request ID: ${String(requestId)}`);\n }\n if (!this._eventStore) {\n // SSE-mode with no live writer and no event store: the\n // response is undeliverable AND not stored. Surface via\n // onerror so the drop is observable (matching pre-PR\n // behaviour), then run the bookkeeping cleanup so the\n // request id is retired.\n this.onerror?.(\n new Error(\n `Response for request ID ${String(requestId)} is undeliverable: per-request stream is disconnected and no eventStore is configured`\n )\n );\n for (const id of relatedIds) {\n this._requestResponseMap.delete(id);\n this._requestToStreamMapping.delete(id);\n }\n return;\n }\n // SSE-mode with no live writer and an event store configured:\n // the response was stored above for replay on Last-Event-ID\n // reconnect. Return cleanly after running the bookkeeping\n // cleanup so the request id is retired.\n for (const id of relatedIds) {\n this._requestResponseMap.delete(id);\n this._requestToStreamMapping.delete(id);\n }\n return;\n }\n if (this._enableJsonResponse && stream.resolveJson) {\n // All responses ready, send as JSON\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json'\n };\n if (this.sessionId !== undefined) {\n headers['mcp-session-id'] = this.sessionId;\n }\n\n const responses = relatedIds.map(id => this._requestResponseMap.get(id)!);\n\n if (responses.length === 1) {\n stream.resolveJson(Response.json(responses[0], { status: 200, headers }));\n } else {\n stream.resolveJson(Response.json(responses, { status: 200, headers }));\n }\n stream.cleanup();\n } else {\n // End the SSE stream\n stream.cleanup();\n }\n // Clean up\n for (const id of relatedIds) {\n this._requestResponseMap.delete(id);\n this._requestToStreamMapping.delete(id);\n }\n }\n }\n }\n}\n","/**\n * `createMcpHandler` — the HTTP entry point for serving the 2026-07-28 protocol\n * revision, with old-school stateless 2025-era serving as the default fallback.\n *\n * The entry classifies every inbound HTTP request exactly once (body-primary,\n * via {@linkcode classifyInboundRequest}) and routes it:\n *\n * - Requests carrying the per-request `_meta` envelope are served on the modern\n * path: a fresh server instance from the consumer's factory, marked as\n * serving the claimed revision, connected to a single-exchange per-request\n * transport.\n * - Requests without an envelope claim (including `initialize`, GET/DELETE\n * session operations, and 2025-era notification POSTs) are legacy traffic.\n * By default they are served per request through the stateless idiom from\n * the same factory (`legacy: 'stateless'`); with `legacy: 'reject'` the\n * endpoint is modern-only strict and answers the documented rejection cells\n * instead — there is no 2025 serving in that mode.\n *\n * There is no handler-valued `legacy` option: an existing legacy deployment\n * (for example a sessionful streamable HTTP wiring) keeps serving 2025 traffic\n * by routing in user land with {@linkcode isLegacyRequest} — the entry's own\n * classification step, exported as a predicate — in front of a strict\n * (`legacy: 'reject'`) handler.\n *\n * The entry performs no Origin/Host validation (mount the origin/host\n * validation middleware in front of it) and no token verification — `authInfo`\n * is pass-through from the caller and is never derived from request headers.\n */\nimport type {\n AuthInfo,\n ClientCapabilities,\n Implementation,\n InboundClassificationOutcome,\n InboundLadderRejection,\n InboundLegacyRoute,\n InboundModernRoute,\n RequestId\n} from '@modelcontextprotocol/core-internal';\nimport {\n classifyInboundRequest,\n CLIENT_CAPABILITIES_META_KEY,\n CLIENT_INFO_META_KEY,\n httpStatusForErrorCode,\n missingClientCapabilities,\n MissingRequiredClientCapabilityError,\n modernOnlyStrictRejection,\n requestMetaOf,\n requiredClientCapabilitiesForRequest,\n scanXMcpHeaderDeclarations,\n SdkError,\n SdkErrorCode,\n setNegotiatedProtocolVersion,\n SUPPORTED_MODERN_PROTOCOL_VERSIONS,\n UnsupportedProtocolVersionError,\n validateMcpParamHeaders,\n validateStandardRequestHeaders\n} from '@modelcontextprotocol/core-internal';\n\nimport { invoke } from './invoke';\nimport { createListenRouter, DEFAULT_LISTEN_KEEPALIVE_MS, DEFAULT_MAX_SUBSCRIPTIONS } from './listenRouter';\nimport { McpServer } from './mcp';\nimport type { PerRequestResponseMode } from './perRequestTransport';\nimport type { Server } from './server';\nimport { installModernOnlyHandlers, seedClientIdentityFromEnvelope } from './server';\nimport type { ServerEventBus, ServerNotifier } from './serverEventBus';\nimport { createServerNotifier, InMemoryServerEventBus } from './serverEventBus';\nimport { WebStandardStreamableHTTPServerTransport } from './streamableHttp';\n\n/* ------------------------------------------------------------------------ *\n * Factory and handler types\n * ------------------------------------------------------------------------ */\n\n/**\n * Construction context handed to an {@linkcode McpServerFactory}.\n *\n * Both serving entries call the factory with this context whenever they need\n * a fresh instance: {@linkcode createMcpHandler} once per HTTP request, and\n * `serveStdio` (from `@modelcontextprotocol/server/stdio`) once per\n * connection — plus once for a `server/discover` probe instance that is\n * discarded again if the client falls back to `initialize`.\n *\n * Zero-argument factories remain assignable unchanged; the context exists for\n * factories that vary by principal or era (for example multi-tenant servers\n * keyed off `authInfo`, or a factory that registers extra surface only for one\n * era).\n */\nexport interface McpRequestContext {\n /**\n * The protocol era the constructed instance will serve: `modern` for\n * 2026-07-28 (per-request envelope) traffic, `legacy` for 2025-era\n * traffic. Under {@linkcode createMcpHandler} a `legacy` instance serves\n * one request through the stateless legacy fallback (the default —\n * `legacy: 'reject'` endpoints are strict and never construct one); under\n * `serveStdio` it serves a connection that opened with the 2025 handshake\n * and stays pinned to that era for its lifetime.\n */\n era: 'legacy' | 'modern';\n /**\n * Validated authentication information passed by the caller of the\n * handler face (pass-through; HTTP only — `serveStdio` never sets it).\n */\n authInfo?: AuthInfo;\n /** The original HTTP request being served, when available (HTTP only — `serveStdio` never sets it). */\n requestInfo?: Request;\n}\n\n/**\n * A factory producing a fresh {@linkcode McpServer} (or low-level\n * {@linkcode Server}) instance for one serving unit: one HTTP request under\n * {@linkcode createMcpHandler}, or one connection (or one discarded\n * `server/discover` probe) under `serveStdio`. The same factory backs every\n * era either entry serves — define your tools, resources and prompts once and\n * serve them to both eras.\n */\nexport type McpServerFactory = (ctx: McpRequestContext) => McpServer | Server | Promise<McpServer | Server>;\n\n/** Caller-provided per-request inputs for {@linkcode McpHttpHandler.fetch} and fetch-shaped legacy handlers ({@linkcode LegacyHttpHandler}). */\nexport interface McpHandlerRequestOptions {\n /**\n * Validated authentication information for the request. Strictly\n * pass-through: the handler never populates this from request headers and\n * performs no token verification of its own.\n */\n authInfo?: AuthInfo;\n /** A pre-parsed JSON request body (e.g. `req.body` from `express.json()`). */\n parsedBody?: unknown;\n}\n\n/**\n * A fetch-shaped handler serving 2025-era traffic: the shape produced by\n * {@linkcode legacyStatelessFallback}, and the shape a hand-wired composition\n * routes legacy requests to (see {@linkcode isLegacyRequest}). It is not a\n * `legacy` option value — the entry's own legacy serving is selected by the\n * `'stateless' | 'reject'` posture only.\n */\nexport type LegacyHttpHandler = (request: Request, options?: McpHandlerRequestOptions) => Promise<Response>;\n\n/** Options for {@linkcode createMcpHandler}. */\nexport interface CreateMcpHandlerOptions {\n /**\n * How 2025-era (non-envelope) traffic is served:\n *\n * - `'stateless'` (the default, also when the option is omitted) —\n * old-school stateless serving: each legacy request is answered by a\n * fresh instance from the same factory over a streamable HTTP transport\n * constructed with only `sessionIdGenerator: undefined` (the established\n * stateless idiom). Because serving is per-request and stateless, GET and\n * DELETE (2025 session operations) are answered with `405` /\n * `Method not allowed.`.\n * - `'reject'` — modern-only strict: legacy-classified requests are\n * rejected with the unsupported-protocol-version error naming the\n * endpoint's supported revisions (legacy-classified notifications are\n * acknowledged with `202` and dropped). **There is no 2025 serving in\n * this mode.**\n *\n * There is no handler-valued option: to keep an existing legacy deployment\n * (for example a sessionful streamable HTTP wiring) serving 2025 traffic\n * next to this entry, route in user land with {@linkcode isLegacyRequest}\n * in front of a `legacy: 'reject'` handler — see that predicate's\n * documentation for the pattern.\n */\n legacy?: 'stateless' | 'reject';\n /** Callback for out-of-band errors and rejected requests (reporting only; it never alters the response). */\n onerror?: (error: Error) => void;\n /**\n * Response shaping for modern (2026-07-28) request exchanges:\n *\n * - `'auto'` (default) — a single JSON body unless the handler emits a\n * related message before its result, in which case the response upgrades\n * to an SSE stream.\n * - `'sse'` — always stream.\n * - `'json'` — never stream. **Mid-call notifications (progress, logging,\n * any related message emitted before the result) are dropped** — only the\n * terminal result is delivered. Listen-class subscription streams are\n * always served over SSE regardless of this setting.\n */\n responseMode?: PerRequestResponseMode;\n /**\n * The change-event bus `subscriptions/listen` streams subscribe to.\n *\n * When omitted, an in-process {@link InMemoryServerEventBus} is created\n * and the returned handler's `notify` sugar publishes onto it.\n * Multi-process deployments supply their own implementation over their\n * pub/sub backend; the same instance can be shared across handlers.\n */\n bus?: ServerEventBus;\n /**\n * Reject a new `subscriptions/listen` with `-32603` 'Subscription limit\n * reached' (in-band, HTTP 200, before the ack) when this many subscription\n * streams are already open on this handler.\n * @default 1024\n */\n maxSubscriptions?: number;\n /**\n * SSE comment-frame keepalive interval for `subscriptions/listen` streams,\n * in milliseconds. Set to `0` to disable.\n * @default 15000\n */\n keepAliveMs?: number;\n}\n\n/**\n * The handler returned by {@linkcode createMcpHandler}: a web-standard\n * `{ fetch, close, notify, bus }` object — the shape Workers/Bun/Deno expect\n * from `export default`. `fetch` is an arrow-assigned bound property: it can be\n * detached and passed around (`const { fetch } = handler`) without losing its\n * binding.\n *\n * Node frameworks (Express, Fastify, plain `node:http`) wrap the handler once\n * with `toNodeHandler(handler)` from `@modelcontextprotocol/node`.\n */\nexport interface McpHttpHandler {\n /** Web-standard face: serve one HTTP request and resolve with the response. */\n fetch: (request: Request, options?: McpHandlerRequestOptions) => Promise<Response>;\n /**\n * Tears down the modern leg: aborts in-flight modern exchanges and closes\n * their per-request instances. Legacy serving is unaffected — the\n * stateless fallback is per-request by construction and holds nothing\n * between exchanges.\n */\n close: () => Promise<void>;\n /**\n * Typed publish-side facade over the handler's `subscriptions/listen` bus:\n * each method publishes the corresponding change event to every open\n * subscription stream that opted in to that notification type.\n *\n * Safe to call when no subscription is open (no-op).\n */\n notify: ServerNotifier;\n /**\n * The change-event bus this handler's `subscriptions/listen` streams\n * subscribe to (the supplied `bus` option, or the auto-created in-process\n * default).\n */\n bus: ServerEventBus;\n}\n\n/* ------------------------------------------------------------------------ *\n * Shared response helpers\n * ------------------------------------------------------------------------ */\n\n/**\n * The JSON-RPC id to echo on an entry-built error response: the body's `id`\n * when the body is a single JSON-RPC request whose id is a string or number,\n * `null` otherwise. Error responses must carry the id of the request they\n * correspond to whenever it could be read; `null` is reserved for the cases\n * where no single request id is determinable — unparseable bodies, body-less\n * methods, notifications, posted responses and batch arrays.\n */\nfunction echoableRequestId(body: unknown): RequestId | null {\n if (body === null || typeof body !== 'object' || Array.isArray(body)) {\n return null;\n }\n const { method, id } = body as { method?: unknown; id?: unknown };\n if (typeof method !== 'string') {\n return null;\n }\n return typeof id === 'string' || typeof id === 'number' ? id : null;\n}\n\nfunction jsonRpcErrorResponse(httpStatus: number, code: number, message: string, data?: unknown, id: RequestId | null = null): Response {\n return Response.json(\n {\n jsonrpc: '2.0',\n error: { code, message, ...(data !== undefined && { data }) },\n id\n },\n { status: httpStatus }\n );\n}\n\nfunction rejectionResponse(rejection: InboundLadderRejection, id: RequestId | null = null): Response {\n return jsonRpcErrorResponse(rejection.httpStatus, rejection.code, rejection.message, rejection.data, id);\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n\nfunction internalServerErrorResponse(id: RequestId | null = null): Response {\n return jsonRpcErrorResponse(500, -32_603, 'Internal server error', undefined, id);\n}\n\n/* ------------------------------------------------------------------------ *\n * The default legacy fallback\n * ------------------------------------------------------------------------ */\n\n/**\n * The entry's default legacy serving (`legacy: 'stateless'`): per-request\n * stateless serving of 2025-era traffic using the same factory as the modern\n * path. Exported as a standalone building block for hand-wired compositions\n * (for example mounting legacy stateless serving on its own route next to a\n * strict modern endpoint).\n *\n * Each POST is served by a fresh instance from the factory connected to a\n * fresh streamable HTTP transport constructed with only\n * `sessionIdGenerator: undefined` — the established stateless idiom, unchanged.\n * Because serving is per-request and stateless, GET and DELETE (2025 session\n * operations) are answered with `405` / `Method not allowed.`, exactly like the\n * canonical stateless example.\n *\n * The optional `onerror` callback receives factory and serving failures on\n * this leg (reporting only — the response stays the 500 internal-error body).\n * The entry passes its own `onerror` here when expanding the default, so\n * legacy-leg failures are never silently swallowed.\n */\nexport function legacyStatelessFallback(factory: McpServerFactory, onerror?: (error: Error) => void): LegacyHttpHandler {\n return async (request, options) => {\n if (request.method.toUpperCase() !== 'POST') {\n return jsonRpcErrorResponse(405, -32_000, 'Method not allowed.');\n }\n try {\n const product = await factory({\n era: 'legacy',\n ...(options?.authInfo !== undefined && { authInfo: options.authInfo }),\n requestInfo: request\n });\n const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n await product.connect(transport);\n\n const teardown = () => {\n void transport.close().catch(() => {});\n void product.close().catch(() => {});\n };\n // Tear the per-request pair down when the client goes away before\n // the exchange completes.\n request.signal?.addEventListener('abort', teardown, { once: true });\n\n const response = await transport.handleRequest(request, {\n ...(options?.authInfo !== undefined && { authInfo: options.authInfo }),\n ...(options?.parsedBody !== undefined && { parsedBody: options.parsedBody })\n });\n if (response.body === null || !(response.headers.get('content-type') ?? '').includes('text/event-stream')) {\n // Non-streaming exchange (a buffered JSON body or a body-less\n // ack): the response is complete, release the pair now.\n teardown();\n return response;\n }\n // Streaming exchange: the legacy transport answers request-bearing\n // POSTs over SSE, so the exchange is only over once the stream has\n // been fully delivered. Wrap the body so the pair is torn down on\n // completion, on a producer error, or when the consumer abandons\n // the stream — the fetch-world analog of the canonical stateless\n // example's close-on-response-end.\n const reader = response.body.getReader();\n let toreDown = false;\n const completeExchange = () => {\n if (!toreDown) {\n toreDown = true;\n teardown();\n }\n };\n const monitoredBody = new ReadableStream<Uint8Array>({\n pull: async controller => {\n try {\n const { done, value } = await reader.read();\n if (done) {\n completeExchange();\n controller.close();\n return;\n }\n if (value !== undefined) {\n controller.enqueue(value);\n }\n } catch (error) {\n completeExchange();\n controller.error(error);\n }\n },\n cancel: reason => {\n completeExchange();\n return reader.cancel(reason).catch(() => {});\n }\n });\n return new Response(monitoredBody, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers\n });\n } catch (error) {\n try {\n onerror?.(toError(error));\n } catch {\n // Reporting must never alter the response.\n }\n return internalServerErrorResponse(echoableRequestId(options?.parsedBody));\n }\n };\n}\n\n/* ------------------------------------------------------------------------ *\n * The entry's classification step (shared with isLegacyRequest)\n * ------------------------------------------------------------------------ */\n\n/** The outcome of the entry's classification step for one inbound HTTP request. */\ntype EntryClassification =\n /** The body bytes could not be read at all (a failing stream, not malformed JSON). */\n | { step: 'unreadable-body' }\n /** A POST with an empty or non-JSON body: nothing to classify, so there is no envelope claim. */\n | { step: 'no-json-body'; forwardRequest: Request }\n /** A classifiable request, with the classifier's routing outcome. */\n | { step: 'classified'; outcome: InboundClassificationOutcome; body: unknown; parsedBody: unknown; forwardRequest: Request };\n\n/**\n * The entry's classification step: read the request body exactly once (unless\n * a pre-parsed body is supplied) and classify the request with\n * {@linkcode classifyInboundRequest}. This is the single code path behind both\n * {@linkcode createMcpHandler}'s routing and the exported\n * {@linkcode isLegacyRequest} predicate, so the two can never disagree.\n *\n * Pass `needsForward: false` when the caller never reads `forwardRequest` —\n * the body-preserving clone is then skipped and `forwardRequest` is the\n * (consumed) input request.\n */\nasync function classifyEntryRequest(request: Request, providedParsedBody?: unknown, needsForward = true): Promise<EntryClassification> {\n const httpMethod = request.method.toUpperCase();\n\n let body: unknown;\n let parsedBody = providedParsedBody;\n let forwardRequest = request;\n let unparseable = false;\n\n if (httpMethod === 'POST') {\n if (parsedBody === undefined) {\n // Read the body exactly once for classification, keeping an unread\n // copy of the original bytes for the legacy leg (web-standard\n // request bodies are single-use) when the caller needs it.\n if (needsForward) {\n forwardRequest = request.clone();\n }\n let bodyText: string;\n try {\n bodyText = await request.text();\n } catch {\n return { step: 'unreadable-body' };\n }\n try {\n body = bodyText.length === 0 ? undefined : JSON.parse(bodyText);\n } catch {\n unparseable = true;\n }\n if (!unparseable && body !== undefined) {\n parsedBody = body;\n }\n } else {\n body = parsedBody;\n }\n\n if (unparseable || body === undefined) {\n return { step: 'no-json-body', forwardRequest };\n }\n }\n\n const outcome = classifyInboundRequest({\n httpMethod,\n protocolVersionHeader: request.headers.get('mcp-protocol-version') ?? undefined,\n mcpMethodHeader: request.headers.get('mcp-method') ?? undefined,\n mcpNameHeader: request.headers.get('mcp-name') ?? undefined,\n ...(body !== undefined && { body })\n });\n return { step: 'classified', outcome, body, parsedBody, forwardRequest };\n}\n\n/**\n * Whether {@linkcode createMcpHandler} would route this request to its legacy\n * (2025-era) serving rather than the modern (2026-07-28) path.\n *\n * Call it with just the request: `await isLegacyRequest(request)`. For a\n * `POST` the body is read from an internal clone, so the request you pass\n * stays fully readable for whichever handler you route it to — no second\n * argument is needed. (In a Node `(req, res)` handler, build that `Request`\n * with `toWebRequest(req)` from `@modelcontextprotocol/node`; behind a body\n * parser, which has already drained the Node stream, build it as\n * `toWebRequest(req, req.body)` so the bytes come from the parsed body —\n * either way the predicate still takes just the request.) The optional\n * `parsedBody` is a perf escape hatch for a body you already hold parsed:\n * pass it and the predicate classifies from the value directly, reading and\n * cloning nothing. It is needed, not just faster, when the request's own\n * body was already read — the internal clone is then impossible (cloning a\n * used body throws a `TypeError`), so such a single-argument call rejects\n * instead of guessing.\n *\n * This is the entry's own classification step exported as a predicate — it\n * runs exactly the code `createMcpHandler` runs to make the routing decision,\n * not a re-implementation — so a hand-wired composition that branches on it\n * can never disagree with the entry. Use it to keep an existing legacy\n * deployment (for example a sessionful streamable HTTP wiring) serving 2025\n * traffic next to a strict modern endpoint, now that the entry has no\n * handler-valued `legacy` option:\n *\n * ```ts\n * import { createMcpHandler, isLegacyRequest } from '@modelcontextprotocol/server';\n *\n * const modern = createMcpHandler(factory, { legacy: 'reject' });\n *\n * export default {\n * async fetch(request: Request): Promise<Response> {\n * if (await isLegacyRequest(request)) {\n * // e.g. an existing sessionful WebStandardStreamableHTTPServerTransport wiring\n * return myExistingLegacyHandler(request);\n * }\n * return modern.fetch(request);\n * }\n * };\n * ```\n *\n * Semantics (identical to the entry's routing):\n *\n * - Returns `true` only for requests with no per-request `_meta` envelope\n * claim: claim-less POSTs (including the `initialize` handshake and 2025-era\n * notification POSTs without a modern protocol-version header), body-less\n * GET/DELETE session operations, all-legacy JSON-RPC batch arrays, posted\n * JSON-RPC responses, and POSTs whose body is empty or not valid JSON.\n * - Returns `false` for everything the modern path answers, including its\n * validation-ladder rejections: a request carrying the envelope claim (even\n * one naming a revision the endpoint does not serve — the modern path\n * answers it with the unsupported-protocol-version error), a malformed\n * envelope behind a present claim (answered `-32602`), a request whose\n * `MCP-Protocol-Version` header names a modern revision but that lacks the\n * envelope (`-32602`), and header/body mismatches (`-32020`). Consumers\n * routing on the predicate must send `false` traffic to the modern handler,\n * never to a legacy handler — the modern path owns those error answers.\n * - `server/discover` probes sent by negotiating clients always carry the\n * envelope claim, so they are never legacy; a hand-built claim-less POST to\n * a method named `server/discover` has no claim and classifies legacy,\n * exactly as the entry itself routes it.\n */\nexport async function isLegacyRequest(request: Request, parsedBody?: unknown): Promise<boolean> {\n // Classify a clone so the caller's request body stays readable; with a\n // pre-parsed body (or a body-less method) nothing is read and no clone is\n // needed. The predicate never reads forwardRequest, so the classification\n // step's own forwarding clone is skipped.\n const probe = parsedBody === undefined && request.method.toUpperCase() === 'POST' ? request.clone() : request;\n const classified = await classifyEntryRequest(probe, parsedBody, false);\n return classified.step === 'no-json-body' || (classified.step === 'classified' && classified.outcome.kind === 'legacy');\n}\n\n/* ------------------------------------------------------------------------ *\n * The entry\n * ------------------------------------------------------------------------ */\n\n/**\n * Creates an HTTP handler that serves the 2026-07-28 protocol revision from a\n * per-request server factory and, by default, falls back to old-school\n * stateless serving for 2025-era traffic. Pass `legacy: 'reject'` for a\n * modern-only strict endpoint.\n *\n * Mounting: `handler.fetch` is the web-standard face (Cloudflare Workers,\n * Deno, Bun, Hono's `c.req.raw`); for Express/Fastify/plain `node:http`, wrap\n * the handler once with `toNodeHandler(handler)` from\n * `@modelcontextprotocol/node`. When mounting bare on a fetch-native runtime,\n * put Origin/Host validation in front of the handler — the entry itself is\n * deliberately validation-free:\n *\n * ```ts\n * import { hostHeaderValidationResponse, originValidationResponse, localhostAllowedHostnames, localhostAllowedOrigins } from '@modelcontextprotocol/server';\n *\n * export default {\n * async fetch(request: Request): Promise<Response> {\n * const rejected =\n * hostHeaderValidationResponse(request, localhostAllowedHostnames()) ??\n * originValidationResponse(request, localhostAllowedOrigins());\n * return rejected ?? handler.fetch(request);\n * }\n * };\n * ```\n *\n * Use ONE factory for both legs: the same tools/resources/prompts definition\n * backs the modern path and the stateless legacy fallback, so the two eras can\n * never drift apart. To keep an existing legacy deployment (for example a\n * sessionful streamable HTTP wiring) serving 2025 traffic instead of the\n * stateless fallback, route in user land with {@linkcode isLegacyRequest} in\n * front of a strict handler — see that predicate's documentation for the\n * pattern. Power users composing transport-neutral routing can also use the\n * exported building blocks directly: {@linkcode classifyInboundRequest} for\n * the era decision and `PerRequestHTTPServerTransport` for single-exchange\n * serving.\n *\n * The entry performs no token verification: `authInfo` given to `fetch` is\n * passed through to handlers and the factory as-is and is never derived from\n * request headers.\n */\nexport function createMcpHandler(factory: McpServerFactory, options: CreateMcpHandlerOptions = {}): McpHttpHandler {\n const { legacy, onerror, responseMode } = options;\n\n // Construction-time guard for JavaScript callers passing a handler as the\n // legacy value: the option only selects a posture ('stateless' | 'reject').\n // Failing loudly here beats silently treating the handler as the default.\n if (typeof legacy === 'function') {\n throw new TypeError(\n \"The 'legacy' option only accepts 'stateless' or 'reject', not a handler function. To serve 2025-era traffic with your own \" +\n \"handler, route in user land with the exported isLegacyRequest(request) predicate in front of a strict (legacy: 'reject') handler.\"\n );\n }\n\n /** Modern per-request instances with an exchange still in flight (close() tears these down). */\n const inflight = new Set<Server>();\n let closed = false;\n\n const reportError = (error: Error) => {\n try {\n onerror?.(error);\n } catch {\n // Reporting must never alter the response.\n }\n };\n\n const bus: ServerEventBus = options.bus ?? new InMemoryServerEventBus(reportError);\n const notify = createServerNotifier(bus);\n const listenRouter = createListenRouter({\n bus,\n maxSubscriptions: options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS,\n keepAliveMs: options.keepAliveMs ?? DEFAULT_LISTEN_KEEPALIVE_MS,\n onerror: reportError\n });\n if (responseMode === 'json') {\n // eslint-disable-next-line no-console\n console.warn(\n \"responseMode: 'json' drops mid-call notifications. subscriptions/listen streams are always served over SSE regardless; \" +\n 'other notifications emitted before a result are dropped.'\n );\n }\n\n // The default posture is the stateless fallback; 'reject' is the only way\n // to turn legacy serving off (modern-only strict).\n const legacyHandler: LegacyHttpHandler | undefined = legacy === 'reject' ? undefined : legacyStatelessFallback(factory, reportError);\n\n async function serveModern(route: InboundModernRoute, request: Request, authInfo: AuthInfo | undefined): Promise<Response> {\n const claimedRevision = route.classification.revision;\n if (claimedRevision === undefined || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedRevision)) {\n // The claim names a revision this endpoint does not serve (an\n // unknown future revision, or a 2025-era revision delivered via the\n // envelope mechanism).\n const error = new UnsupportedProtocolVersionError({\n supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],\n requested: claimedRevision ?? 'unknown'\n });\n reportError(error);\n return jsonRpcErrorResponse(400, error.code, error.message, error.data, echoableRequestId(route.message));\n }\n\n // SEP-2243 standard-header presence and `Mcp-Name` cross-check\n // (`standard-header-validation` rung; the `MCP-Protocol-Version` and\n // `Mcp-Method` *mismatch* cells are already answered inside\n // `classifyInboundRequest` on the edge `era-classification` rung).\n // Evaluated after the supported-revision\n // gate so an envelope naming a revision this endpoint does not serve\n // is still answered with `-32022` (the supported list is the more\n // useful answer to a client speaking the wrong revision); evaluated\n // before the capability gate, the factory call, and the\n // `Mcp-Param-*` rung so a request that fails several rungs is\n // answered by the standard-header rung first.\n const stdHeaderRejection = validateStandardRequestHeaders(\n {\n httpMethod: request.method,\n mcpMethodHeader: request.headers.get('mcp-method') ?? undefined,\n mcpNameHeader: request.headers.get('mcp-name') ?? undefined\n },\n route\n );\n if (stdHeaderRejection !== undefined) {\n reportError(new Error(`Rejected inbound request (${stdHeaderRejection.cell}): ${stdHeaderRejection.message}`));\n return rejectionResponse(stdHeaderRejection, echoableRequestId(route.message));\n }\n\n const meta = route.messageKind === 'request' ? requestMetaOf(route.message.params) : undefined;\n const declaredClientCapabilities = meta?.[CLIENT_CAPABILITIES_META_KEY] as ClientCapabilities | undefined;\n\n // Pre-dispatch capability gate: a request to a method whose processing\n // structurally requires a client capability the request's validated\n // envelope did not declare is refused here, before any instance is\n // constructed or dispatched. Answering at the entry pins the\n // spec-mandated HTTP 400 for this error; a handler-time emission would\n // surface in-band on HTTP 200.\n if (route.messageKind === 'request') {\n const required = requiredClientCapabilitiesForRequest(route.message.method);\n if (required !== undefined) {\n const missing = missingClientCapabilities(required, declaredClientCapabilities);\n if (missing !== undefined) {\n const error = new MissingRequiredClientCapabilityError({ requiredCapabilities: missing });\n reportError(error);\n return jsonRpcErrorResponse(\n httpStatusForErrorCode(error.code, 'ladder'),\n error.code,\n error.message,\n error.data,\n route.message.id\n );\n }\n }\n }\n\n const product = await factory({\n era: 'modern',\n ...(authInfo !== undefined && { authInfo }),\n requestInfo: request\n });\n const server = product instanceof McpServer ? product.server : product;\n\n // Entry-handled `subscriptions/listen`: the router owns ack-first /\n // per-stream filtering / subscription-id stamping / keepalive /\n // capacity / teardown. The factory IS constructed for listen — to read\n // the instance's declared capabilities only, so the acknowledged\n // filter reflects what the server can actually deliver. Unlike the\n // discover path (which connects via the per-request transport and tears\n // down with it), the probe instance is never connected: capabilities\n // are read off the unconnected instance and it is closed immediately.\n // Authorization the consumer performs inside the factory therefore DOES\n // see listen requests, although token verification still belongs at the\n // middleware layer mounted in front of this entry.\n if (route.messageKind === 'request' && route.message.method === 'subscriptions/listen') {\n const capabilities = server.getCapabilities();\n void product.close().catch(reportError);\n return listenRouter.serve(route.message, request.signal, capabilities);\n }\n\n // SEP-2243 `Mcp-Param-*` server-side validation (pre-dispatch ladder\n // rung): for a `tools/call`, look up the named tool's JSON inputSchema\n // on the just-produced instance and compare every `x-mcp-header`\n // declaration against the request's `Mcp-Param-{Name}` headers and the\n // body `arguments`. A mismatch (or a missing header for a present body\n // value, or an invalid Base64 sentinel) emits the same `400` /\n // `-32020` (`HeaderMismatch`) shape the edge cross-checks use. Only\n // applied when the factory returns an `McpServer` (the registry is the\n // schema source); a low-level `Server` factory has no registry, so\n // there is nothing to validate against.\n if (route.messageKind === 'request' && route.message.method === 'tools/call' && product instanceof McpServer) {\n const callParams = route.message.params as { name?: string; arguments?: Record<string, unknown> } | undefined;\n const toolName = typeof callParams?.name === 'string' ? callParams.name : undefined;\n const inputSchema = toolName === undefined ? undefined : product.toolInputSchemaJson(toolName);\n if (inputSchema !== undefined) {\n const scan = scanXMcpHeaderDeclarations(inputSchema);\n if (scan.valid && scan.declarations.length > 0) {\n const rejection = validateMcpParamHeaders(scan.declarations, callParams?.arguments, request.headers);\n if (rejection !== undefined) {\n void product.close().catch(reportError);\n reportError(new Error(`Rejected inbound request (${rejection.cell}): ${rejection.message}`));\n return rejectionResponse(rejection, route.message.id);\n }\n }\n }\n }\n\n // Era-write at instance binding, then modern-only handler installation —\n // both before the instance is connected to the per-request transport.\n setNegotiatedProtocolVersion(server, claimedRevision);\n installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);\n\n if (meta !== undefined) {\n seedClientIdentityFromEnvelope(server, {\n clientInfo: meta[CLIENT_INFO_META_KEY] as Implementation | undefined,\n clientCapabilities: declaredClientCapabilities\n });\n }\n\n // Track the instance until its exchange tears down so close() can abort it.\n const previousOnClose = server.onclose;\n inflight.add(server);\n server.onclose = () => {\n inflight.delete(server);\n previousOnClose?.();\n };\n\n try {\n const response = await invoke(product, route.message, {\n classification: route.classification,\n request,\n ...(authInfo !== undefined && { authInfo }),\n ...(responseMode !== undefined && { responseMode })\n });\n if (route.messageKind === 'notification') {\n // Notification exchanges have no terminal response to ride the\n // transport's auto-close, so release the per-request instance here.\n queueMicrotask(() => void server.close().catch(() => {}));\n }\n return response;\n } catch (error) {\n if (error instanceof SdkError && error.code === SdkErrorCode.ConnectionClosed) {\n // The client went away before a response existed; there is\n // nobody left to answer.\n return new Response(null, { status: 499 });\n }\n // No terminal response will ride the transport's close chain after a\n // failure here: close the per-request instance explicitly and drop it\n // from the in-flight set so repeated failures cannot accumulate\n // connected instances until handler.close().\n await server.close().catch(() => {});\n inflight.delete(server);\n reportError(toError(error));\n return internalServerErrorResponse(echoableRequestId(route.message));\n }\n }\n\n async function serveLegacyRoute(\n route: InboundLegacyRoute,\n forwardRequest: Request,\n authInfo: AuthInfo | undefined,\n parsedBody: unknown\n ): Promise<Response> {\n if (legacyHandler !== undefined) {\n return legacyHandler(forwardRequest, {\n ...(authInfo !== undefined && { authInfo }),\n ...(parsedBody !== undefined && { parsedBody })\n });\n }\n const strict = modernOnlyStrictRejection(route, SUPPORTED_MODERN_PROTOCOL_VERSIONS);\n if (strict === undefined) {\n // Legacy-classified notification on a modern-only endpoint:\n // acknowledged and dropped, never dispatched.\n return new Response(null, { status: 202 });\n }\n reportError(new Error(`Rejected 2025-era request on a modern-only endpoint (${strict.cell}): ${strict.message}`));\n return rejectionResponse(strict, echoableRequestId(parsedBody));\n }\n\n async function handle(request: Request, requestOptions?: McpHandlerRequestOptions): Promise<Response> {\n const authInfo = requestOptions?.authInfo;\n const classified = await classifyEntryRequest(request, requestOptions?.parsedBody);\n\n if (classified.step === 'unreadable-body') {\n return jsonRpcErrorResponse(400, -32_700, 'Parse error: the request body could not be read');\n }\n if (classified.step === 'no-json-body') {\n // No JSON body to classify: there is no envelope claim, so this is\n // legacy traffic when legacy serving is configured (the legacy leg\n // answers its own parse error, unchanged), and a parse error\n // otherwise.\n if (legacyHandler !== undefined) {\n return legacyHandler(classified.forwardRequest, { ...(authInfo !== undefined && { authInfo }) });\n }\n return jsonRpcErrorResponse(400, -32_700, 'Parse error: the request body is not valid JSON');\n }\n\n const { outcome, body, parsedBody, forwardRequest } = classified;\n try {\n switch (outcome.kind) {\n case 'reject': {\n reportError(new Error(`Rejected inbound request (${outcome.cell}): ${outcome.message}`));\n return rejectionResponse(outcome, echoableRequestId(body));\n }\n case 'modern': {\n return await serveModern(outcome, request, authInfo);\n }\n case 'legacy': {\n return await serveLegacyRoute(outcome, forwardRequest, authInfo, parsedBody);\n }\n }\n } catch (error) {\n // Entry-internal failure while serving a classified request (a\n // throwing factory or a failed connect, on either leg): the parsed\n // body is in scope here, so the 500 body echoes the request id when\n // it could be read.\n reportError(toError(error));\n return internalServerErrorResponse(echoableRequestId(body));\n }\n }\n\n const fetchFace = async (request: Request, requestOptions?: McpHandlerRequestOptions): Promise<Response> => {\n if (closed) {\n throw new Error('This MCP handler has been closed');\n }\n try {\n return await handle(request, requestOptions);\n } catch (error) {\n reportError(toError(error));\n return internalServerErrorResponse(echoableRequestId(requestOptions?.parsedBody));\n }\n };\n\n return {\n fetch: fetchFace,\n notify,\n bus,\n close: async () => {\n closed = true;\n listenRouter.closeAll();\n const closing = [...inflight].map(server => server.close().catch(() => {}));\n inflight.clear();\n await Promise.all(closing);\n }\n };\n}\n","export type HostHeaderValidationResult =\n | { ok: true; hostname: string }\n | {\n ok: false;\n errorCode: 'missing_host' | 'invalid_host_header' | 'invalid_host';\n message: string;\n hostHeader?: string;\n hostname?: string;\n };\n\n/**\n * Parse and validate a `Host` header against an allowlist of hostnames (port-agnostic).\n *\n * - Input host header may include a port (e.g. `localhost:3000`) or IPv6 brackets (e.g. `[::1]:3000`).\n * - Allowlist items should be hostnames only (no ports). For IPv6, include brackets (e.g. `[::1]`).\n */\nexport function validateHostHeader(hostHeader: string | null | undefined, allowedHostnames: string[]): HostHeaderValidationResult {\n if (!hostHeader) {\n return { ok: false, errorCode: 'missing_host', message: 'Missing Host header' };\n }\n\n // Use URL API to parse hostname (handles IPv4, IPv6, and regular hostnames)\n let hostname: string;\n try {\n hostname = new URL(`http://${hostHeader}`).hostname;\n } catch {\n return { ok: false, errorCode: 'invalid_host_header', message: `Invalid Host header: ${hostHeader}`, hostHeader };\n }\n\n if (!allowedHostnames.includes(hostname)) {\n return { ok: false, errorCode: 'invalid_host', message: `Invalid Host: ${hostname}`, hostHeader, hostname };\n }\n\n return { ok: true, hostname };\n}\n\n/**\n * Convenience allowlist for `localhost` DNS rebinding protection.\n */\nexport function localhostAllowedHostnames(): string[] {\n return ['localhost', '127.0.0.1', '[::1]'];\n}\n\n/**\n * Web-standard `Request` helper for DNS rebinding protection.\n * @example\n * ```ts source=\"./hostHeaderValidation.examples.ts#hostHeaderValidationResponse_basicUsage\"\n * const result = validateHostHeader(req.headers.get('host'), ['localhost']);\n * ```\n */\nexport function hostHeaderValidationResponse(req: Request, allowedHostnames: string[]): Response | undefined {\n const result = validateHostHeader(req.headers.get('host'), allowedHostnames);\n if (result.ok) return undefined;\n\n return Response.json(\n {\n jsonrpc: '2.0',\n error: {\n code: -32_000,\n message: result.message\n },\n id: null\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n}\n","/**\n * Framework-agnostic Origin header validation helpers.\n *\n * Browsers attach an `Origin` header to cross-origin requests; validating it\n * against an allowlist (alongside Host header validation) protects local and\n * development MCP servers against DNS rebinding and cross-site request\n * forgery. The framework middleware packages (`@modelcontextprotocol/express`,\n * `@modelcontextprotocol/hono`, `@modelcontextprotocol/fastify`,\n * `@modelcontextprotocol/node`) wrap these helpers; use them directly when\n * mounting a handler bare on a fetch-native runtime.\n *\n * Validation is deny-on-failure: a present `Origin` value that cannot be\n * parsed (including the opaque `null` origin) is rejected, never passed\n * through. Requests without an `Origin` header pass — non-browser MCP clients\n * do not send one.\n */\n\nexport type OriginValidationResult =\n | { ok: true; origin?: string; hostname?: string }\n | {\n ok: false;\n errorCode: 'invalid_origin_header' | 'invalid_origin';\n message: string;\n originHeader?: string;\n hostname?: string;\n };\n\n/**\n * Validate an `Origin` header against an allowlist of hostnames (port-agnostic).\n *\n * - A missing/empty `Origin` header passes: non-browser clients do not send one,\n * and only browser-originated requests carry the header this check defends against.\n * - Allowlist items are hostnames only (no scheme, no port), the same convention as\n * `validateHostHeader`. For IPv6, include brackets (e.g. `[::1]`).\n * - Any present value that cannot be parsed as an origin URL — including the literal\n * `null` origin browsers send for opaque contexts — is rejected (deny on failure).\n */\nexport function validateOriginHeader(originHeader: string | null | undefined, allowedOriginHostnames: string[]): OriginValidationResult {\n if (originHeader === null || originHeader === undefined || originHeader === '') {\n return { ok: true };\n }\n\n let hostname: string;\n try {\n hostname = new URL(originHeader).hostname;\n } catch {\n return { ok: false, errorCode: 'invalid_origin_header', message: `Invalid Origin header: ${originHeader}`, originHeader };\n }\n if (hostname === '') {\n // Opaque origins (\"null\") and other non-hierarchical values parse without a\n // hostname; they can never be allowlisted.\n return { ok: false, errorCode: 'invalid_origin_header', message: `Invalid Origin header: ${originHeader}`, originHeader };\n }\n\n if (!allowedOriginHostnames.includes(hostname)) {\n return { ok: false, errorCode: 'invalid_origin', message: `Invalid Origin: ${hostname}`, originHeader, hostname };\n }\n\n return { ok: true, origin: originHeader, hostname };\n}\n\n/**\n * Convenience allowlist of localhost-class origin hostnames, mirroring\n * `localhostAllowedHostnames`.\n */\nexport function localhostAllowedOrigins(): string[] {\n return ['localhost', '127.0.0.1', '[::1]'];\n}\n\n/**\n * Web-standard `Request` helper for Origin validation: returns a `403` JSON-RPC\n * error response when the request's `Origin` header is not allowed, and\n * `undefined` when the request may proceed.\n *\n * ```ts\n * const rejected = originValidationResponse(request, localhostAllowedOrigins());\n * if (rejected) return rejected;\n * ```\n */\nexport function originValidationResponse(req: Request, allowedOriginHostnames: string[]): Response | undefined {\n const result = validateOriginHeader(req.headers.get('origin'), allowedOriginHostnames);\n if (result.ok) return undefined;\n\n return Response.json(\n {\n jsonrpc: '2.0',\n error: {\n code: -32_000,\n message: result.message\n },\n id: null\n },\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n}\n","import type { ServerContext } from '@modelcontextprotocol/core-internal';\n\n/**\n * Options for {@linkcode createRequestStateCodec}.\n */\nexport interface RequestStateCodecOptions {\n /**\n * The HMAC secret. A `string` value is UTF-8-encoded. MUST be at least\n * 32 bytes (256 bits) long; a `RangeError` is thrown at\n * construction otherwise. The same key must be available to every server\n * instance that may receive an echoed `requestState` (so a per-process\n * random key only works when one process serves every round of a flow).\n */\n key: Uint8Array | string;\n\n /**\n * How long a minted `requestState` stays valid, in seconds. An echoed\n * value past its expiry is rejected by {@linkcode RequestStateCodec.verify}.\n * Defaults to `600` (ten minutes).\n */\n ttlSeconds?: number;\n\n /**\n * Optional context binding. Called at mint time and again at verify time;\n * a `requestState` minted under one binding value is rejected when echoed\n * under a different one. Use this to bind state to the authenticated\n * principal and/or the originating method (the spec's user-binding MUST\n * for state that influences authorization), for example:\n *\n * ```ts\n * bind: ctx => `${ctx.mcpReq.method}\\0${ctx.http?.authInfo?.clientId ?? ''}`\n * ```\n *\n * The returned value is stored in the envelope as a domain-separated HMAC\n * tag (keyed by the codec's `key`), not the raw string — so a principal\n * identifier in the binding does not appear in the wire value the client\n * holds.\n *\n * When configured, {@linkcode RequestStateCodec.mint} requires its `ctx`\n * argument.\n */\n bind?: (ctx: ServerContext) => string;\n}\n\n/**\n * The codec returned by {@linkcode createRequestStateCodec}: `mint` seals a\n * JSON-serializable payload into the wire string a handler returns from\n * `inputRequired({ requestState })`; `verify` is the function to drop into\n * {@linkcode server/server.ServerOptions | ServerOptions}`.requestState.verify`\n * (it throws on any failure, which the seam answers as the frozen `-32602`).\n * The decoded payload `verify` resolves with is handed to the handler by the\n * seam via the typed `ctx.mcpReq.requestState<T>()` accessor — `mint<T>` and\n * `requestState<T>()` are the typed encode/read pair.\n */\nexport interface RequestStateCodec<T = unknown> {\n /**\n * Seal `payload` into an opaque wire string. The result is what the\n * handler returns from `inputRequired({ requestState })`.\n *\n * @param ctx The handler's context. Required when the codec was created\n * with a {@linkcode RequestStateCodecOptions.bind | bind}\n * callback; ignored otherwise.\n */\n mint(payload: T, ctx?: ServerContext): Promise<string>;\n\n /**\n * Verify an echoed `requestState` and return the original payload. Throws\n * on any failure (bad MAC, expired, bind mismatch, malformed). The thrown\n * message is a fixed opaque reason code (`'malformed'` / `'mac'` /\n * `'expired'` / `'bind'`) — never the decoded payload, the binding value,\n * or any other context-derived field.\n *\n * Pass this directly as `ServerOptions.requestState.verify`.\n */\n verify(state: string, ctx: ServerContext): Promise<T>;\n}\n\nconst PREFIX = 'v1.';\n\n// Runtime-neutral base64url (no padding) over raw bytes. `btoa`/`atob` are\n// available in browsers, Cloudflare Workers, and Node 16+.\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let bin = '';\n for (const b of bytes) bin += String.fromCodePoint(b);\n return btoa(bin).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '');\n}\n\n// Constant-time equality on the fixed-length base64url bind-tag string. Same\n// guarantee as the body-MAC check (which uses `subtle.verify`): the\n// per-character XOR accumulator does not vary its trip count with the position\n// of the first mismatch. Length is fixed (22 chars for the 128-bit truncated\n// tag), so the early length-check leaks nothing.\nfunction constantTimeTagEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let r = 0;\n for (let i = 0; i < a.length; i++) {\n r |= a.codePointAt(i)! ^ b.codePointAt(i)!;\n }\n return r === 0;\n}\n\nfunction base64UrlToBytes(s: string): Uint8Array<ArrayBuffer> {\n const b64 = s.replaceAll('-', '+').replaceAll('_', '/');\n const bin = atob(b64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.codePointAt(i)!;\n return bytes;\n}\n\n/**\n * Create an opt-in HMAC-SHA256 codec for the multi-round-trip `requestState`\n * (protocol revision 2026-07-28).\n *\n * `requestState` round-trips through the client and is attacker-controlled\n * input on re-entry. The SDK applies no protection of its own; this helper is\n * the convenience implementation of the spec's integrity MUST so authors don't\n * hand-roll HMAC. Wire shape:\n *\n * \"v1.\" b64url({\"p\":<payload>,\"exp\":<unixSeconds>,\"b\":<bindTag>?}) \".\" b64url(mac)\n *\n * where `bindTag` is `b64url(HMAC(key, \"mcp.requestState.bind:\" + bind(ctx))[:16])`\n * — the binding value is never embedded raw.\n *\n * The codec is **signed, not encrypted**: the body is integrity-protected but\n * the client can base64url-decode it and read the payload (`p`) in clear. Do\n * not put secrets in the payload; use an AEAD construction if confidentiality\n * is required. The handler reads its payload back via the typed\n * `ctx.mcpReq.requestState<T>()` accessor — the seam has already run `verify`\n * (integrity proven, payload decoded) by the time the handler is entered.\n *\n * Verification is fail-closed and constant-time (WebCrypto `subtle.verify` for\n * the body MAC; a fixed-length XOR-accumulator compare for the bind tag).\n * See `examples/mrtr/server.ts` for a worked end-to-end example.\n *\n * Design comparison (mcp.d `secureRequestState`, the peer SDK's reference\n * implementation): mcp.d additionally offers an AES-256-GCM encrypted mode and\n * derives independent cipher / bind-HMAC sub-keys from the operator secret via\n * HKDF-SHA256, with an auto-generated per-process ephemeral key when none is\n * supplied. This codec deliberately ships only the signed mode and a single\n * keyed HMAC (domain-separated by input prefix) — HKDF sub-key derivation and\n * an encrypted mode are intentionally out of scope for the initial release.\n */\nexport function createRequestStateCodec<T = unknown>(options: RequestStateCodecOptions): RequestStateCodec<T> {\n const subtle = globalThis.crypto?.subtle;\n if (subtle === undefined) {\n throw new TypeError(\n 'createRequestStateCodec requires the Web Crypto API (globalThis.crypto.subtle); ' +\n 'see https://ts.sdk.modelcontextprotocol.io/v2/troubleshooting for the Node.js polyfill instructions'\n );\n }\n\n // Snapshot the key bytes at construction. When `options.key` is a\n // Uint8Array, holding the caller's reference would let a post-construction\n // mutation (e.g. zeroing the secret for hygiene) silently change the key\n // the lazy `importedKey()` reads on first mint/verify — a TOCTOU on the\n // secret. The owned copy here is what every later read sees.\n const keyBytes = typeof options.key === 'string' ? new TextEncoder().encode(options.key) : Uint8Array.from(options.key);\n if (keyBytes.byteLength < 32) {\n throw new RangeError(`createRequestStateCodec: key must be at least 32 bytes (got ${keyBytes.byteLength})`);\n }\n const ttlSeconds = options.ttlSeconds ?? 600;\n if (!Number.isFinite(ttlSeconds)) {\n // Infinity/NaN would serialize `exp` as JSON `null`, which then fails\n // verify() with the misleading reason 'expired' on every round-trip —\n // fail loudly at construction instead.\n throw new RangeError('createRequestStateCodec: ttlSeconds must be a finite number');\n }\n const bind = options.bind;\n\n // The CryptoKey is imported once (lazily) and reused for every mint/verify.\n // `keyBytes` is already an owned standalone Uint8Array (snapshot above), so\n // it satisfies WebCrypto's BufferSource requirement on every runtime.\n let cryptoKey: ReturnType<typeof subtle.importKey> | undefined;\n const importedKey = (): ReturnType<typeof subtle.importKey> =>\n (cryptoKey ??= subtle.importKey('raw', keyBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign', 'verify']));\n\n const utf8 = new TextEncoder();\n\n // Domain-separated HMAC tag of the binding value, truncated to 128 bits and\n // base64url'd. The label keeps the bind-tag computation separate from the\n // body MAC even though both use the same key (the body MAC's input is the\n // versioned wire string `\"v1.\" + base64url(...)` and can never start with\n // this label).\n const BIND_LABEL = 'mcp.requestState.bind:';\n const bindTag = async (value: string): Promise<string> => {\n const mac = new Uint8Array(await subtle.sign('HMAC', await importedKey(), utf8.encode(BIND_LABEL + value)));\n return bytesToBase64Url(mac.slice(0, 16));\n };\n\n return {\n async mint(payload, ctx) {\n const envelope: { p: T; exp: number; b?: string } = {\n p: payload,\n exp: Math.floor(Date.now() / 1000) + ttlSeconds\n };\n if (bind !== undefined) {\n if (ctx === undefined) {\n throw new TypeError('createRequestStateCodec: mint() requires ctx when a bind callback is configured');\n }\n envelope.b = await bindTag(bind(ctx));\n }\n const body = bytesToBase64Url(utf8.encode(JSON.stringify(envelope)));\n // The MAC covers `PREFIX + body` so the version tag is bound: a\n // valid `body.mac` pair under `v1.` cannot be transplanted to a\n // future `v2.` codec under the same key.\n const mac = new Uint8Array(await subtle.sign('HMAC', await importedKey(), utf8.encode(PREFIX + body)));\n return `${PREFIX}${body}.${bytesToBase64Url(mac)}`;\n },\n\n async verify(state, ctx) {\n // Envelope shape: \"v1.\" body \".\" mac. The MAC is checked FIRST so\n // every other rejection reason is only reachable for a value we\n // minted (or a peer with the key did).\n const dot = state.lastIndexOf('.');\n if (!state.startsWith(PREFIX) || dot <= PREFIX.length) {\n throw new Error('malformed');\n }\n const body = state.slice(PREFIX.length, dot);\n let macBytes: Uint8Array<ArrayBuffer>;\n try {\n macBytes = base64UrlToBytes(state.slice(dot + 1));\n } catch {\n throw new Error('malformed');\n }\n // SubtleCrypto.verify is constant-time by spec — no manual byte\n // compare, no `timingSafeEqual` dependency. The MAC input mirrors\n // mint: `PREFIX + body`, so the version tag is authenticated.\n const ok = await subtle.verify('HMAC', await importedKey(), macBytes, utf8.encode(PREFIX + body));\n if (!ok) {\n throw new Error('mac');\n }\n // The body decoded after a good MAC is by construction the JSON we\n // wrote; a parse failure here would indicate key compromise rather\n // than tampering, but stays fail-closed regardless.\n let envelope: { p: T; exp: number; b?: string };\n try {\n envelope = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(base64UrlToBytes(body))) as {\n p: T;\n exp: number;\n b?: string;\n };\n } catch {\n throw new Error('malformed');\n }\n if (typeof envelope.exp !== 'number' || envelope.exp < Math.floor(Date.now() / 1000)) {\n throw new Error('expired');\n }\n if (bind !== undefined) {\n const expected = await bindTag(bind(ctx));\n if (envelope.b === undefined || !constantTimeTagEqual(envelope.b, expected)) {\n // Opaque reason only — never interpolate the expected/actual\n // binding values (they may carry principal identifiers).\n throw new Error('bind');\n }\n } else if (envelope.b !== undefined) {\n // Fail-closed on configuration drift: a token minted with a\n // bind callback is rejected when verified by an instance that\n // has none configured. Accepting it would silently drop the\n // principal-binding guarantee.\n throw new Error('bind');\n }\n return envelope.p;\n }\n };\n}\n","import type { JsonSchemaType, jsonSchemaValidator, StandardSchemaWithJSON } from '@modelcontextprotocol/core-internal';\nimport { fromJsonSchema as coreFromJsonSchema } from '@modelcontextprotocol/core-internal';\nimport { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims';\n\nlet _defaultValidator: jsonSchemaValidator | undefined;\n\nexport function fromJsonSchema<T = unknown>(schema: JsonSchemaType, validator?: jsonSchemaValidator): StandardSchemaWithJSON<T, T> {\n return coreFromJsonSchema<T>(schema, validator ?? (_defaultValidator ??= new DefaultJsonSchemaValidator()));\n}\n"],"mappings":";;;;;;;;;AA2GA,IAAa,gCAAb,MAAgE;CAC5D;CACA;CACA;CAEA,AAAiB;CACjB,AAAiB;CAEjB,AAAQ,WAAW;CACnB,AAAQ,QAAQ;CAChB,AAAQ,UAAU;CAClB,AAAQ,qBAAqB;;;;;;;;;;CAU7B,AAAQ,sBAAsB;CAC9B,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,SAA+C;AACvD,OAAK,kBAAkB,QAAQ;AAC/B,OAAK,gBAAgB,QAAQ,gBAAgB;;CAGjD,MAAM,QAAuB;AACzB,MAAI,KAAK,SACL,OAAM,IAAI,MAAM,mDAAmD;AAEvE,OAAK,WAAW;;;;;;;;;;;;CAapB,MAAM,cAAc,SAA+C,OAAmD;AAClH,MAAI,KAAK,MACL,OAAM,IAAI,MAAM,mGAAmG;AAEvH,MAAI,CAAC,KAAK,YAAY,KAAK,cAAc,OACrC,OAAM,IAAI,MAAM,+GAA+G;AAEnI,MAAI,KAAK,QACL,OAAM,IAAI,MAAM,0CAA0C;AAE9D,OAAK,QAAQ;EAEb,MAAM,SAAS,OAAO,SAAS;AAC/B,MAAI,QAAQ,SAAS;AACjB,SAAM,KAAK,OAAO;AAClB,SAAM,IAAI,SAAS,aAAa,kBAAkB,qDAAqD;;EAK3G,MAAMA,eAAiC;GACnC,gBAAgB,KAAK;GACrB,GAAI,OAAO,YAAY,UAAa,EAAE,SAAS,MAAM,SAAS;GAC9D,GAAI,OAAO,aAAa,UAAa,EAAE,UAAU,MAAM,UAAU;GACpE;AAED,MAAI,iBAAiB,QAAQ,EAAE;AAC3B,QAAK,aAAa,QAAQ;GAE1B,IAAIC;GACJ,IAAIC;GACJ,MAAM,UAAU,IAAI,SAAmB,gBAAgB,kBAAkB;AACrE,cAAU;AACV,aAAS;KACX;AACF,QAAK,oBAAoB;IAAE;IAAS;IAAS;IAAQ,SAAS;IAAO;AAErE,OAAI,WAAW,QAAW;IACtB,MAAM,gBAAgB,KAAK,KAAK,OAAO;AACvC,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AACzD,SAAK,sBAAsB,OAAO,oBAAoB,SAAS,QAAQ;;AAG3E,QAAK,sBAAsB;AAC3B,OAAI;AACA,SAAK,UAAU,SAAS,aAAa;aAC/B;AACN,SAAK,sBAAsB;;AAG/B,OAAI,KAAK,kBAAkB,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,kBAAkB,QAOzE,MAAK,cAAc;AAEvB,UAAO;;AAKX,OAAK,UAAU,SAAS,aAAa;AACrC,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;CAG9C,MAAM,KAAK,SAAyB,SAA+C;AAC/E,MAAI,KAAK,QAEL;EAGJ,MAAM,aAAa,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ;EACtF,MAAM,YAAY,aAAc,QAA8B,KAAK,SAAS;AAE5E,MAAI,KAAK,eAAe,UAAa,cAAc,UAAa,cAAc,KAAK,YAAY;AAC3F,OAAI,WACA,MAAK,0BAAU,IAAI,MAAM,kDAAkD,OAAQ,QAA6B,GAAG,GAAG,CAAC;AAK3H;;AAGJ,MAAI,YAAY;AACZ,OAAI,KAAK,mBACL;AAEJ,QAAK,qBAAqB;GAW1B,MAAM,eACF,KAAK,uBAAuB,uBAAuB,QAAQ,GACrD,yBAA0B,QAAiC,MAAM,QACjE;AACV,OAAI,iBAAiB,UAAa,KAAK,SAAS,QAAW;AACvD,SAAK,eAAe,SAAS,KAAK,SAAS;KAAE,QAAQ;KAAc,SAAS,EAAE,gBAAgB,oBAAoB;KAAE,CAAC,CAAC;AACtH,yBAAqB,KAAK,KAAK,OAAO,CAAC;AACvC;;AAGJ,OAAI,KAAK,SAAS,UAAa,KAAK,kBAAkB,OAAO;AAGzD,QAAI,KAAK,SAAS,OACd,MAAK,cAAc;AAEvB,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,gBAAgB;AACrB;;AAIJ,QAAK,eAAe,SAAS,KAAK,SAAS;IAAE,QAAQ;IAAK,SAAS,EAAE,gBAAgB,oBAAoB;IAAE,CAAC,CAAC;AAC7G,wBAAqB,KAAK,KAAK,OAAO,CAAC;AACvC;;AAMJ,MAAI,KAAK,kBAAkB,OAEvB;AAEJ,MAAI,KAAK,SAAS,OACd,MAAK,cAAc;AAEvB,OAAK,kBAAkB,QAAQ;;;;;;CAOnC,kBAAkB,SAAuB;AACrC,MAAI,KAAK,WAAW,KAAK,SAAS,UAAa,KAAK,KAAK,OACrD;EAEJ,MAAM,QAAQ,QACT,MAAM,KAAK,CACX,KAAI,SAAQ,KAAK,OAAO,CACxB,KAAK,KAAK;AACf,OAAK,WAAW,GAAG,MAAM,MAAM;;CAGnC,MAAM,QAAuB;AACzB,MAAI,KAAK,QACL;AAEJ,OAAK,UAAU;AAEf,OAAK,iBAAiB;AACtB,OAAK,gBAAgB;AAErB,MAAI,KAAK,SAAS,UAAa,CAAC,KAAK,KAAK,QAAQ;AAC9C,QAAK,KAAK,SAAS;AACnB,OAAI;AACA,SAAK,KAAK,WAAW,OAAO;WACxB;;AAKZ,MAAI,KAAK,sBAAsB,UAAa,CAAC,KAAK,kBAAkB,SAAS;AACzE,QAAK,kBAAkB,UAAU;AACjC,QAAK,kBAAkB,OAAO,IAAI,SAAS,aAAa,kBAAkB,mDAAmD,CAAC;;AAGlI,OAAK,WAAW;;CAGpB,AAAQ,eAAe,UAA0B;AAC7C,MAAI,KAAK,sBAAsB,UAAa,KAAK,kBAAkB,QAC/D;AAEJ,OAAK,kBAAkB,UAAU;AACjC,OAAK,kBAAkB,QAAQ,SAAS;;CAG5C,AAAQ,eAAqB;EACzB,IAAIC;EACJ,MAAM,WAAW,IAAI,eAA2B;GAC5C,QAAO,qBAAoB;AACvB,iBAAa;;GAEjB,cAAc;AAIV,IAAK,KAAK,OAAO;;GAExB,CAAC;AACF,OAAK,OAAO;GAAE;GAAY,SAAS,IAAI,aAAa;GAAE,QAAQ;GAAO;AAErE,OAAK,eACD,IAAI,SAAS,UAAU;GACnB,QAAQ;GACR,SAAS;IACL,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IAGZ,qBAAqB;IACxB;GACJ,CAAC,CACL;;CAGL,AAAQ,iBAAuB;AAC3B,MAAI,KAAK,SAAS,UAAa,CAAC,KAAK,KAAK,QAAQ;AAC9C,QAAK,KAAK,SAAS;AACnB,OAAI;AACA,SAAK,KAAK,WAAW,OAAO;WACxB;;AAIZ,uBAAqB,KAAK,KAAK,OAAO,CAAC;;CAG3C,AAAQ,kBAAkB,SAA+B;AACrD,OAAK,WAAW,yBAAyB,KAAK,UAAU,QAAQ,CAAC,MAAM;;CAG3E,AAAQ,WAAW,OAAqB;AACpC,MAAI,KAAK,SAAS,UAAa,KAAK,KAAK,OACrC;AAEJ,MAAI;AACA,QAAK,KAAK,WAAW,QAAQ,KAAK,KAAK,QAAQ,OAAO,MAAM,CAAC;WACxD,OAAO;AACZ,QAAK,0BAAU,IAAI,MAAM,2CAA2C,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;AC3VzF,eAAsB,OAClB,QACA,SACA,KACiB;CACjB,MAAM,YAAY,IAAI,8BAA8B;EAChD,gBAAgB,IAAI;EACpB,GAAI,IAAI,iBAAiB,UAAa,EAAE,cAAc,IAAI,cAAc;EAC3E,CAAC;AACF,OAAM,OAAO,QAAQ,UAAU;AAC/B,QAAO,UAAU,cAAc,SAAS;EACpC,GAAI,IAAI,YAAY,UAAa,EAAE,SAAS,IAAI,SAAS;EACzD,GAAI,IAAI,aAAa,UAAa,EAAE,UAAU,IAAI,UAAU;EAC/D,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACmKN,IAAa,2CAAb,MAA2E;CAEvE,AAAQ;CACR,AAAQ,WAAoB;CAC5B,AAAQ,UAAmB;CAC3B,AAAQ,iCAA6C,IAAI,KAAK;CAC9D,AAAQ,0CAAkD,IAAI,KAAK;CACnE,AAAQ,sCAAsD,IAAI,KAAK;CACvE,AAAQ,eAAwB;CAChC,AAAQ,sBAA+B;CACvC,AAAQ,yBAAiC;CACzC,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER;CACA;CACA;CACA;CAEA,YAAY,UAA2D,EAAE,EAAE;AACvE,OAAK,qBAAqB,QAAQ;AAClC,OAAK,sBAAsB,QAAQ,sBAAsB;AACzD,OAAK,cAAc,QAAQ;AAC3B,OAAK,wBAAwB,QAAQ;AACrC,OAAK,mBAAmB,QAAQ;AAChC,OAAK,gBAAgB,QAAQ;AAC7B,OAAK,kBAAkB,QAAQ;AAC/B,OAAK,gCAAgC,QAAQ,gCAAgC;AAC7E,OAAK,iBAAiB,QAAQ;AAC9B,OAAK,6BAA6B,QAAQ,6BAA6B;;;;;;CAO3E,MAAM,QAAuB;AACzB,MAAI,KAAK,SACL,OAAM,IAAI,MAAM,4BAA4B;AAEhD,OAAK,WAAW;;;;;;CAOpB,6BAA6B,UAA0B;AACnD,OAAK,6BAA6B;;;;;CAMtC,AAAQ,wBACJ,QACA,MACA,SACA,SACQ;EACR,MAAMC,QAA0D;GAAE;GAAM;GAAS;AACjF,MAAI,SAAS,SAAS,OAClB,OAAM,OAAO,QAAQ;AAEzB,SAAO,SAAS,KACZ;GACI,SAAS;GACT;GACA,IAAI;GACP,EACD;GACI;GACA,SAAS;IACL,gBAAgB;IAChB,GAAG,SAAS;IACf;GACJ,CACJ;;;;;;CAOL,AAAQ,uBAAuB,KAAoC;AAE/D,MAAI,CAAC,KAAK,8BACN;AAIJ,MAAI,KAAK,iBAAiB,KAAK,cAAc,SAAS,GAAG;GACrD,MAAM,aAAa,IAAI,QAAQ,IAAI,OAAO;AAC1C,OAAI,CAAC,cAAc,CAAC,KAAK,cAAc,SAAS,WAAW,EAAE;IACzD,MAAM,QAAQ,wBAAwB;AACtC,SAAK,UAAU,IAAI,MAAM,MAAM,CAAC;AAChC,WAAO,KAAK,wBAAwB,KAAK,OAAS,MAAM;;;AAKhE,MAAI,KAAK,mBAAmB,KAAK,gBAAgB,SAAS,GAAG;GACzD,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAC9C,OAAI,gBAAgB,CAAC,KAAK,gBAAgB,SAAS,aAAa,EAAE;IAC9D,MAAM,QAAQ,0BAA0B;AACxC,SAAK,UAAU,IAAI,MAAM,MAAM,CAAC;AAChC,WAAO,KAAK,wBAAwB,KAAK,OAAS,MAAM;;;;;;;;CAWpE,MAAM,cAAc,KAAc,SAAmD;EAEjF,MAAM,kBAAkB,KAAK,uBAAuB,IAAI;AACxD,MAAI,gBACA,QAAO;AAGX,UAAQ,IAAI,QAAZ;GACI,KAAK,OACD,QAAO,KAAK,kBAAkB,KAAK,QAAQ;GAE/C,KAAK,MACD,QAAO,KAAK,iBAAiB,IAAI;GAErC,KAAK,SACD,QAAO,KAAK,oBAAoB,IAAI;GAExC,QACI,QAAO,KAAK,0BAA0B;;;;;;;;;;;;;;;CAiBlD,AAAQ,qBAAqB,iBAAkC;AAC3D,SAAO,KAAK,2BAA2B,SAAS,gBAAgB,IAAI,mBAAmB;;;;;;;;CAS3F,MAAc,kBACV,YACA,SACA,UACA,iBACa;AACb,MAAI,CAAC,KAAK,YACN;AAMJ,MAAI,CAAC,KAAK,qBAAqB,gBAAgB,CAC3C;EAGJ,MAAM,iBAAiB,MAAM,KAAK,YAAY,WAAW,UAAU,EAAE,CAAmB;EAExF,IAAI,eAAe,OAAO,eAAe;AACzC,MAAI,KAAK,mBAAmB,OACxB,gBAAe,OAAO,eAAe,WAAW,KAAK,eAAe;AAExE,aAAW,QAAQ,QAAQ,OAAO,aAAa,CAAC;;;;;CAMpD,MAAc,iBAAiB,KAAiC;AAG5D,MAAI,CADiB,IAAI,QAAQ,IAAI,SAAS,EAC3B,SAAS,oBAAoB,EAAE;AAC9C,QAAK,0BAAU,IAAI,MAAM,uDAAuD,CAAC;AACjF,UAAO,KAAK,wBAAwB,KAAK,OAAS,uDAAuD;;EAM7G,MAAM,eAAe,KAAK,gBAAgB,IAAI;AAC9C,MAAI,aACA,QAAO;EAEX,MAAM,gBAAgB,KAAK,wBAAwB,IAAI;AACvD,MAAI,cACA,QAAO;AAIX,MAAI,KAAK,aAAa;GAClB,MAAM,cAAc,IAAI,QAAQ,IAAI,gBAAgB;AACpD,OAAI,YACA,QAAO,KAAK,aAAa,YAAY;;AAK7C,MAAI,KAAK,eAAe,IAAI,KAAK,uBAAuB,KAAK,QAAW;AAEpE,QAAK,0BAAU,IAAI,MAAM,uDAAuD,CAAC;AACjF,UAAO,KAAK,wBAAwB,KAAK,OAAS,uDAAuD;;EAG7G,MAAM,UAAU,IAAI,aAAa;EACjC,IAAIC;EAGJ,MAAM,WAAW,IAAI,eAA2B;GAC5C,QAAO,eAAc;AACjB,uBAAmB;;GAEvB,cAAc;AAIV,QAAI,KAAK,eAAe,IAAI,KAAK,uBAAuB,EAAE,eAAe,iBACrE,MAAK,eAAe,OAAO,KAAK,uBAAuB;;GAGlE,CAAC;EAEF,MAAMC,UAAkC;GACpC,gBAAgB;GAChB,iBAAiB;GACjB,YAAY;GACf;AAGD,MAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;AAIrC,OAAK,eAAe,IAAI,KAAK,wBAAwB;GACjD,YAAY;GACZ;GACA,eAAe;AACX,SAAK,eAAe,OAAO,KAAK,uBAAuB;AACvD,QAAI;AACA,sBAAkB,OAAO;YACrB;;GAIf,CAAC;AAEF,SAAO,IAAI,SAAS,UAAU,EAAE,SAAS,CAAC;;;;;;CAO9C,MAAc,aAAa,aAAwC;AAC/D,MAAI,CAAC,KAAK,aAAa;AACnB,QAAK,0BAAU,IAAI,MAAM,6BAA6B,CAAC;AACvD,UAAO,KAAK,wBAAwB,KAAK,OAAS,6BAA6B;;AAGnF,MAAI;GAEA,IAAIC;AACJ,OAAI,KAAK,YAAY,uBAAuB;AACxC,eAAW,MAAM,KAAK,YAAY,sBAAsB,YAAY;AAEpE,QAAI,CAAC,UAAU;AACX,UAAK,0BAAU,IAAI,MAAM,0BAA0B,CAAC;AACpD,YAAO,KAAK,wBAAwB,KAAK,OAAS,0BAA0B;;AAIhF,QAAI,KAAK,eAAe,IAAI,SAAS,KAAK,QAAW;AACjD,UAAK,0BAAU,IAAI,MAAM,oDAAoD,CAAC;AAC9E,YAAO,KAAK,wBAAwB,KAAK,OAAS,oDAAoD;;;GAI9G,MAAMD,UAAkC;IACpC,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IACf;AAED,OAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;GAIrC,MAAM,UAAU,IAAI,aAAa;GACjC,IAAID;GAIJ,IAAIG;GAEJ,MAAM,WAAW,IAAI,eAA2B;IAC5C,QAAO,eAAc;AACjB,wBAAmB;;IAEvB,cAAc;AAOV,SAAI,qBAAqB,UAAa,KAAK,eAAe,IAAI,iBAAiB,EAAE,eAAe,iBAC5F,MAAK,eAAe,OAAO,iBAAiB;;IAGvD,CAAC;GAGF,MAAM,mCAAmB,IAAI,KAAa;AAC1C,sBAAmB,MAAM,KAAK,YAAY,kBAAkB,aAAa,EACrE,MAAM,OAAO,SAAiB,YAA4B;AACtD,qBAAiB,IAAI,QAAQ;AAE7B,QAAI,CADY,KAAK,cAAc,kBAAmB,SAAS,SAAS,QAAQ,CAE5E,KAAI;AACA,sBAAkB,OAAO;YACrB;MAKnB,CAAC;AAEF,QAAK,eAAe,IAAI,kBAAkB;IACtC,YAAY;IACZ;IACA;IACA,eAAe;AACX,UAAK,eAAe,OAAO,iBAAkB;AAC7C,SAAI;AACA,uBAAkB,OAAO;aACrB;;IAIf,CAAC;AASF,OAAI,qBAAqB,KAAK,wBAE1B;QAAI,CADuB,CAAC,GAAG,KAAK,wBAAwB,QAAQ,CAAC,CAAC,SAAS,iBAAiB,EACvE;AACrB,UAAK,eAAe,OAAO,iBAAiB;AAC5C,SAAI;AACA,uBAAkB,OAAO;aACrB;;;AAMhB,UAAO,IAAI,SAAS,UAAU,EAAE,SAAS,CAAC;WACrC,OAAO;AACZ,QAAK,UAAU,MAAe;AAC9B,UAAO,KAAK,wBAAwB,KAAK,OAAS,yBAAyB;;;;;;CAOnF,AAAQ,cACJ,YACA,SACA,SACA,SACO;AACP,MAAI;GACA,IAAI,YAAY;AAEhB,OAAI,QACA,cAAa,OAAO,QAAQ;AAEhC,gBAAa,SAAS,KAAK,UAAU,QAAQ,CAAC;AAC9C,cAAW,QAAQ,QAAQ,OAAO,UAAU,CAAC;AAC7C,UAAO;WACF,OAAO;AACZ,QAAK,UAAU,MAAe;AAC9B,UAAO;;;;;;CAOf,AAAQ,2BAAqC;AACzC,OAAK,0BAAU,IAAI,MAAM,sBAAsB,CAAC;AAChD,SAAO,SAAS,KACZ;GACI,SAAS;GACT,OAAO;IACH,MAAM;IACN,SAAS;IACZ;GACD,IAAI;GACP,EACD;GACI,QAAQ;GACR,SAAS;IACL,OAAO;IACP,gBAAgB;IACnB;GACJ,CACJ;;;;;CAML,MAAc,kBAAkB,KAAc,SAAmD;AAC7F,MAAI;GAEA,MAAM,eAAe,IAAI,QAAQ,IAAI,SAAS;AAE9C,OAAI,CAAC,cAAc,SAAS,mBAAmB,IAAI,CAAC,aAAa,SAAS,oBAAoB,EAAE;AAC5F,SAAK,0BAAU,IAAI,MAAM,iFAAiF,CAAC;AAC3G,WAAO,KAAK,wBACR,KACA,OACA,iFACH;;GAGL,MAAM,KAAK,IAAI,QAAQ,IAAI,eAAe;AAC1C,OAAI,CAAC,MAAM,CAAC,GAAG,SAAS,mBAAmB,EAAE;AACzC,SAAK,0BAAU,IAAI,MAAM,gEAAgE,CAAC;AAC1F,WAAO,KAAK,wBAAwB,KAAK,OAAS,gEAAgE;;GAGtH,MAAM,UAAU;GAEhB,IAAI;AACJ,OAAI,SAAS,eAAe,OACxB,KAAI;AACA,iBAAa,MAAM,IAAI,MAAM;YACxB,OAAO;AACZ,SAAK,UAAU,MAAe;AAC9B,WAAO,KAAK,wBAAwB,KAAK,QAAS,4BAA4B;;OAGlF,cAAa,QAAQ;GAGzB,IAAIC;AAGJ,OAAI;AACA,eAAW,MAAM,QAAQ,WAAW,GAC9B,WAAW,KAAI,QAAO,qBAAqB,MAAM,IAAI,CAAC,GACtD,CAAC,qBAAqB,MAAM,WAAW,CAAC;YACzC,OAAO;AACZ,SAAK,UAAU,MAAe;AAC9B,WAAO,KAAK,wBAAwB,KAAK,QAAS,wCAAwC;;GAS9F,MAAM,0BAA0B,SAAS,MAAK,YAAW,oBAAoB,QAAQ,CAAC;AACtF,OAAI,yBAAyB;AAGzB,QAAI,KAAK,gBAAgB,KAAK,cAAc,QAAW;AACnD,UAAK,0BAAU,IAAI,MAAM,8CAA8C,CAAC;AACxE,YAAO,KAAK,wBAAwB,KAAK,QAAS,8CAA8C;;AAEpG,QAAI,SAAS,SAAS,GAAG;AACrB,UAAK,0BAAU,IAAI,MAAM,8DAA8D,CAAC;AACxF,YAAO,KAAK,wBAAwB,KAAK,QAAS,8DAA8D;;AAEpH,SAAK,YAAY,KAAK,sBAAsB;AAC5C,SAAK,eAAe;AAIpB,QAAI,KAAK,aAAa,KAAK,sBACvB,OAAM,QAAQ,QAAQ,KAAK,sBAAsB,KAAK,UAAU,CAAC;;AAGzE,OAAI,CAAC,yBAAyB;IAI1B,MAAM,eAAe,KAAK,gBAAgB,IAAI;AAC9C,QAAI,aACA,QAAO;IAGX,MAAM,gBAAgB,KAAK,wBAAwB,IAAI;AACvD,QAAI,cACA,QAAO;;AAOf,OAAI,CAFgB,SAAS,MAAK,YAAW,iBAAiB,QAAQ,CAAC,EAErD;AAEd,SAAK,MAAM,WAAW,SAClB,MAAK,YAAY,SAAS;KAAE,UAAU,SAAS;KAAU;KAAS,CAAC;AAEvE,WAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;GAK9C,MAAM,WAAW,OAAO,YAAY;GAKpC,MAAM,cAAc,SAAS,MAAK,MAAK,oBAAoB,EAAE,CAAC;GAC9D,MAAM,wBAAwB,cACxB,YAAY,OAAO,kBAClB,IAAI,QAAQ,IAAI,uBAAuB,IAAI;AAElD,OAAI,KAAK,oBAEL,QAAO,IAAI,SAAkB,YAAW;AACpC,SAAK,eAAe,IAAI,UAAU;KAC9B,aAAa;KACb,eAAe;AACX,WAAK,eAAe,OAAO,SAAS;;KAE3C,CAAC;AAEF,SAAK,MAAM,WAAW,SAClB,KAAI,iBAAiB,QAAQ,CACzB,MAAK,wBAAwB,IAAI,QAAQ,IAAI,SAAS;AAI9D,SAAK,MAAM,WAAW,SAClB,MAAK,YAAY,SAAS;KAAE,UAAU,SAAS;KAAU;KAAS,CAAC;KAEzE;GAIN,MAAM,UAAU,IAAI,aAAa;GACjC,IAAIJ;GAEJ,MAAM,WAAW,IAAI,eAA2B;IAC5C,QAAO,eAAc;AACjB,wBAAmB;;IAEvB,cAAc;AAMV,SAAI,KAAK,eAAe,IAAI,SAAS,EAAE,eAAe,iBAClD,MAAK,eAAe,OAAO,SAAS;;IAG/C,CAAC;GAEF,MAAMC,UAAkC;IACpC,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IACf;AAGD,OAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;AAKrC,QAAK,MAAM,WAAW,SAClB,KAAI,iBAAiB,QAAQ,EAAE;AAC3B,SAAK,eAAe,IAAI,UAAU;KAC9B,YAAY;KACZ;KACA,eAAe;AACX,WAAK,eAAe,OAAO,SAAS;AACpC,UAAI;AACA,wBAAkB,OAAO;cACrB;;KAIf,CAAC;AACF,SAAK,wBAAwB,IAAI,QAAQ,IAAI,SAAS;;AAK9D,SAAM,KAAK,kBAAkB,kBAAmB,SAAS,UAAU,sBAAsB;AAGzF,QAAK,MAAM,WAAW,UAAU;IAK5B,IAAII;IACJ,IAAIC;AACJ,QAAI,iBAAiB,QAAQ,IAAI,KAAK,eAAe,KAAK,qBAAqB,sBAAsB,EAAE;AACnG,4BAAuB;AACnB,WAAK,eAAe,QAAQ,GAAG;;AAEnC,sCAAiC;AAC7B,WAAK,0BAA0B;;;AAIvC,SAAK,YAAY,SAAS;KAAE,UAAU,SAAS;KAAU;KAAS;KAAgB;KAA0B,CAAC;;AAKjH,UAAO,IAAI,SAAS,UAAU;IAAE,QAAQ;IAAK;IAAS,CAAC;WAClD,OAAO;AAEZ,QAAK,UAAU,MAAe;AAC9B,UAAO,KAAK,wBAAwB,KAAK,QAAS,eAAe,EAAE,MAAM,OAAO,MAAM,EAAE,CAAC;;;;;;CAOjG,MAAc,oBAAoB,KAAiC;EAC/D,MAAM,eAAe,KAAK,gBAAgB,IAAI;AAC9C,MAAI,aACA,QAAO;EAEX,MAAM,gBAAgB,KAAK,wBAAwB,IAAI;AACvD,MAAI,cACA,QAAO;AAGX,QAAM,QAAQ,QAAQ,KAAK,mBAAmB,KAAK,UAAW,CAAC;AAC/D,QAAM,KAAK,OAAO;AAClB,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;;;;;;CAO9C,AAAQ,gBAAgB,KAAoC;AACxD,MAAI,KAAK,uBAAuB,OAG5B;AAEJ,MAAI,CAAC,KAAK,cAAc;AAEpB,QAAK,0BAAU,IAAI,MAAM,sCAAsC,CAAC;AAChE,UAAO,KAAK,wBAAwB,KAAK,OAAS,sCAAsC;;EAG5F,MAAM,YAAY,IAAI,QAAQ,IAAI,iBAAiB;AAEnD,MAAI,CAAC,WAAW;AAEZ,QAAK,0BAAU,IAAI,MAAM,iDAAiD,CAAC;AAC3E,UAAO,KAAK,wBAAwB,KAAK,OAAS,iDAAiD;;AAGvG,MAAI,cAAc,KAAK,WAAW;AAE9B,QAAK,0BAAU,IAAI,MAAM,oBAAoB,CAAC;AAC9C,UAAO,KAAK,wBAAwB,KAAK,QAAS,oBAAoB;;;;;;;;;;;;;;;;CAmB9E,AAAQ,wBAAwB,KAAoC;EAChE,MAAM,kBAAkB,IAAI,QAAQ,IAAI,uBAAuB;AAE/D,MAAI,oBAAoB,QAAQ,CAAC,KAAK,2BAA2B,SAAS,gBAAgB,EAAE;GACxF,MAAM,QAAQ,8CAA8C,gBAAgB,wBAAwB,KAAK,2BAA2B,KAAK,KAAK,CAAC;AAC/I,QAAK,UAAU,IAAI,MAAM,MAAM,CAAC;AAChC,UAAO,KAAK,wBAAwB,KAAK,OAAS,MAAM;;;CAKhE,MAAM,QAAuB;AACzB,MAAI,KAAK,QACL;AAEJ,OAAK,UAAU;AAGf,OAAK,MAAM,EAAE,aAAa,KAAK,eAAe,QAAQ,CAClD,UAAS;AAEb,OAAK,eAAe,OAAO;AAG3B,OAAK,oBAAoB,OAAO;AAChC,OAAK,WAAW;;;;;;;CAQpB,eAAe,WAA4B;EACvC,MAAM,WAAW,KAAK,wBAAwB,IAAI,UAAU;AAC5D,MAAI,CAAC,SAAU;EAEf,MAAM,SAAS,KAAK,eAAe,IAAI,SAAS;AAChD,MAAI,OACA,QAAO,SAAS;;;;;;CAQxB,2BAAiC;EAC7B,MAAM,SAAS,KAAK,eAAe,IAAI,KAAK,uBAAuB;AACnE,MAAI,OACA,QAAO,SAAS;;CAIxB,MAAM,KAAK,SAAyB,SAA2D;EAC3F,IAAI,YAAY,SAAS;AACzB,MAAI,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ,CAEnE,aAAY,QAAQ;AAMxB,MAAI,cAAc,QAAW;AAEzB,OAAI,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ,CACnE,OAAM,IAAI,MAAM,8FAA8F;GAKlH,IAAIC;AACJ,OAAI,KAAK,YAEL,WAAU,MAAM,KAAK,YAAY,WAAW,KAAK,wBAAwB,QAAQ;GAGrF,MAAM,gBAAgB,KAAK,eAAe,IAAI,KAAK,uBAAuB;AAC1E,OAAI,kBAAkB,OAElB;AAMJ,OACI,cAAc,cACd,cAAc,YACb,YAAY,UAAa,CAAC,cAAc,kBAAkB,IAAI,QAAQ,EAEvE,MAAK,cAAc,cAAc,YAAY,cAAc,SAAS,SAAS,QAAQ;AAEzF;;EAIJ,MAAM,WAAW,KAAK,wBAAwB,IAAI,UAAU;AAC5D,MAAI,CAAC,SACD,OAAM,IAAI,MAAM,6CAA6C,OAAO,UAAU,GAAG;EAGrF,IAAI,SAAS,KAAK,eAAe,IAAI,SAAS;AAE9C,MAAI,CAAC,KAAK,qBAAqB;GAU3B,IAAIA;AACJ,OAAI,KAAK,aAAa;AAClB,cAAU,MAAM,KAAK,YAAY,WAAW,UAAU,QAAQ;AAI9D,aAAS,KAAK,eAAe,IAAI,SAAS;;AAM9C,OAAI,QAAQ,cAAc,QAAQ,YAAY,YAAY,UAAa,CAAC,OAAO,kBAAkB,IAAI,QAAQ,EACzG,MAAK,cAAc,OAAO,YAAY,OAAO,SAAS,SAAS,QAAQ;;AAI/E,MAAI,wBAAwB,QAAQ,IAAI,uBAAuB,QAAQ,EAAE;AACrE,QAAK,oBAAoB,IAAI,WAAW,QAAQ;GAChD,MAAM,aAAa,CAAC,GAAG,KAAK,wBAAwB,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,QAAQ,SAAS,CAAC,KAAK,CAAC,QAAQ,GAAG;AAKvH,OAF0B,WAAW,OAAM,OAAM,KAAK,oBAAoB,IAAI,GAAG,CAAC,EAE3D;AACnB,QAAI,CAAC,QAAQ;AACT,SAAI,KAAK,oBAGL,OAAM,IAAI,MAAM,6CAA6C,OAAO,UAAU,GAAG;AAErF,SAAI,CAAC,KAAK,aAAa;AAMnB,WAAK,0BACD,IAAI,MACA,2BAA2B,OAAO,UAAU,CAAC,uFAChD,CACJ;AACD,WAAK,MAAM,MAAM,YAAY;AACzB,YAAK,oBAAoB,OAAO,GAAG;AACnC,YAAK,wBAAwB,OAAO,GAAG;;AAE3C;;AAMJ,UAAK,MAAM,MAAM,YAAY;AACzB,WAAK,oBAAoB,OAAO,GAAG;AACnC,WAAK,wBAAwB,OAAO,GAAG;;AAE3C;;AAEJ,QAAI,KAAK,uBAAuB,OAAO,aAAa;KAEhD,MAAMN,UAAkC,EACpC,gBAAgB,oBACnB;AACD,SAAI,KAAK,cAAc,OACnB,SAAQ,oBAAoB,KAAK;KAGrC,MAAM,YAAY,WAAW,KAAI,OAAM,KAAK,oBAAoB,IAAI,GAAG,CAAE;AAEzE,SAAI,UAAU,WAAW,EACrB,QAAO,YAAY,SAAS,KAAK,UAAU,IAAI;MAAE,QAAQ;MAAK;MAAS,CAAC,CAAC;SAEzE,QAAO,YAAY,SAAS,KAAK,WAAW;MAAE,QAAQ;MAAK;MAAS,CAAC,CAAC;AAE1E,YAAO,SAAS;UAGhB,QAAO,SAAS;AAGpB,SAAK,MAAM,MAAM,YAAY;AACzB,UAAK,oBAAoB,OAAO,GAAG;AACnC,UAAK,wBAAwB,OAAO,GAAG;;;;;;;;;;;;;;;;;AC14B3D,SAAS,kBAAkB,MAAiC;AACxD,KAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAChE,QAAO;CAEX,MAAM,EAAE,QAAQ,OAAO;AACvB,KAAI,OAAO,WAAW,SAClB,QAAO;AAEX,QAAO,OAAO,OAAO,YAAY,OAAO,OAAO,WAAW,KAAK;;AAGnE,SAAS,qBAAqB,YAAoB,MAAc,SAAiB,MAAgB,KAAuB,MAAgB;AACpI,QAAO,SAAS,KACZ;EACI,SAAS;EACT,OAAO;GAAE;GAAM;GAAS,GAAI,SAAS,UAAa,EAAE,MAAM;GAAG;EAC7D;EACH,EACD,EAAE,QAAQ,YAAY,CACzB;;AAGL,SAAS,kBAAkB,WAAmC,KAAuB,MAAgB;AACjG,QAAO,qBAAqB,UAAU,YAAY,UAAU,MAAM,UAAU,SAAS,UAAU,MAAM,GAAG;;AAG5G,SAAS,QAAQ,OAAuB;AACpC,QAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;;AAGpE,SAAS,4BAA4B,KAAuB,MAAgB;AACxE,QAAO,qBAAqB,KAAK,QAAS,yBAAyB,QAAW,GAAG;;;;;;;;;;;;;;;;;;;;;AA0BrF,SAAgB,wBAAwB,SAA2B,SAAqD;AACpH,QAAO,OAAO,SAAS,YAAY;AAC/B,MAAI,QAAQ,OAAO,aAAa,KAAK,OACjC,QAAO,qBAAqB,KAAK,OAAS,sBAAsB;AAEpE,MAAI;GACA,MAAM,UAAU,MAAM,QAAQ;IAC1B,KAAK;IACL,GAAI,SAAS,aAAa,UAAa,EAAE,UAAU,QAAQ,UAAU;IACrE,aAAa;IAChB,CAAC;GACF,MAAM,YAAY,IAAI,yCAAyC,EAAE,oBAAoB,QAAW,CAAC;AACjG,SAAM,QAAQ,QAAQ,UAAU;GAEhC,MAAM,iBAAiB;AACnB,IAAK,UAAU,OAAO,CAAC,YAAY,GAAG;AACtC,IAAK,QAAQ,OAAO,CAAC,YAAY,GAAG;;AAIxC,WAAQ,QAAQ,iBAAiB,SAAS,UAAU,EAAE,MAAM,MAAM,CAAC;GAEnE,MAAM,WAAW,MAAM,UAAU,cAAc,SAAS;IACpD,GAAI,SAAS,aAAa,UAAa,EAAE,UAAU,QAAQ,UAAU;IACrE,GAAI,SAAS,eAAe,UAAa,EAAE,YAAY,QAAQ,YAAY;IAC9E,CAAC;AACF,OAAI,SAAS,SAAS,QAAQ,EAAE,SAAS,QAAQ,IAAI,eAAe,IAAI,IAAI,SAAS,oBAAoB,EAAE;AAGvG,cAAU;AACV,WAAO;;GAQX,MAAM,SAAS,SAAS,KAAK,WAAW;GACxC,IAAI,WAAW;GACf,MAAM,yBAAyB;AAC3B,QAAI,CAAC,UAAU;AACX,gBAAW;AACX,eAAU;;;GAGlB,MAAM,gBAAgB,IAAI,eAA2B;IACjD,MAAM,OAAM,eAAc;AACtB,SAAI;MACA,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,UAAI,MAAM;AACN,yBAAkB;AAClB,kBAAW,OAAO;AAClB;;AAEJ,UAAI,UAAU,OACV,YAAW,QAAQ,MAAM;cAExB,OAAO;AACZ,wBAAkB;AAClB,iBAAW,MAAM,MAAM;;;IAG/B,SAAQ,WAAU;AACd,uBAAkB;AAClB,YAAO,OAAO,OAAO,OAAO,CAAC,YAAY,GAAG;;IAEnD,CAAC;AACF,UAAO,IAAI,SAAS,eAAe;IAC/B,QAAQ,SAAS;IACjB,YAAY,SAAS;IACrB,SAAS,SAAS;IACrB,CAAC;WACG,OAAO;AACZ,OAAI;AACA,cAAU,QAAQ,MAAM,CAAC;WACrB;AAGR,UAAO,4BAA4B,kBAAkB,SAAS,WAAW,CAAC;;;;;;;;;;;;;;;AA6BtF,eAAe,qBAAqB,SAAkB,oBAA8B,eAAe,MAAoC;CACnI,MAAM,aAAa,QAAQ,OAAO,aAAa;CAE/C,IAAIO;CACJ,IAAI,aAAa;CACjB,IAAI,iBAAiB;CACrB,IAAI,cAAc;AAElB,KAAI,eAAe,QAAQ;AACvB,MAAI,eAAe,QAAW;AAI1B,OAAI,aACA,kBAAiB,QAAQ,OAAO;GAEpC,IAAIC;AACJ,OAAI;AACA,eAAW,MAAM,QAAQ,MAAM;WAC3B;AACJ,WAAO,EAAE,MAAM,mBAAmB;;AAEtC,OAAI;AACA,WAAO,SAAS,WAAW,IAAI,SAAY,KAAK,MAAM,SAAS;WAC3D;AACJ,kBAAc;;AAElB,OAAI,CAAC,eAAe,SAAS,OACzB,cAAa;QAGjB,QAAO;AAGX,MAAI,eAAe,SAAS,OACxB,QAAO;GAAE,MAAM;GAAgB;GAAgB;;AAWvD,QAAO;EAAE,MAAM;EAAc,SAPb,uBAAuB;GACnC;GACA,uBAAuB,QAAQ,QAAQ,IAAI,uBAAuB,IAAI;GACtE,iBAAiB,QAAQ,QAAQ,IAAI,aAAa,IAAI;GACtD,eAAe,QAAQ,QAAQ,IAAI,WAAW,IAAI;GAClD,GAAI,SAAS,UAAa,EAAE,MAAM;GACrC,CAAC;EACoC;EAAM;EAAY;EAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmE5E,eAAsB,gBAAgB,SAAkB,YAAwC;CAM5F,MAAM,aAAa,MAAM,qBADX,eAAe,UAAa,QAAQ,OAAO,aAAa,KAAK,SAAS,QAAQ,OAAO,GAAG,SACjD,YAAY,MAAM;AACvE,QAAO,WAAW,SAAS,kBAAmB,WAAW,SAAS,gBAAgB,WAAW,QAAQ,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDlH,SAAgB,iBAAiB,SAA2B,UAAmC,EAAE,EAAkB;CAC/G,MAAM,EAAE,QAAQ,SAAS,iBAAiB;AAK1C,KAAI,OAAO,WAAW,WAClB,OAAM,IAAI,UACN,8PAEH;;CAIL,MAAM,2BAAW,IAAI,KAAa;CAClC,IAAI,SAAS;CAEb,MAAM,eAAe,UAAiB;AAClC,MAAI;AACA,aAAU,MAAM;UACZ;;CAKZ,MAAMC,MAAsB,QAAQ,OAAO,IAAI,uBAAuB,YAAY;CAClF,MAAM,SAAS,qBAAqB,IAAI;CACxC,MAAM,eAAe,mBAAmB;EACpC;EACA,kBAAkB,QAAQ,oBAAoB;EAC9C,aAAa,QAAQ,eAAe;EACpC,SAAS;EACZ,CAAC;AACF,KAAI,iBAAiB,OAEjB,SAAQ,KACJ,kLAEH;CAKL,MAAMC,gBAA+C,WAAW,WAAW,SAAY,wBAAwB,SAAS,YAAY;CAEpI,eAAe,YAAY,OAA2B,SAAkB,UAAmD;EACvH,MAAM,kBAAkB,MAAM,eAAe;AAC7C,MAAI,oBAAoB,UAAa,CAAC,mCAAmC,SAAS,gBAAgB,EAAE;GAIhG,MAAM,QAAQ,IAAI,gCAAgC;IAC9C,WAAW,CAAC,GAAG,mCAAmC;IAClD,WAAW,mBAAmB;IACjC,CAAC;AACF,eAAY,MAAM;AAClB,UAAO,qBAAqB,KAAK,MAAM,MAAM,MAAM,SAAS,MAAM,MAAM,kBAAkB,MAAM,QAAQ,CAAC;;EAc7G,MAAM,qBAAqB,+BACvB;GACI,YAAY,QAAQ;GACpB,iBAAiB,QAAQ,QAAQ,IAAI,aAAa,IAAI;GACtD,eAAe,QAAQ,QAAQ,IAAI,WAAW,IAAI;GACrD,EACD,MACH;AACD,MAAI,uBAAuB,QAAW;AAClC,+BAAY,IAAI,MAAM,6BAA6B,mBAAmB,KAAK,KAAK,mBAAmB,UAAU,CAAC;AAC9G,UAAO,kBAAkB,oBAAoB,kBAAkB,MAAM,QAAQ,CAAC;;EAGlF,MAAM,OAAO,MAAM,gBAAgB,YAAY,cAAc,MAAM,QAAQ,OAAO,GAAG;EACrF,MAAM,6BAA6B,OAAO;AAQ1C,MAAI,MAAM,gBAAgB,WAAW;GACjC,MAAM,WAAW,qCAAqC,MAAM,QAAQ,OAAO;AAC3E,OAAI,aAAa,QAAW;IACxB,MAAM,UAAU,0BAA0B,UAAU,2BAA2B;AAC/E,QAAI,YAAY,QAAW;KACvB,MAAM,QAAQ,IAAI,qCAAqC,EAAE,sBAAsB,SAAS,CAAC;AACzF,iBAAY,MAAM;AAClB,YAAO,qBACH,uBAAuB,MAAM,MAAM,SAAS,EAC5C,MAAM,MACN,MAAM,SACN,MAAM,MACN,MAAM,QAAQ,GACjB;;;;EAKb,MAAM,UAAU,MAAM,QAAQ;GAC1B,KAAK;GACL,GAAI,aAAa,UAAa,EAAE,UAAU;GAC1C,aAAa;GAChB,CAAC;EACF,MAAM,SAAS,mBAAmB,YAAY,QAAQ,SAAS;AAa/D,MAAI,MAAM,gBAAgB,aAAa,MAAM,QAAQ,WAAW,wBAAwB;GACpF,MAAM,eAAe,OAAO,iBAAiB;AAC7C,GAAK,QAAQ,OAAO,CAAC,MAAM,YAAY;AACvC,UAAO,aAAa,MAAM,MAAM,SAAS,QAAQ,QAAQ,aAAa;;AAa1E,MAAI,MAAM,gBAAgB,aAAa,MAAM,QAAQ,WAAW,gBAAgB,mBAAmB,WAAW;GAC1G,MAAM,aAAa,MAAM,QAAQ;GACjC,MAAM,WAAW,OAAO,YAAY,SAAS,WAAW,WAAW,OAAO;GAC1E,MAAM,cAAc,aAAa,SAAY,SAAY,QAAQ,oBAAoB,SAAS;AAC9F,OAAI,gBAAgB,QAAW;IAC3B,MAAM,OAAO,2BAA2B,YAAY;AACpD,QAAI,KAAK,SAAS,KAAK,aAAa,SAAS,GAAG;KAC5C,MAAM,YAAY,wBAAwB,KAAK,cAAc,YAAY,WAAW,QAAQ,QAAQ;AACpG,SAAI,cAAc,QAAW;AACzB,MAAK,QAAQ,OAAO,CAAC,MAAM,YAAY;AACvC,kCAAY,IAAI,MAAM,6BAA6B,UAAU,KAAK,KAAK,UAAU,UAAU,CAAC;AAC5F,aAAO,kBAAkB,WAAW,MAAM,QAAQ,GAAG;;;;;AAQrE,+BAA6B,QAAQ,gBAAgB;AACrD,4BAA0B,QAAQ,mCAAmC;AAErE,MAAI,SAAS,OACT,gCAA+B,QAAQ;GACnC,YAAY,KAAK;GACjB,oBAAoB;GACvB,CAAC;EAIN,MAAM,kBAAkB,OAAO;AAC/B,WAAS,IAAI,OAAO;AACpB,SAAO,gBAAgB;AACnB,YAAS,OAAO,OAAO;AACvB,sBAAmB;;AAGvB,MAAI;GACA,MAAM,WAAW,MAAM,OAAO,SAAS,MAAM,SAAS;IAClD,gBAAgB,MAAM;IACtB;IACA,GAAI,aAAa,UAAa,EAAE,UAAU;IAC1C,GAAI,iBAAiB,UAAa,EAAE,cAAc;IACrD,CAAC;AACF,OAAI,MAAM,gBAAgB,eAGtB,sBAAqB,KAAK,OAAO,OAAO,CAAC,YAAY,GAAG,CAAC;AAE7D,UAAO;WACF,OAAO;AACZ,OAAI,iBAAiB,YAAY,MAAM,SAAS,aAAa,iBAGzD,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;AAM9C,SAAM,OAAO,OAAO,CAAC,YAAY,GAAG;AACpC,YAAS,OAAO,OAAO;AACvB,eAAY,QAAQ,MAAM,CAAC;AAC3B,UAAO,4BAA4B,kBAAkB,MAAM,QAAQ,CAAC;;;CAI5E,eAAe,iBACX,OACA,gBACA,UACA,YACiB;AACjB,MAAI,kBAAkB,OAClB,QAAO,cAAc,gBAAgB;GACjC,GAAI,aAAa,UAAa,EAAE,UAAU;GAC1C,GAAI,eAAe,UAAa,EAAE,YAAY;GACjD,CAAC;EAEN,MAAM,SAAS,0BAA0B,OAAO,mCAAmC;AACnF,MAAI,WAAW,OAGX,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC;AAE9C,8BAAY,IAAI,MAAM,wDAAwD,OAAO,KAAK,KAAK,OAAO,UAAU,CAAC;AACjH,SAAO,kBAAkB,QAAQ,kBAAkB,WAAW,CAAC;;CAGnE,eAAe,OAAO,SAAkB,gBAA8D;EAClG,MAAM,WAAW,gBAAgB;EACjC,MAAM,aAAa,MAAM,qBAAqB,SAAS,gBAAgB,WAAW;AAElF,MAAI,WAAW,SAAS,kBACpB,QAAO,qBAAqB,KAAK,QAAS,kDAAkD;AAEhG,MAAI,WAAW,SAAS,gBAAgB;AAKpC,OAAI,kBAAkB,OAClB,QAAO,cAAc,WAAW,gBAAgB,EAAE,GAAI,aAAa,UAAa,EAAE,UAAU,EAAG,CAAC;AAEpG,UAAO,qBAAqB,KAAK,QAAS,kDAAkD;;EAGhG,MAAM,EAAE,SAAS,MAAM,YAAY,mBAAmB;AACtD,MAAI;AACA,WAAQ,QAAQ,MAAhB;IACI,KAAK;AACD,iCAAY,IAAI,MAAM,6BAA6B,QAAQ,KAAK,KAAK,QAAQ,UAAU,CAAC;AACxF,YAAO,kBAAkB,SAAS,kBAAkB,KAAK,CAAC;IAE9D,KAAK,SACD,QAAO,MAAM,YAAY,SAAS,SAAS,SAAS;IAExD,KAAK,SACD,QAAO,MAAM,iBAAiB,SAAS,gBAAgB,UAAU,WAAW;;WAG/E,OAAO;AAKZ,eAAY,QAAQ,MAAM,CAAC;AAC3B,UAAO,4BAA4B,kBAAkB,KAAK,CAAC;;;CAInE,MAAM,YAAY,OAAO,SAAkB,mBAAiE;AACxG,MAAI,OACA,OAAM,IAAI,MAAM,mCAAmC;AAEvD,MAAI;AACA,UAAO,MAAM,OAAO,SAAS,eAAe;WACvC,OAAO;AACZ,eAAY,QAAQ,MAAM,CAAC;AAC3B,UAAO,4BAA4B,kBAAkB,gBAAgB,WAAW,CAAC;;;AAIzF,QAAO;EACH,OAAO;EACP;EACA;EACA,OAAO,YAAY;AACf,YAAS;AACT,gBAAa,UAAU;GACvB,MAAM,UAAU,CAAC,GAAG,SAAS,CAAC,KAAI,WAAU,OAAO,OAAO,CAAC,YAAY,GAAG,CAAC;AAC3E,YAAS,OAAO;AAChB,SAAM,QAAQ,IAAI,QAAQ;;EAEjC;;;;;;;;;;;ACh2BL,SAAgB,mBAAmB,YAAuC,kBAAwD;AAC9H,KAAI,CAAC,WACD,QAAO;EAAE,IAAI;EAAO,WAAW;EAAgB,SAAS;EAAuB;CAInF,IAAIC;AACJ,KAAI;AACA,aAAW,IAAI,IAAI,UAAU,aAAa,CAAC;SACvC;AACJ,SAAO;GAAE,IAAI;GAAO,WAAW;GAAuB,SAAS,wBAAwB;GAAc;GAAY;;AAGrH,KAAI,CAAC,iBAAiB,SAAS,SAAS,CACpC,QAAO;EAAE,IAAI;EAAO,WAAW;EAAgB,SAAS,iBAAiB;EAAY;EAAY;EAAU;AAG/G,QAAO;EAAE,IAAI;EAAM;EAAU;;;;;AAMjC,SAAgB,4BAAsC;AAClD,QAAO;EAAC;EAAa;EAAa;EAAQ;;;;;;;;;AAU9C,SAAgB,6BAA6B,KAAc,kBAAkD;CACzG,MAAM,SAAS,mBAAmB,IAAI,QAAQ,IAAI,OAAO,EAAE,iBAAiB;AAC5E,KAAI,OAAO,GAAI,QAAO;AAEtB,QAAO,SAAS,KACZ;EACI,SAAS;EACT,OAAO;GACH,MAAM;GACN,SAAS,OAAO;GACnB;EACD,IAAI;EACP,EACD;EACI,QAAQ;EACR,SAAS,EAAE,gBAAgB,oBAAoB;EAClD,CACJ;;;;;;;;;;;;;;;AC9BL,SAAgB,qBAAqB,cAAyC,wBAA0D;AACpI,KAAI,iBAAiB,QAAQ,iBAAiB,UAAa,iBAAiB,GACxE,QAAO,EAAE,IAAI,MAAM;CAGvB,IAAIC;AACJ,KAAI;AACA,aAAW,IAAI,IAAI,aAAa,CAAC;SAC7B;AACJ,SAAO;GAAE,IAAI;GAAO,WAAW;GAAyB,SAAS,0BAA0B;GAAgB;GAAc;;AAE7H,KAAI,aAAa,GAGb,QAAO;EAAE,IAAI;EAAO,WAAW;EAAyB,SAAS,0BAA0B;EAAgB;EAAc;AAG7H,KAAI,CAAC,uBAAuB,SAAS,SAAS,CAC1C,QAAO;EAAE,IAAI;EAAO,WAAW;EAAkB,SAAS,mBAAmB;EAAY;EAAc;EAAU;AAGrH,QAAO;EAAE,IAAI;EAAM,QAAQ;EAAc;EAAU;;;;;;AAOvD,SAAgB,0BAAoC;AAChD,QAAO;EAAC;EAAa;EAAa;EAAQ;;;;;;;;;;;;AAa9C,SAAgB,yBAAyB,KAAc,wBAAwD;CAC3G,MAAM,SAAS,qBAAqB,IAAI,QAAQ,IAAI,SAAS,EAAE,uBAAuB;AACtF,KAAI,OAAO,GAAI,QAAO;AAEtB,QAAO,SAAS,KACZ;EACI,SAAS;EACT,OAAO;GACH,MAAM;GACN,SAAS,OAAO;GACnB;EACD,IAAI;EACP,EACD;EACI,QAAQ;EACR,SAAS,EAAE,gBAAgB,oBAAoB;EAClD,CACJ;;;;;ACnBL,MAAM,SAAS;AAIf,SAAS,iBAAiB,OAA2B;CACjD,IAAI,MAAM;AACV,MAAK,MAAM,KAAK,MAAO,QAAO,OAAO,cAAc,EAAE;AACrD,QAAO,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,QAAQ,OAAO,GAAG;;AAQjF,SAAS,qBAAqB,GAAW,GAAoB;AACzD,KAAI,EAAE,WAAW,EAAE,OACf,QAAO;CAEX,IAAI,IAAI;AACR,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC1B,MAAK,EAAE,YAAY,EAAE,GAAI,EAAE,YAAY,EAAE;AAE7C,QAAO,MAAM;;AAGjB,SAAS,iBAAiB,GAAoC;CAC1D,MAAM,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC,WAAW,KAAK,IAAI;CACvD,MAAM,MAAM,KAAK,IAAI;CACrB,MAAM,QAAQ,IAAI,WAAW,IAAI,OAAO;AACxC,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,OAAM,KAAK,IAAI,YAAY,EAAE;AAClE,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCX,SAAgB,wBAAqC,SAAyD;CAC1G,MAAM,SAAS,WAAW,QAAQ;AAClC,KAAI,WAAW,OACX,OAAM,IAAI,UACN,sLAEH;CAQL,MAAM,WAAW,OAAO,QAAQ,QAAQ,WAAW,IAAI,aAAa,CAAC,OAAO,QAAQ,IAAI,GAAG,WAAW,KAAK,QAAQ,IAAI;AACvH,KAAI,SAAS,aAAa,GACtB,OAAM,IAAI,WAAW,+DAA+D,SAAS,WAAW,GAAG;CAE/G,MAAM,aAAa,QAAQ,cAAc;AACzC,KAAI,CAAC,OAAO,SAAS,WAAW,CAI5B,OAAM,IAAI,WAAW,8DAA8D;CAEvF,MAAM,OAAO,QAAQ;CAKrB,IAAIC;CACJ,MAAM,oBACD,cAAc,OAAO,UAAU,OAAO,UAAU;EAAE,MAAM;EAAQ,MAAM;EAAW,EAAE,OAAO,CAAC,QAAQ,SAAS,CAAC;CAElH,MAAM,OAAO,IAAI,aAAa;CAO9B,MAAM,aAAa;CACnB,MAAM,UAAU,OAAO,UAAmC;AAEtD,SAAO,iBADK,IAAI,WAAW,MAAM,OAAO,KAAK,QAAQ,MAAM,aAAa,EAAE,KAAK,OAAO,aAAa,MAAM,CAAC,CAAC,CAC/E,MAAM,GAAG,GAAG,CAAC;;AAG7C,QAAO;EACH,MAAM,KAAK,SAAS,KAAK;GACrB,MAAMC,WAA8C;IAChD,GAAG;IACH,KAAK,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG;IACxC;AACD,OAAI,SAAS,QAAW;AACpB,QAAI,QAAQ,OACR,OAAM,IAAI,UAAU,kFAAkF;AAE1G,aAAS,IAAI,MAAM,QAAQ,KAAK,IAAI,CAAC;;GAEzC,MAAM,OAAO,iBAAiB,KAAK,OAAO,KAAK,UAAU,SAAS,CAAC,CAAC;AAKpE,UAAO,GAAG,SAAS,KAAK,GAAG,iBADf,IAAI,WAAW,MAAM,OAAO,KAAK,QAAQ,MAAM,aAAa,EAAE,KAAK,OAAO,SAAS,KAAK,CAAC,CAAC,CACtD;;EAGpD,MAAM,OAAO,OAAO,KAAK;GAIrB,MAAM,MAAM,MAAM,YAAY,IAAI;AAClC,OAAI,CAAC,MAAM,WAAW,OAAO,IAAI,OAAO,EACpC,OAAM,IAAI,MAAM,YAAY;GAEhC,MAAM,OAAO,MAAM,MAAM,GAAe,IAAI;GAC5C,IAAIC;AACJ,OAAI;AACA,eAAW,iBAAiB,MAAM,MAAM,MAAM,EAAE,CAAC;WAC7C;AACJ,UAAM,IAAI,MAAM,YAAY;;AAMhC,OAAI,CADO,MAAM,OAAO,OAAO,QAAQ,MAAM,aAAa,EAAE,UAAU,KAAK,OAAO,SAAS,KAAK,CAAC,CAE7F,OAAM,IAAI,MAAM,MAAM;GAK1B,IAAID;AACJ,OAAI;AACA,eAAW,KAAK,MAAM,IAAI,YAAY,SAAS,EAAE,OAAO,MAAM,CAAC,CAAC,OAAO,iBAAiB,KAAK,CAAC,CAAC;WAK3F;AACJ,UAAM,IAAI,MAAM,YAAY;;AAEhC,OAAI,OAAO,SAAS,QAAQ,YAAY,SAAS,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,CAChF,OAAM,IAAI,MAAM,UAAU;AAE9B,OAAI,SAAS,QAAW;IACpB,MAAM,WAAW,MAAM,QAAQ,KAAK,IAAI,CAAC;AACzC,QAAI,SAAS,MAAM,UAAa,CAAC,qBAAqB,SAAS,GAAG,SAAS,CAGvE,OAAM,IAAI,MAAM,OAAO;cAEpB,SAAS,MAAM,OAKtB,OAAM,IAAI,MAAM,OAAO;AAE3B,UAAO,SAAS;;EAEvB;;;;;ACrQL,IAAIE;AAEJ,SAAgB,eAA4B,QAAwB,WAA+D;AAC/H,QAAOC,iBAAsB,QAAQ,cAAc,sBAAsB,IAAI,4BAA4B,EAAE"}
|