{"version":3,"file":"mcp-node-body-limit-3aDvNdwQ.mjs","names":["#handler","#policy","#hardened"],"sources":["../src/mcp-server.errors.ts","../src/security/mcp-http-security.ts","../src/security/mcp-node-body-limit.ts"],"sourcesContent":["export type McpServerErrorCode =\n\t\"DUPLICATE_SERVER\" | \"INVALID_DEFINITION\" | \"RUNTIME_CLOSED\" | \"UNKNOWN_SERVER\";\n\nexport class McpServerRuntimeError extends Error {\n\tconstructor(\n\t\treadonly code: McpServerErrorCode,\n\t\tmessage: string,\n\t\toptions?: ErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.name = \"McpServerRuntimeError\";\n\t}\n}\n","import {\n\thostHeaderValidationResponse,\n\tlocalhostAllowedOrigins,\n\toriginValidationResponse,\n\tvalidateOriginHeader,\n} from \"@modelcontextprotocol/server\";\nimport type { McpHandlerRequestOptions } from \"@modelcontextprotocol/server\";\nimport { McpServerRuntimeError } from \"../mcp-server.errors.ts\";\nimport type { McpFetchHandler } from \"../auth/mcp-resource-server.ts\";\n\nexport const MCP_DEFAULT_MAX_BODY_BYTES = 1_048_576;\n\nexport const MCP_CORS_METHODS: readonly string[] = Object.freeze([\n\t\"GET\",\n\t\"POST\",\n\t\"DELETE\",\n\t\"OPTIONS\",\n]);\n\n/**\n * Request headers the 2026-07-28 revision requires browser clients to send.\n * `Mcp-Method`/`Mcp-Name` make every modern MCP POST CORS-preflighted.\n */\nexport const MCP_CORS_ALLOWED_HEADERS: readonly string[] = Object.freeze([\n\t\"authorization\",\n\t\"content-type\",\n\t\"accept\",\n\t\"mcp-protocol-version\",\n\t\"mcp-method\",\n\t\"mcp-name\",\n\t\"mcp-session-id\",\n\t\"last-event-id\",\n]);\n\nexport const MCP_CORS_EXPOSED_HEADERS: readonly string[] = Object.freeze([\n\t\"mcp-session-id\",\n\t\"www-authenticate\",\n]);\n\nconst DEFAULT_CORS_MAX_AGE_SECONDS = 600;\nconst PREFLIGHT_VARY = \"Origin, Access-Control-Request-Method, Access-Control-Request-Headers\";\n\nexport interface McpCorsOptions {\n\t/**\n\t * Allows cookies/credentialed requests. Cookie-authenticated MCP endpoints\n\t * are CSRF-able; leave off unless required. When enabled, `allowedOrigins`\n\t * is mandatory and the grant matches the full origin exactly — never a bare\n\t * hostname — so a compromised sibling scheme or port cannot inherit it.\n\t */\n\treadonly credentials?: boolean;\n\t/**\n\t * Full browser origins (e.g. `https://app.example.com`) permitted to make\n\t * credentialed requests. Required when `credentials` is true; ignored\n\t * otherwise (non-credentialed CORS reflects any origin the allowlist admits).\n\t */\n\treadonly allowedOrigins?: readonly string[];\n\treadonly maxAgeSeconds?: number;\n\treadonly additionalAllowedHeaders?: readonly string[];\n\treadonly additionalExposedHeaders?: readonly string[];\n}\n\nexport interface McpHttpSecurityOptions {\n\t/** Host-header allowlist (hostnames only). Defaults to off: proxies rewrite `Host`, and the Origin rung already blocks DNS rebinding. */\n\treadonly allowedHostnames?: readonly string[] | false;\n\t/**\n\t * Origin-header allowlist (hostnames only). Defaults to localhost-class\n\t * origins, so routable browser origins are denied until configured.\n\t * Requests without an `Origin` header always pass. `false` disables the check.\n\t */\n\treadonly allowedOriginHostnames?: readonly string[] | false;\n\t/** CORS handling for allowed origins. Defaults to on whenever origin validation is on. */\n\treadonly cors?: McpCorsOptions | boolean;\n\t/** Request-body byte cap. Defaults to 1 MiB; `false` disables the cap. */\n\treadonly maxBodyBytes?: number | false;\n}\n\ninterface ResolvedCorsPolicy {\n\treadonly credentials: boolean;\n\treadonly maxAgeSeconds: number;\n\treadonly allowedHeaders: string;\n\treadonly allowedHeaderSet: ReadonlySet<string>;\n\treadonly exposedHeaders: string;\n\treadonly methods: string;\n\t/** Exact-origin allowlist enforced only in credentialed mode. */\n\treadonly allowedOrigins: ReadonlySet<string> | undefined;\n}\n\n/** Reports a pre-dispatch rejection (status ≥ 400) to an outer observer. */\nexport interface McpHardenHooks {\n\treadonly onRejected?: (status: number) => void;\n}\n\nexport interface McpHttpSecurityPolicy {\n\treadonly resolved: true;\n\treadonly allowedHostnames: readonly string[] | undefined;\n\treadonly allowedOriginHostnames: readonly string[] | undefined;\n\treadonly cors: ResolvedCorsPolicy | undefined;\n\treadonly maxBodyBytes: number | undefined;\n}\n\n/** Resolves and validates the declarative options into a frozen policy. */\nexport function resolveMcpHttpSecurity(options?: McpHttpSecurityOptions): McpHttpSecurityPolicy {\n\tif (options !== undefined && (typeof options !== \"object\" || options === null)) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"httpSecurity must be an object when present.\",\n\t\t);\n\t}\n\tconst allowedHostnames =\n\t\toptions?.allowedHostnames === undefined || options.allowedHostnames === false\n\t\t\t? undefined\n\t\t\t: normalizeHostnameList(options.allowedHostnames, \"httpSecurity.allowedHostnames\");\n\tconst allowedOriginHostnames =\n\t\toptions?.allowedOriginHostnames === false\n\t\t\t? undefined\n\t\t\t: options?.allowedOriginHostnames === undefined\n\t\t\t\t? Object.freeze(localhostAllowedOrigins().map((value) => value.toLowerCase()))\n\t\t\t\t: normalizeHostnameList(\n\t\t\t\t\t\toptions.allowedOriginHostnames,\n\t\t\t\t\t\t\"httpSecurity.allowedOriginHostnames\",\n\t\t\t\t\t);\n\tconst cors = resolveCors(options?.cors, allowedOriginHostnames !== undefined);\n\tconst maxBodyBytes =\n\t\toptions?.maxBodyBytes === false\n\t\t\t? undefined\n\t\t\t: (options?.maxBodyBytes ?? MCP_DEFAULT_MAX_BODY_BYTES);\n\tif (maxBodyBytes !== undefined && (!Number.isInteger(maxBodyBytes) || maxBodyBytes <= 0)) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"httpSecurity.maxBodyBytes must be a positive integer or false.\",\n\t\t);\n\t}\n\treturn Object.freeze({\n\t\tresolved: true,\n\t\tallowedHostnames,\n\t\tallowedOriginHostnames,\n\t\tcors,\n\t\tmaxBodyBytes,\n\t});\n}\n\nexport function isMcpHttpSecurityPolicy(value: unknown): value is McpHttpSecurityPolicy {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\tReflect.get(value, \"resolved\") === true &&\n\t\tObject.isFrozen(value)\n\t);\n}\n\n/**\n * The pre-dispatch gate: Host validation, then Origin validation, then CORS\n * preflight. Returns a short-circuit `Response`, or `undefined` to proceed.\n * A preflight from a rejected origin gets the 403 with no CORS headers.\n */\nexport function mcpHttpSecurityRejection(\n\trequest: Request,\n\tpolicy: McpHttpSecurityPolicy,\n): Response | undefined {\n\tif (policy.allowedHostnames !== undefined) {\n\t\tconst rejection = hostHeaderValidationResponse(request, [...policy.allowedHostnames]);\n\t\tif (rejection !== undefined) return rejection;\n\t}\n\tif (policy.allowedOriginHostnames !== undefined) {\n\t\tconst rejection = originValidationResponse(request, [...policy.allowedOriginHostnames]);\n\t\tif (rejection !== undefined) return rejection;\n\t}\n\tif (policy.cors !== undefined && isPreflight(request)) {\n\t\tconst origin = corsAllowedOrigin(request, policy);\n\t\t// A preflight from a disallowed origin gets 403 with no CORS headers.\n\t\tif (origin === undefined) {\n\t\t\treturn new Response(null, { status: 403 });\n\t\t}\n\t\treturn preflightResponse(request, policy.cors, origin);\n\t}\n\treturn undefined;\n}\n\n/**\n * Decorates a response with CORS headers when the request carries an allowed\n * Origin. Rebuilds the response without buffering so streamed SSE bodies keep\n * streaming; a response that already carries an ACAO header is left untouched.\n */\nexport function applyMcpCorsHeaders(\n\trequest: Request,\n\tresponse: Response,\n\tpolicy: McpHttpSecurityPolicy,\n): Response {\n\tif (policy.cors === undefined) return response;\n\tconst origin = corsAllowedOrigin(request, policy);\n\tif (origin === undefined) return response;\n\tif (response.headers.get(\"access-control-allow-origin\") !== null) return response;\n\tconst headers = new Headers(response.headers);\n\theaders.set(\"access-control-allow-origin\", origin);\n\theaders.set(\"access-control-expose-headers\", policy.cors.exposedHeaders);\n\tif (policy.cors.credentials) headers.set(\"access-control-allow-credentials\", \"true\");\n\tappendVary(headers, \"Origin\");\n\treturn new Response(response.body, {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders,\n\t});\n}\n\n/**\n * Enforces the body cap. Returns the request (re-wrapped when the stream had\n * to be counted) or a `413` response. Already-limited requests pass through\n * untouched so double wrapping never buffers twice.\n */\nexport async function limitMcpRequestBody(\n\trequest: Request,\n\tpolicy: McpHttpSecurityPolicy,\n): Promise<Request | Response> {\n\tconst maxBodyBytes = policy.maxBodyBytes;\n\tif (maxBodyBytes === undefined || request.body === null) {\n\t\treturn request;\n\t}\n\tconst declaredLength = Number(request.headers.get(\"content-length\") ?? Number.NaN);\n\tif (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {\n\t\treturn bodyTooLargeResponse(maxBodyBytes);\n\t}\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\tconst reader = request.body.getReader();\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\ttotal += value.byteLength;\n\t\t\tif (total > maxBodyBytes) {\n\t\t\t\tawait reader.cancel();\n\t\t\t\treturn bodyTooLargeResponse(maxBodyBytes);\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\t// The rebuilt request carries an in-memory body, so a stricter inner layer\n\t// can re-read and re-cap it without exhausting a one-shot stream.\n\treturn new Request(request.url, {\n\t\tmethod: request.method,\n\t\theaders: request.headers,\n\t\tbody: concatChunks(chunks, total),\n\t\tsignal: request.signal,\n\t});\n}\n\n/**\n * Wraps any fetch-shaped handler with the full gate → cap → CORS pipeline.\n * The forwarded request is marked as secured so the runtime's *implicit*\n * default gate defers to this explicit layer (an outer override can loosen as\n * well as tighten). Explicit hardened layers still run — the mark suppresses\n * only the runtime's built-in default, never another constructed facade — so\n * composed policies intersect.\n */\nexport function hardenMcpFetch(\n\thandler: {\n\t\tfetch(request: Request, options?: McpHandlerRequestOptions): Promise<Response>;\n\t},\n\tpolicy: McpHttpSecurityPolicy,\n\thooks?: McpHardenHooks,\n): { fetch(request: Request, options?: McpHandlerRequestOptions): Promise<Response> } {\n\treturn {\n\t\tfetch: async (request, options) => {\n\t\t\tconst rejection = mcpHttpSecurityRejection(request, policy);\n\t\t\tif (rejection !== undefined) {\n\t\t\t\treportRejection(rejection.status, hooks);\n\t\t\t\treturn rejection;\n\t\t\t}\n\t\t\tconst limited = await limitMcpRequestBody(request, policy);\n\t\t\tif (limited instanceof Response) {\n\t\t\t\treportRejection(limited.status, hooks);\n\t\t\t\treturn applyMcpCorsHeaders(request, limited, policy);\n\t\t\t}\n\t\t\tmarkMcpRequestSecured(limited);\n\t\t\tconst response = await handler.fetch(limited, options);\n\t\t\treturn applyMcpCorsHeaders(request, response, policy);\n\t\t},\n\t};\n}\n\nfunction reportRejection(status: number, hooks: McpHardenHooks | undefined): void {\n\tif (status >= 400 && hooks?.onRejected !== undefined) {\n\t\ttry {\n\t\t\thooks.onRejected(status);\n\t\t} catch {\n\t\t\t// Observability must never change the response.\n\t\t}\n\t}\n}\n\n/** Marks a request as already gated by the outermost explicit security layer. */\nexport function markMcpRequestSecured(request: Request): void {\n\tsecuredRequests.add(request);\n}\n\nexport function isMcpRequestSecured(request: Request): boolean {\n\treturn securedRequests.has(request);\n}\n\n/** Hardened facade preserving the full `McpFetchHandler` face, like `McpValidatedServer`. */\nexport class McpHardenedServer implements McpFetchHandler {\n\treadonly notify: McpFetchHandler[\"notify\"];\n\treadonly bus: McpFetchHandler[\"bus\"];\n\n\treadonly #handler: McpFetchHandler;\n\treadonly #policy: McpHttpSecurityPolicy;\n\treadonly #hardened: ReturnType<typeof hardenMcpFetch>;\n\n\tconstructor(\n\t\thandler: McpFetchHandler,\n\t\toptions?: McpHttpSecurityOptions | McpHttpSecurityPolicy,\n\t\thooks?: McpHardenHooks,\n\t) {\n\t\tthis.#handler = handler;\n\t\tthis.#policy = isMcpHttpSecurityPolicy(options) ? options : resolveMcpHttpSecurity(options);\n\t\tthis.#hardened = hardenMcpFetch(handler, this.#policy, hooks);\n\t\tthis.notify = handler.notify;\n\t\tthis.bus = handler.bus;\n\t}\n\n\tget policy(): McpHttpSecurityPolicy {\n\t\treturn this.#policy;\n\t}\n\n\tfetch(request: Request, options?: McpHandlerRequestOptions): Promise<Response> {\n\t\treturn this.#hardened.fetch(request, options);\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.#handler.close();\n\t}\n}\n\nconst securedRequests = new WeakSet<Request>();\n\nfunction resolveCors(\n\tcors: McpCorsOptions | boolean | undefined,\n\toriginValidationEnabled: boolean,\n): ResolvedCorsPolicy | undefined {\n\tif (cors === false) return undefined;\n\tif (cors === undefined && !originValidationEnabled) return undefined;\n\tconst options = cors === true || cors === undefined ? {} : cors;\n\tif (typeof options !== \"object\" || options === null) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"httpSecurity.cors must be a boolean or an options object.\",\n\t\t);\n\t}\n\tconst maxAgeSeconds = options.maxAgeSeconds ?? DEFAULT_CORS_MAX_AGE_SECONDS;\n\tif (!Number.isInteger(maxAgeSeconds) || maxAgeSeconds < 0) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"httpSecurity.cors.maxAgeSeconds must be a non-negative integer.\",\n\t\t);\n\t}\n\tconst credentials = options.credentials === true;\n\tconst allowedOrigins = resolveAllowedOrigins(options.allowedOrigins);\n\tif (credentials && allowedOrigins === undefined) {\n\t\t// Credentialed CORS must never reflect an arbitrary Origin: an ACAO+ACAC\n\t\t// grant on hostname-only matching would leak to any scheme/port sibling.\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"httpSecurity.cors.credentials requires an explicit cors.allowedOrigins full-origin allowlist.\",\n\t\t);\n\t}\n\tconst allowedHeaderSet = mergeHeaderSet(\n\t\tMCP_CORS_ALLOWED_HEADERS,\n\t\toptions.additionalAllowedHeaders,\n\t);\n\treturn Object.freeze({\n\t\tcredentials,\n\t\tmaxAgeSeconds,\n\t\tallowedHeaders: [...allowedHeaderSet].join(\", \"),\n\t\tallowedHeaderSet,\n\t\texposedHeaders: [\n\t\t\t...mergeHeaderSet(MCP_CORS_EXPOSED_HEADERS, options.additionalExposedHeaders),\n\t\t].join(\", \"),\n\t\tmethods: MCP_CORS_METHODS.join(\", \"),\n\t\tallowedOrigins,\n\t});\n}\n\nfunction resolveAllowedOrigins(\n\tvalues: readonly string[] | undefined,\n): ReadonlySet<string> | undefined {\n\tif (values === undefined) return undefined;\n\tif (!Array.isArray(values)) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\"httpSecurity.cors.allowedOrigins must be an array of full origins.\",\n\t\t);\n\t}\n\tconst origins = new Set<string>();\n\tfor (const value of values) {\n\t\tlet parsed: URL;\n\t\ttry {\n\t\t\tparsed = new URL(value);\n\t\t} catch {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\t`httpSecurity.cors.allowedOrigins entry \"${String(value)}\" must be a full origin.`,\n\t\t\t);\n\t\t}\n\t\tif (parsed.origin === \"null\") {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\t\"httpSecurity.cors.allowedOrigins entries must be non-opaque origins.\",\n\t\t\t);\n\t\t}\n\t\torigins.add(parsed.origin);\n\t}\n\treturn origins;\n}\n\nfunction mergeHeaderSet(\n\tbase: readonly string[],\n\tadditional?: readonly string[],\n): ReadonlySet<string> {\n\tconst merged = new Set(base.map((header) => header.toLowerCase()));\n\tfor (const header of additional ?? []) {\n\t\tif (typeof header !== \"string\" || header.trim().length === 0) {\n\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\t\"httpSecurity.cors header names must be non-empty strings.\",\n\t\t\t);\n\t\t}\n\t\tmerged.add(header.trim().toLowerCase());\n\t}\n\treturn merged;\n}\n\nfunction normalizeHostnameList(values: readonly string[], field: string): readonly string[] {\n\tif (!Array.isArray(values)) {\n\t\tthrow new McpServerRuntimeError(\n\t\t\t\"INVALID_DEFINITION\",\n\t\t\t`${field} must be an array of hostnames or false.`,\n\t\t);\n\t}\n\t// An empty list is a valid deny-all posture for routable binds.\n\treturn Object.freeze(\n\t\tvalues.map((value, index) => {\n\t\t\tconst normalized = typeof value === \"string\" ? value.trim().toLowerCase() : \"\";\n\t\t\tif (normalized.length === 0) {\n\t\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\t\t`${field}[${String(index)}] must be a non-empty string.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (normalized.includes(\"://\") || normalized.includes(\"/\")) {\n\t\t\t\tthrow new McpServerRuntimeError(\n\t\t\t\t\t\"INVALID_DEFINITION\",\n\t\t\t\t\t`${field}[${String(index)}] must be a hostname without a scheme or path.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn normalized;\n\t\t}),\n\t);\n}\n\nfunction isPreflight(request: Request): boolean {\n\treturn (\n\t\trequest.method === \"OPTIONS\" &&\n\t\trequest.headers.get(\"origin\") !== null &&\n\t\trequest.headers.get(\"access-control-request-method\") !== null\n\t);\n}\n\nfunction preflightResponse(request: Request, cors: ResolvedCorsPolicy, origin: string): Response {\n\tconst headers = new Headers({\n\t\t\"access-control-allow-origin\": origin,\n\t\t\"access-control-allow-methods\": cors.methods,\n\t\t\"access-control-allow-headers\": allowedRequestHeaders(request, cors),\n\t\t\"access-control-max-age\": String(cors.maxAgeSeconds),\n\t\tvary: PREFLIGHT_VARY,\n\t});\n\tif (cors.credentials) headers.set(\"access-control-allow-credentials\", \"true\");\n\t// 200 rather than 204: Express strips headers on 204/304 inside send(), which\n\t// throws when a framework reply path runs after the adapter already responded.\n\treturn new Response(null, { status: 200, headers });\n}\n\n/** Intersects the browser's requested headers with the allowlist; no `*`, which excludes Authorization. */\nfunction allowedRequestHeaders(request: Request, cors: ResolvedCorsPolicy): string {\n\tconst requested = request.headers.get(\"access-control-request-headers\");\n\tif (requested === null) return cors.allowedHeaders;\n\tconst permitted = requested\n\t\t.split(\",\")\n\t\t.map((header) => header.trim().toLowerCase())\n\t\t.filter((header) => header.length > 0 && cors.allowedHeaderSet.has(header));\n\treturn permitted.length === 0 ? cors.allowedHeaders : permitted.join(\", \");\n}\n\n/**\n * The origin to echo in `Access-Control-Allow-Origin`, or `undefined` to omit.\n * Credentialed mode requires an exact full-origin match; non-credentialed mode\n * reflects any origin the hostname allowlist admits.\n */\nexport function corsAllowedOrigin(\n\trequest: Request,\n\tpolicy: McpHttpSecurityPolicy,\n): string | undefined {\n\tconst cors = policy.cors;\n\tif (cors === undefined) return undefined;\n\tconst origin = request.headers.get(\"origin\");\n\tif (origin === null || origin.length === 0) return undefined;\n\tif (cors.credentials) {\n\t\treturn cors.allowedOrigins?.has(origin) === true ? origin : undefined;\n\t}\n\tif (policy.allowedOriginHostnames === undefined) return origin;\n\treturn validateOriginHeader(origin, [...policy.allowedOriginHostnames]).ok ? origin : undefined;\n}\n\nfunction appendVary(headers: Headers, value: string): void {\n\tconst existing = headers.get(\"vary\");\n\tif (existing === null) {\n\t\theaders.set(\"vary\", value);\n\t\treturn;\n\t}\n\tconst present = existing\n\t\t.split(\",\")\n\t\t.some((entry) => entry.trim().toLowerCase() === value.toLowerCase());\n\tif (!present) headers.set(\"vary\", `${existing}, ${value}`);\n}\n\nfunction concatChunks(chunks: readonly Uint8Array[], total: number): Uint8Array<ArrayBuffer> {\n\tconst merged = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tmerged.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn merged;\n}\n\nfunction bodyTooLargeResponse(maxBodyBytes: number): Response {\n\treturn new Response(\n\t\tJSON.stringify({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\terror: {\n\t\t\t\tcode: -32600,\n\t\t\t\tmessage: `Request body exceeds the ${String(maxBodyBytes)}-byte limit.`,\n\t\t\t},\n\t\t\tid: null,\n\t\t}),\n\t\t{ status: 413, headers: { \"content-type\": \"application/json\" } },\n\t);\n}\n","import type { NodeIncomingMessageLike, NodeMcpRequestHandler } from \"@modelcontextprotocol/node\";\nimport { corsAllowedOrigin, isMcpHttpSecurityPolicy } from \"./mcp-http-security.ts\";\nimport type { McpHardenHooks, McpHttpSecurityPolicy } from \"./mcp-http-security.ts\";\n\nexport type McpNodeBodyLimit = number | McpHttpSecurityPolicy | undefined;\n\n/**\n * Caps the raw Node request body before the SDK's `toWebRequest` buffers it\n * unbounded. Skips requests the platform already parsed and bodyless methods.\n * On overflow it answers `413` (with CORS headers when a policy is supplied)\n * and never invokes the wrapped handler; on success the buffered bytes are\n * replayed through the request's own async iterator so `req.auth` and other\n * platform decorations survive.\n *\n * Stream errors during the read (e.g. a peer aborting mid-upload) are captured\n * and re-thrown from the replay iterator, so the wrapped SDK adapter keeps\n * ownership of them through its own `try/catch → onerror → 500` path rather\n * than rejecting the returned promise (which would be an unhandled rejection\n * on fire-and-forget mounts).\n */\nexport function withMcpNodeBodyLimit(\n\thandler: NodeMcpRequestHandler,\n\tlimit: McpNodeBodyLimit,\n\thooks?: McpHardenHooks,\n): NodeMcpRequestHandler {\n\tconst policy = isMcpHttpSecurityPolicy(limit) ? limit : undefined;\n\tconst maxBodyBytes: number | undefined = isMcpHttpSecurityPolicy(limit)\n\t\t? limit.maxBodyBytes\n\t\t: limit;\n\tif (maxBodyBytes === undefined) return handler;\n\treturn async (req, res, parsedBody) => {\n\t\t// Express/Connect invoke mounted handlers as (req, res, next); a function\n\t\t// third argument is Express's `next`, never a body — the SDK drops it too.\n\t\tconst body = typeof parsedBody === \"function\" ? undefined : parsedBody;\n\t\tif (body !== undefined || !methodMayCarryBody(req.method)) {\n\t\t\treturn handler(req, res, parsedBody);\n\t\t}\n\t\tconst declaredLength = declaredContentLength(req);\n\t\tif (declaredLength !== undefined && declaredLength > maxBodyBytes) {\n\t\t\trejectOversize(req, res, maxBodyBytes, policy, hooks);\n\t\t\treturn;\n\t\t}\n\t\tconst chunks: (string | Uint8Array)[] = [];\n\t\tlet total = 0;\n\t\tlet readError: unknown;\n\t\ttry {\n\t\t\tfor await (const chunk of req) {\n\t\t\t\tif (typeof chunk !== \"string\" && !(chunk instanceof Uint8Array)) continue;\n\t\t\t\ttotal += byteLengthOf(chunk);\n\t\t\t\tif (total > maxBodyBytes) {\n\t\t\t\t\trejectOversize(req, res, maxBodyBytes, policy, hooks);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tchunks.push(chunk);\n\t\t\t}\n\t\t} catch (cause) {\n\t\t\t// Peer aborted mid-body / stream error. Hand it back to the adapter\n\t\t\t// via the replay iterator instead of rejecting this promise.\n\t\t\treadError = cause;\n\t\t}\n\t\t// Replay on the original request object rather than a clone: toWebRequest\n\t\t// reads headers/method/auth from this exact object.\n\t\tObject.defineProperty(req, Symbol.asyncIterator, {\n\t\t\tconfigurable: true,\n\t\t\twritable: true,\n\t\t\tvalue: async function* replayBufferedBody(): AsyncGenerator<string | Uint8Array> {\n\t\t\t\tyield* chunks;\n\t\t\t\tif (readError !== undefined) throw readError;\n\t\t\t},\n\t\t});\n\t\treturn handler(req, res, undefined);\n\t};\n}\n\nfunction methodMayCarryBody(method: string | undefined): boolean {\n\tconst normalized = (method ?? \"GET\").toUpperCase();\n\treturn normalized !== \"GET\" && normalized !== \"HEAD\";\n}\n\nfunction declaredContentLength(req: NodeIncomingMessageLike): number | undefined {\n\tconst header = req.headers[\"content-length\"];\n\tconst value = Array.isArray(header) ? header[0] : header;\n\tif (value === undefined) return undefined;\n\tconst parsed = Number(value);\n\treturn Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction byteLengthOf(chunk: unknown): number {\n\tif (typeof chunk === \"string\") return Buffer.byteLength(chunk);\n\tif (chunk instanceof Uint8Array) return chunk.byteLength;\n\treturn 0;\n}\n\nfunction rejectOversize(\n\treq: NodeIncomingMessageLike,\n\tres: {\n\t\twriteHead(statusCode: number, headers?: Record<string, string>): unknown;\n\t\tend(chunk?: string | Uint8Array): unknown;\n\t\tdestroyed?: boolean;\n\t},\n\tmaxBodyBytes: number,\n\tpolicy: McpHttpSecurityPolicy | undefined,\n\thooks: McpHardenHooks | undefined,\n): void {\n\t// Drain what the peer already sent so the 413 can flush, then half-close.\n\tconst resume = Reflect.get(req, \"resume\");\n\tif (typeof resume === \"function\") Reflect.apply(resume, req, []);\n\tif (hooks?.onRejected !== undefined) {\n\t\ttry {\n\t\t\thooks.onRejected(413);\n\t\t} catch {\n\t\t\t// Observation never changes the response.\n\t\t}\n\t}\n\tif (res.destroyed === true) return;\n\tres.writeHead(413, {\n\t\t\"content-type\": \"application/json\",\n\t\tconnection: \"close\",\n\t\t...corsHeadersFor(req, policy),\n\t});\n\tres.end(\n\t\tJSON.stringify({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\terror: {\n\t\t\t\tcode: -32600,\n\t\t\t\tmessage: `Request body exceeds the ${String(maxBodyBytes)}-byte limit.`,\n\t\t\t},\n\t\t\tid: null,\n\t\t}),\n\t);\n}\n\nfunction corsHeadersFor(\n\treq: NodeIncomingMessageLike,\n\tpolicy: McpHttpSecurityPolicy | undefined,\n): Record<string, string> {\n\tif (policy?.cors === undefined) return {};\n\tconst origin = originHeader(req);\n\tif (origin === undefined) return {};\n\t// Reuse the same origin decision the fetch layer applies.\n\tconst allowed = corsAllowedOrigin(\n\t\tnew Request(\"http://body-limit.invalid\", { headers: { origin } }),\n\t\tpolicy,\n\t);\n\tif (allowed === undefined) return {};\n\tconst headers: Record<string, string> = {\n\t\t\"access-control-allow-origin\": allowed,\n\t\t\"access-control-expose-headers\": policy.cors.exposedHeaders,\n\t\tvary: \"Origin\",\n\t};\n\tif (policy.cors.credentials) headers[\"access-control-allow-credentials\"] = \"true\";\n\treturn headers;\n}\n\nfunction originHeader(req: NodeIncomingMessageLike): string | undefined {\n\tconst header = req.headers[\"origin\"];\n\tconst value = Array.isArray(header) ? header[0] : header;\n\treturn typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n"],"mappings":"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"}