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.
Files changed (183) hide show
  1. package/README.md +112 -75
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/adapters/database-adapter.d.ts +11 -1
  4. package/dist/adapters/database-adapter.d.ts.map +1 -1
  5. package/dist/adapters/registration/resources.d.ts.map +1 -1
  6. package/dist/adapters/registration/tools.d.ts.map +1 -1
  7. package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -1
  8. package/dist/adapters/sqlite/query-executor.d.ts.map +1 -1
  9. package/dist/adapters/sqlite/read-write-lock.d.ts +49 -0
  10. package/dist/adapters/sqlite/read-write-lock.d.ts.map +1 -0
  11. package/dist/adapters/sqlite/resources.d.ts +1 -1
  12. package/dist/adapters/sqlite/resources.d.ts.map +1 -1
  13. package/dist/adapters/sqlite/schemas/admin.d.ts +33 -19
  14. package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -1
  15. package/dist/adapters/sqlite/schemas/core.d.ts +96 -0
  16. package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -1
  17. package/dist/adapters/sqlite/schemas/fts.d.ts +4 -0
  18. package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -1
  19. package/dist/adapters/sqlite/schemas/introspection.d.ts +25 -15
  20. package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -1
  21. package/dist/adapters/sqlite/schemas/migration.d.ts +2 -2
  22. package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -1
  23. package/dist/adapters/sqlite/schemas/spatialite.d.ts +1 -0
  24. package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -1
  25. package/dist/adapters/sqlite/schemas/text.d.ts +36 -0
  26. package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -1
  27. package/dist/adapters/sqlite/sqlite-adapter.d.ts +6 -0
  28. package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -1
  29. package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -1
  30. package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -1
  31. package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -1
  32. package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -1
  33. package/dist/adapters/sqlite/tools/admin/pragma.d.ts +0 -4
  34. package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -1
  35. package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -1
  36. package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -1
  37. package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -1
  38. package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -1
  39. package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -1
  40. package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -1
  41. package/dist/adapters/sqlite/tools/core/versioning.d.ts +19 -0
  42. package/dist/adapters/sqlite/tools/core/versioning.d.ts.map +1 -0
  43. package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -1
  44. package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -1
  45. package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -1
  46. package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -1
  47. package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -1
  48. package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -1
  49. package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -1
  50. package/dist/adapters/sqlite/tools/text/helpers.d.ts +9 -0
  51. package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -1
  52. package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -1
  53. package/dist/adapters/sqlite/tools/text/search.d.ts +4 -0
  54. package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -1
  55. package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -1
  56. package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -1
  57. package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -1
  58. package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -1
  59. package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -1
  60. package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -1
  61. package/dist/adapters/sqlite/types.d.ts +5 -1
  62. package/dist/adapters/sqlite/types.d.ts.map +1 -1
  63. package/dist/adapters/sqlite-native/index.d.ts +1 -1
  64. package/dist/adapters/sqlite-native/index.d.ts.map +1 -1
  65. package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -1
  66. package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -1
  67. package/dist/adapters/sqlite-native/tools/window/helpers.d.ts +52 -0
  68. package/dist/adapters/sqlite-native/tools/window/helpers.d.ts.map +1 -0
  69. package/dist/adapters/sqlite-native/tools/window/index.d.ts +7 -0
  70. package/dist/adapters/sqlite-native/tools/window/index.d.ts.map +1 -0
  71. package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts +7 -0
  72. package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts.map +1 -0
  73. package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts +7 -0
  74. package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts.map +1 -0
  75. package/dist/adapters/sqlite-native/tools/window/ntile.d.ts +7 -0
  76. package/dist/adapters/sqlite-native/tools/window/ntile.d.ts.map +1 -0
  77. package/dist/adapters/sqlite-native/tools/window/rank.d.ts +7 -0
  78. package/dist/adapters/sqlite-native/tools/window/rank.d.ts.map +1 -0
  79. package/dist/adapters/sqlite-native/tools/window/row-number.d.ts +7 -0
  80. package/dist/adapters/sqlite-native/tools/window/row-number.d.ts.map +1 -0
  81. package/dist/adapters/sqlite-native/tools/window/running-total.d.ts +7 -0
  82. package/dist/adapters/sqlite-native/tools/window/running-total.d.ts.map +1 -0
  83. package/dist/adapters/sqlite-native/tools/window/schemas.d.ts +159 -0
  84. package/dist/adapters/sqlite-native/tools/window/schemas.d.ts.map +1 -0
  85. package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -1
  86. package/dist/audit/interceptor.d.ts.map +1 -1
  87. package/dist/audit/logger.d.ts +26 -25
  88. package/dist/audit/logger.d.ts.map +1 -1
  89. package/dist/auth/authorization-server-discovery.d.ts.map +1 -1
  90. package/dist/auth/scopes/mapping.d.ts.map +1 -1
  91. package/dist/auth/token-validator.d.ts.map +1 -1
  92. package/dist/{chunk-W5WQVNVX.js → chunk-27C5EE6U.js} +23 -17
  93. package/dist/chunk-2TYICG7B.js +1183 -0
  94. package/dist/{chunk-37G4DLL6.js → chunk-LLIAIJPO.js} +1146 -539
  95. package/dist/{chunk-NV34JSQM.js → chunk-UE7GVOBV.js} +1757 -1331
  96. package/dist/{chunk-L552U3QS.js → chunk-XLIYO3YA.js} +401 -77
  97. package/dist/cli.js +116 -11
  98. package/dist/codemode/api-constants.d.ts.map +1 -1
  99. package/dist/codemode/api.d.ts.map +1 -1
  100. package/dist/codemode/sandbox-factory.d.ts.map +1 -1
  101. package/dist/codemode/sandbox.d.ts +0 -3
  102. package/dist/codemode/sandbox.d.ts.map +1 -1
  103. package/dist/codemode/security.d.ts.map +1 -1
  104. package/dist/codemode/types.d.ts +2 -0
  105. package/dist/codemode/types.d.ts.map +1 -1
  106. package/dist/constants/server-instructions.d.ts +1 -1
  107. package/dist/constants/server-instructions.d.ts.map +1 -1
  108. package/dist/filtering/tool-constants.d.ts +11 -11
  109. package/dist/filtering/tool-constants.d.ts.map +1 -1
  110. package/dist/{http-HWTUVFIA.js → http-ZDMK46QU.js} +195 -32
  111. package/dist/index.js +4 -4
  112. package/dist/observability/metrics.d.ts +36 -0
  113. package/dist/observability/metrics.d.ts.map +1 -0
  114. package/dist/observability/system-db.d.ts +13 -0
  115. package/dist/observability/system-db.d.ts.map +1 -0
  116. package/dist/server/mcp-server.d.ts +3 -0
  117. package/dist/server/mcp-server.d.ts.map +1 -1
  118. package/dist/server/registration/admin-tools.d.ts +6 -0
  119. package/dist/server/registration/admin-tools.d.ts.map +1 -0
  120. package/dist/server/registration/audit-tools/backup.d.ts +8 -0
  121. package/dist/server/registration/audit-tools/backup.d.ts.map +1 -0
  122. package/dist/server/registration/audit-tools/helpers.d.ts +11 -0
  123. package/dist/server/registration/audit-tools/helpers.d.ts.map +1 -0
  124. package/dist/server/registration/audit-tools/index.d.ts +4 -0
  125. package/dist/server/registration/audit-tools/index.d.ts.map +1 -0
  126. package/dist/server/registration/audit-tools/resource.d.ts +8 -0
  127. package/dist/server/registration/audit-tools/resource.d.ts.map +1 -0
  128. package/dist/server/registration/audit-tools/search.d.ts +7 -0
  129. package/dist/server/registration/audit-tools/search.d.ts.map +1 -0
  130. package/dist/server/registration/help-resources.d.ts.map +1 -1
  131. package/dist/server/registration/index.d.ts +3 -1
  132. package/dist/server/registration/index.d.ts.map +1 -1
  133. package/dist/server/registration/observability-resources.d.ts +11 -0
  134. package/dist/server/registration/observability-resources.d.ts.map +1 -0
  135. package/dist/server/subscription-manager.d.ts +35 -0
  136. package/dist/server/subscription-manager.d.ts.map +1 -0
  137. package/dist/{sqlite-TB56Z7G3.js → sqlite-XWZPEZJO.js} +195 -19
  138. package/dist/{sqlite-native-IF75BB3O.js → sqlite-native-5GQ3WKCZ.js} +311 -147
  139. package/dist/transports/http/middleware.d.ts.map +1 -1
  140. package/dist/transports/http/oauth.d.ts.map +1 -1
  141. package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -1
  142. package/dist/transports/http/sessions/stateful.d.ts +5 -1
  143. package/dist/transports/http/sessions/stateful.d.ts.map +1 -1
  144. package/dist/transports/http/transport.d.ts +2 -0
  145. package/dist/transports/http/transport.d.ts.map +1 -1
  146. package/dist/transports/http/types.d.ts +11 -0
  147. package/dist/transports/http/types.d.ts.map +1 -1
  148. package/dist/types/auth.d.ts +4 -0
  149. package/dist/types/auth.d.ts.map +1 -1
  150. package/dist/types/server.d.ts +5 -0
  151. package/dist/types/server.d.ts.map +1 -1
  152. package/dist/utils/annotations.d.ts +8 -0
  153. package/dist/utils/annotations.d.ts.map +1 -1
  154. package/dist/utils/errors/categories.d.ts +16 -11
  155. package/dist/utils/errors/categories.d.ts.map +1 -1
  156. package/dist/utils/errors/classes.d.ts +37 -0
  157. package/dist/utils/errors/classes.d.ts.map +1 -1
  158. package/dist/utils/errors/format.d.ts +2 -2
  159. package/dist/utils/errors/format.d.ts.map +1 -1
  160. package/dist/utils/errors/index.d.ts +1 -1
  161. package/dist/utils/errors/index.d.ts.map +1 -1
  162. package/dist/utils/errors/suggestions.d.ts +1 -0
  163. package/dist/utils/errors/suggestions.d.ts.map +1 -1
  164. package/dist/utils/index.d.ts +3 -0
  165. package/dist/utils/index.d.ts.map +1 -1
  166. package/dist/utils/logger/types.d.ts +1 -1
  167. package/dist/utils/logger/types.d.ts.map +1 -1
  168. package/dist/utils/security-utils.d.ts +29 -0
  169. package/dist/utils/security-utils.d.ts.map +1 -0
  170. package/dist/utils/stream-utils.d.ts +14 -0
  171. package/dist/utils/stream-utils.d.ts.map +1 -0
  172. package/dist/utils/tokens.d.ts +15 -0
  173. package/dist/utils/tokens.d.ts.map +1 -0
  174. package/dist/utils/where-clause.d.ts +0 -13
  175. package/dist/utils/where-clause.d.ts.map +1 -1
  176. package/package.json +43 -44
  177. package/dist/adapters/sqlite-native/tools/window.d.ts +0 -7
  178. package/dist/adapters/sqlite-native/tools/window.d.ts.map +0 -1
  179. package/dist/chunk-E5IESRTK.js +0 -489
  180. package/dist/server/registration/audit-tools.d.ts +0 -13
  181. package/dist/server/registration/audit-tools.d.ts.map +0 -1
  182. package/dist/utils/insights-manager.d.ts +0 -39
  183. package/dist/utils/insights-manager.d.ts.map +0 -1
@@ -1,8 +1,7 @@
1
- import { RowRecordSchema, WhereConditionSchema, sanitizeIdentifier, buildWhereClause, resolveAliases, autoEnableWal, detectAndSetJsonbSupport, SchemaManager, applyCommonPragmas, isDDL, getResourceDefinitions, getPromptDefinitions, validateIdentifier, normalizeSqliteParams, translateSqliteError, getCoreTools, getJsonOperationTools, getJsonHelperTools, getTextTools, getStatsTools, getVirtualTools, getVectorTools, getGeoTools, getAdminTools, getIntrospectionTools, getMigrationTools, getCodeModeTools, validateTableExists, FtsHeadlineSchema } from './chunk-NV34JSQM.js';
2
- import { DatabaseAdapter } from './chunk-W5WQVNVX.js';
3
- import { ErrorResponseFields, write, readOnly, VERSION, admin, writeFs, getToolGroupIcon, idempotent } from './chunk-E5IESRTK.js';
4
- import { logger, formatHandlerError, ValidationError, ConfigurationError, ERROR_CODES, ConnectionError, DbMcpError, ResourceNotFoundError, ExtensionNotAvailableError } from './chunk-L552U3QS.js';
5
- import Database from 'better-sqlite3';
1
+ import { RowRecordSchema, WhereConditionSchema, autoEnableWal, detectAndSetJsonbSupport, SchemaManager, applyCommonPragmas, isDDL, getResourceDefinitions, getPromptDefinitions, resolveAliases, normalizeSqliteParams, translateSqliteError, getCoreTools, getJsonOperationTools, getJsonHelperTools, getTextTools, getStatsTools, getVirtualTools, getVectorTools, getGeoTools, getAdminTools, getIntrospectionTools, getMigrationTools, getCodeModeTools, validateTableExists, sanitizeFtsQuery, FtsHeadlineSchema } from './chunk-UE7GVOBV.js';
2
+ import { DatabaseAdapter } from './chunk-27C5EE6U.js';
3
+ import { ErrorResponseFields, write, readOnly, VERSION, sanitizeIdentifier, buildWhereClause, admin, validateIdentifier, writeFs, getToolGroupIcon, idempotent } from './chunk-2TYICG7B.js';
4
+ import { logger, formatHandlerError, ValidationError, ConfigurationError, ERROR_CODES, ConnectionError, DbMcpError, ErrorCategory, ResourceNotFoundError, ExtensionNotAvailableError } from './chunk-XLIYO3YA.js';
6
5
  import { z } from 'zod';
7
6
  import { createRequire } from 'module';
8
7
  import { fileURLToPath } from 'url';
@@ -22,7 +21,9 @@ var FtsResultSchema = z.object({
22
21
  var FtsSearchOutputSchema = z.object({
23
22
  success: z.boolean(),
24
23
  rowCount: z.number().optional(),
25
- results: z.array(FtsResultSchema).optional()
24
+ results: z.array(FtsResultSchema).optional(),
25
+ nextCursor: z.string().optional(),
26
+ facets: z.record(z.string(), z.number()).optional()
26
27
  }).extend(ErrorResponseFields.shape);
27
28
  var FtsRebuildOutputSchema = z.object({
28
29
  success: z.boolean(),
@@ -65,7 +66,11 @@ var FtsSearchSchema = z.object({
65
66
  return val;
66
67
  }, z.number().optional().default(100)),
67
68
  highlight: z.boolean().optional().default(false).describe("Include highlighted snippets"),
68
- includeRowData: z.boolean().optional().default(true).describe("Include full row data in results")
69
+ includeRowData: z.boolean().optional().default(true).describe("Include full row data in results"),
70
+ cursor: z.string().optional().describe("Opaque cursor for pagination"),
71
+ includeFacets: z.boolean().optional().default(false).describe(
72
+ "Return match counts per column (distribution by matched column)"
73
+ )
69
74
  });
70
75
  var FtsRebuildSchema = z.object({
71
76
  table: z.string().describe("FTS table name to rebuild")
@@ -224,20 +229,46 @@ function createFtsSearchTool(adapter) {
224
229
  }
225
230
  sanitizeIdentifier(input.table);
226
231
  await validateTableExists(adapter, input.table);
232
+ let offset = 0;
233
+ if (input.cursor) {
234
+ try {
235
+ const cursorData = JSON.parse(
236
+ Buffer.from(input.cursor, "base64").toString("utf8")
237
+ );
238
+ if (typeof cursorData["offset"] === "number")
239
+ offset = cursorData["offset"];
240
+ } catch {
241
+ }
242
+ }
227
243
  let selectClause = input.includeRowData ? "*" : "rowid";
228
244
  if (input.highlight) {
229
245
  selectClause += `, highlight("${input.table}", 0, '<b>', '</b>') as snippet`;
230
246
  }
231
247
  if (input.query === "*" || input.query.trim() === "") {
232
- const sql2 = `SELECT ${selectClause}, NULL as rank FROM "${input.table}" ORDER BY rowid LIMIT ${input.limit}`;
248
+ const sql2 = `SELECT ${selectClause}, NULL as rank FROM "${input.table}" ORDER BY rowid LIMIT ${input.limit} OFFSET ${offset}`;
233
249
  const result2 = await adapter.executeReadQuery(sql2, queryParams);
250
+ let nextCursor2;
251
+ if (result2.rows?.length === input.limit) {
252
+ nextCursor2 = Buffer.from(
253
+ JSON.stringify({ offset: offset + input.limit })
254
+ ).toString("base64");
255
+ }
234
256
  return {
235
257
  success: true,
236
258
  rowCount: result2.rows?.length ?? 0,
237
- results: result2.rows
259
+ results: result2.rows,
260
+ nextCursor: nextCursor2
238
261
  };
239
262
  }
240
- const queryEscaped = input.query.replace(/'/g, "''");
263
+ const sanitizedQuery = sanitizeFtsQuery(input.query);
264
+ if (!sanitizedQuery) {
265
+ return {
266
+ success: true,
267
+ rowCount: 0,
268
+ results: []
269
+ };
270
+ }
271
+ const queryEscaped = sanitizedQuery.replace(/'/g, "''");
241
272
  let matchExpr = `"${input.table}" MATCH '${queryEscaped}'`;
242
273
  if (input.columns && input.columns.length > 0) {
243
274
  for (const col of input.columns) {
@@ -246,12 +277,58 @@ function createFtsSearchTool(adapter) {
246
277
  const colFilter = input.columns.map((c) => `${c}:${queryEscaped}`).join(" OR ");
247
278
  matchExpr = `"${input.table}" MATCH '${colFilter}'`;
248
279
  }
249
- const sql = `SELECT ${selectClause}, rank FROM "${input.table}" WHERE ${matchExpr} ORDER BY rank LIMIT ${input.limit}`;
280
+ let columnsToFacet = [];
281
+ if (input.includeFacets) {
282
+ const colResult = await adapter.executeReadQuery(
283
+ `PRAGMA table_info("${input.table}")`,
284
+ []
285
+ );
286
+ const allCols = (colResult.rows ?? []).map((r, i) => ({
287
+ name: String(r["name"]),
288
+ index: i
289
+ }));
290
+ if (input.columns && input.columns.length > 0) {
291
+ columnsToFacet = allCols.filter(
292
+ (c) => input.columns?.includes(c.name)
293
+ );
294
+ } else {
295
+ columnsToFacet = allCols.filter(
296
+ (c) => c.name !== input.table && c.name !== "rank"
297
+ );
298
+ }
299
+ for (const col of columnsToFacet) {
300
+ selectClause += `, highlight("${input.table}", ${col.index}, '', '') as _facet_${col.index}`;
301
+ }
302
+ }
303
+ const sql = `SELECT ${selectClause}, rank FROM "${input.table}" WHERE ${matchExpr} ORDER BY rank LIMIT ${input.limit} OFFSET ${offset}`;
250
304
  const result = await adapter.executeReadQuery(sql, queryParams);
305
+ let nextCursor;
306
+ if (result.rows?.length === input.limit) {
307
+ nextCursor = Buffer.from(
308
+ JSON.stringify({ offset: offset + input.limit })
309
+ ).toString("base64");
310
+ }
311
+ const facets = {};
312
+ if (input.includeFacets && result.rows) {
313
+ for (const col of columnsToFacet) {
314
+ facets[col.name] = 0;
315
+ }
316
+ for (const row of result.rows) {
317
+ for (const col of columnsToFacet) {
318
+ const val = row[`_facet_${col.index}`];
319
+ if (typeof val === "string" && val.includes("")) {
320
+ facets[col.name] = (facets[col.name] ?? 0) + 1;
321
+ }
322
+ Reflect.deleteProperty(row, `_facet_${col.index}`);
323
+ }
324
+ }
325
+ }
251
326
  return {
252
327
  success: true,
253
328
  rowCount: result.rows?.length ?? 0,
254
- results: result.rows
329
+ results: result.rows,
330
+ nextCursor,
331
+ ...input.includeFacets ? { facets } : {}
255
332
  };
256
333
  } catch (error) {
257
334
  if (isFts5UnavailableError(error)) {
@@ -315,7 +392,15 @@ function createFtsMatchInfoTool(adapter) {
315
392
  }
316
393
  sanitizeIdentifier(input.table);
317
394
  await validateTableExists(adapter, input.table);
318
- const queryEscaped = input.query.replace(/'/g, "''");
395
+ const sanitizedQuery = sanitizeFtsQuery(input.query);
396
+ if (!sanitizedQuery) {
397
+ return {
398
+ success: true,
399
+ rowCount: 0,
400
+ results: []
401
+ };
402
+ }
403
+ const queryEscaped = sanitizedQuery.replace(/'/g, "''");
319
404
  let rankExpr;
320
405
  if (input.format === "bm25") {
321
406
  rankExpr = `bm25("${input.table}")`;
@@ -357,8 +442,17 @@ function createFtsHeadlineTool(adapter) {
357
442
  }
358
443
  sanitizeIdentifier(input.table);
359
444
  await validateTableExists(adapter, input.table);
360
- const queryEscaped = input.query.replace(/'/g, "''");
445
+ const sanitizedQuery = sanitizeFtsQuery(input.query);
446
+ if (!sanitizedQuery && input.query !== "*" && input.query.trim() !== "") {
447
+ return {
448
+ success: true,
449
+ rowCount: 0,
450
+ results: []
451
+ };
452
+ }
453
+ const queryEscaped = sanitizedQuery.replace(/'/g, "''");
361
454
  let columnIndex = 0;
455
+ let snippetColumnIndex = -1;
362
456
  if (input.column) {
363
457
  const colResult = await adapter.executeReadQuery(
364
458
  `PRAGMA table_info("${input.table}")`,
@@ -370,12 +464,13 @@ function createFtsHeadlineTool(adapter) {
370
464
  );
371
465
  if (found >= 0) {
372
466
  columnIndex = found;
467
+ snippetColumnIndex = found;
373
468
  }
374
469
  }
375
470
  const startSel = input.startSel.replace(/'/g, "''");
376
471
  const stopSel = input.stopSel.replace(/'/g, "''");
377
472
  const highlightExpr = `highlight("${input.table}", ${String(columnIndex)}, '${startSel}', '${stopSel}')`;
378
- const snippetExpr = `snippet("${input.table}", ${String(columnIndex)}, '${startSel}', '${stopSel}', '...', ${String(input.snippetWords)})`;
473
+ const snippetExpr = `snippet("${input.table}", ${String(snippetColumnIndex)}, '${startSel}', '${stopSel}', '...', ${String(input.snippetWords)})`;
379
474
  if (input.query === "*" || input.query.trim() === "") {
380
475
  const sql2 = `SELECT *, NULL as headline, NULL as snippet, NULL as rank FROM "${input.table}" ORDER BY rowid LIMIT ${String(input.limit)}`;
381
476
  const result2 = await adapter.executeReadQuery(sql2, queryParams);
@@ -515,7 +610,8 @@ var SpatialiteLoadOutputSchema = z.object({
515
610
  message: z.string().optional(),
516
611
  alreadyLoaded: z.boolean().optional(),
517
612
  extensionPath: z.string().optional(),
518
- searchedPaths: z.array(z.string()).optional()
613
+ searchedPaths: z.array(z.string()).optional(),
614
+ version: z.string().optional()
519
615
  }).extend(ErrorResponseFields.shape);
520
616
  var SpatialiteCreateTableOutputSchema = z.object({
521
617
  success: z.boolean(),
@@ -562,14 +658,14 @@ var BeginTransactionSchema = z.object({
562
658
  mode: z.enum(["deferred", "immediate", "exclusive"]).optional().default("deferred").describe(
563
659
  "Transaction mode: deferred waits for first write, immediate acquires lock immediately, exclusive blocks all access"
564
660
  )
565
- });
661
+ }).strict();
566
662
  var SavepointSchema = z.object({
567
663
  name: z.string().describe("Savepoint name")
568
- });
664
+ }).strict();
569
665
  var ExecuteInTransactionSchema = z.object({
570
666
  statements: z.array(z.string()).describe("Array of SQL statements to execute in order"),
571
667
  rollbackOnError: z.boolean().optional().default(true).describe("If true, rollback all changes when any statement fails")
572
- });
668
+ }).strict();
573
669
  function getTransactionTools(adapter) {
574
670
  return [
575
671
  createBeginTransactionTool(adapter),
@@ -612,7 +708,7 @@ function createTransactionStatusTool(adapter) {
612
708
  name: "sqlite_transaction_status",
613
709
  description: "Check whether a transaction is currently active. Returns status and a boolean flag. Read-only \u2014 does not alter transaction state.",
614
710
  group: "transactions",
615
- inputSchema: z.object({}),
711
+ inputSchema: z.object({}).strict(),
616
712
  outputSchema: TransactionStatusOutputSchema,
617
713
  annotations: readOnly("Transaction Status"),
618
714
  requiredScopes: ["read"],
@@ -637,7 +733,7 @@ function createCommitTransactionTool(adapter) {
637
733
  name: "sqlite_transaction_commit",
638
734
  description: "Commit the current transaction, making all changes permanent.",
639
735
  group: "transactions",
640
- inputSchema: z.object({}),
736
+ inputSchema: z.object({}).strict(),
641
737
  outputSchema: TransactionCommitOutputSchema,
642
738
  annotations: write("Commit Transaction"),
643
739
  requiredScopes: ["write"],
@@ -660,7 +756,7 @@ function createRollbackTransactionTool(adapter) {
660
756
  description: "Rollback the current transaction, discarding all changes.",
661
757
  group: "transactions",
662
758
  outputSchema: TransactionRollbackOutputSchema,
663
- inputSchema: z.object({}),
759
+ inputSchema: z.object({}).strict(),
664
760
  annotations: write("Rollback Transaction"),
665
761
  requiredScopes: ["write"],
666
762
  handler: (_params, _context) => {
@@ -858,6 +954,14 @@ function createExecuteInTransactionTool(adapter) {
858
954
  if (transactionStarted) {
859
955
  adapter.commitTransaction();
860
956
  }
957
+ if (results.length > 50) {
958
+ const omitted = results.length - 50;
959
+ results.splice(50);
960
+ results.push({
961
+ statement: "TRUNCATED",
962
+ error: `Results array truncated. Omitted ${omitted} results to conserve payload size.`
963
+ });
964
+ }
861
965
  return {
862
966
  success,
863
967
  error: success ? void 0 : "Transaction completed with errors",
@@ -888,17 +992,28 @@ function createExecuteInTransactionTool(adapter) {
888
992
  } else if (!transactionStarted && !originallyInTransaction) {
889
993
  rollbackMessage = `Transaction failed to start: ${message}`;
890
994
  }
995
+ const totalExecuted = results.length;
996
+ if (results.length > 50) {
997
+ const omitted = results.length - 50;
998
+ results.splice(50);
999
+ results.push({
1000
+ statement: "TRUNCATED",
1001
+ error: `Results array truncated. Omitted ${omitted} results to conserve payload size.`
1002
+ });
1003
+ }
891
1004
  return {
892
1005
  ...formatted,
893
1006
  error: formatted.error ?? rollbackMessage,
894
1007
  message: rollbackMessage,
895
- statementsExecuted: results.length,
1008
+ statementsExecuted: totalExecuted,
896
1009
  results
897
1010
  };
898
1011
  }
899
1012
  }
900
1013
  };
901
1014
  }
1015
+
1016
+ // src/adapters/sqlite-native/tools/window/helpers.ts
902
1017
  var coerceNumber = (val) => {
903
1018
  if (typeof val === "string") {
904
1019
  if (val.trim() === "") return void 0;
@@ -909,93 +1024,6 @@ var coerceNumber = (val) => {
909
1024
  };
910
1025
  var coerceEnumValues2 = (allowed) => (val) => typeof val === "string" && allowed.includes(val) ? val : void 0;
911
1026
  var VALID_DIRECTIONS = ["lag", "lead"];
912
- var RowNumberSchema = z.object({
913
- table: z.string().describe("Table name"),
914
- orderBy: z.string().describe("Column(s) to order by"),
915
- partitionBy: z.string().optional().describe("Column(s) to partition by"),
916
- selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
917
- conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
918
- limit: z.preprocess(
919
- coerceNumber,
920
- z.number().optional().default(20).describe("Maximum rows to return")
921
- )
922
- });
923
- var RankSchema = z.object({
924
- table: z.string().describe("Table name"),
925
- orderBy: z.string().describe("Column(s) to order by (determines rank)"),
926
- partitionBy: z.string().optional().describe("Column(s) to partition by"),
927
- selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
928
- rankType: z.preprocess(
929
- coerceEnumValues2(["rank", "dense_rank", "percent_rank"]),
930
- z.enum(["rank", "dense_rank", "percent_rank"]).optional().default("rank").describe("Rank function type")
931
- ),
932
- conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
933
- limit: z.preprocess(
934
- coerceNumber,
935
- z.number().optional().default(20).describe("Maximum rows to return")
936
- )
937
- });
938
- var LagLeadSchema = z.object({
939
- table: z.string().describe("Table name"),
940
- column: z.string().describe("Column to get lag/lead value from"),
941
- orderBy: z.string().describe("Column(s) to order by"),
942
- direction: z.string().describe("LAG (previous) or LEAD (next) row"),
943
- offset: z.preprocess(
944
- coerceNumber,
945
- z.number().optional().default(1).describe("Number of rows to look back/ahead")
946
- ),
947
- defaultValue: z.string().optional().describe("Default value if no row exists"),
948
- partitionBy: z.string().optional().describe("Column(s) to partition by"),
949
- selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
950
- conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
951
- limit: z.preprocess(
952
- coerceNumber,
953
- z.number().optional().default(20).describe("Maximum rows to return")
954
- )
955
- });
956
- var RunningTotalSchema = z.object({
957
- table: z.string().describe("Table name"),
958
- column: z.string().describe("Column to sum"),
959
- orderBy: z.string().describe("Column(s) to order by"),
960
- partitionBy: z.string().optional().describe("Reset running total for each partition"),
961
- selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
962
- conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
963
- limit: z.preprocess(
964
- coerceNumber,
965
- z.number().optional().default(20).describe("Maximum rows to return")
966
- )
967
- });
968
- var MovingAverageSchema = z.object({
969
- table: z.string().describe("Table name"),
970
- column: z.string().describe("Column to average"),
971
- orderBy: z.string().describe("Column(s) to order by"),
972
- windowSize: z.preprocess(
973
- coerceNumber,
974
- z.number().describe("Number of rows in the moving window")
975
- ),
976
- partitionBy: z.string().optional().describe("Column(s) to partition by"),
977
- selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
978
- conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
979
- limit: z.preprocess(
980
- coerceNumber,
981
- z.number().optional().default(20).describe("Maximum rows to return")
982
- )
983
- });
984
- var NtileSchema = z.object({
985
- table: z.string().describe("Table name"),
986
- orderBy: z.string().describe("Column(s) to order by"),
987
- buckets: z.preprocess(
988
- coerceNumber,
989
- z.number().describe("Number of buckets (e.g., 4 for quartiles)")
990
- ),
991
- partitionBy: z.string().optional().describe("Column(s) to partition by"),
992
- selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
993
- conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
994
- limit: z.preprocess(
995
- coerceNumber,
996
- z.number().optional().default(20).describe("Maximum rows to return")
997
- )
998
- });
999
1027
  async function validateTableExists2(adapter, table) {
1000
1028
  validateIdentifier(table);
1001
1029
  const result = await adapter.executeReadQuery(
@@ -1041,7 +1069,7 @@ async function validateOrderByColumns(adapter, table, orderBy) {
1041
1069
  throw new DbMcpError(
1042
1070
  `Invalid ORDER BY expression: '${colName}' contains disallowed characters. Only column names with optional ASC/DESC are permitted.`,
1043
1071
  "NATIVE_WINDOW_INVALID_ORDERBY",
1044
- "validation" /* VALIDATION */
1072
+ ErrorCategory.VALIDATION
1045
1073
  );
1046
1074
  }
1047
1075
  if (/^(ASC|DESC)$/i.test(colName)) continue;
@@ -1157,19 +1185,100 @@ function validateDefaultValue(value) {
1157
1185
  throw new DbMcpError(
1158
1186
  `Invalid default value: '${value}'. Only numeric literals, single-quoted strings, or NULL are permitted.`,
1159
1187
  "NATIVE_WINDOW_INVALID_DEFAULT",
1160
- "validation" /* VALIDATION */
1188
+ ErrorCategory.VALIDATION
1161
1189
  );
1162
1190
  }
1163
- function getWindowTools(adapter) {
1164
- return [
1165
- createRowNumberTool(adapter),
1166
- createRankTool(adapter),
1167
- createLagLeadTool(adapter),
1168
- createRunningTotalTool(adapter),
1169
- createMovingAverageTool(adapter),
1170
- createNtileTool(adapter)
1171
- ];
1172
- }
1191
+
1192
+ // src/adapters/sqlite-native/tools/window/schemas.ts
1193
+ var RowNumberSchema = z.object({
1194
+ table: z.string().describe("Table name"),
1195
+ orderBy: z.string().describe("Column(s) to order by"),
1196
+ partitionBy: z.string().optional().describe("Column(s) to partition by"),
1197
+ selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
1198
+ conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
1199
+ limit: z.preprocess(
1200
+ coerceNumber,
1201
+ z.number().optional().default(20).describe("Maximum rows to return")
1202
+ )
1203
+ });
1204
+ var RankSchema = z.object({
1205
+ table: z.string().describe("Table name"),
1206
+ orderBy: z.string().describe("Column(s) to order by (determines rank)"),
1207
+ partitionBy: z.string().optional().describe("Column(s) to partition by"),
1208
+ selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
1209
+ rankType: z.preprocess(
1210
+ coerceEnumValues2(["rank", "dense_rank", "percent_rank"]),
1211
+ z.enum(["rank", "dense_rank", "percent_rank"]).optional().default("rank").describe("Rank function type")
1212
+ ),
1213
+ conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
1214
+ limit: z.preprocess(
1215
+ coerceNumber,
1216
+ z.number().optional().default(20).describe("Maximum rows to return")
1217
+ )
1218
+ });
1219
+ var LagLeadSchema = z.object({
1220
+ table: z.string().describe("Table name"),
1221
+ column: z.string().describe("Column to get lag/lead value from"),
1222
+ orderBy: z.string().describe("Column(s) to order by"),
1223
+ direction: z.string().describe("LAG (previous) or LEAD (next) row"),
1224
+ offset: z.preprocess(
1225
+ coerceNumber,
1226
+ z.number().optional().default(1).describe("Number of rows to look back/ahead")
1227
+ ),
1228
+ defaultValue: z.string().optional().describe("Default value if no row exists"),
1229
+ partitionBy: z.string().optional().describe("Column(s) to partition by"),
1230
+ selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
1231
+ conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
1232
+ limit: z.preprocess(
1233
+ coerceNumber,
1234
+ z.number().optional().default(20).describe("Maximum rows to return")
1235
+ )
1236
+ });
1237
+ var RunningTotalSchema = z.object({
1238
+ table: z.string().describe("Table name"),
1239
+ column: z.string().describe("Column to sum"),
1240
+ orderBy: z.string().describe("Column(s) to order by"),
1241
+ partitionBy: z.string().optional().describe("Reset running total for each partition"),
1242
+ selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
1243
+ conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
1244
+ limit: z.preprocess(
1245
+ coerceNumber,
1246
+ z.number().optional().default(20).describe("Maximum rows to return")
1247
+ )
1248
+ });
1249
+ var MovingAverageSchema = z.object({
1250
+ table: z.string().describe("Table name"),
1251
+ column: z.string().describe("Column to average"),
1252
+ orderBy: z.string().describe("Column(s) to order by"),
1253
+ windowSize: z.preprocess(
1254
+ coerceNumber,
1255
+ z.number().describe("Number of rows in the moving window")
1256
+ ),
1257
+ partitionBy: z.string().optional().describe("Column(s) to partition by"),
1258
+ selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
1259
+ conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
1260
+ limit: z.preprocess(
1261
+ coerceNumber,
1262
+ z.number().optional().default(20).describe("Maximum rows to return")
1263
+ )
1264
+ });
1265
+ var NtileSchema = z.object({
1266
+ table: z.string().describe("Table name"),
1267
+ orderBy: z.string().describe("Column(s) to order by"),
1268
+ buckets: z.preprocess(
1269
+ coerceNumber,
1270
+ z.number().describe("Number of buckets (e.g., 4 for quartiles)")
1271
+ ),
1272
+ partitionBy: z.string().optional().describe("Column(s) to partition by"),
1273
+ selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
1274
+ conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
1275
+ limit: z.preprocess(
1276
+ coerceNumber,
1277
+ z.number().optional().default(20).describe("Maximum rows to return")
1278
+ )
1279
+ });
1280
+
1281
+ // src/adapters/sqlite-native/tools/window/row-number.ts
1173
1282
  function createRowNumberTool(adapter) {
1174
1283
  return {
1175
1284
  name: "sqlite_window_row_number",
@@ -1221,6 +1330,8 @@ function createRowNumberTool(adapter) {
1221
1330
  }
1222
1331
  };
1223
1332
  }
1333
+
1334
+ // src/adapters/sqlite-native/tools/window/rank.ts
1224
1335
  function createRankTool(adapter) {
1225
1336
  return {
1226
1337
  name: "sqlite_window_rank",
@@ -1274,6 +1385,8 @@ function createRankTool(adapter) {
1274
1385
  }
1275
1386
  };
1276
1387
  }
1388
+
1389
+ // src/adapters/sqlite-native/tools/window/lag-lead.ts
1277
1390
  function createLagLeadTool(adapter) {
1278
1391
  return {
1279
1392
  name: "sqlite_window_lag_lead",
@@ -1349,6 +1462,8 @@ function createLagLeadTool(adapter) {
1349
1462
  }
1350
1463
  };
1351
1464
  }
1465
+
1466
+ // src/adapters/sqlite-native/tools/window/running-total.ts
1352
1467
  function createRunningTotalTool(adapter) {
1353
1468
  return {
1354
1469
  name: "sqlite_window_running_total",
@@ -1405,6 +1520,8 @@ function createRunningTotalTool(adapter) {
1405
1520
  }
1406
1521
  };
1407
1522
  }
1523
+
1524
+ // src/adapters/sqlite-native/tools/window/moving-average.ts
1408
1525
  function createMovingAverageTool(adapter) {
1409
1526
  return {
1410
1527
  name: "sqlite_window_moving_avg",
@@ -1463,6 +1580,8 @@ function createMovingAverageTool(adapter) {
1463
1580
  }
1464
1581
  };
1465
1582
  }
1583
+
1584
+ // src/adapters/sqlite-native/tools/window/ntile.ts
1466
1585
  function createNtileTool(adapter) {
1467
1586
  return {
1468
1587
  name: "sqlite_window_ntile",
@@ -1515,6 +1634,18 @@ function createNtileTool(adapter) {
1515
1634
  }
1516
1635
  };
1517
1636
  }
1637
+
1638
+ // src/adapters/sqlite-native/tools/window/index.ts
1639
+ function getWindowTools(adapter) {
1640
+ return [
1641
+ createRowNumberTool(adapter),
1642
+ createRankTool(adapter),
1643
+ createLagLeadTool(adapter),
1644
+ createRunningTotalTool(adapter),
1645
+ createMovingAverageTool(adapter),
1646
+ createNtileTool(adapter)
1647
+ ];
1648
+ }
1518
1649
  var coerceNumber2 = (val) => {
1519
1650
  if (typeof val === "string") {
1520
1651
  if (val.trim() === "") return void 0;
@@ -1755,34 +1886,44 @@ function createLoadSpatialiteTool(adapter) {
1755
1886
  outputSchema: SpatialiteLoadOutputSchema,
1756
1887
  requiredScopes: ["admin"],
1757
1888
  annotations: admin("SpatiaLite Load"),
1758
- handler: (_params, _context) => {
1889
+ handler: async (_params, _context) => {
1759
1890
  try {
1760
1891
  const input = LoadSpatialiteSchema.parse(_params);
1761
1892
  if (!input.forceReload && isSpatialiteLoaded(adapter)) {
1762
- return Promise.resolve({
1893
+ const versionResult = await adapter.executeReadQuery(
1894
+ "SELECT spatialite_version() as v"
1895
+ );
1896
+ const version = versionResult.rows?.[0]?.["v"];
1897
+ return {
1763
1898
  success: true,
1764
1899
  message: "SpatiaLite already loaded",
1765
- alreadyLoaded: true
1766
- });
1900
+ alreadyLoaded: true,
1901
+ version
1902
+ };
1767
1903
  }
1768
1904
  const result = tryLoadSpatialite(adapter);
1769
1905
  if (result.success) {
1770
- return Promise.resolve({
1906
+ const versionResult = await adapter.executeReadQuery(
1907
+ "SELECT spatialite_version() as v"
1908
+ );
1909
+ const version = versionResult.rows?.[0]?.["v"];
1910
+ return {
1771
1911
  success: true,
1772
1912
  message: "SpatiaLite loaded successfully",
1773
- extensionPath: result.path
1774
- });
1913
+ extensionPath: result.path,
1914
+ version
1915
+ };
1775
1916
  }
1776
- return Promise.resolve({
1917
+ return {
1777
1918
  success: false,
1778
1919
  error: result.error,
1779
1920
  code: "SPATIALITE_LOAD_FAILED",
1780
1921
  category: "internal",
1781
1922
  recoverable: false,
1782
1923
  searchedPaths: SPATIALITE_PATHS
1783
- });
1924
+ };
1784
1925
  } catch (error) {
1785
- return Promise.resolve(formatHandlerError(error));
1926
+ return formatHandlerError(error);
1786
1927
  }
1787
1928
  }
1788
1929
  };
@@ -2636,16 +2777,18 @@ function savepoint(db, name) {
2636
2777
  }
2637
2778
  function releaseSavepoint(db, name) {
2638
2779
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
2639
- throw new Error(
2640
- "Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars."
2780
+ throw new ValidationError(
2781
+ "Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars.",
2782
+ "INVALID_SAVEPOINT_NAME"
2641
2783
  );
2642
2784
  }
2643
2785
  db.exec(`RELEASE SAVEPOINT "${name}"`);
2644
2786
  }
2645
2787
  function rollbackToSavepoint(db, name) {
2646
2788
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
2647
- throw new Error(
2648
- "Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars."
2789
+ throw new ValidationError(
2790
+ "Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars.",
2791
+ "INVALID_SAVEPOINT_NAME"
2649
2792
  );
2650
2793
  }
2651
2794
  db.exec(`ROLLBACK TO SAVEPOINT "${name}"`);
@@ -2724,7 +2867,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2724
2867
  /**
2725
2868
  * Connect to a SQLite database using better-sqlite3
2726
2869
  */
2727
- connect(config) {
2870
+ async connect(config) {
2728
2871
  if (config.type !== "sqlite") {
2729
2872
  throw new ConfigurationError(
2730
2873
  `Invalid database type: expected 'sqlite', got '${config.type}'`,
@@ -2735,13 +2878,33 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2735
2878
  this.config = sqliteConfig;
2736
2879
  try {
2737
2880
  const filePath = sqliteConfig.filePath ?? sqliteConfig.connectionString ?? ":memory:";
2738
- this.db = new Database(filePath, {
2739
- readonly: false,
2740
- fileMustExist: false
2741
- });
2742
- log.info(`Connected to SQLite database (native): ${filePath}`, {
2743
- code: "SQLITE_CONNECT"
2744
- });
2881
+ if (sqliteConfig.options?.encryptionKey) {
2882
+ const DatabaseDriver = (await import('better-sqlite3-multiple-ciphers')).default;
2883
+ this.db = new DatabaseDriver(filePath, {
2884
+ readonly: false,
2885
+ fileMustExist: false
2886
+ });
2887
+ const escapedKey = sqliteConfig.options.encryptionKey.replace(
2888
+ /"/g,
2889
+ '""'
2890
+ );
2891
+ this.db.pragma(`key = "${escapedKey}"`);
2892
+ log.info(
2893
+ `Connected to SQLite database (native encrypted): ${filePath}`,
2894
+ {
2895
+ code: "SQLITE_CONNECT_ENCRYPTED"
2896
+ }
2897
+ );
2898
+ } else {
2899
+ const DatabaseDriver = (await import('better-sqlite3')).default;
2900
+ this.db = new DatabaseDriver(filePath, {
2901
+ readonly: false,
2902
+ fileMustExist: false
2903
+ });
2904
+ log.info(`Connected to SQLite database (native): ${filePath}`, {
2905
+ code: "SQLITE_CONNECT"
2906
+ });
2907
+ }
2745
2908
  this.applyOptions(sqliteConfig.options);
2746
2909
  const db = this.db;
2747
2910
  autoEnableWal(
@@ -2780,7 +2943,6 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2780
2943
  }
2781
2944
  );
2782
2945
  }
2783
- return Promise.resolve();
2784
2946
  }
2785
2947
  /**
2786
2948
  * Apply SQLite PRAGMA options and load extensions
@@ -2870,6 +3032,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2870
3032
  const result = nativeExecuteWrite(this.ensureDb(), sql, params, log);
2871
3033
  if (isDDL(sql)) {
2872
3034
  this.clearSchemaCache();
3035
+ this.emit("schemaChanged");
2873
3036
  }
2874
3037
  return result;
2875
3038
  }
@@ -2896,6 +3059,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2896
3059
  this.ensureConnected();
2897
3060
  this.ensureDb().exec(sql);
2898
3061
  this.clearSchemaCache();
3062
+ this.emit("schemaChanged");
2899
3063
  return Promise.resolve();
2900
3064
  }
2901
3065
  /**
@@ -2943,7 +3107,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2943
3107
  throw new DbMcpError(
2944
3108
  "Invalid table name",
2945
3109
  "SQLITE_INVALID_TABLE",
2946
- "validation" /* VALIDATION */
3110
+ ErrorCategory.VALIDATION
2947
3111
  );
2948
3112
  }
2949
3113
  const result = await this.executeReadQuery(
@@ -2953,7 +3117,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
2953
3117
  throw new DbMcpError(
2954
3118
  `Table '${tableName}' does not exist`,
2955
3119
  "SQLITE_TABLE_NOT_FOUND",
2956
- "resource" /* RESOURCE */
3120
+ ErrorCategory.RESOURCE
2957
3121
  );
2958
3122
  }
2959
3123
  return {