@pilat/mcp-datalink 1.0.1

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 (95) hide show
  1. package/README.md +442 -0
  2. package/databases.example.json +18 -0
  3. package/dist/__integration__/global-setup.d.ts +8 -0
  4. package/dist/__integration__/global-setup.d.ts.map +1 -0
  5. package/dist/__integration__/global-setup.js +34 -0
  6. package/dist/__integration__/global-setup.js.map +1 -0
  7. package/dist/__integration__/global-teardown.d.ts +8 -0
  8. package/dist/__integration__/global-teardown.d.ts.map +1 -0
  9. package/dist/__integration__/global-teardown.js +17 -0
  10. package/dist/__integration__/global-teardown.js.map +1 -0
  11. package/dist/__integration__/helpers.d.ts +58 -0
  12. package/dist/__integration__/helpers.d.ts.map +1 -0
  13. package/dist/__integration__/helpers.js +568 -0
  14. package/dist/__integration__/helpers.js.map +1 -0
  15. package/dist/__integration__/setup.d.ts +79 -0
  16. package/dist/__integration__/setup.d.ts.map +1 -0
  17. package/dist/__integration__/setup.js +230 -0
  18. package/dist/__integration__/setup.js.map +1 -0
  19. package/dist/adapters/factory.d.ts +40 -0
  20. package/dist/adapters/factory.d.ts.map +1 -0
  21. package/dist/adapters/factory.js +114 -0
  22. package/dist/adapters/factory.js.map +1 -0
  23. package/dist/adapters/index.d.ts +31 -0
  24. package/dist/adapters/index.d.ts.map +1 -0
  25. package/dist/adapters/index.js +34 -0
  26. package/dist/adapters/index.js.map +1 -0
  27. package/dist/adapters/mysql/adapter.d.ts +61 -0
  28. package/dist/adapters/mysql/adapter.d.ts.map +1 -0
  29. package/dist/adapters/mysql/adapter.js +567 -0
  30. package/dist/adapters/mysql/adapter.js.map +1 -0
  31. package/dist/adapters/postgresql/adapter.d.ts +52 -0
  32. package/dist/adapters/postgresql/adapter.d.ts.map +1 -0
  33. package/dist/adapters/postgresql/adapter.js +429 -0
  34. package/dist/adapters/postgresql/adapter.js.map +1 -0
  35. package/dist/adapters/sqlite/adapter.d.ts +56 -0
  36. package/dist/adapters/sqlite/adapter.d.ts.map +1 -0
  37. package/dist/adapters/sqlite/adapter.js +582 -0
  38. package/dist/adapters/sqlite/adapter.js.map +1 -0
  39. package/dist/adapters/types.d.ts +155 -0
  40. package/dist/adapters/types.d.ts.map +1 -0
  41. package/dist/adapters/types.js +7 -0
  42. package/dist/adapters/types.js.map +1 -0
  43. package/dist/config/loader.d.ts +11 -0
  44. package/dist/config/loader.d.ts.map +1 -0
  45. package/dist/config/loader.js +127 -0
  46. package/dist/config/loader.js.map +1 -0
  47. package/dist/index.d.ts +8 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +38 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/server.d.ts +21 -0
  52. package/dist/server.d.ts.map +1 -0
  53. package/dist/server.js +191 -0
  54. package/dist/server.js.map +1 -0
  55. package/dist/tools/describe-table.d.ts +11 -0
  56. package/dist/tools/describe-table.d.ts.map +1 -0
  57. package/dist/tools/describe-table.js +23 -0
  58. package/dist/tools/describe-table.js.map +1 -0
  59. package/dist/tools/execute.d.ts +22 -0
  60. package/dist/tools/execute.d.ts.map +1 -0
  61. package/dist/tools/execute.js +48 -0
  62. package/dist/tools/execute.js.map +1 -0
  63. package/dist/tools/explain.d.ts +25 -0
  64. package/dist/tools/explain.d.ts.map +1 -0
  65. package/dist/tools/explain.js +81 -0
  66. package/dist/tools/explain.js.map +1 -0
  67. package/dist/tools/list-databases.d.ts +18 -0
  68. package/dist/tools/list-databases.d.ts.map +1 -0
  69. package/dist/tools/list-databases.js +17 -0
  70. package/dist/tools/list-databases.js.map +1 -0
  71. package/dist/tools/list-tables.d.ts +22 -0
  72. package/dist/tools/list-tables.d.ts.map +1 -0
  73. package/dist/tools/list-tables.js +43 -0
  74. package/dist/tools/list-tables.js.map +1 -0
  75. package/dist/tools/query.d.ts +25 -0
  76. package/dist/tools/query.d.ts.map +1 -0
  77. package/dist/tools/query.js +109 -0
  78. package/dist/tools/query.js.map +1 -0
  79. package/dist/types.d.ts +93 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +5 -0
  82. package/dist/types.js.map +1 -0
  83. package/dist/utils/errors.d.ts +22 -0
  84. package/dist/utils/errors.d.ts.map +1 -0
  85. package/dist/utils/errors.js +41 -0
  86. package/dist/utils/errors.js.map +1 -0
  87. package/dist/utils/formatter.d.ts +13 -0
  88. package/dist/utils/formatter.d.ts.map +1 -0
  89. package/dist/utils/formatter.js +56 -0
  90. package/dist/utils/formatter.js.map +1 -0
  91. package/dist/utils/truncate.d.ts +37 -0
  92. package/dist/utils/truncate.d.ts.map +1 -0
  93. package/dist/utils/truncate.js +91 -0
  94. package/dist/utils/truncate.js.map +1 -0
  95. package/package.json +65 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Execute tool for INSERT/UPDATE/DELETE statements
3
+ */
4
+ import type { Config, ExecuteResult } from '../types.js';
5
+ export interface ExecuteParams {
6
+ database: string;
7
+ sql: string;
8
+ params?: unknown[];
9
+ }
10
+ /**
11
+ * Execute an INSERT/UPDATE/DELETE statement
12
+ *
13
+ * @param params - Execute parameters including database name, SQL, and optional params
14
+ * @param config - Application configuration
15
+ * @returns ExecuteResult with command type and rows affected
16
+ * @throws DbMcpError with READONLY_VIOLATION if database is readonly
17
+ * @throws DbMcpError with QUERY_BLOCKED if SELECT or dangerous DDL
18
+ * @throws DbMcpError with DATABASE_NOT_FOUND if database not configured
19
+ * @throws DbMcpError with CONNECTION_FAILED if connection fails
20
+ */
21
+ export declare function execute(params: ExecuteParams, config: Config): Promise<ExecuteResult>;
22
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/tools/execute.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIzD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,CA+CxB"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Execute tool for INSERT/UPDATE/DELETE statements
3
+ */
4
+ import { createAdapter } from '../adapters/index.js';
5
+ import { DbMcpError, ErrorCode } from '../utils/errors.js';
6
+ /**
7
+ * Execute an INSERT/UPDATE/DELETE statement
8
+ *
9
+ * @param params - Execute parameters including database name, SQL, and optional params
10
+ * @param config - Application configuration
11
+ * @returns ExecuteResult with command type and rows affected
12
+ * @throws DbMcpError with READONLY_VIOLATION if database is readonly
13
+ * @throws DbMcpError with QUERY_BLOCKED if SELECT or dangerous DDL
14
+ * @throws DbMcpError with DATABASE_NOT_FOUND if database not configured
15
+ * @throws DbMcpError with CONNECTION_FAILED if connection fails
16
+ */
17
+ export async function execute(params, config) {
18
+ const startTime = Date.now();
19
+ // Get database config
20
+ const dbConfig = config.databases[params.database];
21
+ if (!dbConfig) {
22
+ throw new DbMcpError(ErrorCode.DATABASE_NOT_FOUND, `Database "${params.database}" not found in configuration`, { database: params.database, available: Object.keys(config.databases) });
23
+ }
24
+ // Step 1: Check if database is readonly
25
+ if (dbConfig.readonly) {
26
+ throw new DbMcpError(ErrorCode.READONLY_VIOLATION, `Database "${params.database}" is configured as readonly. INSERT/UPDATE/DELETE operations are not allowed.`, { database: params.database });
27
+ }
28
+ // Create adapter for this database
29
+ const adapter = createAdapter(dbConfig, config.defaults);
30
+ // Step 2: Validate query type - blocks SELECT and dangerous DDL
31
+ adapter.validateQueryForTool(params.sql, 'execute');
32
+ // Step 3: Get the command type from parsed query
33
+ const parsed = adapter.parseQuery(params.sql);
34
+ const command = parsed.type.toUpperCase();
35
+ // Step 4: Convert placeholders for non-PostgreSQL dialects
36
+ // PostgreSQL uses $1, $2; MySQL/SQLite use ?
37
+ const sql = adapter.convertPlaceholders(params.sql);
38
+ const result = await adapter.withConnection(async (conn) => {
39
+ return conn.query(sql, params.params ?? []);
40
+ });
41
+ const executionTime = Date.now() - startTime;
42
+ return {
43
+ command,
44
+ rowsAffected: result.rowCount,
45
+ executionTime,
46
+ };
47
+ }
48
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/tools/execute.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQ3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAqB,EACrB,MAAc;IAEd,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,sBAAsB;IACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,kBAAkB,EAC5B,aAAa,MAAM,CAAC,QAAQ,8BAA8B,EAC1D,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CACxE,CAAC;IACJ,CAAC;IAED,wCAAwC;IACxC,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,kBAAkB,EAC5B,aAAa,MAAM,CAAC,QAAQ,+EAA+E,EAC3G,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAC9B,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEzD,gEAAgE;IAChE,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEpD,iDAAiD;IACjD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAE1C,2DAA2D;IAC3D,6CAA6C;IAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAE7C,OAAO;QACL,OAAO;QACP,YAAY,EAAE,MAAM,CAAC,QAAQ;QAC7B,aAAa;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Explain tool for showing query execution plans
3
+ */
4
+ import type { Config } from '../types.js';
5
+ export interface ExplainParams {
6
+ database: string;
7
+ sql: string;
8
+ analyze?: boolean;
9
+ }
10
+ export interface ExplainResult {
11
+ plan: string;
12
+ executionTime: number;
13
+ }
14
+ /**
15
+ * Get the execution plan for a SQL query
16
+ *
17
+ * @param params - Explain parameters including database name, SQL, and optional analyze flag
18
+ * @param config - Application configuration
19
+ * @returns ExplainResult with plan text and execution time
20
+ * @throws DbMcpError with QUERY_BLOCKED if query is dangerous (DROP, TRUNCATE, etc.)
21
+ * @throws DbMcpError with DATABASE_NOT_FOUND if database not configured
22
+ * @throws DbMcpError with CONNECTION_FAILED if connection fails
23
+ */
24
+ export declare function explain(params: ExplainParams, config: Config): Promise<ExplainResult>;
25
+ //# sourceMappingURL=explain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../src/tools/explain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,CAmFxB"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Explain tool for showing query execution plans
3
+ */
4
+ import { createAdapter } from '../adapters/index.js';
5
+ import { DbMcpError, ErrorCode } from '../utils/errors.js';
6
+ /**
7
+ * Get the execution plan for a SQL query
8
+ *
9
+ * @param params - Explain parameters including database name, SQL, and optional analyze flag
10
+ * @param config - Application configuration
11
+ * @returns ExplainResult with plan text and execution time
12
+ * @throws DbMcpError with QUERY_BLOCKED if query is dangerous (DROP, TRUNCATE, etc.)
13
+ * @throws DbMcpError with DATABASE_NOT_FOUND if database not configured
14
+ * @throws DbMcpError with CONNECTION_FAILED if connection fails
15
+ */
16
+ export async function explain(params, config) {
17
+ const startTime = Date.now();
18
+ // Get database config
19
+ const dbConfig = config.databases[params.database];
20
+ if (!dbConfig) {
21
+ throw new DbMcpError(ErrorCode.DATABASE_NOT_FOUND, `Database "${params.database}" not found in configuration`, { database: params.database, available: Object.keys(config.databases) });
22
+ }
23
+ // Create adapter for this database
24
+ const adapter = createAdapter(dbConfig, config.defaults);
25
+ // Step 1: Parse query and check for dangerous operations
26
+ const parsed = adapter.parseQuery(params.sql);
27
+ if (parsed.isDangerous) {
28
+ throw new DbMcpError(ErrorCode.QUERY_BLOCKED, parsed.dangerousReason ?? 'This operation is not allowed', { sql: params.sql, queryType: parsed.type });
29
+ }
30
+ const result = await adapter.withConnection(async (conn) => {
31
+ // Build EXPLAIN query using adapter-specific prefix
32
+ const explainPrefix = adapter.getExplainPrefix(params.analyze ?? false);
33
+ // SQLite and MySQL don't need READ ONLY transactions for EXPLAIN:
34
+ // - SQLite: Doesn't support READ ONLY transactions
35
+ // - MySQL: EXPLAIN doesn't execute the query, and READ ONLY tx blocks
36
+ // EXPLAIN on UPDATE/DELETE even though they're safe
37
+ //
38
+ // Defense in depth is still provided by:
39
+ // 1. SQL parser blocking dangerous operations (DROP, TRUNCATE, etc.)
40
+ // 2. EXPLAIN not executing the query (MySQL) / EXPLAIN QUERY PLAN (SQLite)
41
+ // 3. Database adapter opening in readonly mode when configured
42
+ if (adapter.type === 'sqlite' || adapter.type === 'mysql') {
43
+ return await conn.query(explainPrefix + params.sql);
44
+ }
45
+ // PostgreSQL: Use READ ONLY transaction since EXPLAIN ANALYZE executes the query
46
+ await conn.execute('BEGIN TRANSACTION READ ONLY');
47
+ try {
48
+ const queryResult = await conn.query(explainPrefix + params.sql);
49
+ await conn.execute('COMMIT');
50
+ return queryResult;
51
+ }
52
+ catch (error) {
53
+ await conn.execute('ROLLBACK');
54
+ throw error;
55
+ }
56
+ });
57
+ // Step 3: Format plan as text (join rows with newlines)
58
+ // Different databases have different EXPLAIN output formats:
59
+ // - PostgreSQL: Single column with plan text
60
+ // - MySQL: Multiple columns (id, select_type, table, type, key, rows, Extra, etc.)
61
+ // - SQLite: 4 columns (id, parent, notused, detail)
62
+ const planLines = result.rows.map((row) => {
63
+ if (adapter.type === 'sqlite' && row.length >= 4) {
64
+ // SQLite: extract the 'detail' column (4th column, index 3)
65
+ return String(row[3]);
66
+ }
67
+ if (adapter.type === 'mysql' && row.length > 1) {
68
+ // MySQL: Join all columns with tabs for tabular output
69
+ // Columns: id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
70
+ return row.map((col) => (col === null ? 'NULL' : String(col))).join('\t');
71
+ }
72
+ // PostgreSQL: first column is the plan line
73
+ return row[0];
74
+ });
75
+ const executionTime = Date.now() - startTime;
76
+ return {
77
+ plan: planLines.join('\n'),
78
+ executionTime,
79
+ };
80
+ }
81
+ //# sourceMappingURL=explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/tools/explain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAa3D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAqB,EACrB,MAAc;IAEd,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,sBAAsB;IACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,kBAAkB,EAC5B,aAAa,MAAM,CAAC,QAAQ,8BAA8B,EAC1D,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CACxE,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEzD,yDAAyD;IACzD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAE9C,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,aAAa,EACvB,MAAM,CAAC,eAAe,IAAI,+BAA+B,EACzD,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,CAC5C,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACzD,oDAAoD;QACpD,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;QAExE,kEAAkE;QAClE,mDAAmD;QACnD,sEAAsE;QACtE,sDAAsD;QACtD,EAAE;QACF,yCAAyC;QACzC,qEAAqE;QACrE,2EAA2E;QAC3E,+DAA+D;QAC/D,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1D,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtD,CAAC;QAED,iFAAiF;QACjF,MAAM,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAEjE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC7B,OAAO,WAAW,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC/B,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,6DAA6D;IAC7D,6CAA6C;IAC7C,mFAAmF;IACnF,oDAAoD;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACjD,4DAA4D;YAC5D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,uDAAuD;YACvD,6GAA6G;YAC7G,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,CAAC;QACD,4CAA4C;QAC5C,OAAO,GAAG,CAAC,CAAC,CAAW,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAE7C,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1B,aAAa;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * list_databases tool - returns configured databases from config
3
+ */
4
+ import type { Config } from '../types.js';
5
+ export interface ListDatabasesResult {
6
+ databases: Array<{
7
+ name: string;
8
+ readonly: boolean;
9
+ }>;
10
+ }
11
+ /**
12
+ * Returns all configured databases with their readonly flags.
13
+ *
14
+ * @param config - The application config containing database configurations
15
+ * @returns List of databases with name and readonly status
16
+ */
17
+ export declare function listDatabases(config: Config): ListDatabasesResult;
18
+ //# sourceMappingURL=list-databases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-databases.d.ts","sourceRoot":"","sources":["../../src/tools/list-databases.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC,CAAC;CACJ;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAOjE"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * list_databases tool - returns configured databases from config
3
+ */
4
+ /**
5
+ * Returns all configured databases with their readonly flags.
6
+ *
7
+ * @param config - The application config containing database configurations
8
+ * @returns List of databases with name and readonly status
9
+ */
10
+ export function listDatabases(config) {
11
+ const databases = Object.entries(config.databases).map(([name, dbConfig]) => ({
12
+ name,
13
+ readonly: dbConfig.readonly,
14
+ }));
15
+ return { databases };
16
+ }
17
+ //# sourceMappingURL=list-databases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-databases.js","sourceRoot":"","sources":["../../src/tools/list-databases.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5E,IAAI;QACJ,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC5B,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * list_tables tool - lists tables in a database schema
3
+ */
4
+ import type { Config, TableInfo } from '../types.js';
5
+ export interface ListTablesParams {
6
+ database: string;
7
+ schema?: string;
8
+ }
9
+ export interface ListTablesResult {
10
+ tables: TableInfo[];
11
+ truncated: boolean;
12
+ totalAvailable?: number;
13
+ }
14
+ /**
15
+ * Lists tables and views in a database schema.
16
+ *
17
+ * @param params - Database name and optional schema (defaults to "public")
18
+ * @param config - The application config
19
+ * @returns List of tables with truncation info if over maxTables limit
20
+ */
21
+ export declare function listTables(params: ListTablesParams, config: Config): Promise<ListTablesResult>;
22
+ //# sourceMappingURL=list-tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-tables.d.ts","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIrD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CAuC3B"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * list_tables tool - lists tables in a database schema
3
+ */
4
+ import { createAdapter } from '../adapters/index.js';
5
+ import { DbMcpError, ErrorCode } from '../utils/errors.js';
6
+ /**
7
+ * Lists tables and views in a database schema.
8
+ *
9
+ * @param params - Database name and optional schema (defaults to "public")
10
+ * @param config - The application config
11
+ * @returns List of tables with truncation info if over maxTables limit
12
+ */
13
+ export async function listTables(params, config) {
14
+ const maxTables = config.defaults.maxTables;
15
+ // Get database config
16
+ const dbConfig = config.databases[params.database];
17
+ if (!dbConfig) {
18
+ throw new DbMcpError(ErrorCode.DATABASE_NOT_FOUND, `Database "${params.database}" not found in configuration`, { database: params.database, available: Object.keys(config.databases) });
19
+ }
20
+ // Create adapter for this database
21
+ const adapter = createAdapter(dbConfig, config.defaults);
22
+ // Use provided schema or adapter's default schema
23
+ // PostgreSQL: "public", MySQL: database name, SQLite: "main"
24
+ const schema = params.schema ?? adapter.getDefaultSchema();
25
+ return adapter.withConnection(async (conn) => {
26
+ const result = await conn.listTables(schema, maxTables);
27
+ const allTables = result.tables;
28
+ const totalAvailable = result.totalAvailable;
29
+ const truncated = totalAvailable > maxTables;
30
+ if (truncated) {
31
+ return {
32
+ tables: allTables.slice(0, maxTables),
33
+ truncated: true,
34
+ totalAvailable,
35
+ };
36
+ }
37
+ return {
38
+ tables: allTables,
39
+ truncated: false,
40
+ };
41
+ });
42
+ }
43
+ //# sourceMappingURL=list-tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-tables.js","sourceRoot":"","sources":["../../src/tools/list-tables.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAa3D;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAwB,EACxB,MAAc;IAEd,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;IAE5C,sBAAsB;IACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,kBAAkB,EAC5B,aAAa,MAAM,CAAC,QAAQ,8BAA8B,EAC1D,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CACxE,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEzD,kDAAkD;IAClD,6DAA6D;IAC7D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAE3D,OAAO,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;QAChC,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7C,MAAM,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC;QAE7C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO;gBACL,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;gBACrC,SAAS,EAAE,IAAI;gBACf,cAAc;aACf,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Query tool for executing SELECT statements
3
+ */
4
+ import type { Config, QueryResult } from '../types.js';
5
+ export interface QueryParams {
6
+ database: string;
7
+ sql: string;
8
+ params?: unknown[];
9
+ }
10
+ /**
11
+ * Format QueryResult as Markdown table followed by metadata
12
+ */
13
+ export declare function formatQueryResultAsMarkdown(result: QueryResult): string;
14
+ /**
15
+ * Execute a SELECT query and return formatted results
16
+ *
17
+ * @param params - Query parameters including database name, SQL, and optional params
18
+ * @param config - Application configuration
19
+ * @returns QueryResult with columns, rows, and metadata
20
+ * @throws DbMcpError with QUERY_BLOCKED if not a SELECT query
21
+ * @throws DbMcpError with DATABASE_NOT_FOUND if database not configured
22
+ * @throws DbMcpError with CONNECTION_FAILED if connection fails
23
+ */
24
+ export declare function query(params: QueryParams, config: Config): Promise<QueryResult>;
25
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAMvD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAqBvE;AAED;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,CAAC,CA6FtB"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Query tool for executing SELECT statements
3
+ */
4
+ import { createAdapter } from '../adapters/index.js';
5
+ import { DbMcpError, ErrorCode } from '../utils/errors.js';
6
+ import { truncateRows, truncateCell, checkTotalSize } from '../utils/truncate.js';
7
+ import { formatAsMarkdownTable, formatValue } from '../utils/formatter.js';
8
+ /**
9
+ * Format QueryResult as Markdown table followed by metadata
10
+ */
11
+ export function formatQueryResultAsMarkdown(result) {
12
+ const parts = [];
13
+ // Data as Markdown table
14
+ const table = formatAsMarkdownTable(result.columns, result.rows);
15
+ if (table) {
16
+ parts.push(table);
17
+ }
18
+ else {
19
+ parts.push('_No results_');
20
+ }
21
+ // Metadata section
22
+ parts.push('');
23
+ parts.push(`**Rows:** ${result.rowCount}${result.truncated ? ` (truncated from ${result.totalAvailable ?? 'unknown'})` : ''}`);
24
+ parts.push(`**Execution time:** ${result.executionTime}ms`);
25
+ if (result.truncated && result.hint) {
26
+ parts.push(`**Hint:** ${result.hint}`);
27
+ }
28
+ return parts.join('\n');
29
+ }
30
+ /**
31
+ * Execute a SELECT query and return formatted results
32
+ *
33
+ * @param params - Query parameters including database name, SQL, and optional params
34
+ * @param config - Application configuration
35
+ * @returns QueryResult with columns, rows, and metadata
36
+ * @throws DbMcpError with QUERY_BLOCKED if not a SELECT query
37
+ * @throws DbMcpError with DATABASE_NOT_FOUND if database not configured
38
+ * @throws DbMcpError with CONNECTION_FAILED if connection fails
39
+ */
40
+ export async function query(params, config) {
41
+ const startTime = Date.now();
42
+ // Get database config
43
+ const dbConfig = config.databases[params.database];
44
+ if (!dbConfig) {
45
+ throw new DbMcpError(ErrorCode.DATABASE_NOT_FOUND, `Database "${params.database}" not found in configuration`, { database: params.database, available: Object.keys(config.databases) });
46
+ }
47
+ // Create adapter for this database
48
+ const adapter = createAdapter(dbConfig, config.defaults);
49
+ // Step 1: Validate that this is a SELECT query
50
+ adapter.validateQueryForTool(params.sql, 'query');
51
+ // Step 2: Parse query and inject LIMIT if missing
52
+ const parsed = adapter.parseQuery(params.sql);
53
+ let sql = params.sql;
54
+ if (!parsed.hasLimit) {
55
+ // Get maxRows from database config or defaults
56
+ const maxRows = dbConfig?.maxRows ?? config.defaults.maxRows;
57
+ sql = adapter.injectLimit(params.sql, maxRows);
58
+ }
59
+ // Step 3: Convert placeholders for non-PostgreSQL dialects
60
+ // PostgreSQL uses $1, $2; MySQL/SQLite use ?
61
+ sql = adapter.convertPlaceholders(sql);
62
+ const result = await adapter.withConnection(async (conn) => {
63
+ return conn.query(sql, params.params ?? []);
64
+ });
65
+ const columns = result.fields.map((field) => field.name);
66
+ const rawRows = result.rows;
67
+ // Step 4: Format each cell value
68
+ let formattedRows = rawRows.map((row) => row.map((cell) => formatValue(cell)));
69
+ // Step 5: Truncate individual cells if over maxCellLength
70
+ let anyCellTruncated = false;
71
+ formattedRows = formattedRows.map((row) => row.map((cell) => {
72
+ const truncated = truncateCell(cell, config.defaults.maxCellLength);
73
+ if (truncated.truncated) {
74
+ anyCellTruncated = true;
75
+ }
76
+ return truncated.value;
77
+ }));
78
+ // Step 6: Truncate rows if over maxRows
79
+ const { rows: truncatedRows, info: rowTruncationInfo } = truncateRows(formattedRows, config.defaults.maxRows);
80
+ // Step 7: Check total size
81
+ const tableOutput = formatAsMarkdownTable(columns, truncatedRows);
82
+ const sizeInfo = checkTotalSize(tableOutput, config.defaults.maxTotalSize);
83
+ // Determine final truncation state
84
+ const truncated = rowTruncationInfo.truncated || anyCellTruncated || sizeInfo.truncated;
85
+ // Determine truncation reason (priority: maxTotalSize > maxRows > maxCellLength)
86
+ let truncationReason;
87
+ if (sizeInfo.truncated) {
88
+ truncationReason = sizeInfo.truncationReason;
89
+ }
90
+ else if (rowTruncationInfo.truncated) {
91
+ truncationReason = rowTruncationInfo.truncationReason;
92
+ }
93
+ else if (anyCellTruncated) {
94
+ truncationReason = 'maxCellLength';
95
+ }
96
+ const executionTime = Date.now() - startTime;
97
+ return {
98
+ columns,
99
+ rows: truncatedRows,
100
+ rowCount: truncatedRows.length,
101
+ truncated,
102
+ truncationReason,
103
+ totalAvailable: rowTruncationInfo.totalAvailable,
104
+ returned: rowTruncationInfo.returned,
105
+ hint: rowTruncationInfo.hint ?? sizeInfo.hint,
106
+ executionTime,
107
+ };
108
+ }
109
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Core types for db-mcp server
3
+ */
4
+ export type QueryType = 'select' | 'insert' | 'update' | 'delete' | 'other';
5
+ export interface ParsedQuery {
6
+ /** The type of SQL query */
7
+ type: QueryType;
8
+ /** Whether the query has a LIMIT clause (for SELECT queries) */
9
+ hasLimit: boolean;
10
+ /** Whether the query is dangerous (DROP, TRUNCATE, ALTER, etc.) */
11
+ isDangerous: boolean;
12
+ /** Reason why query is considered dangerous */
13
+ dangerousReason?: string;
14
+ /** The original SQL string */
15
+ sql: string;
16
+ }
17
+ export interface DatabaseConfig {
18
+ url: string;
19
+ readonly: boolean;
20
+ maxRows?: number;
21
+ }
22
+ export interface DefaultsConfig {
23
+ maxRows: number;
24
+ maxCellLength: number;
25
+ maxTotalSize: number;
26
+ maxColumns: number;
27
+ maxTables: number;
28
+ maxIndexes: number;
29
+ timeout: number;
30
+ }
31
+ export interface Config {
32
+ databases: Record<string, DatabaseConfig>;
33
+ defaults: DefaultsConfig;
34
+ }
35
+ /** Raw config shape before defaults are applied */
36
+ export interface RawConfig {
37
+ databases?: Record<string, Partial<DatabaseConfig> & {
38
+ url: string;
39
+ }>;
40
+ defaults?: Partial<DefaultsConfig>;
41
+ }
42
+ export interface QueryResult {
43
+ columns: string[];
44
+ rows: unknown[][];
45
+ rowCount: number;
46
+ truncated: boolean;
47
+ truncationReason?: string;
48
+ totalAvailable?: number;
49
+ returned?: number;
50
+ hint?: string;
51
+ executionTime: number;
52
+ }
53
+ export interface ExecuteResult {
54
+ command: string;
55
+ rowsAffected: number;
56
+ executionTime: number;
57
+ }
58
+ export interface ColumnInfo {
59
+ name: string;
60
+ type: string;
61
+ nullable: boolean;
62
+ default: string | null;
63
+ primaryKey: boolean;
64
+ }
65
+ export interface IndexInfo {
66
+ name: string;
67
+ columns: string[];
68
+ unique: boolean;
69
+ primary: boolean;
70
+ }
71
+ export interface ForeignKeyInfo {
72
+ column: string;
73
+ references: {
74
+ table: string;
75
+ column: string;
76
+ };
77
+ }
78
+ export interface TableDescription {
79
+ table: string;
80
+ schema: string;
81
+ columns: ColumnInfo[];
82
+ indexes: IndexInfo[];
83
+ foreignKeys: ForeignKeyInfo[];
84
+ truncated: boolean;
85
+ truncationReason?: string;
86
+ }
87
+ export interface TableInfo {
88
+ name: string;
89
+ schema: string;
90
+ type: 'table' | 'view';
91
+ rows_estimate: number | null;
92
+ }
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,gEAAgE;IAChE,QAAQ,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core types for db-mcp server
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Error types and handling for db-mcp server
3
+ */
4
+ export declare const ErrorCode: {
5
+ readonly INVALID_SQL: "INVALID_SQL";
6
+ readonly MULTI_STATEMENT: "MULTI_STATEMENT";
7
+ readonly QUERY_BLOCKED: "QUERY_BLOCKED";
8
+ readonly CONNECTION_FAILED: "CONNECTION_FAILED";
9
+ readonly QUERY_TIMEOUT: "QUERY_TIMEOUT";
10
+ readonly DATABASE_NOT_FOUND: "DATABASE_NOT_FOUND";
11
+ readonly CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND";
12
+ readonly CONFIG_INVALID: "CONFIG_INVALID";
13
+ readonly READONLY_VIOLATION: "READONLY_VIOLATION";
14
+ };
15
+ export type ErrorCodeType = typeof ErrorCode[keyof typeof ErrorCode];
16
+ export declare class DbMcpError extends Error {
17
+ readonly code: ErrorCodeType;
18
+ readonly details?: Record<string, unknown>;
19
+ constructor(code: ErrorCodeType, message: string, details?: Record<string, unknown>);
20
+ toJSON(): Record<string, unknown>;
21
+ }
22
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,SAAS;;;;;;;;;;CAiBZ,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,OAAO,SAAS,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAErE,qBAAa,UAAW,SAAQ,KAAK;IACnC,SAAgB,IAAI,EAAE,aAAa,CAAC;IACpC,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEtC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYnF,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQlC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Error types and handling for db-mcp server
3
+ */
4
+ export const ErrorCode = {
5
+ // SQL validation errors
6
+ INVALID_SQL: 'INVALID_SQL',
7
+ MULTI_STATEMENT: 'MULTI_STATEMENT',
8
+ QUERY_BLOCKED: 'QUERY_BLOCKED',
9
+ // Database errors
10
+ CONNECTION_FAILED: 'CONNECTION_FAILED',
11
+ QUERY_TIMEOUT: 'QUERY_TIMEOUT',
12
+ DATABASE_NOT_FOUND: 'DATABASE_NOT_FOUND',
13
+ // Configuration errors
14
+ CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',
15
+ CONFIG_INVALID: 'CONFIG_INVALID',
16
+ // Access errors
17
+ READONLY_VIOLATION: 'READONLY_VIOLATION',
18
+ };
19
+ export class DbMcpError extends Error {
20
+ code;
21
+ details;
22
+ constructor(code, message, details) {
23
+ super(message);
24
+ this.name = 'DbMcpError';
25
+ this.code = code;
26
+ this.details = details;
27
+ // Maintain proper stack trace in V8
28
+ if (Error.captureStackTrace) {
29
+ Error.captureStackTrace(this, DbMcpError);
30
+ }
31
+ }
32
+ toJSON() {
33
+ return {
34
+ name: this.name,
35
+ code: this.code,
36
+ message: this.message,
37
+ details: this.details,
38
+ };
39
+ }
40
+ }
41
+ //# sourceMappingURL=errors.js.map