db-mcp 3.0.2 → 5.0.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/README.md +112 -75
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/database-adapter.d.ts +11 -1
- package/dist/adapters/database-adapter.d.ts.map +1 -1
- package/dist/adapters/registration/resources.d.ts.map +1 -1
- package/dist/adapters/registration/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -1
- package/dist/adapters/sqlite/query-executor.d.ts.map +1 -1
- package/dist/adapters/sqlite/read-write-lock.d.ts +49 -0
- package/dist/adapters/sqlite/read-write-lock.d.ts.map +1 -0
- package/dist/adapters/sqlite/resources.d.ts +1 -1
- package/dist/adapters/sqlite/resources.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/admin.d.ts +33 -19
- package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/core.d.ts +96 -0
- package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/fts.d.ts +4 -0
- package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/introspection.d.ts +25 -15
- package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/migration.d.ts +2 -2
- package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/spatialite.d.ts +1 -0
- package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/text.d.ts +36 -0
- package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -1
- package/dist/adapters/sqlite/sqlite-adapter.d.ts +6 -0
- package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts +0 -4
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/versioning.d.ts +19 -0
- package/dist/adapters/sqlite/tools/core/versioning.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/helpers.d.ts +9 -0
- package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/search.d.ts +4 -0
- package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -1
- package/dist/adapters/sqlite/types.d.ts +5 -1
- package/dist/adapters/sqlite/types.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/index.d.ts +1 -1
- package/dist/adapters/sqlite-native/index.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/tools/window/helpers.d.ts +52 -0
- package/dist/adapters/sqlite-native/tools/window/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/index.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/index.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/ntile.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/ntile.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/rank.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/rank.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/row-number.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/row-number.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/running-total.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/running-total.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/schemas.d.ts +159 -0
- package/dist/adapters/sqlite-native/tools/window/schemas.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -1
- package/dist/audit/interceptor.d.ts.map +1 -1
- package/dist/audit/logger.d.ts +26 -25
- package/dist/audit/logger.d.ts.map +1 -1
- package/dist/auth/authorization-server-discovery.d.ts.map +1 -1
- package/dist/auth/scopes/mapping.d.ts.map +1 -1
- package/dist/auth/token-validator.d.ts.map +1 -1
- package/dist/{chunk-W5WQVNVX.js → chunk-27C5EE6U.js} +23 -17
- package/dist/chunk-2TYICG7B.js +1183 -0
- package/dist/{chunk-37G4DLL6.js → chunk-LLIAIJPO.js} +1146 -539
- package/dist/{chunk-NV34JSQM.js → chunk-UE7GVOBV.js} +1757 -1331
- package/dist/{chunk-L552U3QS.js → chunk-XLIYO3YA.js} +401 -77
- package/dist/cli.js +116 -11
- package/dist/codemode/api-constants.d.ts.map +1 -1
- package/dist/codemode/api.d.ts.map +1 -1
- package/dist/codemode/sandbox-factory.d.ts.map +1 -1
- package/dist/codemode/sandbox.d.ts +0 -3
- package/dist/codemode/sandbox.d.ts.map +1 -1
- package/dist/codemode/security.d.ts.map +1 -1
- package/dist/codemode/types.d.ts +2 -0
- package/dist/codemode/types.d.ts.map +1 -1
- package/dist/constants/server-instructions.d.ts +1 -1
- package/dist/constants/server-instructions.d.ts.map +1 -1
- package/dist/filtering/tool-constants.d.ts +11 -11
- package/dist/filtering/tool-constants.d.ts.map +1 -1
- package/dist/{http-HWTUVFIA.js → http-ZDMK46QU.js} +195 -32
- package/dist/index.js +4 -4
- package/dist/observability/metrics.d.ts +36 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/system-db.d.ts +13 -0
- package/dist/observability/system-db.d.ts.map +1 -0
- package/dist/server/mcp-server.d.ts +3 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/registration/admin-tools.d.ts +6 -0
- package/dist/server/registration/admin-tools.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/backup.d.ts +8 -0
- package/dist/server/registration/audit-tools/backup.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/helpers.d.ts +11 -0
- package/dist/server/registration/audit-tools/helpers.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/index.d.ts +4 -0
- package/dist/server/registration/audit-tools/index.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/resource.d.ts +8 -0
- package/dist/server/registration/audit-tools/resource.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/search.d.ts +7 -0
- package/dist/server/registration/audit-tools/search.d.ts.map +1 -0
- package/dist/server/registration/help-resources.d.ts.map +1 -1
- package/dist/server/registration/index.d.ts +3 -1
- package/dist/server/registration/index.d.ts.map +1 -1
- package/dist/server/registration/observability-resources.d.ts +11 -0
- package/dist/server/registration/observability-resources.d.ts.map +1 -0
- package/dist/server/subscription-manager.d.ts +35 -0
- package/dist/server/subscription-manager.d.ts.map +1 -0
- package/dist/{sqlite-TB56Z7G3.js → sqlite-XWZPEZJO.js} +195 -19
- package/dist/{sqlite-native-IF75BB3O.js → sqlite-native-5GQ3WKCZ.js} +311 -147
- package/dist/transports/http/middleware.d.ts.map +1 -1
- package/dist/transports/http/oauth.d.ts.map +1 -1
- package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -1
- package/dist/transports/http/sessions/stateful.d.ts +5 -1
- package/dist/transports/http/sessions/stateful.d.ts.map +1 -1
- package/dist/transports/http/transport.d.ts +2 -0
- package/dist/transports/http/transport.d.ts.map +1 -1
- package/dist/transports/http/types.d.ts +11 -0
- package/dist/transports/http/types.d.ts.map +1 -1
- package/dist/types/auth.d.ts +4 -0
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/server.d.ts +5 -0
- package/dist/types/server.d.ts.map +1 -1
- package/dist/utils/annotations.d.ts +8 -0
- package/dist/utils/annotations.d.ts.map +1 -1
- package/dist/utils/errors/categories.d.ts +16 -11
- package/dist/utils/errors/categories.d.ts.map +1 -1
- package/dist/utils/errors/classes.d.ts +37 -0
- package/dist/utils/errors/classes.d.ts.map +1 -1
- package/dist/utils/errors/format.d.ts +2 -2
- package/dist/utils/errors/format.d.ts.map +1 -1
- package/dist/utils/errors/index.d.ts +1 -1
- package/dist/utils/errors/index.d.ts.map +1 -1
- package/dist/utils/errors/suggestions.d.ts +1 -0
- package/dist/utils/errors/suggestions.d.ts.map +1 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/logger/types.d.ts +1 -1
- package/dist/utils/logger/types.d.ts.map +1 -1
- package/dist/utils/security-utils.d.ts +29 -0
- package/dist/utils/security-utils.d.ts.map +1 -0
- package/dist/utils/stream-utils.d.ts +14 -0
- package/dist/utils/stream-utils.d.ts.map +1 -0
- package/dist/utils/tokens.d.ts +15 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/where-clause.d.ts +0 -13
- package/dist/utils/where-clause.d.ts.map +1 -1
- package/package.json +43 -44
- package/dist/adapters/sqlite-native/tools/window.d.ts +0 -7
- package/dist/adapters/sqlite-native/tools/window.d.ts.map +0 -1
- package/dist/chunk-E5IESRTK.js +0 -489
- package/dist/server/registration/audit-tools.d.ts +0 -13
- package/dist/server/registration/audit-tools.d.ts.map +0 -1
- package/dist/utils/insights-manager.d.ts +0 -39
- package/dist/utils/insights-manager.d.ts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createModuleLogger, DbMcpError, runWithAuthContext, ERROR_CODES, logger, SUPPORTED_SCOPES, scopesGrantToolAccess, InsufficientScopeError, hasAdminScope, hasReadScope, isOAuthError, BASE_SCOPES, AuthServerDiscoveryError, JwksFetchError, parseScopes, TokenExpiredError, InvalidSignatureError, InvalidTokenError, TokenMissingError } from './chunk-
|
|
1
|
+
import { createModuleLogger, DbMcpError, ErrorCategory, metrics, runWithAuthContext, ERROR_CODES, logger, ConfigurationError, SUPPORTED_SCOPES, scopesGrantToolAccess, InsufficientScopeError, hasAdminScope, hasReadScope, isOAuthError, BASE_SCOPES, AuthServerDiscoveryError, JwksFetchError, parseScopes, TokenExpiredError, InvalidSignatureError, InvalidTokenError, TokenMissingError } from './chunk-XLIYO3YA.js';
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { localhostHostValidation } from '@modelcontextprotocol/sdk/server/middleware/hostHeaderValidation.js';
|
|
4
4
|
import cors from 'cors';
|
|
@@ -148,6 +148,9 @@ var JSONRPC_INTERNAL_ERROR = -32603;
|
|
|
148
148
|
var HTTP_REQUEST_TIMEOUT_MS = 12e4;
|
|
149
149
|
var HTTP_KEEP_ALIVE_TIMEOUT_MS = 65e3;
|
|
150
150
|
var HTTP_HEADERS_TIMEOUT_MS = 66e3;
|
|
151
|
+
var SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
152
|
+
var SESSION_SWEEP_INTERVAL_MS = 1 * 60 * 1e3;
|
|
153
|
+
var SESSION_ABSOLUTE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
151
154
|
function setupSecurityHeaders(state) {
|
|
152
155
|
if (!state.app) return;
|
|
153
156
|
state.app.disable("x-powered-by");
|
|
@@ -251,7 +254,12 @@ function setupRateLimiting(state) {
|
|
|
251
254
|
skip: (req) => req.path === "/health",
|
|
252
255
|
handler: (_req, res, _next, options) => {
|
|
253
256
|
res.status(options.statusCode).json({
|
|
254
|
-
|
|
257
|
+
success: false,
|
|
258
|
+
error: "Too Many Requests",
|
|
259
|
+
code: "RATE_LIMIT_ERROR",
|
|
260
|
+
category: "rate_limit",
|
|
261
|
+
suggestion: "Wait before retrying. Reduce request frequency or configure MCP_RATE_LIMIT_MAX.",
|
|
262
|
+
recoverable: true
|
|
255
263
|
});
|
|
256
264
|
}
|
|
257
265
|
});
|
|
@@ -273,7 +281,7 @@ async function setupStatelessEndpoints(state) {
|
|
|
273
281
|
throw new DbMcpError(
|
|
274
282
|
"Transport or server not initialized",
|
|
275
283
|
ERROR_CODES.SERVER.TRANSPORT_ERROR.full,
|
|
276
|
-
|
|
284
|
+
ErrorCategory.INTERNAL
|
|
277
285
|
);
|
|
278
286
|
}
|
|
279
287
|
state.statelessTransport = new StreamableHTTPServerTransport({
|
|
@@ -354,15 +362,49 @@ function isValidSessionId(id) {
|
|
|
354
362
|
if (id.length !== 36) return false;
|
|
355
363
|
return /^[0-9a-fA-F-]{36}$/.test(id);
|
|
356
364
|
}
|
|
365
|
+
function touchSession(state, sessionId) {
|
|
366
|
+
state.sessionLastActivity.set(sessionId, Date.now());
|
|
367
|
+
}
|
|
357
368
|
function setupStatefulEndpoints(state) {
|
|
358
369
|
if (!state.app || !state.mcpServer) {
|
|
359
370
|
throw new DbMcpError(
|
|
360
371
|
"Transport or server not initialized",
|
|
361
372
|
ERROR_CODES.SERVER.TRANSPORT_ERROR.full,
|
|
362
|
-
|
|
373
|
+
ErrorCategory.INTERNAL
|
|
363
374
|
);
|
|
364
375
|
}
|
|
365
376
|
const server = state.mcpServer;
|
|
377
|
+
const sessionSweepTimer = setInterval(() => {
|
|
378
|
+
const now = Date.now();
|
|
379
|
+
for (const [sid, lastActivity] of state.sessionLastActivity) {
|
|
380
|
+
const idleMs = now - lastActivity;
|
|
381
|
+
if (idleMs <= SESSION_TIMEOUT_MS) continue;
|
|
382
|
+
if ((state.sessionLocks.get(sid) ?? 0) > 0) continue;
|
|
383
|
+
if (state.transports.has(sid)) {
|
|
384
|
+
logger5.info("Expiring idle HTTP session", {
|
|
385
|
+
code: "HTTP_SESSION_EXPIRE",
|
|
386
|
+
sessionId: sid,
|
|
387
|
+
idleMinutes: Math.round(idleMs / 6e4)
|
|
388
|
+
});
|
|
389
|
+
const t = state.transports.get(sid);
|
|
390
|
+
if (t) {
|
|
391
|
+
void t.close();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (state.sseTransports.has(sid)) {
|
|
395
|
+
logger5.info("Expiring idle SSE session", {
|
|
396
|
+
code: "SSE_SESSION_EXPIRE",
|
|
397
|
+
sessionId: sid,
|
|
398
|
+
idleMinutes: Math.round(idleMs / 6e4)
|
|
399
|
+
});
|
|
400
|
+
const t = state.sseTransports.get(sid);
|
|
401
|
+
if (t) {
|
|
402
|
+
void t.close();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}, SESSION_SWEEP_INTERVAL_MS);
|
|
407
|
+
sessionSweepTimer.unref();
|
|
366
408
|
state.app.post("/mcp", (req, res) => {
|
|
367
409
|
const sessionId = req.headers["mcp-session-id"];
|
|
368
410
|
if (sessionId !== void 0 && !isValidSessionId(sessionId)) {
|
|
@@ -412,10 +454,23 @@ function setupStatefulEndpoints(state) {
|
|
|
412
454
|
});
|
|
413
455
|
return;
|
|
414
456
|
}
|
|
457
|
+
const createdAt = state.sessionCreatedAt.get(sessionId) ?? Date.now();
|
|
458
|
+
if (Date.now() - createdAt > SESSION_ABSOLUTE_TTL_MS) {
|
|
459
|
+
res.status(401).json({
|
|
460
|
+
jsonrpc: "2.0",
|
|
461
|
+
error: {
|
|
462
|
+
code: JSONRPC_SERVER_ERROR,
|
|
463
|
+
message: "Unauthorized: Session absolute TTL expired"
|
|
464
|
+
},
|
|
465
|
+
id: null
|
|
466
|
+
});
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
touchSession(state, sessionId);
|
|
415
470
|
httpTransport = existingTransport;
|
|
416
471
|
} else if (sessionId === void 0 && isNewSessionRequest(req.body)) {
|
|
417
472
|
const maxSessions = state.config.maxSessions ?? 1e3;
|
|
418
|
-
if (state.transports.size >= maxSessions) {
|
|
473
|
+
if (state.transports.size + state.sseTransports.size >= maxSessions) {
|
|
419
474
|
res.status(429).json({
|
|
420
475
|
jsonrpc: "2.0",
|
|
421
476
|
error: {
|
|
@@ -434,6 +489,8 @@ function setupStatefulEndpoints(state) {
|
|
|
434
489
|
sessionId: sid
|
|
435
490
|
});
|
|
436
491
|
state.transports.set(sid, newTransport);
|
|
492
|
+
touchSession(state, sid);
|
|
493
|
+
state.sessionCreatedAt.set(sid, Date.now());
|
|
437
494
|
state.sessionOwners.set(sid, req.auth?.sub);
|
|
438
495
|
}
|
|
439
496
|
});
|
|
@@ -446,6 +503,12 @@ function setupStatefulEndpoints(state) {
|
|
|
446
503
|
});
|
|
447
504
|
state.transports.delete(sid);
|
|
448
505
|
state.sessionOwners.delete(sid);
|
|
506
|
+
state.sessionLastActivity.delete(sid);
|
|
507
|
+
state.sessionCreatedAt.delete(sid);
|
|
508
|
+
state.sessionLocks.delete(sid);
|
|
509
|
+
if ("subscriptionManager" in server) {
|
|
510
|
+
server.subscriptionManager.unsubscribeSession(sid);
|
|
511
|
+
}
|
|
449
512
|
}
|
|
450
513
|
};
|
|
451
514
|
await connectionMutex.acquire().then(async (release) => {
|
|
@@ -489,11 +552,28 @@ function setupStatefulEndpoints(state) {
|
|
|
489
552
|
release();
|
|
490
553
|
}
|
|
491
554
|
});
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
555
|
+
const activeSid = newTransport.sessionId;
|
|
556
|
+
try {
|
|
557
|
+
if (activeSid) {
|
|
558
|
+
const count = state.sessionLocks.get(activeSid) ?? 0;
|
|
559
|
+
state.sessionLocks.set(activeSid, count + 1);
|
|
560
|
+
}
|
|
561
|
+
await newTransport.handleRequest(
|
|
562
|
+
asIncoming(req),
|
|
563
|
+
asServerResponse(res),
|
|
564
|
+
req.body
|
|
565
|
+
);
|
|
566
|
+
} finally {
|
|
567
|
+
if (activeSid) {
|
|
568
|
+
const count = state.sessionLocks.get(activeSid) ?? 0;
|
|
569
|
+
if (count > 1) {
|
|
570
|
+
state.sessionLocks.set(activeSid, count - 1);
|
|
571
|
+
} else {
|
|
572
|
+
state.sessionLocks.delete(activeSid);
|
|
573
|
+
}
|
|
574
|
+
touchSession(state, activeSid);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
497
577
|
return;
|
|
498
578
|
} else {
|
|
499
579
|
res.status(400).json({
|
|
@@ -507,11 +587,28 @@ function setupStatefulEndpoints(state) {
|
|
|
507
587
|
return;
|
|
508
588
|
}
|
|
509
589
|
if (httpTransport !== void 0) {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
590
|
+
const activeSid = sessionId;
|
|
591
|
+
try {
|
|
592
|
+
if (activeSid) {
|
|
593
|
+
const count = state.sessionLocks.get(activeSid) ?? 0;
|
|
594
|
+
state.sessionLocks.set(activeSid, count + 1);
|
|
595
|
+
}
|
|
596
|
+
await httpTransport.handleRequest(
|
|
597
|
+
asIncoming(req),
|
|
598
|
+
asServerResponse(res),
|
|
599
|
+
req.body
|
|
600
|
+
);
|
|
601
|
+
} finally {
|
|
602
|
+
if (activeSid) {
|
|
603
|
+
const count = state.sessionLocks.get(activeSid) ?? 0;
|
|
604
|
+
if (count > 1) {
|
|
605
|
+
state.sessionLocks.set(activeSid, count - 1);
|
|
606
|
+
} else {
|
|
607
|
+
state.sessionLocks.delete(activeSid);
|
|
608
|
+
}
|
|
609
|
+
touchSession(state, activeSid);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
515
612
|
}
|
|
516
613
|
} catch (error) {
|
|
517
614
|
logger5.error("Error handling MCP request", {
|
|
@@ -546,6 +643,12 @@ function setupStatefulEndpoints(state) {
|
|
|
546
643
|
res.status(403).send("Forbidden: session belongs to a different client");
|
|
547
644
|
return;
|
|
548
645
|
}
|
|
646
|
+
const createdAt = state.sessionCreatedAt.get(sessionId) ?? Date.now();
|
|
647
|
+
if (Date.now() - createdAt > SESSION_ABSOLUTE_TTL_MS) {
|
|
648
|
+
res.status(401).send("Unauthorized: Session absolute TTL expired");
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
touchSession(state, sessionId);
|
|
549
652
|
const lastEventId = req.headers["last-event-id"];
|
|
550
653
|
if (lastEventId !== void 0) {
|
|
551
654
|
logger5.debug("Client reconnecting with Last-Event-ID", {
|
|
@@ -555,7 +658,24 @@ function setupStatefulEndpoints(state) {
|
|
|
555
658
|
});
|
|
556
659
|
}
|
|
557
660
|
if (httpTransport !== void 0) {
|
|
558
|
-
void
|
|
661
|
+
void (async () => {
|
|
662
|
+
try {
|
|
663
|
+
const count = state.sessionLocks.get(sessionId) ?? 0;
|
|
664
|
+
state.sessionLocks.set(sessionId, count + 1);
|
|
665
|
+
await httpTransport.handleRequest(
|
|
666
|
+
asIncoming(req),
|
|
667
|
+
asServerResponse(res)
|
|
668
|
+
);
|
|
669
|
+
} finally {
|
|
670
|
+
const count = state.sessionLocks.get(sessionId) ?? 0;
|
|
671
|
+
if (count > 1) {
|
|
672
|
+
state.sessionLocks.set(sessionId, count - 1);
|
|
673
|
+
} else {
|
|
674
|
+
state.sessionLocks.delete(sessionId);
|
|
675
|
+
}
|
|
676
|
+
touchSession(state, sessionId);
|
|
677
|
+
}
|
|
678
|
+
})();
|
|
559
679
|
}
|
|
560
680
|
});
|
|
561
681
|
state.app.delete("/mcp", (req, res) => {
|
|
@@ -578,9 +698,27 @@ function setupStatefulEndpoints(state) {
|
|
|
578
698
|
sessionId
|
|
579
699
|
});
|
|
580
700
|
if (httpTransport !== void 0) {
|
|
581
|
-
void
|
|
701
|
+
void (async () => {
|
|
702
|
+
try {
|
|
703
|
+
const count = state.sessionLocks.get(sessionId) ?? 0;
|
|
704
|
+
state.sessionLocks.set(sessionId, count + 1);
|
|
705
|
+
await httpTransport.handleRequest(
|
|
706
|
+
asIncoming(req),
|
|
707
|
+
asServerResponse(res)
|
|
708
|
+
);
|
|
709
|
+
} finally {
|
|
710
|
+
const count = state.sessionLocks.get(sessionId) ?? 0;
|
|
711
|
+
if (count > 1) {
|
|
712
|
+
state.sessionLocks.set(sessionId, count - 1);
|
|
713
|
+
} else {
|
|
714
|
+
state.sessionLocks.delete(sessionId);
|
|
715
|
+
}
|
|
716
|
+
touchSession(state, sessionId);
|
|
717
|
+
}
|
|
718
|
+
})();
|
|
582
719
|
}
|
|
583
720
|
});
|
|
721
|
+
return sessionSweepTimer;
|
|
584
722
|
}
|
|
585
723
|
var logger6 = createModuleLogger("HTTP");
|
|
586
724
|
var connectionMutex2 = new Mutex();
|
|
@@ -598,6 +736,8 @@ function setupLegacySSEEndpoints(state) {
|
|
|
598
736
|
void (async () => {
|
|
599
737
|
try {
|
|
600
738
|
state.sseTransports.set(sseTransport.sessionId, sseTransport);
|
|
739
|
+
touchSession(state, sseTransport.sessionId);
|
|
740
|
+
state.sessionCreatedAt.set(sseTransport.sessionId, Date.now());
|
|
601
741
|
state.sessionOwners.set(sseTransport.sessionId, req.auth?.sub);
|
|
602
742
|
sseTransport.onclose = () => {
|
|
603
743
|
logger6.info("Legacy SSE transport closed", {
|
|
@@ -606,6 +746,11 @@ function setupLegacySSEEndpoints(state) {
|
|
|
606
746
|
});
|
|
607
747
|
state.sseTransports.delete(sseTransport.sessionId);
|
|
608
748
|
state.sessionOwners.delete(sseTransport.sessionId);
|
|
749
|
+
state.sessionLastActivity.delete(sseTransport.sessionId);
|
|
750
|
+
state.sessionCreatedAt.delete(sseTransport.sessionId);
|
|
751
|
+
if ("subscriptionManager" in server) {
|
|
752
|
+
server.subscriptionManager.unsubscribeSession(sseTransport.sessionId);
|
|
753
|
+
}
|
|
609
754
|
};
|
|
610
755
|
const origSend = sseTransport.send.bind(sseTransport);
|
|
611
756
|
sseTransport.send = async (message) => {
|
|
@@ -666,6 +811,8 @@ function setupLegacySSEEndpoints(state) {
|
|
|
666
811
|
req.on("close", () => {
|
|
667
812
|
state.sseTransports.delete(sseTransport.sessionId);
|
|
668
813
|
state.sessionOwners.delete(sseTransport.sessionId);
|
|
814
|
+
state.sessionLastActivity.delete(sseTransport.sessionId);
|
|
815
|
+
state.sessionCreatedAt.delete(sseTransport.sessionId);
|
|
669
816
|
});
|
|
670
817
|
});
|
|
671
818
|
state.app.post("/messages", (req, res) => {
|
|
@@ -704,6 +851,7 @@ function setupLegacySSEEndpoints(state) {
|
|
|
704
851
|
});
|
|
705
852
|
return;
|
|
706
853
|
}
|
|
854
|
+
touchSession(state, sessionId);
|
|
707
855
|
void sseTransport.handlePostMessage(
|
|
708
856
|
asIncoming(req),
|
|
709
857
|
asServerResponse(res),
|
|
@@ -852,7 +1000,7 @@ var AuthorizationServerDiscovery = class {
|
|
|
852
1000
|
const url = new URL(this.authServerUrl);
|
|
853
1001
|
const isLocalDev = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
854
1002
|
if (!isLocalDev) {
|
|
855
|
-
throw new
|
|
1003
|
+
throw new ConfigurationError(
|
|
856
1004
|
`Security: Authorization server URL must use HTTPS in production. Got: ${this.authServerUrl}. Set NODE_ENV=development to allow HTTP for local testing.`
|
|
857
1005
|
);
|
|
858
1006
|
}
|
|
@@ -897,7 +1045,7 @@ var AuthorizationServerDiscovery = class {
|
|
|
897
1045
|
throw new DbMcpError(
|
|
898
1046
|
`HTTP ${String(response.status)}: ${response.statusText}`,
|
|
899
1047
|
ERROR_CODES.AUTH.DISCOVERY_FAILED.full,
|
|
900
|
-
|
|
1048
|
+
ErrorCategory.CONNECTION
|
|
901
1049
|
);
|
|
902
1050
|
}
|
|
903
1051
|
const metadata = await response.json();
|
|
@@ -931,14 +1079,14 @@ var AuthorizationServerDiscovery = class {
|
|
|
931
1079
|
throw new DbMcpError(
|
|
932
1080
|
"Missing required field: issuer",
|
|
933
1081
|
"AUTH_DISCOVERY_INVALID",
|
|
934
|
-
|
|
1082
|
+
ErrorCategory.VALIDATION
|
|
935
1083
|
);
|
|
936
1084
|
}
|
|
937
1085
|
if (!metadata.token_endpoint) {
|
|
938
1086
|
throw new DbMcpError(
|
|
939
1087
|
"Missing required field: token_endpoint",
|
|
940
1088
|
"AUTH_DISCOVERY_INVALID",
|
|
941
|
-
|
|
1089
|
+
ErrorCategory.VALIDATION
|
|
942
1090
|
);
|
|
943
1091
|
}
|
|
944
1092
|
try {
|
|
@@ -948,7 +1096,7 @@ var AuthorizationServerDiscovery = class {
|
|
|
948
1096
|
throw new DbMcpError(
|
|
949
1097
|
"Invalid URL format in metadata fields",
|
|
950
1098
|
"AUTH_DISCOVERY_INVALID",
|
|
951
|
-
|
|
1099
|
+
ErrorCategory.VALIDATION
|
|
952
1100
|
);
|
|
953
1101
|
}
|
|
954
1102
|
const expectedIssuer = this.authServerUrl;
|
|
@@ -956,7 +1104,7 @@ var AuthorizationServerDiscovery = class {
|
|
|
956
1104
|
throw new DbMcpError(
|
|
957
1105
|
`Issuer validation failed. Per RFC 8414 \xA73.3, the issuer MUST be identical to the authorization server URL.`,
|
|
958
1106
|
"AUTH_ISSUER_MISMATCH",
|
|
959
|
-
|
|
1107
|
+
ErrorCategory.VALIDATION
|
|
960
1108
|
);
|
|
961
1109
|
}
|
|
962
1110
|
}
|
|
@@ -968,7 +1116,7 @@ var AuthorizationServerDiscovery = class {
|
|
|
968
1116
|
throw new DbMcpError(
|
|
969
1117
|
"Authorization server metadata not yet discovered. Call discover() first.",
|
|
970
1118
|
"AUTH_DISCOVERY_REQUIRED",
|
|
971
|
-
|
|
1119
|
+
ErrorCategory.INTERNAL
|
|
972
1120
|
);
|
|
973
1121
|
}
|
|
974
1122
|
return this.cachedMetadata;
|
|
@@ -984,7 +1132,7 @@ var AuthorizationServerDiscovery = class {
|
|
|
984
1132
|
throw new DbMcpError(
|
|
985
1133
|
"Authorization server does not provide jwks_uri",
|
|
986
1134
|
"AUTH_DISCOVERY_INVALID",
|
|
987
|
-
|
|
1135
|
+
ErrorCategory.VALIDATION
|
|
988
1136
|
);
|
|
989
1137
|
}
|
|
990
1138
|
return metadata.jwks_uri;
|
|
@@ -1076,7 +1224,7 @@ var TokenValidator = class _TokenValidator {
|
|
|
1076
1224
|
const url = new URL(config.jwksUri);
|
|
1077
1225
|
const isLocalDev = url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
|
1078
1226
|
if (!isLocalDev) {
|
|
1079
|
-
throw new
|
|
1227
|
+
throw new ConfigurationError(
|
|
1080
1228
|
`Security: JWKS URI must use HTTPS in production. Got: ${config.jwksUri}. Set ALLOW_HTTP_JWKS=true to allow HTTP for local testing.`
|
|
1081
1229
|
);
|
|
1082
1230
|
}
|
|
@@ -1286,7 +1434,7 @@ function applyAuthMiddleware(state) {
|
|
|
1286
1434
|
const corsOrigins = state.config.corsOrigins ?? [];
|
|
1287
1435
|
const isPubliclyExposed = state.config.oauth.enabled || state.config.noAuthEnforcement;
|
|
1288
1436
|
if (corsOrigins.includes("*") && isPubliclyExposed) {
|
|
1289
|
-
throw new
|
|
1437
|
+
throw new ConfigurationError(
|
|
1290
1438
|
"Security: CORS wildcard origin ('*') is forbidden when authentication is enabled or enforcement is explicitly disabled. Configure explicit origins via --cors-origins for production deployments."
|
|
1291
1439
|
);
|
|
1292
1440
|
}
|
|
@@ -1435,7 +1583,7 @@ function applyScopeEnforcementMiddleware(state) {
|
|
|
1435
1583
|
async function setupOAuth(state, resourceUri) {
|
|
1436
1584
|
logger10.info("Setting up OAuth 2.1...", { code: "HTTP_OAUTH_SETUP" });
|
|
1437
1585
|
if (state.config.oauth.enabled && !state.config.oauth.audience) {
|
|
1438
|
-
throw new
|
|
1586
|
+
throw new ConfigurationError(
|
|
1439
1587
|
"Security: OAuth audience must be explicitly configured when OAuth is enabled."
|
|
1440
1588
|
);
|
|
1441
1589
|
}
|
|
@@ -1489,6 +1637,8 @@ var logger11 = createModuleLogger("HTTP");
|
|
|
1489
1637
|
var HttpTransport = class {
|
|
1490
1638
|
/** Internal state shared with session/middleware/oauth modules */
|
|
1491
1639
|
state;
|
|
1640
|
+
/** Sweep timer for session timeout cleanup */
|
|
1641
|
+
sweepTimer = null;
|
|
1492
1642
|
constructor(config) {
|
|
1493
1643
|
this.state = {
|
|
1494
1644
|
config: {
|
|
@@ -1502,6 +1652,9 @@ var HttpTransport = class {
|
|
|
1502
1652
|
transports: /* @__PURE__ */ new Map(),
|
|
1503
1653
|
sseTransports: /* @__PURE__ */ new Map(),
|
|
1504
1654
|
sessionOwners: /* @__PURE__ */ new Map(),
|
|
1655
|
+
sessionLastActivity: /* @__PURE__ */ new Map(),
|
|
1656
|
+
sessionCreatedAt: /* @__PURE__ */ new Map(),
|
|
1657
|
+
sessionLocks: /* @__PURE__ */ new Map(),
|
|
1505
1658
|
statelessTransport: null,
|
|
1506
1659
|
resourceServer: null,
|
|
1507
1660
|
authServerDiscovery: null,
|
|
@@ -1530,7 +1683,7 @@ var HttpTransport = class {
|
|
|
1530
1683
|
throw new DbMcpError(
|
|
1531
1684
|
"trustedProxyIps cannot be an empty array if specified",
|
|
1532
1685
|
"CONFIG_ERROR",
|
|
1533
|
-
|
|
1686
|
+
ErrorCategory.CONFIGURATION
|
|
1534
1687
|
);
|
|
1535
1688
|
}
|
|
1536
1689
|
this.state.app.set("trust proxy", this.state.config.trustedProxyIps);
|
|
@@ -1549,7 +1702,7 @@ var HttpTransport = class {
|
|
|
1549
1702
|
throw new DbMcpError(
|
|
1550
1703
|
"HTTP transport is enabled without authentication. You must configure OAuth (--oauth-enabled) or explicitly bypass this check with --no-auth-enforcement.",
|
|
1551
1704
|
"AUTH_REQUIRED",
|
|
1552
|
-
|
|
1705
|
+
ErrorCategory.CONFIGURATION
|
|
1553
1706
|
);
|
|
1554
1707
|
}
|
|
1555
1708
|
if (this.state.config.oauth.enabled) {
|
|
@@ -1590,6 +1743,12 @@ var HttpTransport = class {
|
|
|
1590
1743
|
});
|
|
1591
1744
|
applyAuthMiddleware(this.state);
|
|
1592
1745
|
applyScopeEnforcementMiddleware(this.state);
|
|
1746
|
+
if (this.state.config.metricsExport === "prometheus") {
|
|
1747
|
+
this.state.app.get("/metrics", (_req, res) => {
|
|
1748
|
+
res.set("Content-Type", "text/plain");
|
|
1749
|
+
res.send(metrics.toPrometheus());
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1593
1752
|
const oauthEnabled = this.state.config.oauth?.enabled ?? false;
|
|
1594
1753
|
let lastNoAuthWarning = 0;
|
|
1595
1754
|
this.state.app.use((req, _res, next) => {
|
|
@@ -1617,7 +1776,7 @@ var HttpTransport = class {
|
|
|
1617
1776
|
if (this.state.config.stateless) {
|
|
1618
1777
|
await setupStatelessEndpoints(this.state);
|
|
1619
1778
|
} else {
|
|
1620
|
-
setupStatefulEndpoints(this.state);
|
|
1779
|
+
this.sweepTimer = setupStatefulEndpoints(this.state);
|
|
1621
1780
|
}
|
|
1622
1781
|
if (!this.state.config.stateless) {
|
|
1623
1782
|
setupLegacySSEEndpoints(this.state);
|
|
@@ -1642,7 +1801,7 @@ var HttpTransport = class {
|
|
|
1642
1801
|
throw new DbMcpError(
|
|
1643
1802
|
"Transport not initialized. Call initialize() first.",
|
|
1644
1803
|
ERROR_CODES.SERVER.START_FAILED.full,
|
|
1645
|
-
|
|
1804
|
+
ErrorCategory.INTERNAL
|
|
1646
1805
|
);
|
|
1647
1806
|
}
|
|
1648
1807
|
return new Promise((resolve, reject) => {
|
|
@@ -1682,6 +1841,10 @@ var HttpTransport = class {
|
|
|
1682
1841
|
* Stop the server and close all active sessions
|
|
1683
1842
|
*/
|
|
1684
1843
|
async stop() {
|
|
1844
|
+
if (this.sweepTimer) {
|
|
1845
|
+
clearInterval(this.sweepTimer);
|
|
1846
|
+
this.sweepTimer = null;
|
|
1847
|
+
}
|
|
1685
1848
|
for (const [sessionId, transport] of this.state.transports) {
|
|
1686
1849
|
try {
|
|
1687
1850
|
logger11.debug("Closing transport", {
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_CONFIG, DbMcpServer, createServer } from './chunk-
|
|
2
|
-
export { DatabaseAdapter } from './chunk-
|
|
3
|
-
export { NAME, VERSION } from './chunk-
|
|
4
|
-
export { ALL_TOOL_GROUPS, AuthenticationError, AuthorizationError, ConnectionError, DbMcpError, META_GROUPS, QueryError, TOOL_GROUPS, ValidationError, filterTools, getFilterSummary, getToolFilterFromEnv, isToolEnabled, parseToolFilter } from './chunk-
|
|
1
|
+
export { DEFAULT_CONFIG, DbMcpServer, createServer } from './chunk-LLIAIJPO.js';
|
|
2
|
+
export { DatabaseAdapter } from './chunk-27C5EE6U.js';
|
|
3
|
+
export { NAME, VERSION } from './chunk-2TYICG7B.js';
|
|
4
|
+
export { ALL_TOOL_GROUPS, AuthenticationError, AuthorizationError, ConnectionError, DbMcpError, META_GROUPS, QueryError, TOOL_GROUPS, ValidationError, filterTools, getFilterSummary, getToolFilterFromEnv, isToolEnabled, parseToolFilter } from './chunk-XLIYO3YA.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* db-mcp — Observability Metrics
|
|
3
|
+
*
|
|
4
|
+
* In-memory streaming metrics aggregator for tools and resources.
|
|
5
|
+
* Uses a zero-dependency circular buffer to estimate latency percentiles
|
|
6
|
+
* (p50, p95, p99) without memory bloat.
|
|
7
|
+
*/
|
|
8
|
+
import type { SystemDb } from "./system-db.js";
|
|
9
|
+
export interface MetricSummary {
|
|
10
|
+
calls: number;
|
|
11
|
+
errors: number;
|
|
12
|
+
tokens: number;
|
|
13
|
+
p50: number;
|
|
14
|
+
p95: number;
|
|
15
|
+
p99: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ResourceMetricSummary {
|
|
18
|
+
reads: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class MetricsRegistry {
|
|
21
|
+
private tools;
|
|
22
|
+
private resources;
|
|
23
|
+
private systemDb;
|
|
24
|
+
private flushTimer;
|
|
25
|
+
setSystemDb(systemDb: SystemDb): void;
|
|
26
|
+
private loadHistorical;
|
|
27
|
+
private startFlushTimer;
|
|
28
|
+
private flushToDb;
|
|
29
|
+
close(): void;
|
|
30
|
+
recordToolCall(toolName: string, durationMs: number, success: boolean, tokens?: number): void;
|
|
31
|
+
recordResourceRead(uri: string): void;
|
|
32
|
+
getSummary(): Record<string, unknown>;
|
|
33
|
+
toPrometheus(): string;
|
|
34
|
+
}
|
|
35
|
+
export declare const metrics: MetricsRegistry;
|
|
36
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/observability/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK/C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;CACf;AA+ED,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,UAAU,CAA+C;IAEjE,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAMrC,OAAO,CAAC,cAAc;IAsCtB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,SAAS;IAiCjB,KAAK,IAAI,IAAI;IAQb,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,MAAM,SAAI,GACT,IAAI;IASP,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IASrC,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAkBrC,YAAY,IAAI,MAAM;CAwCvB;AAGD,eAAO,MAAM,OAAO,iBAAwB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Database } from "better-sqlite3";
|
|
2
|
+
export interface SystemDbConfig {
|
|
3
|
+
dbPath: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class SystemDb {
|
|
6
|
+
private db;
|
|
7
|
+
private readonly config;
|
|
8
|
+
constructor(config: SystemDbConfig);
|
|
9
|
+
init(): Promise<void>;
|
|
10
|
+
getDb(): Database;
|
|
11
|
+
close(): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=system-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-db.d.ts","sourceRoot":"","sources":["../../src/observability/system-db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM/C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE5B,MAAM,EAAE,cAAc;IAI5B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmF3B,KAAK,IAAI,QAAQ;IAOjB,KAAK,IAAI,IAAI;CAMd"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { McpServerConfig, DatabaseConfig } from "../types/index.js";
|
|
8
8
|
import type { DatabaseAdapter } from "../adapters/database-adapter.js";
|
|
9
|
+
import { SubscriptionManager } from "./subscription-manager.js";
|
|
9
10
|
/**
|
|
10
11
|
* Main db-mcp server class
|
|
11
12
|
*
|
|
@@ -18,8 +19,10 @@ export declare class DbMcpServer {
|
|
|
18
19
|
private config;
|
|
19
20
|
private auditLogger;
|
|
20
21
|
private backupManager;
|
|
22
|
+
private systemDb;
|
|
21
23
|
private auditInterceptor;
|
|
22
24
|
private auditInitPromise;
|
|
25
|
+
readonly subscriptionManager: SubscriptionManager;
|
|
23
26
|
constructor(config: McpServerConfig);
|
|
24
27
|
/**
|
|
25
28
|
* Register a database adapter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/server/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAwCvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AA+ChE;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,gBAAgB,CAA8B;IACtD,SAAgB,mBAAmB,EAAE,mBAAmB,CAAC;gBAE7C,MAAM,EAAE,eAAe;IAyLnC;;OAEG;IACG,eAAe,CACnB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAiEhB;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAI1D;;OAEG;IACH,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAI3C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B;;OAEG;YACW,UAAU;IAiBxB;;OAEG;YACW,SAAS;IAyDvB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAwC/B;;;OAGG;YACW,eAAe;CA8C9B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,WAAW,CAEjE;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,eAAe,CAKnD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-tools.d.ts","sourceRoot":"","sources":["../../../src/server/registration/admin-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAazE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkL1D"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { DatabaseAdapter } from "../../../adapters/database-adapter.js";
|
|
3
|
+
import type { BackupManager } from "../../../audit/backup-manager.js";
|
|
4
|
+
/**
|
|
5
|
+
* Register audit backup tools for snapshot management.
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerAuditBackupTools(server: McpServer, backupManager: BackupManager | null, adaptersMap: Map<string, DatabaseAdapter>): void;
|
|
8
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../../../src/server/registration/audit-tools/backup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAqBtE;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,aAAa,GAAG,IAAI,EACnC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GACxC,IAAI,CAkoBN"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Force redaction of SQL string literals to prevent secret exposure
|
|
3
|
+
* in audit logs and backups, regardless of operator configuration.
|
|
4
|
+
*/
|
|
5
|
+
export declare function redactSqlLiterals(text: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Validate DDL to prevent execution of unauthorized or destructive statements
|
|
8
|
+
* during restore operations from tampered backups.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateDdl(sql: string): void;
|
|
11
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/server/registration/audit-tools/helpers.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAqB7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/registration/audit-tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { BackupManager } from "../../../audit/backup-manager.js";
|
|
3
|
+
import type { AuditLogger } from "../../../audit/logger.js";
|
|
4
|
+
/**
|
|
5
|
+
* Register the sqlite://audit resource for agent access to audit log.
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerAuditResource(server: McpServer, auditLogger: AuditLogger | null, backupManager: BackupManager | null): void;
|
|
8
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../../src/server/registration/audit-tools/resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAI5D;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,GAAG,IAAI,EAC/B,aAAa,EAAE,aAAa,GAAG,IAAI,GAClC,IAAI,CAuCN"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { AuditLogger } from "../../../audit/logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register the sqlite_audit_search tool.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerAuditSearchTool(server: McpServer, auditLogger: AuditLogger | null): void;
|
|
7
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../src/server/registration/audit-tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAe5D;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,GAAG,IAAI,GAC9B,IAAI,CA6EN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-resources.d.ts","sourceRoot":"","sources":["../../../src/server/registration/help-resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAa,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"help-resources.d.ts","sourceRoot":"","sources":["../../../src/server/registration/help-resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAa,MAAM,sBAAsB,CAAC;AAMxE;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,gBAAgB,GAC3B,IAAI,CAuFN"}
|