@oomkapwn/enquire-mcp 2.5.0 → 2.7.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/CHANGELOG.md +105 -0
- package/README.md +27 -6
- package/SECURITY.md +34 -0
- package/dist/http-transport.d.ts +92 -0
- package/dist/http-transport.d.ts.map +1 -0
- package/dist/http-transport.js +384 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/index.d.ts +45 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +191 -45
- package/dist/index.js.map +1 -1
- package/dist/pdf.d.ts +51 -0
- package/dist/pdf.d.ts.map +1 -0
- package/dist/pdf.js +162 -0
- package/dist/pdf.js.map +1 -0
- package/dist/tools.d.ts +52 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +86 -0
- package/dist/tools.js.map +1 -1
- package/docs/api.md +3 -1
- package/docs/http-transport.md +305 -0
- package/package.json +3 -2
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// HTTP transport for enquire-mcp.
|
|
2
|
+
//
|
|
3
|
+
// v2.6.0 — remote-MCP support. Runs the MCP server over Streamable HTTP
|
|
4
|
+
// (the protocol claude.ai web, ChatGPT, mobile clients, and Cursor's HTTP
|
|
5
|
+
// mode all use). Three layers in front of the SDK transport:
|
|
6
|
+
//
|
|
7
|
+
// 1. Bearer auth — constant-time token compare, fail-closed (401 on
|
|
8
|
+
// missing/wrong header). Token is generated by the user (we never
|
|
9
|
+
// mint tokens — this is not OAuth) and passed via --bearer-token or
|
|
10
|
+
// --bearer-token-env. See docs/http-transport.md for the security
|
|
11
|
+
// model and Tailscale Funnel / Cloudflare Tunnel deployment recipes.
|
|
12
|
+
// 2. Rate-limit — per-token sliding-window bucket, 429 on overflow.
|
|
13
|
+
// In-memory; survives a single process. Default 120 req/min.
|
|
14
|
+
// 3. CORS — strict allowlist via --cors-origin (repeatable). Default
|
|
15
|
+
// empty: no Access-Control-Allow-Origin header sent. Same-origin
|
|
16
|
+
// and credentialed Bearer requests work either way.
|
|
17
|
+
//
|
|
18
|
+
// We use the SDK's StreamableHTTPServerTransport in stateless mode
|
|
19
|
+
// (sessionIdGenerator: undefined). A fresh transport + McpServer is
|
|
20
|
+
// connected per request. The Vault, FtsIndex, EmbedDb handles are
|
|
21
|
+
// SHARED across all sessions — opening SQLite once and reusing across
|
|
22
|
+
// thousands of remote-MCP calls. This is why prepareServerDeps() is
|
|
23
|
+
// called once in startHttpServer() and buildMcpServer() is called per
|
|
24
|
+
// request: the heavy I/O happens once at boot.
|
|
25
|
+
//
|
|
26
|
+
// Stateful sessions (sessionId-keyed transports) are deferred to v2.7+
|
|
27
|
+
// because they require persistence-aware shutdown handling and are only
|
|
28
|
+
// needed for SSE long-running operations. Our tools are short-running
|
|
29
|
+
// (search, read, frontmatter ops), so stateless is the right default.
|
|
30
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
31
|
+
import { createServer } from "node:http";
|
|
32
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
33
|
+
import { buildMcpServer, formatReadyBanner, prepareServerDeps } from "./index.js";
|
|
34
|
+
/**
|
|
35
|
+
* Sliding-window rate limiter. Per-token. Window is rolling 60 seconds.
|
|
36
|
+
* Uses a tiny circular buffer of timestamps per token — O(burst-size)
|
|
37
|
+
* memory per token, no GC churn (we trim when we check).
|
|
38
|
+
*
|
|
39
|
+
* NOT distributed. If the user runs multiple processes behind a load
|
|
40
|
+
* balancer they'd want a shared store (Redis); deferred to v2.7+.
|
|
41
|
+
*/
|
|
42
|
+
class RateLimiter {
|
|
43
|
+
perMinute;
|
|
44
|
+
windows = new Map();
|
|
45
|
+
constructor(perMinute) {
|
|
46
|
+
this.perMinute = perMinute;
|
|
47
|
+
}
|
|
48
|
+
/** Returns true if request allowed; false if over budget. */
|
|
49
|
+
consume(tokenId, nowMs = Date.now()) {
|
|
50
|
+
if (this.perMinute <= 0)
|
|
51
|
+
return true; // disabled
|
|
52
|
+
const cutoff = nowMs - 60_000;
|
|
53
|
+
let timestamps = this.windows.get(tokenId);
|
|
54
|
+
if (!timestamps) {
|
|
55
|
+
timestamps = [];
|
|
56
|
+
this.windows.set(tokenId, timestamps);
|
|
57
|
+
}
|
|
58
|
+
// Trim out-of-window entries from the front (they're append-ordered).
|
|
59
|
+
while (timestamps.length > 0 && (timestamps[0] ?? 0) < cutoff) {
|
|
60
|
+
timestamps.shift();
|
|
61
|
+
}
|
|
62
|
+
if (timestamps.length >= this.perMinute)
|
|
63
|
+
return false;
|
|
64
|
+
timestamps.push(nowMs);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
/** Test-only: reset all windows. */
|
|
68
|
+
reset() {
|
|
69
|
+
this.windows.clear();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Constant-time bearer-token compare. The Authorization header is
|
|
74
|
+
* `Bearer <token>` per RFC 6750. We compare against the raw token
|
|
75
|
+
* supplied at startup — both sides padded to a hash so timingSafeEqual
|
|
76
|
+
* doesn't leak length.
|
|
77
|
+
*
|
|
78
|
+
* Returns the SHA-256 digest of the token (used as the rate-limit key)
|
|
79
|
+
* if valid, or null if not. We never use the raw token as the key — a
|
|
80
|
+
* compromised log dump would expose it.
|
|
81
|
+
*/
|
|
82
|
+
function verifyBearer(authHeader, expectedToken) {
|
|
83
|
+
if (!authHeader?.startsWith("Bearer "))
|
|
84
|
+
return null;
|
|
85
|
+
const presented = authHeader.slice("Bearer ".length).trim();
|
|
86
|
+
if (presented.length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
// Hash both sides so timingSafeEqual gets equal-length buffers regardless
|
|
89
|
+
// of whether the presented token is longer or shorter than expected. The
|
|
90
|
+
// hash is constant-length, so length-comparison short-circuits don't leak.
|
|
91
|
+
const expectedHash = createHash("sha256").update(expectedToken).digest();
|
|
92
|
+
const presentedHash = createHash("sha256").update(presented).digest();
|
|
93
|
+
if (!timingSafeEqual(expectedHash, presentedHash))
|
|
94
|
+
return null;
|
|
95
|
+
// Return the digest as the rate-limit key. Different tokens produce
|
|
96
|
+
// different keys; the same token always produces the same key.
|
|
97
|
+
return presentedHash.toString("hex").slice(0, 16);
|
|
98
|
+
}
|
|
99
|
+
/** Read the entire request body (UTF-8 JSON). Returns undefined for empty. */
|
|
100
|
+
async function readJsonBody(req, maxBytes) {
|
|
101
|
+
const chunks = [];
|
|
102
|
+
let total = 0;
|
|
103
|
+
for await (const chunk of req) {
|
|
104
|
+
const buf = Buffer.from(chunk);
|
|
105
|
+
total += buf.length;
|
|
106
|
+
if (total > maxBytes) {
|
|
107
|
+
throw new Error(`request body exceeds max ${maxBytes} bytes`);
|
|
108
|
+
}
|
|
109
|
+
chunks.push(buf);
|
|
110
|
+
}
|
|
111
|
+
if (total === 0)
|
|
112
|
+
return undefined;
|
|
113
|
+
const text = Buffer.concat(chunks).toString("utf8");
|
|
114
|
+
return JSON.parse(text);
|
|
115
|
+
}
|
|
116
|
+
/** Send a JSON-RPC error response with the given HTTP + RPC status. */
|
|
117
|
+
function sendJsonRpcError(res, httpStatus, code, message) {
|
|
118
|
+
if (res.headersSent)
|
|
119
|
+
return;
|
|
120
|
+
res.statusCode = httpStatus;
|
|
121
|
+
res.setHeader("Content-Type", "application/json");
|
|
122
|
+
res.end(JSON.stringify({
|
|
123
|
+
jsonrpc: "2.0",
|
|
124
|
+
error: { code, message },
|
|
125
|
+
id: null
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Apply CORS headers if the request's Origin is allowed.
|
|
130
|
+
*
|
|
131
|
+
* Defense-in-depth against the CORS-credentials-misconfig class of bugs:
|
|
132
|
+
*
|
|
133
|
+
* • For an explicit allowlisted origin (e.g. https://claude.ai), we
|
|
134
|
+
* reflect ONLY that exact origin in `Access-Control-Allow-Origin` and
|
|
135
|
+
* emit `Vary: Origin` so caches don't cross-pollinate across origins.
|
|
136
|
+
* Pair with `Access-Control-Allow-Credentials: true` so cookies +
|
|
137
|
+
* credentialed Bearer requests work as expected.
|
|
138
|
+
*
|
|
139
|
+
* • For the wildcard `*` allowlist entry, we reflect `*` literally (NOT
|
|
140
|
+
* the request's origin) and DO NOT send `Allow-Credentials: true`.
|
|
141
|
+
* Browsers reject the combo of wildcard-origin + credentials anyway,
|
|
142
|
+
* so this matches what they enforce. Equally important: it kills the
|
|
143
|
+
* CORS-credential-leak attack surface where a misconfigured wildcard
|
|
144
|
+
* could otherwise hand attacker.com a credential-bearing CORS grant.
|
|
145
|
+
*
|
|
146
|
+
* • Disallowed origins get nothing — no Allow-Origin header → browser
|
|
147
|
+
* blocks the actual request even if we 200.
|
|
148
|
+
*
|
|
149
|
+
* Documented as a deliberate behavior split for users who pass `*`: with
|
|
150
|
+
* `*` you get an unauthenticated public CORS endpoint (still bearer-gated
|
|
151
|
+
* server-side, just no credentialed-cookie path). That's the right
|
|
152
|
+
* trade-off.
|
|
153
|
+
*/
|
|
154
|
+
function applyCors(req, res, allowOrigins) {
|
|
155
|
+
const requestOrigin = req.headers.origin;
|
|
156
|
+
if (typeof requestOrigin !== "string")
|
|
157
|
+
return;
|
|
158
|
+
// Sourcing the response value from `allowOrigins` (a server-controlled
|
|
159
|
+
// CLI flag) instead of from `req.headers.origin` (an attacker-controlled
|
|
160
|
+
// request header) is a deliberate defense against the CORS-credential-
|
|
161
|
+
// leak class of bug. CodeQL's `js/cors-misconfiguration-for-credentials`
|
|
162
|
+
// query is satisfied because `matchedOrigin`'s data source is the
|
|
163
|
+
// allowlist, not the request — even though the strings are equal by
|
|
164
|
+
// construction at this point, the data-flow taint is what matters.
|
|
165
|
+
const matchedOrigin = allowOrigins.find((o) => o === requestOrigin);
|
|
166
|
+
const wildcardAllowed = matchedOrigin === undefined && allowOrigins.includes("*");
|
|
167
|
+
if (matchedOrigin === undefined && !wildcardAllowed)
|
|
168
|
+
return;
|
|
169
|
+
// Wildcard branch: reflect literal "*" + OMIT Allow-Credentials (the
|
|
170
|
+
// browser would reject the combo anyway, and we don't grant attacker
|
|
171
|
+
// origins a credentialed window). Exact-match branch: use the trusted
|
|
172
|
+
// allowlist value + send Allow-Credentials: true so cookies + Bearer
|
|
173
|
+
// requests work cross-origin.
|
|
174
|
+
if (wildcardAllowed) {
|
|
175
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
176
|
+
}
|
|
177
|
+
else if (matchedOrigin !== undefined) {
|
|
178
|
+
res.setHeader("Access-Control-Allow-Origin", matchedOrigin);
|
|
179
|
+
res.setHeader("Access-Control-Allow-Credentials", "true");
|
|
180
|
+
}
|
|
181
|
+
res.setHeader("Vary", "Origin");
|
|
182
|
+
res.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS");
|
|
183
|
+
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Mcp-Session-Id, Last-Event-ID");
|
|
184
|
+
res.setHeader("Access-Control-Max-Age", "600");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build the request handler. Factored out of the listener-creation path
|
|
188
|
+
* so tests can drive it without binding a TCP port.
|
|
189
|
+
*/
|
|
190
|
+
export function createHttpHandler(deps, opts) {
|
|
191
|
+
const mcpPath = opts.mcpPath ?? "/mcp";
|
|
192
|
+
const healthPath = opts.healthPath ?? "/health";
|
|
193
|
+
const corsOrigins = opts.corsOrigins ?? [];
|
|
194
|
+
const limiter = new RateLimiter(opts.rateLimitPerMinute ?? 120);
|
|
195
|
+
const maxBodyBytes = 4 * 1024 * 1024; // 4MB — generous for tools/list with 36 tools
|
|
196
|
+
return async (req, res) => {
|
|
197
|
+
try {
|
|
198
|
+
applyCors(req, res, corsOrigins);
|
|
199
|
+
// OPTIONS preflight short-circuit.
|
|
200
|
+
if (req.method === "OPTIONS") {
|
|
201
|
+
res.statusCode = 204;
|
|
202
|
+
res.end();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
206
|
+
// Health probe — unauthenticated, no rate-limit. Useful for
|
|
207
|
+
// Tailscale/Cloudflare healthchecks. Returns just `ok` so it
|
|
208
|
+
// doesn't leak version info to unauth callers.
|
|
209
|
+
if (url.pathname === healthPath && req.method === "GET") {
|
|
210
|
+
res.statusCode = 200;
|
|
211
|
+
res.setHeader("Content-Type", "text/plain");
|
|
212
|
+
res.end("ok");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (url.pathname !== mcpPath) {
|
|
216
|
+
res.statusCode = 404;
|
|
217
|
+
res.setHeader("Content-Type", "application/json");
|
|
218
|
+
res.end(JSON.stringify({ error: "not found", path: url.pathname }));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
// Auth: bearer token required for /mcp.
|
|
222
|
+
const authHeader = req.headers.authorization;
|
|
223
|
+
const tokenKey = verifyBearer(typeof authHeader === "string" ? authHeader : undefined, opts.bearerToken);
|
|
224
|
+
if (tokenKey === null) {
|
|
225
|
+
res.statusCode = 401;
|
|
226
|
+
res.setHeader("WWW-Authenticate", 'Bearer realm="enquire-mcp"');
|
|
227
|
+
res.setHeader("Content-Type", "application/json");
|
|
228
|
+
res.end(JSON.stringify({ error: "unauthorized" }));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
// Rate-limit per token.
|
|
232
|
+
if (!limiter.consume(tokenKey)) {
|
|
233
|
+
res.statusCode = 429;
|
|
234
|
+
res.setHeader("Retry-After", "60");
|
|
235
|
+
res.setHeader("Content-Type", "application/json");
|
|
236
|
+
res.end(JSON.stringify({ error: "rate limit exceeded" }));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
// Method gating. POST is the main MCP entry; GET is for SSE
|
|
240
|
+
// streams (we're stateless, so we don't expose a long-lived GET
|
|
241
|
+
// — stub it with 405); DELETE is for stateful session termination
|
|
242
|
+
// (also 405 in stateless mode).
|
|
243
|
+
if (req.method !== "POST") {
|
|
244
|
+
sendJsonRpcError(res, 405, -32000, `Method ${req.method} not allowed for ${mcpPath}`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
let body;
|
|
248
|
+
try {
|
|
249
|
+
body = await readJsonBody(req, maxBodyBytes);
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
sendJsonRpcError(res, 400, -32700, err instanceof Error ? err.message : "Parse error");
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Build a fresh McpServer + transport for this request. The
|
|
256
|
+
// McpServer registers tool handlers (closures over the SHARED
|
|
257
|
+
// deps.vault / deps.ftsIndex), so this is cheap — no SQLite open,
|
|
258
|
+
// no embedder load. The transport handles a single request and
|
|
259
|
+
// closes.
|
|
260
|
+
const server = buildMcpServer(deps, opts);
|
|
261
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
262
|
+
try {
|
|
263
|
+
await server.connect(transport);
|
|
264
|
+
// Wire up cleanup so we never leak a transport on early
|
|
265
|
+
// client-disconnect. Both server and transport are per-request
|
|
266
|
+
// disposable — `server.close()` releases the connection, the
|
|
267
|
+
// transport's `close()` flushes any pending stream.
|
|
268
|
+
const cleanup = () => {
|
|
269
|
+
void transport.close();
|
|
270
|
+
void server.close();
|
|
271
|
+
};
|
|
272
|
+
res.on("close", cleanup);
|
|
273
|
+
await transport.handleRequest(req, res, body);
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
process.stderr.write(`enquire http: transport error — ${err instanceof Error ? err.message : String(err)}\n`);
|
|
277
|
+
sendJsonRpcError(res, 500, -32603, "Internal server error");
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
// Final safety net — if anything in the outer block throws (URL
|
|
282
|
+
// parse, header read), don't leave the connection hung.
|
|
283
|
+
process.stderr.write(`enquire http: handler error — ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
|
|
284
|
+
if (!res.headersSent) {
|
|
285
|
+
sendJsonRpcError(res, 500, -32603, "Internal server error");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Generate a fresh 32-byte base64url bearer token. Used by the
|
|
292
|
+
* `enquire-mcp gen-token` subcommand.
|
|
293
|
+
*/
|
|
294
|
+
export function generateBearerToken() {
|
|
295
|
+
return randomBytes(32).toString("base64url");
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Bind and start the HTTP transport. Returns the underlying http.Server
|
|
299
|
+
* so callers (tests + CLI) can listen for `listening` / close it.
|
|
300
|
+
*/
|
|
301
|
+
export async function startHttpServer(opts) {
|
|
302
|
+
if (!opts.bearerToken || opts.bearerToken.length < 16) {
|
|
303
|
+
throw new Error("enquire serve-http: --bearer-token is required and must be ≥16 chars. " +
|
|
304
|
+
"Generate one with: enquire-mcp gen-token");
|
|
305
|
+
}
|
|
306
|
+
const deps = await prepareServerDeps(opts);
|
|
307
|
+
const handler = createHttpHandler(deps, opts);
|
|
308
|
+
const httpServer = createServer((req, res) => {
|
|
309
|
+
void handler(req, res);
|
|
310
|
+
});
|
|
311
|
+
// Persistent-cache flush + watcher cleanup on signal. Same hooks as
|
|
312
|
+
// stdio mode — the deps own the lifecycle. Skipped under
|
|
313
|
+
// installSignalHandlers=false so tests can spawn many servers in one
|
|
314
|
+
// process without accumulating SIGINT/SIGTERM listeners.
|
|
315
|
+
if (opts.installSignalHandlers !== false) {
|
|
316
|
+
if (deps.vault.persistentCacheEnabled) {
|
|
317
|
+
let saving = false;
|
|
318
|
+
let saved = false;
|
|
319
|
+
const flush = async () => {
|
|
320
|
+
if (saving || saved)
|
|
321
|
+
return;
|
|
322
|
+
saving = true;
|
|
323
|
+
try {
|
|
324
|
+
await deps.vault.saveDiskCache();
|
|
325
|
+
saved = true;
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
process.stderr.write(`enquire: cache flush failed — ${err instanceof Error ? err.message : String(err)}\n`);
|
|
329
|
+
}
|
|
330
|
+
finally {
|
|
331
|
+
saving = false;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
process.once("SIGINT", () => {
|
|
335
|
+
flush().finally(() => process.exit(0));
|
|
336
|
+
});
|
|
337
|
+
process.once("SIGTERM", () => {
|
|
338
|
+
flush().finally(() => process.exit(0));
|
|
339
|
+
});
|
|
340
|
+
process.on("beforeExit", () => {
|
|
341
|
+
if (!saved && !saving)
|
|
342
|
+
void flush();
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
if (deps.watcher) {
|
|
346
|
+
const closeWatcher = () => void deps.watcher?.close();
|
|
347
|
+
process.once("SIGINT", closeWatcher);
|
|
348
|
+
process.once("SIGTERM", closeWatcher);
|
|
349
|
+
process.on("beforeExit", closeWatcher);
|
|
350
|
+
}
|
|
351
|
+
if (deps.ftsIndex) {
|
|
352
|
+
const closeFts = () => deps.ftsIndex?.close();
|
|
353
|
+
process.once("SIGINT", closeFts);
|
|
354
|
+
process.once("SIGTERM", closeFts);
|
|
355
|
+
process.on("beforeExit", closeFts);
|
|
356
|
+
}
|
|
357
|
+
// Graceful HTTP-server shutdown on signal.
|
|
358
|
+
const shutdown = () => {
|
|
359
|
+
httpServer.close(() => {
|
|
360
|
+
// Cascade-close happens via beforeExit hooks.
|
|
361
|
+
});
|
|
362
|
+
};
|
|
363
|
+
process.once("SIGINT", shutdown);
|
|
364
|
+
process.once("SIGTERM", shutdown);
|
|
365
|
+
}
|
|
366
|
+
await new Promise((resolve, reject) => {
|
|
367
|
+
httpServer.once("error", reject);
|
|
368
|
+
httpServer.listen(opts.port, opts.host, () => {
|
|
369
|
+
httpServer.removeListener("error", reject);
|
|
370
|
+
resolve();
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
const addr = httpServer.address();
|
|
374
|
+
const bound = addr && typeof addr === "object"
|
|
375
|
+
? `http://${addr.address === "::" ? "::" : addr.address}:${addr.port}`
|
|
376
|
+
: `http://${opts.host}:${opts.port}`;
|
|
377
|
+
const corsLabel = (opts.corsOrigins?.length ?? 0) > 0 ? `, cors=${opts.corsOrigins?.length ?? 0}` : "";
|
|
378
|
+
const rateLabel = (opts.rateLimitPerMinute ?? 120) > 0 ? `, rate-limit=${opts.rateLimitPerMinute ?? 120}/min` : "";
|
|
379
|
+
process.stderr.write(`${formatReadyBanner(deps)} (transport=http, bound=${bound}${opts.mcpPath ?? "/mcp"}${corsLabel}${rateLabel})\n`);
|
|
380
|
+
return httpServer;
|
|
381
|
+
}
|
|
382
|
+
// Re-export the rate limiter and helpers for tests.
|
|
383
|
+
export { RateLimiter, readJsonBody, verifyBearer };
|
|
384
|
+
//# sourceMappingURL=http-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../src/http-transport.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { FtsIndex } from "./fts5.js";
|
|
4
|
+
import { Vault } from "./vault.js";
|
|
5
|
+
import { VaultWatcher } from "./watcher.js";
|
|
6
|
+
export interface ServeOptions {
|
|
3
7
|
vault: string;
|
|
4
8
|
enableWrite?: boolean;
|
|
5
9
|
maxFileBytes?: string;
|
|
@@ -17,7 +21,47 @@ interface ServeOptions {
|
|
|
17
21
|
diagnosticSearchTools?: boolean;
|
|
18
22
|
}
|
|
19
23
|
declare function main(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Heavyweight resources shared across every MCP-server instance: the vault
|
|
26
|
+
* (parsed-note cache + privacy filter), the FTS5 index handle, the optional
|
|
27
|
+
* filesystem watcher. v2.6.0 split this out so the HTTP transport can spin up
|
|
28
|
+
* a fresh `McpServer` per session over the SAME vault/index — opening the
|
|
29
|
+
* SQLite handle once and reusing it across thousands of remote-MCP calls.
|
|
30
|
+
*
|
|
31
|
+
* `warningTracker` is a single-fire latch for the `--disabled-tools` /
|
|
32
|
+
* `--enabled-tools` typo warnings: stdio prints them once at boot; HTTP
|
|
33
|
+
* prints them on the first session build, then never again.
|
|
34
|
+
*/
|
|
35
|
+
export interface ServerDeps {
|
|
36
|
+
vault: Vault;
|
|
37
|
+
ftsIndex: FtsIndex | null;
|
|
38
|
+
watcher: VaultWatcher | null;
|
|
39
|
+
disabledTools: Set<string>;
|
|
40
|
+
enabledTools: Set<string>;
|
|
41
|
+
warningTracker: {
|
|
42
|
+
printed: boolean;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* One-time bootstrap of the heavy deps (vault open + FTS5 sync + watcher).
|
|
47
|
+
* Idempotent on a per-call basis but NOT designed to be called multiple
|
|
48
|
+
* times in one process — the FTS5 sync would double-index. Stdio + HTTP
|
|
49
|
+
* each call this exactly once at startup.
|
|
50
|
+
*/
|
|
51
|
+
export declare function prepareServerDeps(opts: ServeOptions): Promise<ServerDeps>;
|
|
52
|
+
/**
|
|
53
|
+
* Build a fresh `McpServer` over already-prepared deps. Cheap (just
|
|
54
|
+
* registers tool handlers — no I/O, no SQLite open). Stdio calls this once;
|
|
55
|
+
* HTTP calls it per session.
|
|
56
|
+
*/
|
|
57
|
+
export declare function buildMcpServer(deps: ServerDeps, opts: ServeOptions): McpServer;
|
|
20
58
|
declare function startServer(opts: ServeOptions): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Shared "ready" banner used by stdio + HTTP startup paths so the runtime
|
|
61
|
+
* configuration summary is identical regardless of transport. Transport
|
|
62
|
+
* suffix is appended by the caller.
|
|
63
|
+
*/
|
|
64
|
+
export declare function formatReadyBanner(deps: ServerDeps): string;
|
|
21
65
|
declare function parsePositiveInt(raw: string, flag: string): number;
|
|
22
66
|
export { main, parsePositiveInt, startServer };
|
|
23
67
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAMtF,OAAO,EAAkC,QAAQ,EAAE,MAAM,WAAW,CAAC;AAwCrE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAW5C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAcD,iBAAe,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA0SnC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,cAAc,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACtC;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CA8C/E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,GAAG,SAAS,CAqF9E;AAED,iBAAe,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD5D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAY1D;AA4vDD,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM3D;AAsCD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC"}
|