{"version":3,"file":"index.mjs","names":["error: { code: number; message: string; data?: string }","streamController: ReadableStreamDefaultController<Uint8Array>","keepAliveTimer: ReturnType<typeof setInterval> | undefined","headers: Record<string, string>","streamId: string | undefined","replayedStreamId: string | undefined","messages: JSONRPCMessage[]","scopeChallengeResponse: Response | undefined","closeSSEStream: (() => void) | undefined","closeStandaloneSSEStream: (() => void) | undefined","eventId: string | undefined","body: unknown","bodyText: string","bus: ServerEventBus","legacyHandler: LegacyHttpHandler | undefined","hostname: string","hostname: string","scheme: string","cryptoKey: ReturnType<typeof subtle.importKey> | undefined","envelope: { p: T; exp: number; b?: string }","macBytes: Uint8Array<ArrayBuffer>","_defaultValidator: jsonSchemaValidator | undefined","coreFromJsonSchema"],"sources":["../src/server/invoke.ts","../src/server/requestBody.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 * 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    /** SSE keep-alive interval for the exchange. */\n    keepAliveMs?: number;\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        ...(ctx.keepAliveMs !== undefined && { keepAliveMs: ctx.keepAliveMs })\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","/** Default upper bound, in bytes, on a request body read by the HTTP entry points (4 MiB). */\nexport const DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;\n\n/** Upper bound on the number of messages accepted in one JSON-RPC batch array. */\nexport const MAX_BATCH_SIZE = 100;\n\n/** The message answered with 413 for a request body over `maxBytes`. */\nexport function requestBodyTooLargeMessage(maxBytes: number): string {\n    return `Payload Too Large: Request body must not exceed ${maxBytes} bytes`;\n}\n\n/**\n * Resolves a `maxRequestBodySize` option to the bound to apply: the default when\n * omitted, otherwise the value itself, which must be a positive finite number of\n * bytes (a `RangeError` is thrown at configuration time for anything else).\n */\nexport function resolveMaxRequestBodySize(value: number | undefined): number {\n    if (value === undefined) {\n        return DEFAULT_MAX_REQUEST_BODY_SIZE;\n    }\n    if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {\n        throw new RangeError(`maxRequestBodySize must be a positive number of bytes, got ${String(value)}`);\n    }\n    return value;\n}\n\n/**\n * Reads a request body as text, up to `maxBytes` (default\n * {@linkcode DEFAULT_MAX_REQUEST_BODY_SIZE}). A declared `Content-Length` over the\n * limit is refused without reading anything; otherwise the read stops as soon as\n * more than the limit has arrived. Stream failures propagate.\n */\nexport async function readRequestBody(\n    request: Request,\n    maxBytes: number = DEFAULT_MAX_REQUEST_BODY_SIZE\n): Promise<{ tooLarge: true } | { tooLarge: false; text: string }> {\n    if (Number(request.headers.get('content-length')) > maxBytes) {\n        return { tooLarge: true };\n    }\n    if (request.body === null) {\n        return { tooLarge: false, text: '' };\n    }\n    const reader = request.body.getReader();\n    const decoder = new TextDecoder();\n    let received = 0;\n    let text = '';\n    try {\n        for (;;) {\n            const { done, value } = await reader.read();\n            if (done) {\n                break;\n            }\n            received += value.byteLength;\n            if (received > maxBytes) {\n                return { tooLarge: true };\n            }\n            text += decoder.decode(value, { stream: true });\n        }\n    } finally {\n        reader.releaseLock();\n    }\n    return { tooLarge: false, text: text + decoder.decode() };\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, JSONRPCRequest, MessageExtraInfo, RequestId, Transport } from '@modelcontextprotocol/core-internal';\nimport {\n    DEFAULT_NEGOTIATED_PROTOCOL_VERSION,\n    isInitializeRequest,\n    isJsonContentType,\n    isJSONRPCErrorResponse,\n    isJSONRPCRequest,\n    isJSONRPCResultResponse,\n    JSONRPCMessageSchema,\n    SUPPORTED_PROTOCOL_VERSIONS\n} from '@modelcontextprotocol/core-internal';\n\nimport { MAX_BATCH_SIZE, readRequestBody, requestBodyTooLargeMessage, resolveMaxRequestBodySize } from './requestBody';\nimport type { ScopeChallengeHandler } from './scopeChallenge';\nimport { createScopeChallengeResponse, findScopeChallenge, scopeChallengeResourceMetadataUrl } from './scopeChallenge';\nimport { armSseKeepAlive, DEFAULT_SSE_KEEP_ALIVE_MS } from './sseKeepAlive';\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     * Interval in milliseconds between SSE keep-alive comment frames.\n     * Defaults to `15000`; set to `0` to disable.\n     */\n    keepAliveMs?: number;\n\n    /**\n     * Upper bound, in bytes, on a POST body the transport reads itself. A body\n     * over the bound (declared `Content-Length`, or observed while streaming)\n     * is answered `413` before anything is parsed. Not applied when the caller\n     * supplies `parsedBody`. Must be a positive number.\n     * @default 4194304 (4 MiB)\n     */\n    maxRequestBodySize?: 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 reading and parsing the request body.\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 *     // Stateless example: create a server and a transport per request.\n *     const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n *     const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n *     await server.connect(transport);\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 *         // Stateless example: create a server and a transport per request.\n *         const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n *         const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n *         await server.connect(transport);\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 _hasHandledRequest: 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    private _keepAliveMs: number;\n    private _maxRequestBodySize: number;\n    private _scopeChallengeResolver?: ScopeChallengeHandler;\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        this._keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS;\n        this._maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);\n    }\n\n    private startKeepAlive(\n        controller: ReadableStreamDefaultController<Uint8Array>,\n        encoder: InstanceType<typeof TextEncoder>\n    ): ReturnType<typeof setInterval> | undefined {\n        if (this._closed) return undefined;\n\n        const timer = armSseKeepAlive(this._keepAliveMs, () => {\n            try {\n                controller.enqueue(encoder.encode(': keepalive\\n\\n'));\n            } catch {\n                if (timer !== undefined) clearInterval(timer);\n            }\n        });\n        return timer;\n    }\n\n    /** Sets the scope challenge resolver for parsed JSON-RPC requests. */\n    setScopeChallengeResolver(resolver: ScopeChallengeHandler): void {\n        this._scopeChallengeResolver = resolver;\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    private async _checkScopeChallenge(messages: JSONRPCMessage[], authInfo?: AuthInfo): Promise<Response | undefined> {\n        // Active whenever a connected McpServer supplied a resolver (it\n        // resolves per-primitive scopeChallenge callbacks); the challenge's\n        // resource_metadata parameter is derived from the verified AuthInfo\n        // and omitted when unavailable.\n        if (!this._scopeChallengeResolver) {\n            return undefined;\n        }\n        const requests: JSONRPCRequest[] = messages.filter(message => isJSONRPCRequest(message));\n        const challenge = await findScopeChallenge(requests, authInfo, this._scopeChallengeResolver);\n        return challenge === undefined ? undefined : createScopeChallengeResponse(challenge, scopeChallengeResourceMetadataUrl(authInfo));\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        if (this._closed) {\n            return this.createJsonErrorResponse(404, -32_001, 'Session not found');\n        }\n\n        // A stateless transport (no sessionIdGenerator) serves exactly one request.\n        if (!this.sessionIdGenerator && this._hasHandledRequest) {\n            throw new Error('Stateless transport cannot be reused across requests. Create a new transport per request.');\n        }\n        this._hasHandledRequest = true;\n\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        // Captured by cancel/cleanup before it is assigned after stream setup.\n        // eslint-disable-next-line prefer-const\n        let keepAliveTimer: ReturnType<typeof setInterval> | undefined;\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                if (keepAliveTimer !== undefined) clearInterval(keepAliveTimer);\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            'X-Accel-Buffering': 'no'\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                if (keepAliveTimer !== undefined) clearInterval(keepAliveTimer);\n                this._streamMapping.delete(this._standaloneSseStreamId);\n                try {\n                    streamController!.close();\n                } catch {\n                    // Controller might already be closed\n                }\n            }\n        });\n\n        keepAliveTimer = this.startKeepAlive(streamController!, encoder);\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                'X-Accel-Buffering': 'no'\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            let keepAliveTimer: ReturnType<typeof setInterval> | undefined;\n            let cancelled = false;\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                    cancelled = true;\n                    if (keepAliveTimer !== undefined) clearInterval(keepAliveTimer);\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            if (this._closed || cancelled) {\n                try {\n                    streamController!.close();\n                } catch {\n                    // Controller already closed/cancelled.\n                }\n                return this.createJsonErrorResponse(404, -32_001, 'Session not found');\n            }\n\n            this._streamMapping.get(replayedStreamId)?.cleanup();\n            this._streamMapping.set(replayedStreamId, {\n                controller: streamController!,\n                encoder,\n                replayedEventIds,\n                cleanup: () => {\n                    if (keepAliveTimer !== undefined) clearInterval(keepAliveTimer);\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            if (this._streamMapping.get(replayedStreamId)?.controller === streamController!) {\n                keepAliveTimer = this.startKeepAlive(streamController!, encoder);\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            // Accept is a comma-separated list, so a substring check is the intended semantics here (unlike Content-Type below).\n            // eslint-disable-next-line no-restricted-syntax\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            // Parsed media type, never a substring match — see\n            // isJsonContentType. This check stays here for hand-wired\n            // transports; via createMcpHandler the entry's own check answers\n            // first.\n            const ct = req.headers.get('content-type');\n            if (!isJsonContentType(ct)) {\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                    const body = await readRequestBody(req, this._maxRequestBodySize);\n                    if (body.tooLarge) {\n                        const message = requestBodyTooLargeMessage(this._maxRequestBodySize);\n                        this.onerror?.(new Error(message));\n                        return this.createJsonErrorResponse(413, -32_000, message);\n                    }\n                    rawMessage = JSON.parse(body.text);\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            if (Array.isArray(rawMessage) && rawMessage.length > MAX_BATCH_SIZE) {\n                this.onerror?.(new Error(`Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE} messages`));\n                return this.createJsonErrorResponse(400, -32_600, `Invalid Request: Batch must not exceed ${MAX_BATCH_SIZE} messages`);\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            if (this._closed) {\n                return this.createJsonErrorResponse(404, -32_001, 'Session not found');\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            if (this._closed) {\n                return this.createJsonErrorResponse(404, -32_001, 'Session not found');\n            }\n\n            // Check before opening SSE so an insufficient token can receive HTTP 403.\n            let scopeChallengeResponse: Response | undefined;\n            try {\n                scopeChallengeResponse = await this._checkScopeChallenge(messages, options?.authInfo);\n            } catch (error) {\n                this.onerror?.(error as Error);\n                return this.createJsonErrorResponse(500, -32_603, 'Internal server error');\n            }\n            if (scopeChallengeResponse) {\n                return scopeChallengeResponse;\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            let keepAliveTimer: ReturnType<typeof setInterval> | undefined;\n\n            const readable = new ReadableStream<Uint8Array>({\n                start: controller => {\n                    streamController = controller;\n                },\n                cancel: () => {\n                    if (keepAliveTimer !== undefined) clearInterval(keepAliveTimer);\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, no-transform',\n                Connection: 'keep-alive',\n                'X-Accel-Buffering': 'no'\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                            if (keepAliveTimer !== undefined) clearInterval(keepAliveTimer);\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            if (this._streamMapping.get(streamId)?.controller === streamController!) {\n                keepAliveTimer = this.startKeepAlive(streamController!, encoder);\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        try {\n            await Promise.resolve(this._onsessionclosed?.(this.sessionId!));\n            return new Response(null, { status: 200 });\n        } finally {\n            await this.close();\n        }\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    InboundHttpRequest,\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    isJsonContentType,\n    mediaTypeEssence,\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_MAX_SUBSCRIPTIONS } from './listenRouter';\nimport { McpServer } from './mcp';\nimport type { PerRequestResponseMode } from './perRequestTransport';\nimport { DEFAULT_MAX_REQUEST_BODY_SIZE, readRequestBody, requestBodyTooLargeMessage, resolveMaxRequestBodySize } from './requestBody';\nimport { createScopeChallengeResponse, findScopeChallenge, scopeChallengeResourceMetadataUrl } from './scopeChallenge';\nimport type { Server } from './server';\nimport { installModernOnlyHandlers, seedClientIdentityFromEnvelope, serverIdentityOf } from './server';\nimport type { ServerEventBus, ServerNotifier } from './serverEventBus';\nimport { createServerNotifier, InMemoryServerEventBus } from './serverEventBus';\nimport { DEFAULT_SSE_KEEP_ALIVE_MS } from './sseKeepAlive';\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 every SSE stream this handler\n     * serves. In modern `auto` mode it starts after SSE upgrade. Set to `0` to disable.\n     * @default 15000\n     */\n    keepAliveMs?: number;\n    /**\n     * Upper bound, in bytes, on a POST body the handler reads itself (the\n     * classification step and the stateless legacy leg). A body over the bound\n     * is answered `413` before anything is parsed or any server instance is\n     * created. Not applied to a body supplied as `parsedBody`. Must be a\n     * positive number. Hand-wired compositions routing on\n     * {@linkcode isLegacyRequest} pass the same value to the predicate.\n     * @default 4194304 (4 MiB)\n     */\n    maxRequestBodySize?: 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        // This entry serves POST only, so every 405 it answers names POST (RFC 9110 §15.5.6).\n        { status: httpStatus, ...(httpStatus === 405 && { headers: { Allow: 'POST' } }) }\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/** Throws when the factory returned an instance that is still connected to another exchange. */\nfunction assertNotServing(server: Server): void {\n    if (server.transport !== undefined) {\n        throw new Error('The factory returned an instance that is still serving another request. Return a new instance for each request.');\n    }\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 */\nfunction createLegacyStatelessFallback(\n    factory: McpServerFactory,\n    onerror?: (error: Error) => void,\n    keepAliveMs?: number,\n    maxRequestBodySize?: number\n): 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({\n                sessionIdGenerator: undefined,\n                ...(keepAliveMs !== undefined && { keepAliveMs }),\n                ...(maxRequestBodySize !== undefined && { maxRequestBodySize })\n            });\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 || mediaTypeEssence(response.headers.get('content-type')) !== '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/** Options for {@linkcode legacyStatelessFallback}. */\nexport interface LegacyStatelessFallbackOptions {\n    /**\n     * Upper bound, in bytes, on a POST body the leg reads itself (not applied\n     * to a body supplied as `parsedBody`). Must be a positive number.\n     * @default 4194304 (4 MiB)\n     */\n    maxRequestBodySize?: number;\n}\n\nexport function legacyStatelessFallback(\n    factory: McpServerFactory,\n    onerror?: (error: Error) => void,\n    options?: LegacyStatelessFallbackOptions\n): LegacyHttpHandler {\n    return createLegacyStatelessFallback(factory, onerror, undefined, resolveMaxRequestBodySize(options?.maxRequestBodySize));\n}\n\n/* ------------------------------------------------------------------------ *\n * The entry's classification step (shared with isLegacyRequest)\n * ------------------------------------------------------------------------ */\n\n/**\n * Read the SEP-2243 standard request headers off the inbound request.\n *\n * Both halves of the standard-header story need them — the body-primary\n * classifier for its cross-check cells, and\n * {@linkcode validateStandardRequestHeaders} for the presence half — and a\n * header read at one site but not the other is precisely how a required header\n * goes unenforced: that divergence is what let a modern POST omitting\n * `MCP-Protocol-Version` be served. Read them here once so a header added to\n * {@linkcode InboundHttpRequest} reaches both sites together.\n */\nfunction standardHeadersOf(request: Request): Omit<InboundHttpRequest, 'httpMethod' | 'body'> {\n    return {\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    };\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 body over the size limit; nothing past the limit was read. */\n    | { step: 'body-too-large' }\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(\n    request: Request,\n    providedParsedBody?: unknown,\n    needsForward = true,\n    maxRequestBodySize: number = DEFAULT_MAX_REQUEST_BODY_SIZE\n): 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                const read = await readRequestBody(request, maxRequestBodySize);\n                if (read.tooLarge) {\n                    return { step: 'body-too-large' };\n                }\n                bodyText = read.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        ...standardHeadersOf(request),\n        ...(body !== undefined && { body })\n    });\n    return { step: 'classified', outcome, body, parsedBody, forwardRequest };\n}\n\n/** Options for {@linkcode isLegacyRequest}. */\nexport interface IsLegacyRequestOptions {\n    /**\n     * The same `maxRequestBodySize` the handler the predicate routes for was\n     * created with, so the two read the body under one bound (a body over it\n     * classifies `false`; the modern handler answers `413`).\n     * @default 4194304 (4 MiB)\n     */\n    maxRequestBodySize?: number;\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. It is classification only: hand-wired\n * compositions must validate Content-Type themselves (415 for POSTs whose\n * media type is not `application/json`, via {@linkcode isJsonContentType})\n * before dispatching either leg — routing the legacy leg into the SDK\n * transports gets their built-in check, but a custom modern leg has none. 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`), header/body mismatches (`-32020`), and a POST body\n *   over the size limit (413). 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, options?: IsLegacyRequestOptions): Promise<boolean> {\n    const maxRequestBodySize = resolveMaxRequestBodySize(options?.maxRequestBodySize);\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, maxRequestBodySize);\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 — such compositions must reject POSTs whose Content-Type media type\n * is not `application/json` (415) before parsing the body, using\n * {@linkcode isJsonContentType}; neither building block performs this\n * validation itself.\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    const maxRequestBodySize = resolveMaxRequestBodySize(options.maxRequestBodySize);\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_SSE_KEEP_ALIVE_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 =\n        legacy === 'reject' ? undefined : createLegacyStatelessFallback(factory, reportError, options.keepAliveMs, maxRequestBodySize);\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 (`MCP-Protocol-Version`,\n        // `Mcp-Method`) 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        // which only cross-checks a protocol-version header that is present).\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({ httpMethod: request.method, ...standardHeadersOf(request) }, route);\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 short-circuits\n        // before factory construction and pins the spec-mandated HTTP 400 for\n        // this error unconditionally; a handler-time -32021 (the\n        // input_required gate) also maps to 400 at the per-request transport,\n        // but only while no response has been committed.\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        assertNotServing(server);\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            const serverInfo = serverIdentityOf(server);\n            void product.close().catch(reportError);\n            return listenRouter.serve(route.message, request.signal, capabilities, serverInfo);\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                // A tool that is invalid only for a `number`-typed declaration is still checked.\n                if (scan.declarations !== undefined && 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        // Run scope preflight after Mcp-Param headers have been checked against\n        // the body. Active whenever the factory's instance registers a\n        // per-primitive scopeChallenge callback — no handler-level\n        // configuration exists: the challenge's resource_metadata parameter is\n        // derived from the verified AuthInfo (stamped by the bearer-auth gate,\n        // or the token's RFC 8707 resource identifier) and omitted otherwise.\n        if (route.messageKind === 'request' && product instanceof McpServer) {\n            try {\n                const challenge = await findScopeChallenge([route.message], authInfo, context => product.resolveScopeChallenge(context));\n                if (challenge !== undefined) {\n                    void product.close().catch(reportError);\n                    return createScopeChallengeResponse(challenge, scopeChallengeResourceMetadataUrl(authInfo));\n                }\n            } catch (error) {\n                void product.close().catch(reportError);\n                reportError(toError(error));\n                return internalServerErrorResponse(route.message.id);\n            }\n        }\n\n        // Checked again after the awaits above, before anything is written to the instance.\n        assertNotServing(server);\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        const onExchangeClose = () => {\n            inflight.delete(server);\n            // Restore by identity so a handler installed during the exchange is kept.\n            if (server.onclose === onExchangeClose) {\n                server.onclose = previousOnClose;\n            }\n            previousOnClose?.();\n        };\n        server.onclose = onExchangeClose;\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                ...(options.keepAliveMs !== undefined && { keepAliveMs: options.keepAliveMs })\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\n        // Content-Type check, answered before the body is read (parsed media\n        // type — see isJsonContentType). Load-bearing for the modern leg,\n        // whose ladder does not inspect Content-Type; the legacy transport\n        // keeps its own check for hand-wired use, so via this entry a\n        // doubly-invalid request answers 415 here before the transport's 406\n        // Accept check would.\n        if (request.method.toUpperCase() === 'POST' && !isJsonContentType(request.headers.get('content-type'))) {\n            reportError(new Error('Unsupported Media Type: Content-Type must be application/json'));\n            return jsonRpcErrorResponse(415, -32_000, 'Unsupported Media Type: Content-Type must be application/json');\n        }\n\n        const classified = await classifyEntryRequest(request, requestOptions?.parsedBody, true, maxRequestBodySize);\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 === 'body-too-large') {\n            return jsonRpcErrorResponse(413, -32_000, requestBodyTooLargeMessage(maxRequestBodySize));\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 * - A browser extension's origin carries its extension ID as the hostname; list the\n *   ID to allow one extension. An allowlist item of the form `<scheme>://*`\n *   (lowercase, e.g. `moz-extension://*`) allows every origin of that scheme, which\n *   Firefox needs because its extension IDs differ on every install.\n *   `http://*` and `https://*` are not honoured: list websites by hostname.\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    let scheme: string;\n    try {\n        const url = new URL(originHeader);\n        hostname = url.hostname;\n        scheme = url.protocol;\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    const schemeAllowed = scheme !== 'http:' && scheme !== 'https:' && allowedOriginHostnames.includes(`${scheme}//*`);\n    if (!schemeAllowed && !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":"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"}