@quantakrypto/mcp 0.1.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/HOSTING.md ADDED
@@ -0,0 +1,184 @@
1
+ # Hosting quantakrypto MCP as a remote service
2
+
3
+ This document describes how to run `@quantakrypto/mcp` as a hosted, multi-tenant
4
+ service rather than a per-user local stdio process. The shipped `src/http.ts` is
5
+ the minimal, working core of this design; everything below is the path from that
6
+ scaffold to production.
7
+
8
+ ## 0. Safe-by-default posture (what `src/http.ts` enforces today)
9
+
10
+ The stdio transport trusts the local user and is fully featured. The HTTP
11
+ transport is **hardened by default** (P0-1 / security-audit Q-01–Q-03) because a
12
+ hosted endpoint is reachable by untrusted peers. Out of the box `node dist/http.js`:
13
+
14
+ - **Binds to `127.0.0.1`**, not `0.0.0.0`. Override with `QUANTAKRYPTO_MCP_HOST`.
15
+ Binding to a **non-loopback host without a token is refused at startup** — an
16
+ unauthenticated, network-reachable tool server would be an open relay into the
17
+ arbitrary-file-read tools.
18
+ - **Requires Bearer auth when `QUANTAKRYPTO_MCP_TOKEN` is set.** Every `/mcp` request
19
+ must carry `Authorization: Bearer <token>`; auth is checked *before* the body
20
+ is read or dispatched. Missing/invalid token → `401` with `WWW-Authenticate: Bearer`.
21
+ `GET /health` is unauthenticated.
22
+ - **Gates the filesystem tools off by default.** `scan_path`, `inventory_crypto`
23
+ and `generate_cbom` take a client-supplied path straight into `core.scan` and
24
+ would otherwise be an arbitrary-directory reader (`/etc`, `/root/.ssh`, …) with
25
+ matched-line snippets echoed back. Over HTTP they are registered **only when
26
+ `QUANTAKRYPTO_MCP_ALLOW_FS=1`**, so both `tools/list` and `tools/call` reflect the
27
+ gate. The knowledge tools (`explain_finding`, `suggest_hybrid`, `list_rules`)
28
+ are pure and always exposed. The gating is a pure function (`gateHttpTools`),
29
+ unit-tested in `test/http.test.ts`.
30
+ - **Bounds each request.** A 1 MiB request-body cap (always), a per-request tool
31
+ timeout (`QUANTAKRYPTO_MCP_TIMEOUT_MS`, default 30 s → `504`) and a response-size cap
32
+ (`QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES`, default 4 MiB → `500`).
33
+
34
+ | Env var | Default | Purpose |
35
+ | --- | --- | --- |
36
+ | `QUANTAKRYPTO_MCP_HOST` (or `HOST`) | `127.0.0.1` | Bind interface. Non-loopback **requires** a token. |
37
+ | `PORT` | `3000` | Listen port. |
38
+ | `QUANTAKRYPTO_MCP_TOKEN` | _(unset)_ | When set, requires `Authorization: Bearer <token>`. |
39
+ | `QUANTAKRYPTO_MCP_ALLOW_FS` | _(off)_ | `1`/`true` exposes the filesystem tools over HTTP. |
40
+ | `QUANTAKRYPTO_MCP_TIMEOUT_MS` | `30000` | Per-request tool-execution deadline. |
41
+ | `QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES` | `4194304` | Response-body size cap. |
42
+
43
+ **Design choice — refuse vs. warn on a wide-open bind.** Binding to a
44
+ non-loopback host with `QUANTAKRYPTO_MCP_TOKEN` unset is **refused** (startup fails)
45
+ rather than merely warned, because the failure mode is severe and silent (an
46
+ internet-reachable arbitrary-tool endpoint). A non-loopback bind *with* a token
47
+ is allowed but emits a hard `WARNING` to stderr. Even then, the recommendation
48
+ remains to terminate TLS and validate keys at a gateway (§3) and to leave the
49
+ filesystem tools off unless the path surface is sandboxed (§3.1 of the security
50
+ audit). The sections below describe the remaining production hardening.
51
+
52
+ ## 1. Transport choice
53
+
54
+ MCP defines two transports:
55
+
56
+ - **stdio** — newline-delimited JSON over a child process's stdin/stdout. Ideal
57
+ for *local* agents (Claude Desktop/Code spawns the bin). Not hostable: one
58
+ process per client, no network surface.
59
+ - **Streamable HTTP** — JSON-RPC over HTTP. A client `POST`s a JSON-RPC message
60
+ to a single endpoint (`/mcp`) and either gets a JSON response back, or upgrades
61
+ to an SSE (`text/event-stream`) stream for server-initiated messages.
62
+
63
+ **For hosting, use Streamable HTTP.** Our `http.ts` implements the JSON
64
+ request/response half (sufficient for stateless tool calls). To fully conform,
65
+ add:
66
+
67
+ - **SSE responses**: when a client sends `Accept: text/event-stream`, reply with
68
+ an event stream so the server can push notifications/progress. quantakrypto's tools
69
+ are currently synchronous request/response, so this is optional until we add
70
+ long-running scans with progress events.
71
+ - **`GET /mcp`**: opens a standalone SSE stream for server→client messages.
72
+
73
+ ```
74
+ ┌────────────┐ POST /mcp (JSON-RPC) ┌──────────────────┐
75
+ MCP │ │ ───────────────────────► │ HTTP transport │
76
+ client ◄──┤ client │ │ (src/http.ts) │
77
+ │ │ ◄─── 200 JSON / SSE ───── │ │
78
+ └────────────┘ └────────┬─────────┘
79
+ │ handle()
80
+ ┌────────▼─────────┐
81
+ │ McpServer │
82
+ │ (src/server.ts) │
83
+ └────────┬─────────┘
84
+ │ tools
85
+ ┌────────▼─────────┐
86
+ │ @quantakrypto/core │
87
+ └──────────────────┘
88
+ ```
89
+
90
+ ## 2. Multi-tenant sessions
91
+
92
+ The MCP Streamable HTTP transport uses an **`Mcp-Session-Id`** header. Our
93
+ scaffold echoes a provided id or mints one with `randomUUID()`, but keeps **no
94
+ state** (every request is independent). For production:
95
+
96
+ 1. On `initialize`, mint a session id, create a `Session` record, and return the
97
+ id in the `Mcp-Session-Id` response header.
98
+ 2. Require that header on every subsequent request; reject unknown/expired
99
+ sessions with `404` (so clients re-`initialize`).
100
+ 3. Store per-session state in a shared store (Redis / Postgres), **not** process
101
+ memory, so any instance behind a load balancer can serve any session:
102
+ - tenant/identity, negotiated protocol version, capabilities;
103
+ - rate-limit counters, usage metering;
104
+ - any in-flight long-running scan handles.
105
+ 4. Expire idle sessions (TTL) and support explicit teardown
106
+ (`DELETE /mcp` with the session header).
107
+
108
+ Keep the `McpServer` instance **stateless and shared** across sessions — it
109
+ already is (the only mutable field is an informational `initialized` flag, which
110
+ should move into the session record once sessions exist).
111
+
112
+ ## 3. Authentication & API keys
113
+
114
+ stdio trusts the local user; a hosted endpoint must not.
115
+
116
+ - **API keys / bearer tokens.** Require `Authorization: Bearer <token>` on
117
+ `/mcp`. Validate before `readBody`/dispatch. Map the key → tenant for metering
118
+ and quotas. This is the natural place to gate access in `handleMcpPost`.
119
+ - **OAuth 2.1.** The MCP spec defines an OAuth flow for HTTP transports
120
+ (Protected Resource Metadata + Authorization Server). For first-party clients,
121
+ scoped API keys are simpler; add OAuth when third-party clients must connect on
122
+ a user's behalf.
123
+ - **mTLS / network policy.** For internal/enterprise deployments, terminate mTLS
124
+ at the gateway and keep `/mcp` private.
125
+ - Never log request bodies that may contain source code; treat scanned content
126
+ as sensitive.
127
+
128
+ ## 4. Rate limiting & quotas
129
+
130
+ - **Per-key token bucket** at the edge (gateway) and a backstop in-process limit.
131
+ Scans are CPU- and I/O-bound, so limit by *concurrent scans* per tenant, not
132
+ just request rate.
133
+ - **Body size cap** — already enforced (`MAX_BODY_BYTES`, 1 MiB). Make it
134
+ configurable and tenant-tiered.
135
+ - **Per-call timeouts** for tool execution; return an `isError` tool result on
136
+ timeout rather than hanging the connection.
137
+ - **Cost metering** keyed by session/tenant for billing and abuse detection.
138
+
139
+ ## 5. Scaling
140
+
141
+ - **Stateless app tier.** With sessions in a shared store, run N replicas behind
142
+ an L7 load balancer; no sticky sessions needed for request/response. *Sticky
143
+ routing is required only for long-lived SSE streams* — pin those to the
144
+ instance that owns the stream, or use a pub/sub fan-out (Redis) so any instance
145
+ can deliver server→client events.
146
+ - **Horizontal autoscale** on CPU (scans are CPU-heavy). Consider offloading
147
+ large scans to a worker queue and returning progress over SSE.
148
+ - **Caching.** Cache `tools/list`, `list_rules`, and remediation lookups (static
149
+ per core version). Optionally cache scan results keyed by a content hash.
150
+ - **Health & readiness.** `GET /health` exists; add a readiness probe that checks
151
+ the session store and a liveness probe that excludes it.
152
+ - **Observability.** Structured logs (never bodies), per-method latency/error
153
+ metrics, and tracing across HTTP → `McpServer.handle` → core.
154
+
155
+ ## 6. What runs server-side vs. in core
156
+
157
+ | Concern | Where |
158
+ | --- | --- |
159
+ | HTTP framing, sessions, auth, rate limiting, metering | **HTTP transport / gateway** (`src/http.ts` + infra) |
160
+ | JSON-RPC 2.0 dispatch, MCP methods, error mapping | **`McpServer`** (`src/server.ts`) — pure, reused by every transport |
161
+ | Tool schemas, argument validation, result shaping | **Tools** (`src/tools.ts`) |
162
+ | Crypto detection, inventory, remediation knowledge | **`@quantakrypto/core`** — the single source of truth; transports never reimplement detection logic |
163
+
164
+ The guiding principle: **transports do I/O and policy; `McpServer` does protocol;
165
+ `@quantakrypto/core` does cryptographic analysis.** Hosting adds an HTTP/edge layer
166
+ around the exact same `McpServer` used over stdio, so behaviour is identical
167
+ whether quantakrypto runs locally or as a service.
168
+
169
+ ## 7. Minimal deployment example
170
+
171
+ ```bash
172
+ # Container entrypoint. A non-loopback bind REQUIRES a token (else startup is
173
+ # refused). Leave QUANTAKRYPTO_MCP_ALLOW_FS unset to keep the filesystem tools off.
174
+ PORT=8080 \
175
+ QUANTAKRYPTO_MCP_HOST=0.0.0.0 \
176
+ QUANTAKRYPTO_MCP_TOKEN="$(cat /run/secrets/quantakrypto_mcp_token)" \
177
+ node dist/http.js
178
+ ```
179
+
180
+ Put it behind a gateway that terminates TLS, validates API keys, applies rate
181
+ limits, and forwards to `/mcp`. Run ≥2 replicas with a shared session store and a
182
+ health check on `/health`. The built-in Bearer check is a backstop; the gateway
183
+ should remain the primary auth boundary. Enable `QUANTAKRYPTO_MCP_ALLOW_FS=1` only when
184
+ the scanned path surface is sandboxed (e.g. a read-only, dedicated mount).
package/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # @quantakrypto/mcp
2
+
3
+ A **Model Context Protocol (MCP) server** that gives AI coding agents post-quantum
4
+ readiness superpowers. It scans code for classical (quantum-vulnerable) asymmetric
5
+ cryptography and recommends NIST post-quantum / hybrid migrations, all backed by
6
+ [`@quantakrypto/core`](../core).
7
+
8
+ - **Zero runtime dependencies.** The MCP / JSON-RPC 2.0 protocol is implemented
9
+ from scratch on Node built-ins (`node:readline`, `node:http`, `node:process`).
10
+ The only dependency is `@quantakrypto/core`.
11
+ - **Two transports.** A `stdio` transport (the `quantakrypto-mcp` bin) for local agents
12
+ like Claude, and a hostable `http` transport for running quantakrypto as a remote
13
+ service (see [HOSTING.md](./HOSTING.md)).
14
+ - **Transport-agnostic core.** All protocol logic lives in a pure, unit-tested
15
+ `McpServer` class; transports only do I/O.
16
+
17
+ ## Install / register with an MCP client
18
+
19
+ The published package exposes a `quantakrypto-mcp` binary that speaks MCP over stdio:
20
+
21
+ ```bash
22
+ # Claude Code / Claude Desktop
23
+ claude mcp add quantakrypto npx @quantakrypto/mcp
24
+ ```
25
+
26
+ Equivalently, in an MCP client config:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "quantakrypto": {
32
+ "command": "npx",
33
+ "args": ["@quantakrypto/mcp"]
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ The bin is `quantakrypto-mcp` (→ `dist/stdio.js`). You can also run it directly:
40
+
41
+ ```bash
42
+ node dist/stdio.js
43
+ ```
44
+
45
+ ## Protocol
46
+
47
+ MCP **stdio transport** is newline-delimited JSON: exactly one JSON-RPC 2.0
48
+ message per line on stdin/stdout (this is *not* HTTP-style `Content-Length`
49
+ framing). Supported methods:
50
+
51
+ | Method | Notes |
52
+ | --- | --- |
53
+ | `initialize` | Replies with `protocolVersion`, `capabilities.tools.listChanged = false`, and `serverInfo { name: "quantakrypto", version }`. |
54
+ | `notifications/initialized` | Notification; no response. |
55
+ | `ping` | Replies `{}`. |
56
+ | `tools/list` | Lists all tools with JSON-Schema `inputSchema`. |
57
+ | `tools/call` | Runs a tool, returns `{ content: [...], isError? }`. |
58
+
59
+ Unknown methods return JSON-RPC error `-32601`; bad params return `-32602`;
60
+ unparseable input returns `-32700`; non-request objects return `-32600`.
61
+
62
+ ## Tools
63
+
64
+ Each tool returns MCP content: `{ content: [{ type: "text", text }], isError? }`.
65
+
66
+ ### `scan_path`
67
+
68
+ Scan a file or directory for quantum-vulnerable cryptography.
69
+
70
+ ```json
71
+ {
72
+ "type": "object",
73
+ "properties": {
74
+ "path": { "type": "string", "description": "Path to scan." },
75
+ "format": { "type": "string", "enum": ["summary", "json"] }
76
+ },
77
+ "required": ["path"]
78
+ }
79
+ ```
80
+
81
+ Returns a readiness summary (or the raw `ScanResult` JSON when `format: "json"`).
82
+
83
+ ### `inventory_crypto`
84
+
85
+ Produce a 0–100 readiness score plus counts by algorithm, category, and severity.
86
+
87
+ ```json
88
+ {
89
+ "type": "object",
90
+ "properties": { "path": { "type": "string" } },
91
+ "required": ["path"]
92
+ }
93
+ ```
94
+
95
+ ### `explain_finding`
96
+
97
+ Explain a finding and its remediation. Provide a `ruleId`, an `algorithm`, or both.
98
+
99
+ ```json
100
+ {
101
+ "type": "object",
102
+ "properties": {
103
+ "ruleId": { "type": "string" },
104
+ "algorithm": { "type": "string", "description": "RSA, ECDH, ECDSA, …" }
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### `suggest_hybrid`
110
+
111
+ Recommend a PQC / hybrid migration from an `algorithm` or free-text `context`.
112
+
113
+ ```json
114
+ {
115
+ "type": "object",
116
+ "properties": {
117
+ "algorithm": { "type": "string" },
118
+ "context": { "type": "string" }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### `list_rules`
124
+
125
+ List the quantakrypto detector catalog (ids + descriptions). No input.
126
+
127
+ ```json
128
+ { "type": "object", "properties": {} }
129
+ ```
130
+
131
+ ### `generate_cbom`
132
+
133
+ Scan a path and emit a **CycloneDX 1.6 Cryptographic Bill of Materials (CBOM)**
134
+ of the classical cryptographic assets found, for compliance / supply-chain
135
+ tooling. Reads the filesystem, so it is gated like `scan_path` over HTTP.
136
+
137
+ ```json
138
+ {
139
+ "type": "object",
140
+ "properties": { "path": { "type": "string" } },
141
+ "required": ["path"]
142
+ }
143
+ ```
144
+
145
+ ## Hosted HTTP server (safe-by-default)
146
+
147
+ The same `McpServer` can be served over HTTP (a Streamable-HTTP-style JSON-RPC
148
+ endpoint) for remote deployments. The stdio transport trusts the local user and
149
+ is fully featured; the **HTTP transport is hardened**, because a hosted endpoint
150
+ is reachable by untrusted peers:
151
+
152
+ - **Binds to `127.0.0.1` by default** (not `0.0.0.0`). Override via
153
+ `QUANTAKRYPTO_MCP_HOST`. Binding to a non-loopback host **without a token is refused
154
+ at startup** (it would be an open, unauthenticated tool relay).
155
+ - **Bearer-token auth.** Set `QUANTAKRYPTO_MCP_TOKEN` and every `/mcp` request must
156
+ send `Authorization: Bearer <token>`, else `401`. With no token set, only the
157
+ loopback bind is allowed.
158
+ - **Filesystem tools are disabled by default.** `scan_path`, `inventory_crypto`
159
+ and `generate_cbom` read arbitrary server paths, so over HTTP they are exposed
160
+ only when `QUANTAKRYPTO_MCP_ALLOW_FS=1`. The knowledge tools (`explain_finding`,
161
+ `suggest_hybrid`, `list_rules`) are always available. `tools/list` and
162
+ `tools/call` both reflect the gating.
163
+ - **Limits.** A 1 MiB request-body cap (always), a per-request tool timeout
164
+ (`QUANTAKRYPTO_MCP_TIMEOUT_MS`, default 30000 → `504` on timeout) and a response-size
165
+ cap (`QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES`, default 4 MiB).
166
+
167
+ | Env var | Default | Purpose |
168
+ | --- | --- | --- |
169
+ | `QUANTAKRYPTO_MCP_HOST` (or `HOST`) | `127.0.0.1` | Bind interface. Non-loopback requires a token. |
170
+ | `PORT` | `3000` | Listen port. |
171
+ | `QUANTAKRYPTO_MCP_TOKEN` | _(unset)_ | When set, requires `Authorization: Bearer <token>`. |
172
+ | `QUANTAKRYPTO_MCP_ALLOW_FS` | _(off)_ | `1`/`true` exposes the filesystem tools over HTTP. |
173
+ | `QUANTAKRYPTO_MCP_TIMEOUT_MS` | `30000` | Per-request tool-execution deadline. |
174
+ | `QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES` | `4194304` | Response-body size cap. |
175
+
176
+ ```bash
177
+ # Local, knowledge tools only (default safe posture)
178
+ node dist/http.js
179
+
180
+ # Local with the filesystem tools enabled
181
+ QUANTAKRYPTO_MCP_ALLOW_FS=1 node dist/http.js
182
+
183
+ # Reachable from the network: a token is mandatory
184
+ QUANTAKRYPTO_MCP_HOST=0.0.0.0 QUANTAKRYPTO_MCP_TOKEN="$(openssl rand -hex 32)" node dist/http.js
185
+ ```
186
+
187
+ Endpoints:
188
+
189
+ - `POST /mcp` — one JSON-RPC 2.0 message; the JSON-RPC response is the
190
+ `application/json` body. Notifications get `202` with no body. An
191
+ `mcp-session-id` header is echoed or minted on each request.
192
+ - `GET /health` — liveness probe returning `{ "status": "ok" }` (no auth).
193
+
194
+ ```bash
195
+ curl -s localhost:3000/health
196
+ curl -s localhost:3000/mcp \
197
+ -H 'content-type: application/json' \
198
+ -H 'authorization: Bearer YOUR_TOKEN' \
199
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
200
+ ```
201
+
202
+ See [HOSTING.md](./HOSTING.md) for the full production design (auth, multi-tenant
203
+ sessions, rate limiting, scaling). A sample request/response transcript lives in
204
+ [`examples/transcript.jsonl`](./examples/transcript.jsonl).
205
+
206
+ ## Programmatic use
207
+
208
+ ```ts
209
+ import { createQuantakryptoServer } from "@quantakrypto/mcp";
210
+
211
+ const server = createQuantakryptoServer();
212
+ const res = await server.handle({ jsonrpc: "2.0", id: 1, method: "tools/list" });
213
+ ```
214
+
215
+ ## Development
216
+
217
+ ```bash
218
+ npm run build # tsc -b
219
+ npm test # node --import tsx --test test/*.test.ts
220
+ ```
221
+
222
+ Tests drive `McpServer.handle` directly (and the stdio loop via in-memory
223
+ streams) — no process spawning.
224
+
225
+ ## License
226
+
227
+ Apache-2.0
package/dist/http.d.ts ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * quantakrypto MCP — hostable HTTP transport (Streamable-HTTP-style JSON-RPC).
4
+ *
5
+ * A zero-dependency {@link node:http} server that exposes the same
6
+ * {@link McpServer} over HTTP so the quantakrypto MCP can run as a remote service:
7
+ *
8
+ * POST /mcp — body is a single JSON-RPC 2.0 message; the JSON-RPC
9
+ * response is returned as the 200 response body
10
+ * (`application/json`). Notifications get HTTP 202 with no body.
11
+ * GET /health — liveness probe, returns `{ status: "ok", ... }`.
12
+ *
13
+ * This is the minimal-but-working core of the MCP Streamable HTTP transport.
14
+ * The full spec also supports an SSE response (`text/event-stream`) for
15
+ * server-initiated messages; this server speaks the JSON request/response half,
16
+ * which is sufficient for stateless tool calls. See HOSTING.md for the
17
+ * production design (auth, multi-tenant sessions, rate limiting, scaling).
18
+ *
19
+ * SAFE-BY-DEFAULT POSTURE (P0-1). Unlike the stdio transport — which trusts the
20
+ * local user and stays fully featured — the HTTP transport is hardened because a
21
+ * hosted endpoint is reachable by untrusted peers:
22
+ *
23
+ * - Binds to 127.0.0.1 by default (NOT 0.0.0.0). Override with QUANTAKRYPTO_MCP_HOST.
24
+ * - Bearer-token auth: when QUANTAKRYPTO_MCP_TOKEN is set, every /mcp request must
25
+ * send `Authorization: Bearer <token>` (else 401). Binding to a non-loopback
26
+ * host WITHOUT a token is refused at startup (it would be an open relay).
27
+ * - The filesystem tools (scan_path, inventory_crypto, generate_cbom) read
28
+ * arbitrary server paths and are DISABLED over HTTP unless QUANTAKRYPTO_MCP_ALLOW_FS=1
29
+ * (security audit Q-01). The knowledge tools (explain_finding, suggest_hybrid,
30
+ * list_rules) are always available. Gating is enforced by registering only the
31
+ * permitted tools, so tools/list and tools/call both reflect it.
32
+ * - Per-request timeout (QUANTAKRYPTO_MCP_TIMEOUT_MS) and a response-size cap
33
+ * (QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES), in addition to the 1 MiB request-body cap.
34
+ *
35
+ * Run with `node dist/http.js` (PORT/QUANTAKRYPTO_MCP_* from env).
36
+ */
37
+ import type { Server } from "node:http";
38
+ import type { ToolDefinition } from "./protocol.js";
39
+ import type { McpServer } from "./server.js";
40
+ /** Header carrying the MCP session id (per the Streamable HTTP transport). */
41
+ export declare const SESSION_HEADER = "mcp-session-id";
42
+ export interface HttpServerOptions {
43
+ /** Port to listen on. Defaults to env PORT or 3000. */
44
+ port?: number;
45
+ /** Host/interface to bind. Defaults to QUANTAKRYPTO_MCP_HOST / HOST or "127.0.0.1". */
46
+ host?: string;
47
+ /** Bearer token required on /mcp. Defaults to QUANTAKRYPTO_MCP_TOKEN (empty = none). */
48
+ token?: string;
49
+ /** Expose the filesystem tools over HTTP. Defaults to QUANTAKRYPTO_MCP_ALLOW_FS=1. */
50
+ allowFs?: boolean;
51
+ /** Per-request tool-execution timeout (ms). Defaults to QUANTAKRYPTO_MCP_TIMEOUT_MS. */
52
+ timeoutMs?: number;
53
+ /** Response-body size cap (bytes). Defaults to QUANTAKRYPTO_MCP_MAX_RESPONSE_BYTES. */
54
+ maxResponseBytes?: number;
55
+ }
56
+ /** A minimal env shape so the config resolver is pure and testable. */
57
+ export type HttpEnv = Record<string, string | undefined>;
58
+ /** Resolved, validated HTTP transport configuration. */
59
+ export interface HttpConfig {
60
+ host: string;
61
+ port: number;
62
+ /** The bearer token, or "" when auth is disabled. */
63
+ token: string;
64
+ /** Whether the filesystem tools are exposed over HTTP. */
65
+ allowFs: boolean;
66
+ timeoutMs: number;
67
+ maxResponseBytes: number;
68
+ /** True when the host is a loopback interface (safe without auth). */
69
+ loopback: boolean;
70
+ }
71
+ /**
72
+ * Resolve the HTTP transport config from env + explicit overrides. Pure: does
73
+ * no I/O and never reads `process` directly. Overrides win over env.
74
+ */
75
+ export declare function resolveHttpConfig(env: HttpEnv, options?: HttpServerOptions): HttpConfig;
76
+ /** True when binding to `host` keeps the server private to this machine. */
77
+ export declare function isLoopbackHost(host: string): boolean;
78
+ /**
79
+ * Decide whether a non-loopback bind is permitted. A server reachable from the
80
+ * network MUST require auth; binding wide-open without a token would be an open,
81
+ * unauthenticated arbitrary-tool relay. Pure decision used at startup.
82
+ */
83
+ export declare function startupDecision(config: HttpConfig): {
84
+ ok: boolean;
85
+ reason?: string;
86
+ };
87
+ /** A request-authorization outcome. */
88
+ export interface AuthDecision {
89
+ authorized: boolean;
90
+ /** HTTP status to use when not authorized. */
91
+ status?: number;
92
+ message?: string;
93
+ }
94
+ /**
95
+ * Decide whether a request is authorized given the configured token and the
96
+ * incoming Authorization header. When no token is configured, all requests are
97
+ * allowed (the loopback / trusted-edge case). Pure and testable.
98
+ */
99
+ export declare function authorizeRequest(token: string, authorizationHeader: string | undefined): AuthDecision;
100
+ /**
101
+ * Select the tools to expose over HTTP for a given policy. The knowledge tools
102
+ * are always returned; the filesystem tools are included only when
103
+ * `allowFs` is true. Pure function of its inputs — the single source of truth
104
+ * for HTTP tool gating, so tools/list and tools/call stay consistent.
105
+ */
106
+ export declare function gateHttpTools(tools: readonly ToolDefinition[], allowFs: boolean): ToolDefinition[];
107
+ /**
108
+ * Build (but do not start) the HTTP server wrapping an {@link McpServer}.
109
+ * Exposed for testing and for embedding in a larger process. The `config`
110
+ * carries the resolved auth / timeout / response-cap policy.
111
+ */
112
+ export declare function createHttpServer(server: McpServer, config: HttpConfig): Server;
113
+ /**
114
+ * Build the HTTP-facing {@link McpServer}: the same server used over stdio but
115
+ * with the filesystem tools gated per policy. Exposed for tests.
116
+ */
117
+ export declare function createHttpMcpServer(config: HttpConfig): McpServer;
118
+ /** Start the HTTP server, resolving once it is listening. */
119
+ export declare function startHttpServer(options?: HttpServerOptions): Promise<Server>;
120
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAmB,MAAM,EAAkB,MAAM,WAAW,CAAC;AAQzE,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,eAAe,CAAC;AAErE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,8EAA8E;AAC9E,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAc/C,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD,uEAAuE;AACvE,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEzD,wDAAwD;AACxD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAoB3F;AASD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG;IACnD,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAUA;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,mBAAmB,EAAE,MAAM,GAAG,SAAS,GACtC,YAAY,CAYd;AAUD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,EAAE,OAAO,GACf,cAAc,EAAE,CAGlB;AA4DD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAW9E;AAyGD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAEjE;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+BhF"}