@conte777/db-view-mcp 1.0.0 → 1.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.
Files changed (44) hide show
  1. package/dist/config/loader.d.ts +1 -0
  2. package/dist/config/loader.js +25 -1
  3. package/dist/config/loader.js.map +1 -1
  4. package/dist/config/types.d.ts +20 -0
  5. package/dist/config/types.js +5 -0
  6. package/dist/config/types.js.map +1 -1
  7. package/dist/connectors/clickhouse.d.ts +2 -2
  8. package/dist/connectors/clickhouse.js +4 -3
  9. package/dist/connectors/clickhouse.js.map +1 -1
  10. package/dist/connectors/instrumented.d.ts +18 -0
  11. package/dist/connectors/instrumented.js +52 -0
  12. package/dist/connectors/instrumented.js.map +1 -0
  13. package/dist/connectors/interface.d.ts +2 -2
  14. package/dist/connectors/manager.d.ts +6 -0
  15. package/dist/connectors/manager.js +58 -5
  16. package/dist/connectors/manager.js.map +1 -1
  17. package/dist/connectors/postgresql.d.ts +2 -2
  18. package/dist/connectors/postgresql.js +29 -11
  19. package/dist/connectors/postgresql.js.map +1 -1
  20. package/dist/index.js +9 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/tools/readonly/explain.d.ts +2 -0
  23. package/dist/tools/readonly/explain.js +2 -1
  24. package/dist/tools/readonly/explain.js.map +1 -1
  25. package/dist/tools/readonly/performance.d.ts +1 -2
  26. package/dist/tools/readonly/performance.js +6 -6
  27. package/dist/tools/readonly/performance.js.map +1 -1
  28. package/dist/tools/readonly/schema.d.ts +2 -0
  29. package/dist/tools/readonly/schema.js +2 -1
  30. package/dist/tools/readonly/schema.js.map +1 -1
  31. package/dist/tools/registry.js +2 -2
  32. package/dist/tools/registry.js.map +1 -1
  33. package/dist/tools/write/transaction.d.ts +18 -0
  34. package/dist/tools/write/transaction.js +70 -13
  35. package/dist/tools/write/transaction.js.map +1 -1
  36. package/dist/transport/http.d.ts +1 -0
  37. package/dist/transport/http.js +26 -13
  38. package/dist/transport/http.js.map +1 -1
  39. package/dist/utils/logger.d.ts +15 -0
  40. package/dist/utils/logger.js +52 -0
  41. package/dist/utils/logger.js.map +1 -0
  42. package/dist/utils/sql-validator.js +41 -21
  43. package/dist/utils/sql-validator.js.map +1 -1
  44. package/package.json +5 -2
@@ -5,10 +5,12 @@ export declare function createExplainParams(dbIds: string[]): {
5
5
  [x: string]: string;
6
6
  }>;
7
7
  sql: z.ZodString;
8
+ analyze: z.ZodOptional<z.ZodBoolean>;
8
9
  };
9
10
  export declare function explainHandler(manager: ConnectorManager): (params: {
10
11
  database: string;
11
12
  sql: string;
13
+ analyze?: boolean;
12
14
  }) => Promise<{
13
15
  content: {
14
16
  type: "text";
@@ -5,6 +5,7 @@ export function createExplainParams(dbIds) {
5
5
  return {
6
6
  database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
7
7
  sql: z.string().describe("SQL query to explain"),
8
+ analyze: z.boolean().optional().describe("Run EXPLAIN ANALYZE (actually executes the query). Default: false"),
8
9
  };
9
10
  }
10
11
  export function explainHandler(manager) {
@@ -15,7 +16,7 @@ export function explainHandler(manager) {
15
16
  }
16
17
  try {
17
18
  const connector = await manager.getConnector(params.database);
18
- const result = await connector.explain(params.sql);
19
+ const result = await connector.explain(params.sql, params.analyze ?? false);
19
20
  return formatSuccess({ data: result.plan, database: params.database });
20
21
  }
21
22
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../../src/tools/readonly/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxG,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACjD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAyB;IACtD,OAAO,KAAK,EAAE,MAAyC,EAAE,EAAE;QACzD,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,WAAW,CAAC,UAAU,CAAC,KAAM,EAAE,oBAAoB,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnD,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../../src/tools/readonly/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxG,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAChD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;KAC9G,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAyB;IACtD,OAAO,KAAK,EAAE,MAA4D,EAAE,EAAE;QAC5E,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,WAAW,CAAC,UAAU,CAAC,KAAM,EAAE,oBAAoB,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;YAC5E,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -6,7 +6,7 @@ interface SlowQuery {
6
6
  timestamp: Date;
7
7
  database: string;
8
8
  }
9
- declare class PerformanceTracker {
9
+ export declare class PerformanceTracker {
10
10
  private slowQueries;
11
11
  private threshold;
12
12
  recordQuery(sql: string, duration: number, database: string): void;
@@ -15,7 +15,6 @@ declare class PerformanceTracker {
15
15
  getThreshold(): number;
16
16
  reset(): void;
17
17
  }
18
- export declare const performanceTracker: PerformanceTracker;
19
18
  export declare function createPerformanceParams(dbIds: string[]): {
20
19
  database: z.ZodEnum<{
21
20
  [x: string]: string;
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { formatSuccess, formatError } from "../../utils/response.js";
3
- class PerformanceTracker {
3
+ export class PerformanceTracker {
4
4
  slowQueries = [];
5
5
  threshold = 1000; // ms
6
6
  recordQuery(sql, duration, database) {
@@ -26,7 +26,6 @@ class PerformanceTracker {
26
26
  this.slowQueries = [];
27
27
  }
28
28
  }
29
- export const performanceTracker = new PerformanceTracker();
30
29
  export function createPerformanceParams(dbIds) {
31
30
  return {
32
31
  database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
@@ -36,29 +35,30 @@ export function createPerformanceParams(dbIds) {
36
35
  };
37
36
  }
38
37
  export function performanceHandler(manager) {
38
+ const tracker = manager.getPerformanceTracker();
39
39
  return async (params) => {
40
40
  try {
41
41
  switch (params.action) {
42
42
  case "getSlowQueries":
43
43
  return formatSuccess({
44
- data: performanceTracker.getSlowQueries(params.database, params.limit),
44
+ data: tracker.getSlowQueries(params.database, params.limit),
45
45
  database: params.database,
46
46
  });
47
47
  case "getMetrics":
48
48
  return formatSuccess({
49
49
  data: {
50
- slowQueryThreshold: performanceTracker.getThreshold(),
50
+ slowQueryThreshold: tracker.getThreshold(),
51
51
  connectedDatabases: manager.getDatabaseIds(),
52
52
  },
53
53
  database: params.database,
54
54
  });
55
55
  case "reset":
56
- performanceTracker.reset();
56
+ tracker.reset();
57
57
  return formatSuccess({ data: "Performance metrics reset" });
58
58
  case "setThreshold":
59
59
  if (!params.threshold)
60
60
  return formatError("threshold is required for setThreshold");
61
- performanceTracker.setThreshold(params.threshold);
61
+ tracker.setThreshold(params.threshold);
62
62
  return formatSuccess({ data: `Threshold set to ${params.threshold}ms` });
63
63
  default:
64
64
  return formatError(`Unknown action: ${params.action}`);
@@ -1 +1 @@
1
- {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/tools/readonly/performance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/tools/readonly/performance.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,11 @@ export declare function createSchemaParams(dbIds: string[]): {
4
4
  database: z.ZodEnum<{
5
5
  [x: string]: string;
6
6
  }>;
7
+ schema: z.ZodOptional<z.ZodString>;
7
8
  };
8
9
  export declare function schemaHandler(manager: ConnectorManager): (params: {
9
10
  database: string;
11
+ schema?: string;
10
12
  }) => Promise<{
11
13
  content: {
12
14
  type: "text";
@@ -3,13 +3,14 @@ import { formatSuccess, formatError } from "../../utils/response.js";
3
3
  export function createSchemaParams(dbIds) {
4
4
  return {
5
5
  database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
6
+ schema: z.string().optional().describe("Schema name (default: 'public' for PostgreSQL, ignored for ClickHouse)"),
6
7
  };
7
8
  }
8
9
  export function schemaHandler(manager) {
9
10
  return async (params) => {
10
11
  try {
11
12
  const connector = await manager.getConnector(params.database);
12
- const ddl = await connector.getSchema();
13
+ const ddl = await connector.getSchema(params.schema);
13
14
  return formatSuccess({ data: ddl, database: params.database });
14
15
  }
15
16
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/readonly/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAErE,MAAM,UAAU,kBAAkB,CAAC,KAAe;IAChD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;KACzG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB;IACrD,OAAO,KAAK,EAAE,MAA4B,EAAE,EAAE;QAC5C,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,CAAC;YACxC,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/readonly/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAErE,MAAM,UAAU,kBAAkB,CAAC,KAAe;IAChD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,KAA8B,CAAC,CAAC,QAAQ,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wEAAwE,CAAC;KACjH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB;IACrD,OAAO,KAAK,EAAE,MAA6C,EAAE,EAAE;QAC7D,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrD,OAAO,aAAa,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -35,8 +35,8 @@ function registerPerDatabaseTools(server, manager, dbIds) {
35
35
  server.tool(`query_${dbId}`, `Execute a read-only SQL query on ${dbId}${desc}`, { sql: createQueryToolParams(singleDbIds).sql, maxRows: createQueryToolParams(singleDbIds).maxRows }, async (params) => queryToolHandler(manager)({ database: dbId, ...params }));
36
36
  server.tool(`list_tables_${dbId}`, `List tables on ${dbId}${desc}`, { schema: createListTablesParams(singleDbIds).schema }, async (params) => listTablesHandler(manager)({ database: dbId, ...params }));
37
37
  server.tool(`describe_table_${dbId}`, `Describe table structure on ${dbId}${desc}`, { table: createDescribeTableParams(singleDbIds).table, schema: createDescribeTableParams(singleDbIds).schema }, async (params) => describeTableHandler(manager)({ database: dbId, ...params }));
38
- server.tool(`schema_${dbId}`, `Get full schema of ${dbId}${desc}`, {}, async () => schemaHandler(manager)({ database: dbId }));
39
- server.tool(`explain_query_${dbId}`, `Run EXPLAIN on ${dbId}${desc}`, { sql: createExplainParams(singleDbIds).sql }, async (params) => explainHandler(manager)({ database: dbId, ...params }));
38
+ server.tool(`schema_${dbId}`, `Get full schema of ${dbId}${desc}`, { schema: createSchemaParams(singleDbIds).schema }, async (params) => schemaHandler(manager)({ database: dbId, ...params }));
39
+ server.tool(`explain_query_${dbId}`, `Run EXPLAIN on ${dbId}${desc}`, { sql: createExplainParams(singleDbIds).sql, analyze: createExplainParams(singleDbIds).analyze }, async (params) => explainHandler(manager)({ database: dbId, ...params }));
40
40
  server.tool(`performance_${dbId}`, `Performance metrics for ${dbId}${desc}`, {
41
41
  action: createPerformanceParams(singleDbIds).action,
42
42
  threshold: createPerformanceParams(singleDbIds).threshold,
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,22 @@
1
1
  import { z } from "zod";
2
2
  import type { ConnectorManager } from "../../connectors/manager.js";
3
+ import type { TransactionHandle } from "../../connectors/interface.js";
4
+ interface TransactionEntry {
5
+ handle: TransactionHandle;
6
+ database: string;
7
+ timer: ReturnType<typeof setTimeout>;
8
+ }
9
+ export declare class TransactionStore {
10
+ private entries;
11
+ private ttlMs;
12
+ constructor(ttlMs?: number);
13
+ add(handle: TransactionHandle, database: string): void;
14
+ get(id: string): TransactionEntry | undefined;
15
+ remove(id: string): void;
16
+ cleanupAll(): Promise<void>;
17
+ private autoRollback;
18
+ }
19
+ export declare const transactionStore: TransactionStore;
3
20
  export declare function createTransactionParams(dbIds: string[]): {
4
21
  database: z.ZodEnum<{
5
22
  [x: string]: string;
@@ -26,3 +43,4 @@ export declare function transactionHandler(manager: ConnectorManager): (params:
26
43
  text: string;
27
44
  }[];
28
45
  }>;
46
+ export {};
@@ -1,6 +1,63 @@
1
1
  import { z } from "zod";
2
2
  import { formatSuccess, formatError } from "../../utils/response.js";
3
- const activeTransactions = new Map();
3
+ import { getLogger } from "../../utils/logger.js";
4
+ const DEFAULT_TX_TTL_MS = 5 * 60 * 1000; // 5 minutes
5
+ export class TransactionStore {
6
+ entries = new Map();
7
+ ttlMs;
8
+ constructor(ttlMs = DEFAULT_TX_TTL_MS) {
9
+ this.ttlMs = ttlMs;
10
+ }
11
+ add(handle, database) {
12
+ const timer = setTimeout(() => {
13
+ this.autoRollback(handle.id);
14
+ }, this.ttlMs);
15
+ timer.unref();
16
+ this.entries.set(handle.id, { handle, database, timer });
17
+ }
18
+ get(id) {
19
+ return this.entries.get(id);
20
+ }
21
+ remove(id) {
22
+ const entry = this.entries.get(id);
23
+ if (entry) {
24
+ clearTimeout(entry.timer);
25
+ this.entries.delete(id);
26
+ }
27
+ }
28
+ async cleanupAll() {
29
+ const logger = getLogger();
30
+ const ids = Array.from(this.entries.keys());
31
+ for (const id of ids) {
32
+ await this.autoRollback(id);
33
+ }
34
+ logger.info("All transactions cleaned up", { count: ids.length });
35
+ }
36
+ async autoRollback(id) {
37
+ const entry = this.entries.get(id);
38
+ if (!entry)
39
+ return;
40
+ const logger = getLogger();
41
+ try {
42
+ await entry.handle.rollback();
43
+ logger.warn("Transaction auto-rolled back due to TTL expiry", {
44
+ transactionId: id,
45
+ database: entry.database,
46
+ });
47
+ }
48
+ catch (err) {
49
+ logger.error("Failed to auto-rollback transaction", {
50
+ transactionId: id,
51
+ error: String(err),
52
+ });
53
+ }
54
+ finally {
55
+ clearTimeout(entry.timer);
56
+ this.entries.delete(id);
57
+ }
58
+ }
59
+ }
60
+ export const transactionStore = new TransactionStore();
4
61
  export function createTransactionParams(dbIds) {
5
62
  return {
6
63
  database: z.enum(dbIds).describe(`Database ID. Available: ${dbIds.join(", ")}`),
@@ -17,7 +74,7 @@ export function transactionHandler(manager) {
17
74
  case "begin": {
18
75
  const connector = await manager.getConnector(params.database);
19
76
  const tx = await connector.beginTransaction();
20
- activeTransactions.set(tx.id, tx);
77
+ transactionStore.add(tx, params.database);
21
78
  return formatSuccess({
22
79
  data: { transactionId: tx.id, message: "Transaction started" },
23
80
  database: params.database,
@@ -28,10 +85,10 @@ export function transactionHandler(manager) {
28
85
  return formatError("transactionId is required for execute");
29
86
  if (!params.statement)
30
87
  return formatError("statement is required for execute");
31
- const tx = activeTransactions.get(params.transactionId);
32
- if (!tx)
88
+ const entry = transactionStore.get(params.transactionId);
89
+ if (!entry)
33
90
  return formatError(`Transaction not found: ${params.transactionId}`, "TX_NOT_FOUND");
34
- const result = await tx.execute(params.statement, params.params);
91
+ const result = await entry.handle.execute(params.statement, params.params);
35
92
  return formatSuccess({
36
93
  rows: result.rows,
37
94
  count: result.rowCount,
@@ -41,11 +98,11 @@ export function transactionHandler(manager) {
41
98
  case "commit": {
42
99
  if (!params.transactionId)
43
100
  return formatError("transactionId is required for commit");
44
- const tx = activeTransactions.get(params.transactionId);
45
- if (!tx)
101
+ const entry = transactionStore.get(params.transactionId);
102
+ if (!entry)
46
103
  return formatError(`Transaction not found: ${params.transactionId}`, "TX_NOT_FOUND");
47
- await tx.commit();
48
- activeTransactions.delete(params.transactionId);
104
+ await entry.handle.commit();
105
+ transactionStore.remove(params.transactionId);
49
106
  return formatSuccess({
50
107
  data: { message: "Transaction committed" },
51
108
  database: params.database,
@@ -54,11 +111,11 @@ export function transactionHandler(manager) {
54
111
  case "rollback": {
55
112
  if (!params.transactionId)
56
113
  return formatError("transactionId is required for rollback");
57
- const tx = activeTransactions.get(params.transactionId);
58
- if (!tx)
114
+ const entry = transactionStore.get(params.transactionId);
115
+ if (!entry)
59
116
  return formatError(`Transaction not found: ${params.transactionId}`, "TX_NOT_FOUND");
60
- await tx.rollback();
61
- activeTransactions.delete(params.transactionId);
117
+ await entry.handle.rollback();
118
+ transactionStore.remove(params.transactionId);
62
119
  return formatSuccess({
63
120
  data: { message: "Transaction rolled back" },
64
121
  database: params.database,
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../src/tools/write/transaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../src/tools/write/transaction.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import type { AppConfig, HttpTransportConfig } from "../config/types.js";
6
6
  interface SessionEntry {
7
7
  transport: StreamableHTTPServerTransport;
8
8
  server: McpServer;
9
+ lastAccessedAt: number;
9
10
  }
10
11
  export declare function startHttpTransport(config: AppConfig, transportConfig: HttpTransportConfig): Promise<{
11
12
  httpServer: Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>;
@@ -1,18 +1,22 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { randomUUID, timingSafeEqual } from "node:crypto";
2
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
3
  import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
4
4
  import { createConnectorManager, createMcpServerInstance } from "../server.js";
5
+ import { getLogger } from "../utils/logger.js";
5
6
  export async function startHttpTransport(config, transportConfig) {
7
+ const logger = getLogger();
6
8
  const manager = createConnectorManager(config);
7
9
  await manager.connectEager();
8
10
  const sessions = new Map();
9
11
  const { host, port } = transportConfig;
10
12
  const app = createMcpExpressApp({ host });
11
13
  if (transportConfig.auth) {
12
- const expectedToken = transportConfig.auth.token;
14
+ const expectedValue = `Bearer ${transportConfig.auth.token}`;
15
+ const expectedBuf = Buffer.from(expectedValue);
13
16
  app.use("/mcp", (req, res, next) => {
14
- const authHeader = req.headers.authorization;
15
- if (!authHeader || authHeader !== `Bearer ${expectedToken}`) {
17
+ const authHeader = req.headers.authorization ?? "";
18
+ const actualBuf = Buffer.from(authHeader);
19
+ if (actualBuf.length !== expectedBuf.length || !timingSafeEqual(actualBuf, expectedBuf)) {
16
20
  res.status(401).json({ error: "Unauthorized" });
17
21
  return;
18
22
  }
@@ -24,6 +28,19 @@ export async function startHttpTransport(config, transportConfig) {
24
28
  }
25
29
  else {
26
30
  setupStatefulRoutes(app, manager, config, sessions);
31
+ const sessionTimeout = transportConfig.sessionTimeout;
32
+ const cleanupInterval = setInterval(() => {
33
+ const now = Date.now();
34
+ for (const [sid, entry] of sessions) {
35
+ if (now - entry.lastAccessedAt > sessionTimeout) {
36
+ logger.info("Cleaning up expired session", { sessionId: sid });
37
+ entry.transport.close().catch(() => { });
38
+ entry.server.close().catch(() => { });
39
+ sessions.delete(sid);
40
+ }
41
+ }
42
+ }, 60_000);
43
+ cleanupInterval.unref();
27
44
  }
28
45
  setupHealthEndpoint(app, manager, sessions);
29
46
  const httpServer = await new Promise((resolve) => {
@@ -31,14 +48,9 @@ export async function startHttpTransport(config, transportConfig) {
31
48
  resolve(server);
32
49
  });
33
50
  });
34
- console.error(`db-view-mcp HTTP server listening on http://${host}:${port}/mcp`);
35
- console.error(`Health check: http://${host}:${port}/health`);
36
- if (transportConfig.stateless) {
37
- console.error("Mode: stateless");
38
- }
39
- else {
40
- console.error("Mode: stateful (session-based)");
41
- }
51
+ logger.info(`HTTP server listening on http://${host}:${port}/mcp`);
52
+ logger.info(`Health check: http://${host}:${port}/health`);
53
+ logger.info(`Mode: ${transportConfig.stateless ? "stateless" : "stateful (session-based)"}`);
42
54
  return { httpServer, manager, sessions };
43
55
  }
44
56
  function setupStatelessRoutes(app, manager, config) {
@@ -59,6 +71,7 @@ function setupStatefulRoutes(app, manager, config, sessions) {
59
71
  const sessionId = req.headers["mcp-session-id"];
60
72
  if (sessionId && sessions.has(sessionId)) {
61
73
  const session = sessions.get(sessionId);
74
+ session.lastAccessedAt = Date.now();
62
75
  await session.transport.handleRequest(req, res, req.body);
63
76
  return;
64
77
  }
@@ -71,7 +84,7 @@ function setupStatefulRoutes(app, manager, config, sessions) {
71
84
  const transport = new StreamableHTTPServerTransport({
72
85
  sessionIdGenerator: () => randomUUID(),
73
86
  onsessioninitialized: (newSessionId) => {
74
- sessions.set(newSessionId, { transport, server });
87
+ sessions.set(newSessionId, { transport, server, lastAccessedAt: Date.now() });
75
88
  },
76
89
  });
77
90
  transport.onclose = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ type LogLevel = "debug" | "info" | "warn" | "error";
2
+ export declare class Logger {
3
+ private level;
4
+ private context;
5
+ constructor(level?: LogLevel, context?: Record<string, unknown>);
6
+ child(context: Record<string, unknown>): Logger;
7
+ debug(message: string, data?: Record<string, unknown>): void;
8
+ info(message: string, data?: Record<string, unknown>): void;
9
+ warn(message: string, data?: Record<string, unknown>): void;
10
+ error(message: string, data?: Record<string, unknown>): void;
11
+ private log;
12
+ }
13
+ export declare function initLogger(level: LogLevel): Logger;
14
+ export declare function getLogger(): Logger;
15
+ export {};
@@ -0,0 +1,52 @@
1
+ const LOG_LEVELS = {
2
+ debug: 0,
3
+ info: 1,
4
+ warn: 2,
5
+ error: 3,
6
+ };
7
+ export class Logger {
8
+ level;
9
+ context;
10
+ constructor(level = "info", context = {}) {
11
+ this.level = LOG_LEVELS[level];
12
+ this.context = context;
13
+ }
14
+ child(context) {
15
+ const child = new Logger("debug", { ...this.context, ...context });
16
+ child.level = this.level;
17
+ return child;
18
+ }
19
+ debug(message, data) {
20
+ this.log("debug", message, data);
21
+ }
22
+ info(message, data) {
23
+ this.log("info", message, data);
24
+ }
25
+ warn(message, data) {
26
+ this.log("warn", message, data);
27
+ }
28
+ error(message, data) {
29
+ this.log("error", message, data);
30
+ }
31
+ log(level, message, data) {
32
+ if (LOG_LEVELS[level] < this.level)
33
+ return;
34
+ const entry = {
35
+ level,
36
+ message,
37
+ timestamp: new Date().toISOString(),
38
+ ...this.context,
39
+ ...data,
40
+ };
41
+ process.stderr.write(JSON.stringify(entry) + "\n");
42
+ }
43
+ }
44
+ let globalLogger = new Logger("info");
45
+ export function initLogger(level) {
46
+ globalLogger = new Logger(level);
47
+ return globalLogger;
48
+ }
49
+ export function getLogger() {
50
+ return globalLogger;
51
+ }
52
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AASF,MAAM,OAAO,MAAM;IACT,KAAK,CAAS;IACd,OAAO,CAA0B;IAEzC,YAAY,QAAkB,MAAM,EAAE,UAAmC,EAAE;QACzE,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,OAAgC;QACpC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QACnE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAEO,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAA8B;QAC1E,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK;YAAE,OAAO;QAE3C,MAAM,KAAK,GAAa;YACtB,KAAK;YACL,OAAO;YACP,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,GAAG,IAAI,CAAC,OAAO;YACf,GAAG,IAAI;SACR,CAAC;QAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;CACF;AAED,IAAI,YAAY,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;AAEtC,MAAM,UAAU,UAAU,CAAC,KAAe;IACxC,YAAY,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -1,34 +1,54 @@
1
1
  const WRITE_KEYWORDS = [
2
- "INSERT",
3
- "UPDATE",
4
- "DELETE",
5
- "DROP",
6
- "ALTER",
7
- "TRUNCATE",
8
- "CREATE",
9
- "GRANT",
10
- "REVOKE",
11
- "REPLACE",
12
- "MERGE",
2
+ "INSERT", "UPDATE", "DELETE", "DROP",
3
+ "ALTER", "TRUNCATE", "CREATE",
4
+ "GRANT", "REVOKE", "REPLACE", "MERGE",
5
+ "COPY", "CALL",
13
6
  ];
14
- const WRITE_PATTERN = new RegExp(`^\\s*(${WRITE_KEYWORDS.join("|")})\\b`, "i");
15
- const MULTI_STATEMENT_PATTERN = /;\s*\S/;
7
+ const WRITE_PATTERN = new RegExp(`\\b(${WRITE_KEYWORDS.join("|")})\\b`, "i");
8
+ function stripStringLiterals(sql) {
9
+ // Replace single-quoted strings (handling escaped quotes)
10
+ let result = sql.replace(/'(?:[^'\\]|\\.)*'/g, "__STR__");
11
+ // Replace double-quoted identifiers
12
+ result = result.replace(/"(?:[^"\\]|\\.)*"/g, "__ID__");
13
+ // Replace dollar-quoted strings (PostgreSQL): $$...$$, $tag$...$tag$
14
+ result = result.replace(/\$([^$]*)\$[\s\S]*?\$\1\$/g, "__STR__");
15
+ return result;
16
+ }
17
+ function stripComments(sql) {
18
+ // Remove block comments
19
+ let result = sql.replace(/\/\*[\s\S]*?\*\//g, " ");
20
+ // Remove line comments
21
+ result = result.replace(/--[^\n]*/g, " ");
22
+ return result;
23
+ }
24
+ function normalizeWhitespace(sql) {
25
+ return sql.replace(/\s+/g, " ").trim();
26
+ }
16
27
  export function validateReadonlySql(sql) {
17
28
  const trimmed = sql.trim();
18
29
  if (!trimmed) {
19
30
  return { valid: false, error: "Empty SQL statement" };
20
31
  }
21
- if (MULTI_STATEMENT_PATTERN.test(trimmed)) {
22
- return {
23
- valid: false,
24
- error: "Multiple statements are not allowed in read-only mode",
25
- };
32
+ // Normalize: strip strings first, then comments, then whitespace
33
+ const noStrings = stripStringLiterals(trimmed);
34
+ const noComments = stripComments(noStrings);
35
+ const normalized = normalizeWhitespace(noComments);
36
+ // Check for multiple statements (after removing string literals)
37
+ if (normalized.includes(";")) {
38
+ const afterSemicolon = normalized.split(";").slice(1).join(";").trim();
39
+ if (afterSemicolon.length > 0) {
40
+ return {
41
+ valid: false,
42
+ error: "Multiple statements are not allowed in read-only mode",
43
+ };
44
+ }
26
45
  }
27
- if (WRITE_PATTERN.test(trimmed)) {
28
- const match = trimmed.match(/^\s*(\w+)/);
46
+ // Check for write keywords anywhere in normalized SQL
47
+ const match = normalized.match(WRITE_PATTERN);
48
+ if (match) {
29
49
  return {
30
50
  valid: false,
31
- error: `Statement '${match?.[1]?.toUpperCase()}' is not allowed in read-only mode`,
51
+ error: `Statement '${match[1].toUpperCase()}' is not allowed in read-only mode`,
32
52
  };
33
53
  }
34
54
  return { valid: true };