@quantakrypto/mcp 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +1 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/tools.d.ts +1 -1
- package/package.json +3 -3
package/dist/http.js
CHANGED
|
@@ -180,7 +180,7 @@ export function authorizeRequest(token, authorizationHeader) {
|
|
|
180
180
|
if (token.length === 0)
|
|
181
181
|
return { authorized: true };
|
|
182
182
|
const header = (authorizationHeader ?? "").trim();
|
|
183
|
-
const match = /^Bearer\s+(
|
|
183
|
+
const match = /^Bearer\s+(\S.*)$/i.exec(header);
|
|
184
184
|
const presented = match?.[1]?.trim();
|
|
185
185
|
if (!presented) {
|
|
186
186
|
return { authorized: false, status: 401, message: "missing bearer token" };
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * quantakrypto MCP — hostable HTTP transport (Streamable-HTTP-style JSON-RPC).\n *\n * A zero-dependency {@link node:http} server that exposes the same\n * {@link McpServer} over HTTP so the quantakrypto MCP can run as a remote service:\n *\n * POST /mcp — body is a single JSON-RPC 2.0 message; the JSON-RPC\n * response is returned as the 200 response body\n * (`application/json`). Notifications get HTTP 202 with no body.\n * GET /health — liveness probe, returns `{ status: \"ok\", ... }`.\n *\n * This is the minimal-but-working core of the MCP Streamable HTTP transport.\n * The full spec also supports an SSE response (`text/event-stream`) for\n * server-initiated messages; this server speaks the JSON request/response half,\n * which is sufficient for stateless tool calls. See HOSTING.md for the\n * production design (auth, multi-tenant sessions, rate limiting, scaling).\n *\n * SAFE-BY-DEFAULT POSTURE (P0-1). Unlike the stdio transport — which trusts the\n * local user and stays fully featured — the HTTP transport is hardened because a\n * hosted endpoint is reachable by untrusted peers:\n *\n * - Binds to 127.0.0.1 by default (NOT 0.0.0.0). Override with QUANTAKRYPTO_MCP_HOST.\n * - Bearer-token auth: when QUANTAKRYPTO_MCP_TOKEN is set, every /mcp request must\n * send `Authorization: Bearer <token>` (else 401). Binding to a non-loopback\n * host WITHOUT a token is refused at startup (it would be an open relay).\n * - The filesystem tools (scan_path, inventory_crypto, generate_cbom) read\n * arbitrary server paths and are DISABLED over HTTP unless QUANTAKRYPTO_MCP_ALLOW_FS=1\n * (security audit Q-01). The networked probe_endpoint tool is likewise DISABLED\n * over HTTP unless QUANTAKRYPTO_MCP_ALLOW_NETWORK=1 (a hosted server should not\n * probe arbitrary hosts). The knowledge tools (explain_finding, suggest_hybrid,\n * list_rules) are always available. Gating is enforced by registering only the\n * permitted tools, so tools/list and tools/call both reflect it.\n * - Per-request timeout (QUANTAKRYPTO_MCP_TIMEOUT_MS) and a response-size cap\n * (QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES), in addition to the 1 MiB request-body cap.\n *\n * Run with `node dist/http.js` (PORT/QUANTAKRYPTO_MCP_* from env).\n */\n\nimport { createServer } from \"node:http\";\nimport type { IncomingMessage, Server, ServerResponse } from \"node:http\";\nimport { createHash, randomUUID, timingSafeEqual } from \"node:crypto\";\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport process from \"node:process\";\n\nimport { createQuantakryptoServer } from \"./index.js\";\nimport { ErrorCode, makeFailure } from \"./protocol.js\";\nimport type { JsonRpcResponse, ToolDefinition } from \"./protocol.js\";\nimport { quantakryptoTools, FS_TOOL_NAMES, NETWORK_TOOL_NAMES } from \"./tools.js\";\nimport type { McpServer } from \"./server.js\";\n\n/** Header carrying the MCP session id (per the Streamable HTTP transport). */\nconst SESSION_HEADER = \"mcp-session-id\";\n\n/** Maximum accepted request body size (1 MiB) — a basic abuse guard. */\nconst MAX_BODY_BYTES = 1024 * 1024;\n\n/** Default per-request tool-execution deadline (ms). */\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Default cap on the serialized response body (4 MiB). */\nconst DEFAULT_MAX_RESPONSE_BYTES = 4 * 1024 * 1024;\n\n/** Loopback hosts that are safe to bind without authentication. */\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"::1\", \"localhost\"]);\n\ninterface HttpServerOptions {\n /** Port to listen on. Defaults to env PORT or 3000. */\n port?: number;\n /** Host/interface to bind. Defaults to QUANTAKRYPTO_MCP_HOST / HOST or \"127.0.0.1\". */\n host?: string;\n /** Bearer token required on /mcp. Defaults to QUANTAKRYPTO_MCP_TOKEN (empty = none). */\n token?: string;\n /** Expose the filesystem tools over HTTP. Defaults to QUANTAKRYPTO_MCP_ALLOW_FS=1. */\n allowFs?: boolean;\n /**\n * Expose the networked probe_endpoint tool over HTTP. Off by default (a hosted\n * server should not probe arbitrary hosts); enable only on a trusted deployment.\n * Defaults to QUANTAKRYPTO_MCP_ALLOW_NETWORK=1.\n */\n allowNetwork?: boolean;\n /** Per-request tool-execution timeout (ms). Defaults to QUANTAKRYPTO_MCP_TIMEOUT_MS. */\n timeoutMs?: number;\n /** Response-body size cap (bytes). Defaults to QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES. */\n maxResponseBytes?: number;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Pure policy (P0-1) — host/auth/tool-gating decisions, fully unit-testable. */\n/* -------------------------------------------------------------------------- */\n\n/** A minimal env shape so the config resolver is pure and testable. */\ntype HttpEnv = Record<string, string | undefined>;\n\n/** Resolved, validated HTTP transport configuration. */\ninterface HttpConfig {\n host: string;\n port: number;\n /** The bearer token, or \"\" when auth is disabled. */\n token: string;\n /** Whether the filesystem tools are exposed over HTTP. */\n allowFs: boolean;\n /** Whether the networked probe_endpoint tool is exposed over HTTP (default off). */\n allowNetwork: boolean;\n timeoutMs: number;\n maxResponseBytes: number;\n /** True when the host is a loopback interface (safe without auth). */\n loopback: boolean;\n /**\n * Extra origin hosts to allow on `POST /mcp` (lower-cased hostnames), beyond\n * the implicit loopback set and the bind host. From QUANTAKRYPTO_MCP_ALLOW_ORIGIN.\n */\n allowedOrigins: string[];\n}\n\n/**\n * Resolve the HTTP transport config from env + explicit overrides. Pure: does\n * no I/O and never reads `process` directly. Overrides win over env.\n */\nexport function resolveHttpConfig(env: HttpEnv, options: HttpServerOptions = {}): HttpConfig {\n const host = options.host ?? env.QUANTAKRYPTO_MCP_HOST ?? env.HOST ?? \"127.0.0.1\";\n const port = options.port ?? toInt(env.PORT, 3000);\n const token = (options.token ?? env.QUANTAKRYPTO_MCP_TOKEN ?? \"\").trim();\n const allowFs =\n options.allowFs ??\n (env.QUANTAKRYPTO_MCP_ALLOW_FS === \"1\" || env.QUANTAKRYPTO_MCP_ALLOW_FS === \"true\");\n const allowNetwork =\n options.allowNetwork ??\n (env.QUANTAKRYPTO_MCP_ALLOW_NETWORK === \"1\" || env.QUANTAKRYPTO_MCP_ALLOW_NETWORK === \"true\");\n const timeoutMs = options.timeoutMs ?? toInt(env.QUANTAKRYPTO_MCP_TIMEOUT_MS, DEFAULT_TIMEOUT_MS);\n const maxResponseBytes =\n options.maxResponseBytes ??\n toInt(env.QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES, DEFAULT_MAX_RESPONSE_BYTES);\n const allowedOrigins = parseOriginList(env.QUANTAKRYPTO_MCP_ALLOW_ORIGIN);\n return {\n host,\n port,\n token,\n allowFs,\n allowNetwork,\n timeoutMs,\n maxResponseBytes,\n loopback: isLoopbackHost(host),\n allowedOrigins,\n };\n}\n\n/**\n * Parse the comma-separated origin allow-list into lower-cased hostnames. Each\n * entry may be a bare host or a full origin URL; either way only the hostname is\n * retained (the value compared against `new URL(Origin).hostname`).\n */\nfunction parseOriginList(value: string | undefined): string[] {\n const out = new Set<string>();\n for (const raw of (value ?? \"\").split(\",\")) {\n const entry = raw.trim().toLowerCase();\n if (entry.length === 0) continue;\n try {\n out.add(new URL(entry).hostname);\n } catch {\n out.add(entry); // bare hostname (no scheme).\n }\n }\n return [...out];\n}\n\n/** Parse a positive integer from an env string, falling back on bad input. */\nfunction toInt(value: string | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;\n}\n\n/** True when binding to `host` keeps the server private to this machine. */\nexport function isLoopbackHost(host: string): boolean {\n return LOOPBACK_HOSTS.has(host.trim().toLowerCase());\n}\n\n/**\n * Decide whether a non-loopback bind is permitted. A server reachable from the\n * network MUST require auth; binding wide-open without a token would be an open,\n * unauthenticated arbitrary-tool relay. Pure decision used at startup.\n */\nexport function startupDecision(config: HttpConfig): {\n ok: boolean;\n reason?: string;\n} {\n if (!config.loopback && config.token.length === 0) {\n return {\n ok: false,\n reason:\n `refusing to bind to non-loopback host \"${config.host}\" without a token. ` +\n `Set QUANTAKRYPTO_MCP_TOKEN to require Bearer auth, or bind to 127.0.0.1.`,\n };\n }\n return { ok: true };\n}\n\n/**\n * Decide whether a request's `Origin` / `Host` is acceptable, to defend the\n * default no-token loopback config against DNS-rebinding and localhost-CSRF: a\n * malicious web page can POST to `http://127.0.0.1:<port>/mcp`, but the browser\n * stamps a foreign `Origin` we can reject. Pure and testable.\n *\n * Policy:\n * - No `Origin` header (curl, a native MCP client, same-origin GET) → allow;\n * the header is a browser artifact and absence is not an attack signal here.\n * - An `Origin` present → its host must be a configured loopback host (or a\n * host explicitly added to the allow-list). A foreign origin is rejected.\n * - When the server itself binds a non-loopback interface, a token is already\n * mandatory (see {@link startupDecision}); the loopback allow-list still\n * applies but auth is the primary control there.\n */\nexport function originDecision(\n allowedHosts: ReadonlySet<string>,\n originHeader: string | undefined,\n): { ok: boolean; reason?: string } {\n const origin = (originHeader ?? \"\").trim();\n if (origin.length === 0) return { ok: true }; // non-browser client; nothing to check.\n if (origin.toLowerCase() === \"null\") {\n return { ok: false, reason: \"opaque/null Origin is not allowed\" };\n }\n let host: string;\n try {\n host = new URL(origin).hostname.toLowerCase();\n } catch {\n return { ok: false, reason: \"malformed Origin header\" };\n }\n if (allowedHosts.has(host)) return { ok: true };\n return { ok: false, reason: `Origin host \"${host}\" is not in the allow-list` };\n}\n\n/** The hosts an `Origin` may name. Loopback by default, plus the bind host. */\nexport function allowedOriginHosts(config: HttpConfig): Set<string> {\n const hosts = new Set<string>([\"127.0.0.1\", \"::1\", \"localhost\"]);\n // Allow the interface the server is actually bound to (e.g. a LAN address with\n // a token), so a same-host browser client keeps working.\n hosts.add(config.host.trim().toLowerCase());\n for (const extra of config.allowedOrigins) hosts.add(extra);\n return hosts;\n}\n\n/** A request-authorization outcome. */\ninterface AuthDecision {\n authorized: boolean;\n /** HTTP status to use when not authorized. */\n status?: number;\n message?: string;\n}\n\n/**\n * Decide whether a request is authorized given the configured token and the\n * incoming Authorization header. When no token is configured, all requests are\n * allowed (the loopback / trusted-edge case). Pure and testable.\n */\nexport function authorizeRequest(\n token: string,\n authorizationHeader: string | undefined,\n): AuthDecision {\n if (token.length === 0) return { authorized: true };\n const header = (authorizationHeader ?? \"\").trim();\n const match = /^Bearer\\s+(.+)$/i.exec(header);\n const presented = match?.[1]?.trim();\n if (!presented) {\n return { authorized: false, status: 401, message: \"missing bearer token\" };\n }\n if (!timingSafeEqualStr(presented, token)) {\n return { authorized: false, status: 401, message: \"invalid bearer token\" };\n }\n return { authorized: true };\n}\n\n/**\n * Constant-time string compare. Both inputs are hashed with the same algorithm\n * to fixed-length digests before {@link timingSafeEqual}, so the comparison runs\n * over equal-length buffers and the early length-mismatch return (which leaked\n * the configured token's length) is gone. The hashing is a domain-separation /\n * length-equalization step, not a secrecy measure: `timingSafeEqual` still does\n * the constant-time work and rejects unequal digests.\n */\nexport function timingSafeEqualStr(a: string, b: string): boolean {\n const ha = createHash(\"sha256\").update(a, \"utf8\").digest();\n const hb = createHash(\"sha256\").update(b, \"utf8\").digest();\n // Same algorithm ⇒ identical digest length ⇒ timingSafeEqual never throws.\n return timingSafeEqual(ha, hb);\n}\n\n/**\n * Select the tools to expose over HTTP for a given policy. The knowledge tools\n * are always returned; the filesystem tools are included only when `allowFs` is\n * true, and the networked probe tool only when `allowNetwork` is true (both off by\n * default). Pure function of its inputs — the single source of truth for HTTP tool\n * gating, so tools/list and tools/call stay consistent.\n */\nexport function gateHttpTools(\n tools: readonly ToolDefinition[],\n allowFs: boolean,\n allowNetwork = false,\n): ToolDefinition[] {\n const fsNames = new Set(FS_TOOL_NAMES);\n const networkNames = new Set(NETWORK_TOOL_NAMES);\n return tools.filter(\n (t) =>\n (allowNetwork || !networkNames.has(t.name)) && // networked tools: opt-in on HTTP\n (allowFs || !fsNames.has(t.name)), // fs tools: opt-in on HTTP\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* HTTP plumbing */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Error thrown by {@link readBody} when the request body exceeds the size cap.\n * Distinguished from a transport/I/O error so the caller can map it to HTTP 413\n * specifically, while genuine read failures map to 400/500 (M1).\n */\nexport class BodyTooLargeError extends Error {\n override readonly name = \"BodyTooLargeError\";\n constructor(message = \"request body too large\") {\n super(message);\n }\n}\n\n/**\n * Read a request body fully, enforcing the size cap. Resolves to the raw string.\n * Rejects with a {@link BodyTooLargeError} when the cap is exceeded, and with the\n * original transport error (an I/O failure) otherwise — the two are mapped to\n * different HTTP statuses by the caller (M1).\n */\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0;\n let done = false;\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => {\n if (done) return;\n size += chunk.length;\n if (size > MAX_BODY_BYTES) {\n // Stop consuming and reject. We deliberately do NOT destroy the socket\n // here: the caller still needs to flush a 413 response, so it owns the\n // teardown (resume-and-drain) once that response is written.\n done = true;\n req.pause();\n reject(new BodyTooLargeError());\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => {\n if (!done) resolve(Buffer.concat(chunks).toString(\"utf8\"));\n });\n req.on(\"error\", (err: Error) => {\n if (!done) {\n done = true;\n reject(err);\n }\n });\n });\n}\n\n/** Write a JSON response with the given status and optional extra headers. */\nfunction sendJson(\n res: ServerResponse,\n status: number,\n body: unknown,\n headers: Record<string, string> = {},\n): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(payload).toString(),\n ...headers,\n });\n res.end(payload);\n}\n\n/** Error raised by {@link withTimeout} when the request deadline elapses. */\nclass RequestTimeoutError extends Error {\n override readonly name = \"RequestTimeoutError\";\n constructor(message = \"request timed out\") {\n super(message);\n }\n}\n\n/**\n * Race a handler against a deadline. On timeout the returned promise rejects with\n * a {@link RequestTimeoutError} AND the supplied {@link AbortController} is\n * aborted, so the in-flight work (a `scan()` wired to `controller.signal`) stops\n * cooperatively instead of running unbounded in the background after the 504.\n *\n * The controller is always aborted once the race settles (success, failure, or\n * timeout) so no scan keeps running past its response.\n */\nfunction withTimeout<T>(promise: Promise<T>, ms: number, controller: AbortController): Promise<T> {\n if (!(ms > 0)) return promise;\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n controller.abort(); // cancel the underlying scan — no leaked background work.\n reject(new RequestTimeoutError());\n }, ms);\n timer.unref?.();\n promise.then(\n (value) => {\n clearTimeout(timer);\n controller.abort(); // settle the signal so nothing lingers post-response.\n resolve(value);\n },\n (err: unknown) => {\n clearTimeout(timer);\n controller.abort();\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\n/**\n * Build (but do not start) the HTTP server wrapping an {@link McpServer}.\n * Exposed for testing and for embedding in a larger process. The `config`\n * carries the resolved auth / timeout / response-cap policy.\n */\nexport function createHttpServer(server: McpServer, config: HttpConfig): Server {\n return createServer((req, res) => {\n void handleRequest(server, config, req, res).catch((err: unknown) => {\n // Last-resort handler: log the detail locally, return a generic message so\n // a remote caller never sees server internals (paths, stack traces).\n logServerError(\"unhandled request error\", err);\n if (!res.headersSent) {\n sendJson(res, 500, makeFailure(null, ErrorCode.InternalError, \"internal error\"));\n } else {\n res.end();\n }\n });\n });\n}\n\n/** Log a server-side error detail to stderr (never sent to the remote caller). */\nfunction logServerError(context: string, err: unknown): void {\n const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);\n process.stderr.write(`quantakrypto MCP (http): ${context}: ${detail}\\n`);\n}\n\n/** Extract the (single) `Origin` request header, if present. */\nfunction originHeader(req: IncomingMessage): string | undefined {\n const value = req.headers.origin;\n return Array.isArray(value) ? value[0] : value;\n}\n\n/** Route and handle a single HTTP request. */\nasync function handleRequest(\n server: McpServer,\n config: HttpConfig,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n const url = req.url ?? \"/\";\n const method = req.method ?? \"GET\";\n const path = url.split(\"?\")[0];\n\n if (method === \"GET\" && path === \"/health\") {\n sendJson(res, 200, { status: \"ok\", server: \"quantakrypto\", transport: \"http\" });\n return;\n }\n\n if (path === \"/mcp\") {\n if (method !== \"POST\") {\n // The full transport also allows GET for an SSE stream; we don't here.\n sendJson(res, 405, makeFailure(null, ErrorCode.InvalidRequest, \"method not allowed\"), {\n allow: \"POST\",\n });\n return;\n }\n // DNS-rebinding / localhost-CSRF guard: reject a foreign browser Origin\n // BEFORE auth/body, so the default no-token loopback config is not a\n // confused deputy for a malicious web page. (P0 — origin validation.)\n const origin = originDecision(allowedOriginHosts(config), originHeader(req));\n if (!origin.ok) {\n sendJson(\n res,\n 403,\n makeFailure(null, ErrorCode.InvalidRequest, origin.reason ?? \"forbidden origin\"),\n );\n return;\n }\n // Authenticate BEFORE reading the body or dispatching (Q-02).\n const auth = authorizeRequest(config.token, req.headers.authorization);\n if (!auth.authorized) {\n sendJson(\n res,\n auth.status ?? 401,\n makeFailure(null, ErrorCode.InvalidRequest, auth.message ?? \"unauthorized\"),\n { \"www-authenticate\": \"Bearer\" },\n );\n return;\n }\n await handleMcpPost(server, config, req, res);\n return;\n }\n\n sendJson(res, 404, makeFailure(null, ErrorCode.MethodNotFound, \"not found\"));\n}\n\n/** Handle `POST /mcp`: parse one JSON-RPC message, dispatch, return the result. */\nasync function handleMcpPost(\n server: McpServer,\n config: HttpConfig,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n // Session handling (stateless here): echo a provided session id, else mint one.\n // A production server would look this up in a session store — see HOSTING.md.\n const incomingSession = req.headers[SESSION_HEADER];\n const sessionId =\n (Array.isArray(incomingSession) ? incomingSession[0] : incomingSession) ?? randomUUID();\n const sessionHeaders = { [SESSION_HEADER]: sessionId };\n\n let raw: string;\n try {\n raw = await readBody(req);\n } catch (err) {\n // M1: only the size-cap rejection is a 413. A genuine transport/I/O error\n // (the client aborted, a socket reset) is a 400 — it is the request that\n // failed, not a server fault — and never echoes the raw error text.\n if (err instanceof BodyTooLargeError) {\n // Flush the 413 first, then tear down the connection so a still-uploading\n // client stops sending. Destroying on `finish` guarantees the response is\n // written before the socket goes away (avoids a connection-reset race).\n res.on(\"finish\", () => req.destroy());\n sendJson(res, 413, makeFailure(null, ErrorCode.InvalidRequest, \"request body too large\"), {\n ...sessionHeaders,\n connection: \"close\",\n });\n } else {\n logServerError(\"error reading request body\", err);\n sendJson(\n res,\n 400,\n makeFailure(null, ErrorCode.InvalidRequest, \"error reading request body\"),\n sessionHeaders,\n );\n }\n return;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n sendJson(res, 400, makeFailure(null, ErrorCode.ParseError, \"parse error\"), sessionHeaders);\n return;\n }\n\n // Cancellation: the controller's signal is threaded into the tool handler (and\n // thus into `scan()`); withTimeout aborts it on deadline so a timed-out\n // request stops the underlying work instead of leaking it (P0 — timeout/abort).\n const controller = new AbortController();\n let response: JsonRpcResponse | null;\n try {\n response = await withTimeout(\n server.handle(parsed, { signal: controller.signal }),\n config.timeoutMs,\n controller,\n );\n } catch (err) {\n if (err instanceof RequestTimeoutError) {\n sendJson(\n res,\n 504,\n makeFailure(null, ErrorCode.InternalError, \"request timed out\"),\n sessionHeaders,\n );\n } else {\n // server.handle never rejects in practice (it catches internally), but be\n // defensive and never leak a raw message.\n logServerError(\"error dispatching request\", err);\n sendJson(\n res,\n 500,\n makeFailure(null, ErrorCode.InternalError, \"internal error\"),\n sessionHeaders,\n );\n }\n return;\n }\n\n if (response === null) {\n // Notification — acknowledge with 202 and no body.\n res.writeHead(202, sessionHeaders);\n res.end();\n return;\n }\n\n // Enforce the response-size cap (Q-03): never stream back an unbounded body.\n const serialized = JSON.stringify(response);\n if (Buffer.byteLength(serialized) > config.maxResponseBytes) {\n sendJson(\n res,\n 500,\n makeFailure(null, ErrorCode.InternalError, \"response too large\"),\n sessionHeaders,\n );\n return;\n }\n sendJson(res, 200, response, sessionHeaders);\n}\n\n/**\n * Build the HTTP-facing {@link McpServer}: the same server used over stdio but\n * with the filesystem tools gated per policy. Exposed for tests.\n */\nexport function createHttpMcpServer(config: HttpConfig): McpServer {\n return createQuantakryptoServer({\n tools: gateHttpTools(quantakryptoTools, config.allowFs, config.allowNetwork),\n });\n}\n\n/** Start the HTTP server, resolving once it is listening. */\nfunction startHttpServer(options: HttpServerOptions = {}): Promise<Server> {\n const config = resolveHttpConfig(process.env, options);\n\n const decision = startupDecision(config);\n if (!decision.ok) {\n return Promise.reject(new Error(decision.reason ?? \"refusing to start\"));\n }\n if (!config.loopback) {\n process.stderr.write(\n `quantakrypto MCP (http): WARNING binding to non-loopback host ${config.host}; ` +\n `Bearer auth is required and active.\\n`,\n );\n }\n\n const mcp = createHttpMcpServer(config);\n const httpServer = createHttpServer(mcp, config);\n return new Promise((resolve) => {\n httpServer.listen(config.port, config.host, () => {\n const auth = config.token ? \"bearer-auth\" : \"no-auth\";\n const fs = config.allowFs ? \"fs-tools:on\" : \"fs-tools:off\";\n const probe = config.allowNetwork ? \"probe:on\" : \"probe:off\";\n process.stderr.write(\n `quantakrypto MCP server (http) listening on http://${config.host}:${config.port} ` +\n `[${auth}, ${fs}, ${probe}]\\n`,\n );\n process.stderr.write(\n ` POST http://${config.host}:${config.port}/mcp ` +\n `GET http://${config.host}:${config.port}/health\\n`,\n );\n resolve(httpServer);\n });\n });\n}\n\n/** Entry point when run directly. */\nfunction main(): void {\n startHttpServer().catch((err: unknown) => {\n const messageText = err instanceof Error ? err.message : String(err);\n process.stderr.write(`quantakrypto MCP (http) failed to start: ${messageText}\\n`);\n process.exitCode = 1;\n });\n}\n\n/** True when this module is the program's entry point (handles symlinks). */\nfunction isMainModule(): boolean {\n const argv1 = process.argv[1];\n if (!argv1) return false;\n const thisPath = fileURLToPath(import.meta.url);\n try {\n return realpathSync(argv1) === realpathSync(thisPath);\n } catch {\n return argv1 === thisPath;\n }\n}\n\n// Only auto-run when invoked as a script, not when imported by tests.\nif (isMainModule()) {\n main();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGlF,8EAA8E;AAC9E,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAExC,wEAAwE;AACxE,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC,wDAAwD;AACxD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,2DAA2D;AAC3D,MAAM,0BAA0B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnD,mEAAmE;AACnE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;AAmDlE;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY,EAAE,UAA6B,EAAE;IAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,IAAI,IAAI,WAAW,CAAC;IAClF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACzE,MAAM,OAAO,GACX,OAAO,CAAC,OAAO;QACf,CAAC,GAAG,CAAC,yBAAyB,KAAK,GAAG,IAAI,GAAG,CAAC,yBAAyB,KAAK,MAAM,CAAC,CAAC;IACtF,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY;QACpB,CAAC,GAAG,CAAC,8BAA8B,KAAK,GAAG,IAAI,GAAG,CAAC,8BAA8B,KAAK,MAAM,CAAC,CAAC;IAChG,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,2BAA2B,EAAE,kBAAkB,CAAC,CAAC;IAClG,MAAM,gBAAgB,GACpB,OAAO,CAAC,gBAAgB;QACxB,KAAK,CAAC,GAAG,CAAC,mCAAmC,EAAE,0BAA0B,CAAC,CAAC;IAC7E,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC1E,OAAO;QACL,IAAI;QACJ,IAAI;QACJ,KAAK;QACL,OAAO;QACP,YAAY;QACZ,SAAS;QACT,gBAAgB;QAChB,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC;QAC9B,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,KAAyB;IAChD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,IAAI,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,6BAA6B;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAClB,CAAC;AAED,8EAA8E;AAC9E,SAAS,KAAK,CAAC,KAAyB,EAAE,QAAgB;IACxD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChE,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAkB;IAIhD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,0CAA0C,MAAM,CAAC,IAAI,qBAAqB;gBAC1E,0EAA0E;SAC7E,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAC5B,YAAiC,EACjC,YAAgC;IAEhC,MAAM,MAAM,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,wCAAwC;IACtF,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;QACpC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC;IACpE,CAAC;IACD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC1D,CAAC;IACD,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,IAAI,4BAA4B,EAAE,CAAC;AACjF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,MAAkB;IACnD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;IACjE,+EAA+E;IAC/E,yDAAyD;IACzD,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,cAAc;QAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,KAAK,CAAC;AACf,CAAC;AAUD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAa,EACb,mBAAuC;IAEvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS,EAAE,CAAS;IACrD,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3D,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3D,2EAA2E;IAC3E,OAAO,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,OAAgB,EAChB,YAAY,GAAG,KAAK;IAEpB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACjD,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,kCAAkC;QACjF,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CACpC,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACxB,IAAI,GAAG,mBAAmB,CAAC;IAC7C,YAAY,OAAO,GAAG,wBAAwB;QAC5C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;;;GAKG;AACH,SAAS,QAAQ,CAAC,GAAoB;IACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,IAAI;gBAAE,OAAO;YACjB,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,IAAI,IAAI,GAAG,cAAc,EAAE,CAAC;gBAC1B,uEAAuE;gBACvE,uEAAuE;gBACvE,6DAA6D;gBAC7D,IAAI,GAAG,IAAI,CAAC;gBACZ,GAAG,CAAC,KAAK,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;gBAChC,OAAO;YACT,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,CAAC,IAAI;gBAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,GAAG,IAAI,CAAC;gBACZ,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,SAAS,QAAQ,CACf,GAAmB,EACnB,MAAc,EACd,IAAa,EACb,UAAkC,EAAE;IAEpC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;QACpB,cAAc,EAAE,iCAAiC;QACjD,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE;QACvD,GAAG,OAAO;KACX,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,6EAA6E;AAC7E,MAAM,mBAAoB,SAAQ,KAAK;IACnB,IAAI,GAAG,qBAAqB,CAAC;IAC/C,YAAY,OAAO,GAAG,mBAAmB;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAI,OAAmB,EAAE,EAAU,EAAE,UAA2B;IAClF,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAC9B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,0DAA0D;YAC9E,MAAM,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;QACpC,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE;YACR,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,sDAAsD;YAC1E,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,EACD,CAAC,GAAY,EAAE,EAAE;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,MAAkB;IACpE,OAAO,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC/B,KAAK,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YAClE,2EAA2E;YAC3E,qEAAqE;YACrE,cAAc,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC;YACnF,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,SAAS,cAAc,CAAC,OAAe,EAAE,GAAY;IACnD,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED,gEAAgE;AAChE,SAAS,YAAY,CAAC,GAAoB;IACxC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACjD,CAAC;AAED,8CAA8C;AAC9C,KAAK,UAAU,aAAa,CAC1B,MAAiB,EACjB,MAAkB,EAClB,GAAoB,EACpB,GAAmB;IAEnB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;IACnC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/B,IAAI,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3C,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAChF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,uEAAuE;YACvE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,oBAAoB,CAAC,EAAE;gBACpF,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,wEAAwE;QACxE,qEAAqE;QACrE,sEAAsE;QACtE,MAAM,MAAM,GAAG,cAAc,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,QAAQ,CACN,GAAG,EACH,GAAG,EACH,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,IAAI,kBAAkB,CAAC,CACjF,CAAC;YACF,OAAO;QACT,CAAC;QACD,8DAA8D;QAC9D,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,QAAQ,CACN,GAAG,EACH,IAAI,CAAC,MAAM,IAAI,GAAG,EAClB,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC,EAC3E,EAAE,kBAAkB,EAAE,QAAQ,EAAE,CACjC,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,mFAAmF;AACnF,KAAK,UAAU,aAAa,CAC1B,MAAiB,EACjB,MAAkB,EAClB,GAAoB,EACpB,GAAmB;IAEnB,gFAAgF;IAChF,8EAA8E;IAC9E,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACpD,MAAM,SAAS,GACb,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,UAAU,EAAE,CAAC;IAC1F,MAAM,cAAc,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAEvD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0EAA0E;QAC1E,yEAAyE;QACzE,oEAAoE;QACpE,IAAI,GAAG,YAAY,iBAAiB,EAAE,CAAC;YACrC,0EAA0E;YAC1E,0EAA0E;YAC1E,wEAAwE;YACxE,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACtC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,wBAAwB,CAAC,EAAE;gBACxF,GAAG,cAAc;gBACjB,UAAU,EAAE,OAAO;aACpB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;YAClD,QAAQ,CACN,GAAG,EACH,GAAG,EACH,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,4BAA4B,CAAC,EACzE,cAAc,CACf,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,cAAc,CAAC,CAAC;QAC3F,OAAO;IACT,CAAC;IAED,+EAA+E;IAC/E,wEAAwE;IACxE,gFAAgF;IAChF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,QAAgC,CAAC;IACrC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,WAAW,CAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,EACpD,MAAM,CAAC,SAAS,EAChB,UAAU,CACX,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACvC,QAAQ,CACN,GAAG,EACH,GAAG,EACH,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,aAAa,EAAE,mBAAmB,CAAC,EAC/D,cAAc,CACf,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,0EAA0E;YAC1E,0CAA0C;YAC1C,cAAc,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;YACjD,QAAQ,CACN,GAAG,EACH,GAAG,EACH,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,aAAa,EAAE,gBAAgB,CAAC,EAC5D,cAAc,CACf,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,mDAAmD;QACnD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACnC,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,6EAA6E;IAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC5D,QAAQ,CACN,GAAG,EACH,GAAG,EACH,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,aAAa,EAAE,oBAAoB,CAAC,EAChE,cAAc,CACf,CAAC;QACF,OAAO;IACT,CAAC;IACD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAkB;IACpD,OAAO,wBAAwB,CAAC;QAC9B,KAAK,EAAE,aAAa,CAAC,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,YAAY,CAAC;KAC7E,CAAC,CAAC;AACL,CAAC;AAED,6DAA6D;AAC7D,SAAS,eAAe,CAAC,UAA6B,EAAE;IACtD,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,mBAAmB,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,iEAAiE,MAAM,CAAC,IAAI,IAAI;YAC9E,uCAAuC,CAC1C,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YACtD,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;YAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;YAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sDAAsD,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,GAAG;gBACjF,IAAI,IAAI,KAAK,EAAE,KAAK,KAAK,KAAK,CACjC,CAAC;YACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,iBAAiB,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,SAAS;gBAClD,cAAc,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,WAAW,CACtD,CAAC;YACF,OAAO,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qCAAqC;AACrC,SAAS,IAAI;IACX,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACvC,MAAM,WAAW,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,WAAW,IAAI,CAAC,CAAC;QAClF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6EAA6E;AAC7E,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,YAAY,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,KAAK,QAAQ,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,IAAI,EAAE,CAAC;AACT,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * quantakrypto MCP — hostable HTTP transport (Streamable-HTTP-style JSON-RPC).\n *\n * A zero-dependency {@link node:http} server that exposes the same\n * {@link McpServer} over HTTP so the quantakrypto MCP can run as a remote service:\n *\n * POST /mcp — body is a single JSON-RPC 2.0 message; the JSON-RPC\n * response is returned as the 200 response body\n * (`application/json`). Notifications get HTTP 202 with no body.\n * GET /health — liveness probe, returns `{ status: \"ok\", ... }`.\n *\n * This is the minimal-but-working core of the MCP Streamable HTTP transport.\n * The full spec also supports an SSE response (`text/event-stream`) for\n * server-initiated messages; this server speaks the JSON request/response half,\n * which is sufficient for stateless tool calls. See HOSTING.md for the\n * production design (auth, multi-tenant sessions, rate limiting, scaling).\n *\n * SAFE-BY-DEFAULT POSTURE (P0-1). Unlike the stdio transport — which trusts the\n * local user and stays fully featured — the HTTP transport is hardened because a\n * hosted endpoint is reachable by untrusted peers:\n *\n * - Binds to 127.0.0.1 by default (NOT 0.0.0.0). Override with QUANTAKRYPTO_MCP_HOST.\n * - Bearer-token auth: when QUANTAKRYPTO_MCP_TOKEN is set, every /mcp request must\n * send `Authorization: Bearer <token>` (else 401). Binding to a non-loopback\n * host WITHOUT a token is refused at startup (it would be an open relay).\n * - The filesystem tools (scan_path, inventory_crypto, generate_cbom) read\n * arbitrary server paths and are DISABLED over HTTP unless QUANTAKRYPTO_MCP_ALLOW_FS=1\n * (security audit Q-01). The networked probe_endpoint tool is likewise DISABLED\n * over HTTP unless QUANTAKRYPTO_MCP_ALLOW_NETWORK=1 (a hosted server should not\n * probe arbitrary hosts). The knowledge tools (explain_finding, suggest_hybrid,\n * list_rules) are always available. Gating is enforced by registering only the\n * permitted tools, so tools/list and tools/call both reflect it.\n * - Per-request timeout (QUANTAKRYPTO_MCP_TIMEOUT_MS) and a response-size cap\n * (QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES), in addition to the 1 MiB request-body cap.\n *\n * Run with `node dist/http.js` (PORT/QUANTAKRYPTO_MCP_* from env).\n */\n\nimport { createServer } from \"node:http\";\nimport type { IncomingMessage, Server, ServerResponse } from \"node:http\";\nimport { createHash, randomUUID, timingSafeEqual } from \"node:crypto\";\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport process from \"node:process\";\n\nimport { createQuantakryptoServer } from \"./index.js\";\nimport { ErrorCode, makeFailure } from \"./protocol.js\";\nimport type { JsonRpcResponse, ToolDefinition } from \"./protocol.js\";\nimport { quantakryptoTools, FS_TOOL_NAMES, NETWORK_TOOL_NAMES } from \"./tools.js\";\nimport type { McpServer } from \"./server.js\";\n\n/** Header carrying the MCP session id (per the Streamable HTTP transport). */\nconst SESSION_HEADER = \"mcp-session-id\";\n\n/** Maximum accepted request body size (1 MiB) — a basic abuse guard. */\nconst MAX_BODY_BYTES = 1024 * 1024;\n\n/** Default per-request tool-execution deadline (ms). */\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Default cap on the serialized response body (4 MiB). */\nconst DEFAULT_MAX_RESPONSE_BYTES = 4 * 1024 * 1024;\n\n/** Loopback hosts that are safe to bind without authentication. */\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"::1\", \"localhost\"]);\n\ninterface HttpServerOptions {\n /** Port to listen on. Defaults to env PORT or 3000. */\n port?: number;\n /** Host/interface to bind. Defaults to QUANTAKRYPTO_MCP_HOST / HOST or \"127.0.0.1\". */\n host?: string;\n /** Bearer token required on /mcp. Defaults to QUANTAKRYPTO_MCP_TOKEN (empty = none). */\n token?: string;\n /** Expose the filesystem tools over HTTP. Defaults to QUANTAKRYPTO_MCP_ALLOW_FS=1. */\n allowFs?: boolean;\n /**\n * Expose the networked probe_endpoint tool over HTTP. Off by default (a hosted\n * server should not probe arbitrary hosts); enable only on a trusted deployment.\n * Defaults to QUANTAKRYPTO_MCP_ALLOW_NETWORK=1.\n */\n allowNetwork?: boolean;\n /** Per-request tool-execution timeout (ms). Defaults to QUANTAKRYPTO_MCP_TIMEOUT_MS. */\n timeoutMs?: number;\n /** Response-body size cap (bytes). Defaults to QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES. */\n maxResponseBytes?: number;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Pure policy (P0-1) — host/auth/tool-gating decisions, fully unit-testable. */\n/* -------------------------------------------------------------------------- */\n\n/** A minimal env shape so the config resolver is pure and testable. */\ntype HttpEnv = Record<string, string | undefined>;\n\n/** Resolved, validated HTTP transport configuration. */\ninterface HttpConfig {\n host: string;\n port: number;\n /** The bearer token, or \"\" when auth is disabled. */\n token: string;\n /** Whether the filesystem tools are exposed over HTTP. */\n allowFs: boolean;\n /** Whether the networked probe_endpoint tool is exposed over HTTP (default off). */\n allowNetwork: boolean;\n timeoutMs: number;\n maxResponseBytes: number;\n /** True when the host is a loopback interface (safe without auth). */\n loopback: boolean;\n /**\n * Extra origin hosts to allow on `POST /mcp` (lower-cased hostnames), beyond\n * the implicit loopback set and the bind host. From QUANTAKRYPTO_MCP_ALLOW_ORIGIN.\n */\n allowedOrigins: string[];\n}\n\n/**\n * Resolve the HTTP transport config from env + explicit overrides. Pure: does\n * no I/O and never reads `process` directly. Overrides win over env.\n */\nexport function resolveHttpConfig(env: HttpEnv, options: HttpServerOptions = {}): HttpConfig {\n const host = options.host ?? env.QUANTAKRYPTO_MCP_HOST ?? env.HOST ?? \"127.0.0.1\";\n const port = options.port ?? toInt(env.PORT, 3000);\n const token = (options.token ?? env.QUANTAKRYPTO_MCP_TOKEN ?? \"\").trim();\n const allowFs =\n options.allowFs ??\n (env.QUANTAKRYPTO_MCP_ALLOW_FS === \"1\" || env.QUANTAKRYPTO_MCP_ALLOW_FS === \"true\");\n const allowNetwork =\n options.allowNetwork ??\n (env.QUANTAKRYPTO_MCP_ALLOW_NETWORK === \"1\" || env.QUANTAKRYPTO_MCP_ALLOW_NETWORK === \"true\");\n const timeoutMs = options.timeoutMs ?? toInt(env.QUANTAKRYPTO_MCP_TIMEOUT_MS, DEFAULT_TIMEOUT_MS);\n const maxResponseBytes =\n options.maxResponseBytes ??\n toInt(env.QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES, DEFAULT_MAX_RESPONSE_BYTES);\n const allowedOrigins = parseOriginList(env.QUANTAKRYPTO_MCP_ALLOW_ORIGIN);\n return {\n host,\n port,\n token,\n allowFs,\n allowNetwork,\n timeoutMs,\n maxResponseBytes,\n loopback: isLoopbackHost(host),\n allowedOrigins,\n };\n}\n\n/**\n * Parse the comma-separated origin allow-list into lower-cased hostnames. Each\n * entry may be a bare host or a full origin URL; either way only the hostname is\n * retained (the value compared against `new URL(Origin).hostname`).\n */\nfunction parseOriginList(value: string | undefined): string[] {\n const out = new Set<string>();\n for (const raw of (value ?? \"\").split(\",\")) {\n const entry = raw.trim().toLowerCase();\n if (entry.length === 0) continue;\n try {\n out.add(new URL(entry).hostname);\n } catch {\n out.add(entry); // bare hostname (no scheme).\n }\n }\n return [...out];\n}\n\n/** Parse a positive integer from an env string, falling back on bad input. */\nfunction toInt(value: string | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;\n}\n\n/** True when binding to `host` keeps the server private to this machine. */\nexport function isLoopbackHost(host: string): boolean {\n return LOOPBACK_HOSTS.has(host.trim().toLowerCase());\n}\n\n/**\n * Decide whether a non-loopback bind is permitted. A server reachable from the\n * network MUST require auth; binding wide-open without a token would be an open,\n * unauthenticated arbitrary-tool relay. Pure decision used at startup.\n */\nexport function startupDecision(config: HttpConfig): {\n ok: boolean;\n reason?: string;\n} {\n if (!config.loopback && config.token.length === 0) {\n return {\n ok: false,\n reason:\n `refusing to bind to non-loopback host \"${config.host}\" without a token. ` +\n `Set QUANTAKRYPTO_MCP_TOKEN to require Bearer auth, or bind to 127.0.0.1.`,\n };\n }\n return { ok: true };\n}\n\n/**\n * Decide whether a request's `Origin` / `Host` is acceptable, to defend the\n * default no-token loopback config against DNS-rebinding and localhost-CSRF: a\n * malicious web page can POST to `http://127.0.0.1:<port>/mcp`, but the browser\n * stamps a foreign `Origin` we can reject. Pure and testable.\n *\n * Policy:\n * - No `Origin` header (curl, a native MCP client, same-origin GET) → allow;\n * the header is a browser artifact and absence is not an attack signal here.\n * - An `Origin` present → its host must be a configured loopback host (or a\n * host explicitly added to the allow-list). A foreign origin is rejected.\n * - When the server itself binds a non-loopback interface, a token is already\n * mandatory (see {@link startupDecision}); the loopback allow-list still\n * applies but auth is the primary control there.\n */\nexport function originDecision(\n allowedHosts: ReadonlySet<string>,\n originHeader: string | undefined,\n): { ok: boolean; reason?: string } {\n const origin = (originHeader ?? \"\").trim();\n if (origin.length === 0) return { ok: true }; // non-browser client; nothing to check.\n if (origin.toLowerCase() === \"null\") {\n return { ok: false, reason: \"opaque/null Origin is not allowed\" };\n }\n let host: string;\n try {\n host = new URL(origin).hostname.toLowerCase();\n } catch {\n return { ok: false, reason: \"malformed Origin header\" };\n }\n if (allowedHosts.has(host)) return { ok: true };\n return { ok: false, reason: `Origin host \"${host}\" is not in the allow-list` };\n}\n\n/** The hosts an `Origin` may name. Loopback by default, plus the bind host. */\nexport function allowedOriginHosts(config: HttpConfig): Set<string> {\n const hosts = new Set<string>([\"127.0.0.1\", \"::1\", \"localhost\"]);\n // Allow the interface the server is actually bound to (e.g. a LAN address with\n // a token), so a same-host browser client keeps working.\n hosts.add(config.host.trim().toLowerCase());\n for (const extra of config.allowedOrigins) hosts.add(extra);\n return hosts;\n}\n\n/** A request-authorization outcome. */\ninterface AuthDecision {\n authorized: boolean;\n /** HTTP status to use when not authorized. */\n status?: number;\n message?: string;\n}\n\n/**\n * Decide whether a request is authorized given the configured token and the\n * incoming Authorization header. When no token is configured, all requests are\n * allowed (the loopback / trusted-edge case). Pure and testable.\n */\nexport function authorizeRequest(\n token: string,\n authorizationHeader: string | undefined,\n): AuthDecision {\n if (token.length === 0) return { authorized: true };\n const header = (authorizationHeader ?? \"\").trim();\n const match = /^Bearer\\s+(\\S.*)$/i.exec(header);\n const presented = match?.[1]?.trim();\n if (!presented) {\n return { authorized: false, status: 401, message: \"missing bearer token\" };\n }\n if (!timingSafeEqualStr(presented, token)) {\n return { authorized: false, status: 401, message: \"invalid bearer token\" };\n }\n return { authorized: true };\n}\n\n/**\n * Constant-time string compare. Both inputs are hashed with the same algorithm\n * to fixed-length digests before {@link timingSafeEqual}, so the comparison runs\n * over equal-length buffers and the early length-mismatch return (which leaked\n * the configured token's length) is gone. The hashing is a domain-separation /\n * length-equalization step, not a secrecy measure: `timingSafeEqual` still does\n * the constant-time work and rejects unequal digests.\n */\nexport function timingSafeEqualStr(a: string, b: string): boolean {\n const ha = createHash(\"sha256\").update(a, \"utf8\").digest();\n const hb = createHash(\"sha256\").update(b, \"utf8\").digest();\n // Same algorithm ⇒ identical digest length ⇒ timingSafeEqual never throws.\n return timingSafeEqual(ha, hb);\n}\n\n/**\n * Select the tools to expose over HTTP for a given policy. The knowledge tools\n * are always returned; the filesystem tools are included only when `allowFs` is\n * true, and the networked probe tool only when `allowNetwork` is true (both off by\n * default). Pure function of its inputs — the single source of truth for HTTP tool\n * gating, so tools/list and tools/call stay consistent.\n */\nexport function gateHttpTools(\n tools: readonly ToolDefinition[],\n allowFs: boolean,\n allowNetwork = false,\n): ToolDefinition[] {\n const fsNames = new Set(FS_TOOL_NAMES);\n const networkNames = new Set(NETWORK_TOOL_NAMES);\n return tools.filter(\n (t) =>\n (allowNetwork || !networkNames.has(t.name)) && // networked tools: opt-in on HTTP\n (allowFs || !fsNames.has(t.name)), // fs tools: opt-in on HTTP\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* HTTP plumbing */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Error thrown by {@link readBody} when the request body exceeds the size cap.\n * Distinguished from a transport/I/O error so the caller can map it to HTTP 413\n * specifically, while genuine read failures map to 400/500 (M1).\n */\nexport class BodyTooLargeError extends Error {\n override readonly name = \"BodyTooLargeError\";\n constructor(message = \"request body too large\") {\n super(message);\n }\n}\n\n/**\n * Read a request body fully, enforcing the size cap. Resolves to the raw string.\n * Rejects with a {@link BodyTooLargeError} when the cap is exceeded, and with the\n * original transport error (an I/O failure) otherwise — the two are mapped to\n * different HTTP statuses by the caller (M1).\n */\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0;\n let done = false;\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => {\n if (done) return;\n size += chunk.length;\n if (size > MAX_BODY_BYTES) {\n // Stop consuming and reject. We deliberately do NOT destroy the socket\n // here: the caller still needs to flush a 413 response, so it owns the\n // teardown (resume-and-drain) once that response is written.\n done = true;\n req.pause();\n reject(new BodyTooLargeError());\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => {\n if (!done) resolve(Buffer.concat(chunks).toString(\"utf8\"));\n });\n req.on(\"error\", (err: Error) => {\n if (!done) {\n done = true;\n reject(err);\n }\n });\n });\n}\n\n/** Write a JSON response with the given status and optional extra headers. */\nfunction sendJson(\n res: ServerResponse,\n status: number,\n body: unknown,\n headers: Record<string, string> = {},\n): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(payload).toString(),\n ...headers,\n });\n res.end(payload);\n}\n\n/** Error raised by {@link withTimeout} when the request deadline elapses. */\nclass RequestTimeoutError extends Error {\n override readonly name = \"RequestTimeoutError\";\n constructor(message = \"request timed out\") {\n super(message);\n }\n}\n\n/**\n * Race a handler against a deadline. On timeout the returned promise rejects with\n * a {@link RequestTimeoutError} AND the supplied {@link AbortController} is\n * aborted, so the in-flight work (a `scan()` wired to `controller.signal`) stops\n * cooperatively instead of running unbounded in the background after the 504.\n *\n * The controller is always aborted once the race settles (success, failure, or\n * timeout) so no scan keeps running past its response.\n */\nfunction withTimeout<T>(promise: Promise<T>, ms: number, controller: AbortController): Promise<T> {\n if (!(ms > 0)) return promise;\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n controller.abort(); // cancel the underlying scan — no leaked background work.\n reject(new RequestTimeoutError());\n }, ms);\n timer.unref?.();\n promise.then(\n (value) => {\n clearTimeout(timer);\n controller.abort(); // settle the signal so nothing lingers post-response.\n resolve(value);\n },\n (err: unknown) => {\n clearTimeout(timer);\n controller.abort();\n reject(err instanceof Error ? err : new Error(String(err)));\n },\n );\n });\n}\n\n/**\n * Build (but do not start) the HTTP server wrapping an {@link McpServer}.\n * Exposed for testing and for embedding in a larger process. The `config`\n * carries the resolved auth / timeout / response-cap policy.\n */\nexport function createHttpServer(server: McpServer, config: HttpConfig): Server {\n return createServer((req, res) => {\n void handleRequest(server, config, req, res).catch((err: unknown) => {\n // Last-resort handler: log the detail locally, return a generic message so\n // a remote caller never sees server internals (paths, stack traces).\n logServerError(\"unhandled request error\", err);\n if (!res.headersSent) {\n sendJson(res, 500, makeFailure(null, ErrorCode.InternalError, \"internal error\"));\n } else {\n res.end();\n }\n });\n });\n}\n\n/** Log a server-side error detail to stderr (never sent to the remote caller). */\nfunction logServerError(context: string, err: unknown): void {\n const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);\n process.stderr.write(`quantakrypto MCP (http): ${context}: ${detail}\\n`);\n}\n\n/** Extract the (single) `Origin` request header, if present. */\nfunction originHeader(req: IncomingMessage): string | undefined {\n const value = req.headers.origin;\n return Array.isArray(value) ? value[0] : value;\n}\n\n/** Route and handle a single HTTP request. */\nasync function handleRequest(\n server: McpServer,\n config: HttpConfig,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n const url = req.url ?? \"/\";\n const method = req.method ?? \"GET\";\n const path = url.split(\"?\")[0];\n\n if (method === \"GET\" && path === \"/health\") {\n sendJson(res, 200, { status: \"ok\", server: \"quantakrypto\", transport: \"http\" });\n return;\n }\n\n if (path === \"/mcp\") {\n if (method !== \"POST\") {\n // The full transport also allows GET for an SSE stream; we don't here.\n sendJson(res, 405, makeFailure(null, ErrorCode.InvalidRequest, \"method not allowed\"), {\n allow: \"POST\",\n });\n return;\n }\n // DNS-rebinding / localhost-CSRF guard: reject a foreign browser Origin\n // BEFORE auth/body, so the default no-token loopback config is not a\n // confused deputy for a malicious web page. (P0 — origin validation.)\n const origin = originDecision(allowedOriginHosts(config), originHeader(req));\n if (!origin.ok) {\n sendJson(\n res,\n 403,\n makeFailure(null, ErrorCode.InvalidRequest, origin.reason ?? \"forbidden origin\"),\n );\n return;\n }\n // Authenticate BEFORE reading the body or dispatching (Q-02).\n const auth = authorizeRequest(config.token, req.headers.authorization);\n if (!auth.authorized) {\n sendJson(\n res,\n auth.status ?? 401,\n makeFailure(null, ErrorCode.InvalidRequest, auth.message ?? \"unauthorized\"),\n { \"www-authenticate\": \"Bearer\" },\n );\n return;\n }\n await handleMcpPost(server, config, req, res);\n return;\n }\n\n sendJson(res, 404, makeFailure(null, ErrorCode.MethodNotFound, \"not found\"));\n}\n\n/** Handle `POST /mcp`: parse one JSON-RPC message, dispatch, return the result. */\nasync function handleMcpPost(\n server: McpServer,\n config: HttpConfig,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n // Session handling (stateless here): echo a provided session id, else mint one.\n // A production server would look this up in a session store — see HOSTING.md.\n const incomingSession = req.headers[SESSION_HEADER];\n const sessionId =\n (Array.isArray(incomingSession) ? incomingSession[0] : incomingSession) ?? randomUUID();\n const sessionHeaders = { [SESSION_HEADER]: sessionId };\n\n let raw: string;\n try {\n raw = await readBody(req);\n } catch (err) {\n // M1: only the size-cap rejection is a 413. A genuine transport/I/O error\n // (the client aborted, a socket reset) is a 400 — it is the request that\n // failed, not a server fault — and never echoes the raw error text.\n if (err instanceof BodyTooLargeError) {\n // Flush the 413 first, then tear down the connection so a still-uploading\n // client stops sending. Destroying on `finish` guarantees the response is\n // written before the socket goes away (avoids a connection-reset race).\n res.on(\"finish\", () => req.destroy());\n sendJson(res, 413, makeFailure(null, ErrorCode.InvalidRequest, \"request body too large\"), {\n ...sessionHeaders,\n connection: \"close\",\n });\n } else {\n logServerError(\"error reading request body\", err);\n sendJson(\n res,\n 400,\n makeFailure(null, ErrorCode.InvalidRequest, \"error reading request body\"),\n sessionHeaders,\n );\n }\n return;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n sendJson(res, 400, makeFailure(null, ErrorCode.ParseError, \"parse error\"), sessionHeaders);\n return;\n }\n\n // Cancellation: the controller's signal is threaded into the tool handler (and\n // thus into `scan()`); withTimeout aborts it on deadline so a timed-out\n // request stops the underlying work instead of leaking it (P0 — timeout/abort).\n const controller = new AbortController();\n let response: JsonRpcResponse | null;\n try {\n response = await withTimeout(\n server.handle(parsed, { signal: controller.signal }),\n config.timeoutMs,\n controller,\n );\n } catch (err) {\n if (err instanceof RequestTimeoutError) {\n sendJson(\n res,\n 504,\n makeFailure(null, ErrorCode.InternalError, \"request timed out\"),\n sessionHeaders,\n );\n } else {\n // server.handle never rejects in practice (it catches internally), but be\n // defensive and never leak a raw message.\n logServerError(\"error dispatching request\", err);\n sendJson(\n res,\n 500,\n makeFailure(null, ErrorCode.InternalError, \"internal error\"),\n sessionHeaders,\n );\n }\n return;\n }\n\n if (response === null) {\n // Notification — acknowledge with 202 and no body.\n res.writeHead(202, sessionHeaders);\n res.end();\n return;\n }\n\n // Enforce the response-size cap (Q-03): never stream back an unbounded body.\n const serialized = JSON.stringify(response);\n if (Buffer.byteLength(serialized) > config.maxResponseBytes) {\n sendJson(\n res,\n 500,\n makeFailure(null, ErrorCode.InternalError, \"response too large\"),\n sessionHeaders,\n );\n return;\n }\n sendJson(res, 200, response, sessionHeaders);\n}\n\n/**\n * Build the HTTP-facing {@link McpServer}: the same server used over stdio but\n * with the filesystem tools gated per policy. Exposed for tests.\n */\nexport function createHttpMcpServer(config: HttpConfig): McpServer {\n return createQuantakryptoServer({\n tools: gateHttpTools(quantakryptoTools, config.allowFs, config.allowNetwork),\n });\n}\n\n/** Start the HTTP server, resolving once it is listening. */\nfunction startHttpServer(options: HttpServerOptions = {}): Promise<Server> {\n const config = resolveHttpConfig(process.env, options);\n\n const decision = startupDecision(config);\n if (!decision.ok) {\n return Promise.reject(new Error(decision.reason ?? \"refusing to start\"));\n }\n if (!config.loopback) {\n process.stderr.write(\n `quantakrypto MCP (http): WARNING binding to non-loopback host ${config.host}; ` +\n `Bearer auth is required and active.\\n`,\n );\n }\n\n const mcp = createHttpMcpServer(config);\n const httpServer = createHttpServer(mcp, config);\n return new Promise((resolve) => {\n httpServer.listen(config.port, config.host, () => {\n const auth = config.token ? \"bearer-auth\" : \"no-auth\";\n const fs = config.allowFs ? \"fs-tools:on\" : \"fs-tools:off\";\n const probe = config.allowNetwork ? \"probe:on\" : \"probe:off\";\n process.stderr.write(\n `quantakrypto MCP server (http) listening on http://${config.host}:${config.port} ` +\n `[${auth}, ${fs}, ${probe}]\\n`,\n );\n process.stderr.write(\n ` POST http://${config.host}:${config.port}/mcp ` +\n `GET http://${config.host}:${config.port}/health\\n`,\n );\n resolve(httpServer);\n });\n });\n}\n\n/** Entry point when run directly. */\nfunction main(): void {\n startHttpServer().catch((err: unknown) => {\n const messageText = err instanceof Error ? err.message : String(err);\n process.stderr.write(`quantakrypto MCP (http) failed to start: ${messageText}\\n`);\n process.exitCode = 1;\n });\n}\n\n/** True when this module is the program's entry point (handles symlinks). */\nfunction isMainModule(): boolean {\n const argv1 = process.argv[1];\n if (!argv1) return false;\n const thisPath = fileURLToPath(import.meta.url);\n try {\n return realpathSync(argv1) === realpathSync(thisPath);\n } catch {\n return argv1 === thisPath;\n }\n}\n\n// Only auto-run when invoked as a script, not when imported by tests.\nif (isMainModule()) {\n main();\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type { JsonRpcRequest, JsonRpcResponse, JsonRpcSuccess, JsonRpcFailure, T
|
|
|
16
16
|
/** The MCP server name advertised to clients. */
|
|
17
17
|
export declare const SERVER_NAME = "quantakrypto";
|
|
18
18
|
/** The version reported by the server (kept in sync with @quantakrypto/core). */
|
|
19
|
-
export declare const SERVER_VERSION = "0.
|
|
19
|
+
export declare const SERVER_VERSION = "0.6.0";
|
|
20
20
|
export interface CreateServerOptions {
|
|
21
21
|
/** Override the advertised server version (defaults to @quantakrypto/core VERSION). */
|
|
22
22
|
version?: string;
|
package/dist/tools.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare const NETWORK_TOOL_NAMES: readonly string[];
|
|
|
57
57
|
/** All quantakrypto MCP tools, in a stable order. */
|
|
58
58
|
export declare const quantakryptoTools: ToolDefinition[];
|
|
59
59
|
/** The core version these tools are built against (re-exported for diagnostics). */
|
|
60
|
-
export declare const CORE_VERSION = "0.
|
|
60
|
+
export declare const CORE_VERSION = "0.6.0";
|
|
61
61
|
/** Exposed for tests and advanced callers. */
|
|
62
62
|
export declare const __test: {
|
|
63
63
|
normalizeAlgorithm: typeof normalizeAlgorithm;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quantakrypto/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"mcpName": "io.github.quantakrypto/pqc-tools",
|
|
5
5
|
"description": "quantakrypto MCP — post-quantum readiness for AI coding agents via the Model Context Protocol. Zero runtime dependencies (stdio JSON-RPC implemented in-house).",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@quantakrypto/core": "0.
|
|
43
|
-
"@quantakrypto/qprobe": "0.
|
|
42
|
+
"@quantakrypto/core": "0.6.0",
|
|
43
|
+
"@quantakrypto/qprobe": "0.6.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsc -b",
|