db-mcp 2.0.0 → 3.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 (553) hide show
  1. package/README.md +96 -91
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/adapters/database-adapter.d.ts +173 -0
  4. package/dist/adapters/database-adapter.d.ts.map +1 -0
  5. package/dist/adapters/query-validation.d.ts +20 -0
  6. package/dist/adapters/query-validation.d.ts.map +1 -0
  7. package/dist/adapters/registration/index.d.ts +4 -0
  8. package/dist/adapters/registration/index.d.ts.map +1 -0
  9. package/dist/adapters/registration/prompts.d.ts +7 -0
  10. package/dist/adapters/registration/prompts.d.ts.map +1 -0
  11. package/dist/adapters/registration/resources.d.ts +7 -0
  12. package/dist/adapters/registration/resources.d.ts.map +1 -0
  13. package/dist/adapters/registration/tools.d.ts +9 -0
  14. package/dist/adapters/registration/tools.d.ts.map +1 -0
  15. package/dist/adapters/sqlite/index.d.ts +9 -0
  16. package/dist/adapters/sqlite/index.d.ts.map +1 -0
  17. package/dist/adapters/sqlite/json-utils.d.ts +100 -0
  18. package/dist/adapters/sqlite/json-utils.d.ts.map +1 -0
  19. package/dist/adapters/sqlite/prompts/analysis.d.ts +23 -0
  20. package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -0
  21. package/dist/adapters/sqlite/prompts/index.d.ts +16 -0
  22. package/dist/adapters/sqlite/prompts/index.d.ts.map +1 -0
  23. package/dist/adapters/sqlite/prompts/query.d.ts +19 -0
  24. package/dist/adapters/sqlite/prompts/query.d.ts.map +1 -0
  25. package/dist/adapters/sqlite/prompts/schema.d.ts +20 -0
  26. package/dist/adapters/sqlite/prompts/schema.d.ts.map +1 -0
  27. package/dist/adapters/sqlite/query-executor.d.ts +38 -0
  28. package/dist/adapters/sqlite/query-executor.d.ts.map +1 -0
  29. package/dist/adapters/sqlite/resources.d.ts +13 -0
  30. package/dist/adapters/sqlite/resources.d.ts.map +1 -0
  31. package/dist/adapters/sqlite/schema-manager.d.ts +69 -0
  32. package/dist/adapters/sqlite/schema-manager.d.ts.map +1 -0
  33. package/dist/adapters/sqlite/schemas/admin.d.ts +459 -0
  34. package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -0
  35. package/dist/adapters/sqlite/schemas/codemode.d.ts +30 -0
  36. package/dist/adapters/sqlite/schemas/codemode.d.ts.map +1 -0
  37. package/dist/adapters/sqlite/schemas/common.d.ts +9 -0
  38. package/dist/adapters/sqlite/schemas/common.d.ts.map +1 -0
  39. package/dist/adapters/sqlite/schemas/core.d.ts +530 -0
  40. package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -0
  41. package/dist/adapters/sqlite/schemas/error-mixin.d.ts +10 -0
  42. package/dist/adapters/sqlite/schemas/error-mixin.d.ts.map +1 -0
  43. package/dist/adapters/sqlite/schemas/fts.d.ts +106 -0
  44. package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -0
  45. package/dist/adapters/sqlite/schemas/geo.d.ts +135 -0
  46. package/dist/adapters/sqlite/schemas/geo.d.ts.map +1 -0
  47. package/dist/adapters/sqlite/schemas/index.d.ts +23 -0
  48. package/dist/adapters/sqlite/schemas/index.d.ts.map +1 -0
  49. package/dist/adapters/sqlite/schemas/introspection.d.ts +583 -0
  50. package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -0
  51. package/dist/adapters/sqlite/schemas/json.d.ts +849 -0
  52. package/dist/adapters/sqlite/schemas/json.d.ts.map +1 -0
  53. package/dist/adapters/sqlite/schemas/migration.d.ts +220 -0
  54. package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -0
  55. package/dist/adapters/sqlite/schemas/native.d.ts +235 -0
  56. package/dist/adapters/sqlite/schemas/native.d.ts.map +1 -0
  57. package/dist/adapters/sqlite/schemas/server.d.ts +13 -0
  58. package/dist/adapters/sqlite/schemas/server.d.ts.map +1 -0
  59. package/dist/adapters/sqlite/schemas/spatialite.d.ts +114 -0
  60. package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -0
  61. package/dist/adapters/sqlite/schemas/stats.d.ts +780 -0
  62. package/dist/adapters/sqlite/schemas/stats.d.ts.map +1 -0
  63. package/dist/adapters/sqlite/schemas/text.d.ts +570 -0
  64. package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -0
  65. package/dist/adapters/sqlite/schemas/vector.d.ts +252 -0
  66. package/dist/adapters/sqlite/schemas/vector.d.ts.map +1 -0
  67. package/dist/adapters/sqlite/schemas/virtual.d.ts +257 -0
  68. package/dist/adapters/sqlite/schemas/virtual.d.ts.map +1 -0
  69. package/dist/adapters/sqlite/schemas/where.d.ts +20 -0
  70. package/dist/adapters/sqlite/schemas/where.d.ts.map +1 -0
  71. package/dist/adapters/sqlite/sqlite-adapter/lifecycle.d.ts +13 -0
  72. package/dist/adapters/sqlite/sqlite-adapter/lifecycle.d.ts.map +1 -0
  73. package/dist/adapters/sqlite/sqlite-adapter/schema.d.ts +7 -0
  74. package/dist/adapters/sqlite/sqlite-adapter/schema.d.ts.map +1 -0
  75. package/dist/adapters/sqlite/sqlite-adapter.d.ts +138 -0
  76. package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -0
  77. package/dist/adapters/sqlite/tools/admin/backup/analyze.d.ts +7 -0
  78. package/dist/adapters/sqlite/tools/admin/backup/analyze.d.ts.map +1 -0
  79. package/dist/adapters/sqlite/tools/admin/backup/create.d.ts +11 -0
  80. package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -0
  81. package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts +7 -0
  82. package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -0
  83. package/dist/adapters/sqlite/tools/admin/backup/index.d.ts +7 -0
  84. package/dist/adapters/sqlite/tools/admin/backup/index.d.ts.map +1 -0
  85. package/dist/adapters/sqlite/tools/admin/backup/integrity.d.ts +7 -0
  86. package/dist/adapters/sqlite/tools/admin/backup/integrity.d.ts.map +1 -0
  87. package/dist/adapters/sqlite/tools/admin/backup/optimize.d.ts +7 -0
  88. package/dist/adapters/sqlite/tools/admin/backup/optimize.d.ts.map +1 -0
  89. package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts +7 -0
  90. package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -0
  91. package/dist/adapters/sqlite/tools/admin/helpers.d.ts +18 -0
  92. package/dist/adapters/sqlite/tools/admin/helpers.d.ts.map +1 -0
  93. package/dist/adapters/sqlite/tools/admin/index.d.ts +10 -0
  94. package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -0
  95. package/dist/adapters/sqlite/tools/admin/pragma.d.ts +37 -0
  96. package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -0
  97. package/dist/adapters/sqlite/tools/admin/reindex.d.ts +10 -0
  98. package/dist/adapters/sqlite/tools/admin/reindex.d.ts.map +1 -0
  99. package/dist/adapters/sqlite/tools/admin/verify.d.ts +13 -0
  100. package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -0
  101. package/dist/adapters/sqlite/tools/admin/wal.d.ts +10 -0
  102. package/dist/adapters/sqlite/tools/admin/wal.d.ts.map +1 -0
  103. package/dist/adapters/sqlite/tools/codemode.d.ts +22 -0
  104. package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -0
  105. package/dist/adapters/sqlite/tools/column-validation.d.ts +26 -0
  106. package/dist/adapters/sqlite/tools/column-validation.d.ts.map +1 -0
  107. package/dist/adapters/sqlite/tools/core/alter-table.d.ts +11 -0
  108. package/dist/adapters/sqlite/tools/core/alter-table.d.ts.map +1 -0
  109. package/dist/adapters/sqlite/tools/core/constraints.d.ts +10 -0
  110. package/dist/adapters/sqlite/tools/core/constraints.d.ts.map +1 -0
  111. package/dist/adapters/sqlite/tools/core/convenience-helpers.d.ts +20 -0
  112. package/dist/adapters/sqlite/tools/core/convenience-helpers.d.ts.map +1 -0
  113. package/dist/adapters/sqlite/tools/core/convenience-schemas.d.ts +20 -0
  114. package/dist/adapters/sqlite/tools/core/convenience-schemas.d.ts.map +1 -0
  115. package/dist/adapters/sqlite/tools/core/convenience.d.ts +29 -0
  116. package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -0
  117. package/dist/adapters/sqlite/tools/core/datetime.d.ts +11 -0
  118. package/dist/adapters/sqlite/tools/core/datetime.d.ts.map +1 -0
  119. package/dist/adapters/sqlite/tools/core/index.d.ts +14 -0
  120. package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -0
  121. package/dist/adapters/sqlite/tools/core/indexes.d.ts +20 -0
  122. package/dist/adapters/sqlite/tools/core/indexes.d.ts.map +1 -0
  123. package/dist/adapters/sqlite/tools/core/queries.d.ts +16 -0
  124. package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -0
  125. package/dist/adapters/sqlite/tools/core/tables.d.ts +37 -0
  126. package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -0
  127. package/dist/adapters/sqlite/tools/core/triggers.d.ts +18 -0
  128. package/dist/adapters/sqlite/tools/core/triggers.d.ts.map +1 -0
  129. package/dist/adapters/sqlite/tools/fts.d.ts +13 -0
  130. package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -0
  131. package/dist/adapters/sqlite/tools/geo.d.ts +14 -0
  132. package/dist/adapters/sqlite/tools/geo.d.ts.map +1 -0
  133. package/dist/adapters/sqlite/tools/index.d.ts +33 -0
  134. package/dist/adapters/sqlite/tools/index.d.ts.map +1 -0
  135. package/dist/adapters/sqlite/tools/introspection/analysis/constraints.d.ts +10 -0
  136. package/dist/adapters/sqlite/tools/introspection/analysis/constraints.d.ts.map +1 -0
  137. package/dist/adapters/sqlite/tools/introspection/analysis/diff.d.ts +11 -0
  138. package/dist/adapters/sqlite/tools/introspection/analysis/diff.d.ts.map +1 -0
  139. package/dist/adapters/sqlite/tools/introspection/analysis/index.d.ts +10 -0
  140. package/dist/adapters/sqlite/tools/introspection/analysis/index.d.ts.map +1 -0
  141. package/dist/adapters/sqlite/tools/introspection/analysis/risks.d.ts +9 -0
  142. package/dist/adapters/sqlite/tools/introspection/analysis/risks.d.ts.map +1 -0
  143. package/dist/adapters/sqlite/tools/introspection/analysis/snapshot.d.ts +40 -0
  144. package/dist/adapters/sqlite/tools/introspection/analysis/snapshot.d.ts.map +1 -0
  145. package/dist/adapters/sqlite/tools/introspection/diagnostics/index.d.ts +9 -0
  146. package/dist/adapters/sqlite/tools/introspection/diagnostics/index.d.ts.map +1 -0
  147. package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts +10 -0
  148. package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -0
  149. package/dist/adapters/sqlite/tools/introspection/diagnostics/query-plan.d.ts +10 -0
  150. package/dist/adapters/sqlite/tools/introspection/diagnostics/query-plan.d.ts.map +1 -0
  151. package/dist/adapters/sqlite/tools/introspection/diagnostics/storage.d.ts +10 -0
  152. package/dist/adapters/sqlite/tools/introspection/diagnostics/storage.d.ts.map +1 -0
  153. package/dist/adapters/sqlite/tools/introspection/graph/helpers.d.ts +44 -0
  154. package/dist/adapters/sqlite/tools/introspection/graph/helpers.d.ts.map +1 -0
  155. package/dist/adapters/sqlite/tools/introspection/graph/index.d.ts +9 -0
  156. package/dist/adapters/sqlite/tools/introspection/graph/index.d.ts.map +1 -0
  157. package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts +12 -0
  158. package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -0
  159. package/dist/adapters/sqlite/tools/introspection/index.d.ts +17 -0
  160. package/dist/adapters/sqlite/tools/introspection/index.d.ts.map +1 -0
  161. package/dist/adapters/sqlite/tools/json-helpers/helpers.d.ts +21 -0
  162. package/dist/adapters/sqlite/tools/json-helpers/helpers.d.ts.map +1 -0
  163. package/dist/adapters/sqlite/tools/json-helpers/index.d.ts +17 -0
  164. package/dist/adapters/sqlite/tools/json-helpers/index.d.ts.map +1 -0
  165. package/dist/adapters/sqlite/tools/json-helpers/read.d.ts +24 -0
  166. package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -0
  167. package/dist/adapters/sqlite/tools/json-helpers/write.d.ts +24 -0
  168. package/dist/adapters/sqlite/tools/json-helpers/write.d.ts.map +1 -0
  169. package/dist/adapters/sqlite/tools/json-operations/crud.d.ts +39 -0
  170. package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -0
  171. package/dist/adapters/sqlite/tools/json-operations/diff.d.ts +11 -0
  172. package/dist/adapters/sqlite/tools/json-operations/diff.d.ts.map +1 -0
  173. package/dist/adapters/sqlite/tools/json-operations/helpers.d.ts +18 -0
  174. package/dist/adapters/sqlite/tools/json-operations/helpers.d.ts.map +1 -0
  175. package/dist/adapters/sqlite/tools/json-operations/index.d.ts +10 -0
  176. package/dist/adapters/sqlite/tools/json-operations/index.d.ts.map +1 -0
  177. package/dist/adapters/sqlite/tools/json-operations/query.d.ts +24 -0
  178. package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -0
  179. package/dist/adapters/sqlite/tools/json-operations/security.d.ts +19 -0
  180. package/dist/adapters/sqlite/tools/json-operations/security.d.ts.map +1 -0
  181. package/dist/adapters/sqlite/tools/json-operations/transform.d.ts +24 -0
  182. package/dist/adapters/sqlite/tools/json-operations/transform.d.ts.map +1 -0
  183. package/dist/adapters/sqlite/tools/migration/helpers.d.ts +34 -0
  184. package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -0
  185. package/dist/adapters/sqlite/tools/migration/index.d.ts +15 -0
  186. package/dist/adapters/sqlite/tools/migration/index.d.ts.map +1 -0
  187. package/dist/adapters/sqlite/tools/migration/tracking/apply.d.ts +4 -0
  188. package/dist/adapters/sqlite/tools/migration/tracking/apply.d.ts.map +1 -0
  189. package/dist/adapters/sqlite/tools/migration/tracking/history.d.ts +4 -0
  190. package/dist/adapters/sqlite/tools/migration/tracking/history.d.ts.map +1 -0
  191. package/dist/adapters/sqlite/tools/migration/tracking/index.d.ts +7 -0
  192. package/dist/adapters/sqlite/tools/migration/tracking/index.d.ts.map +1 -0
  193. package/dist/adapters/sqlite/tools/migration/tracking/init.d.ts +4 -0
  194. package/dist/adapters/sqlite/tools/migration/tracking/init.d.ts.map +1 -0
  195. package/dist/adapters/sqlite/tools/migration/tracking/record.d.ts +4 -0
  196. package/dist/adapters/sqlite/tools/migration/tracking/record.d.ts.map +1 -0
  197. package/dist/adapters/sqlite/tools/migration/tracking/rollback.d.ts +4 -0
  198. package/dist/adapters/sqlite/tools/migration/tracking/rollback.d.ts.map +1 -0
  199. package/dist/adapters/sqlite/tools/migration/tracking/status.d.ts +4 -0
  200. package/dist/adapters/sqlite/tools/migration/tracking/status.d.ts.map +1 -0
  201. package/dist/adapters/sqlite/tools/stats/advanced.d.ts +28 -0
  202. package/dist/adapters/sqlite/tools/stats/advanced.d.ts.map +1 -0
  203. package/dist/adapters/sqlite/tools/stats/anomaly-detection.d.ts +22 -0
  204. package/dist/adapters/sqlite/tools/stats/anomaly-detection.d.ts.map +1 -0
  205. package/dist/adapters/sqlite/tools/stats/basic.d.ts +32 -0
  206. package/dist/adapters/sqlite/tools/stats/basic.d.ts.map +1 -0
  207. package/dist/adapters/sqlite/tools/stats/helpers.d.ts +27 -0
  208. package/dist/adapters/sqlite/tools/stats/helpers.d.ts.map +1 -0
  209. package/dist/adapters/sqlite/tools/stats/index.d.ts +12 -0
  210. package/dist/adapters/sqlite/tools/stats/index.d.ts.map +1 -0
  211. package/dist/adapters/sqlite/tools/stats/inference/hypothesis.d.ts +7 -0
  212. package/dist/adapters/sqlite/tools/stats/inference/hypothesis.d.ts.map +1 -0
  213. package/dist/adapters/sqlite/tools/stats/inference/index.d.ts +4 -0
  214. package/dist/adapters/sqlite/tools/stats/inference/index.d.ts.map +1 -0
  215. package/dist/adapters/sqlite/tools/stats/inference/outlier.d.ts +7 -0
  216. package/dist/adapters/sqlite/tools/stats/inference/outlier.d.ts.map +1 -0
  217. package/dist/adapters/sqlite/tools/stats/inference/regression.d.ts +7 -0
  218. package/dist/adapters/sqlite/tools/stats/inference/regression.d.ts.map +1 -0
  219. package/dist/adapters/sqlite/tools/stats/math-helpers.d.ts +17 -0
  220. package/dist/adapters/sqlite/tools/stats/math-helpers.d.ts.map +1 -0
  221. package/dist/adapters/sqlite/tools/stats/schema-risks.d.ts +15 -0
  222. package/dist/adapters/sqlite/tools/stats/schema-risks.d.ts.map +1 -0
  223. package/dist/adapters/sqlite/tools/text/formatting.d.ts +48 -0
  224. package/dist/adapters/sqlite/tools/text/formatting.d.ts.map +1 -0
  225. package/dist/adapters/sqlite/tools/text/helpers.d.ts +22 -0
  226. package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -0
  227. package/dist/adapters/sqlite/tools/text/index.d.ts +10 -0
  228. package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -0
  229. package/dist/adapters/sqlite/tools/text/regex.d.ts +21 -0
  230. package/dist/adapters/sqlite/tools/text/regex.d.ts.map +1 -0
  231. package/dist/adapters/sqlite/tools/text/search.d.ts +17 -0
  232. package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -0
  233. package/dist/adapters/sqlite/tools/text/sentiment.d.ts +13 -0
  234. package/dist/adapters/sqlite/tools/text/sentiment.d.ts.map +1 -0
  235. package/dist/adapters/sqlite/tools/text/validate.d.ts +11 -0
  236. package/dist/adapters/sqlite/tools/text/validate.d.ts.map +1 -0
  237. package/dist/adapters/sqlite/tools/vector/helpers.d.ts +11 -0
  238. package/dist/adapters/sqlite/tools/vector/helpers.d.ts.map +1 -0
  239. package/dist/adapters/sqlite/tools/vector/index.d.ts +14 -0
  240. package/dist/adapters/sqlite/tools/vector/index.d.ts.map +1 -0
  241. package/dist/adapters/sqlite/tools/vector/metadata.d.ts +28 -0
  242. package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -0
  243. package/dist/adapters/sqlite/tools/vector/search.d.ts +16 -0
  244. package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -0
  245. package/dist/adapters/sqlite/tools/vector/storage.d.ts +24 -0
  246. package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -0
  247. package/dist/adapters/sqlite/tools/vector/tools.d.ts +9 -0
  248. package/dist/adapters/sqlite/tools/vector/tools.d.ts.map +1 -0
  249. package/dist/adapters/sqlite/tools/virtual/analysis.d.ts +24 -0
  250. package/dist/adapters/sqlite/tools/virtual/analysis.d.ts.map +1 -0
  251. package/dist/adapters/sqlite/tools/virtual/extensions.d.ts +13 -0
  252. package/dist/adapters/sqlite/tools/virtual/extensions.d.ts.map +1 -0
  253. package/dist/adapters/sqlite/tools/virtual/helpers.d.ts +18 -0
  254. package/dist/adapters/sqlite/tools/virtual/helpers.d.ts.map +1 -0
  255. package/dist/adapters/sqlite/tools/virtual/index.d.ts +10 -0
  256. package/dist/adapters/sqlite/tools/virtual/index.d.ts.map +1 -0
  257. package/dist/adapters/sqlite/tools/virtual/views.d.ts +21 -0
  258. package/dist/adapters/sqlite/tools/virtual/views.d.ts.map +1 -0
  259. package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts +4 -0
  260. package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -0
  261. package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts +4 -0
  262. package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -0
  263. package/dist/adapters/sqlite/tools/virtual/vtable/drop.d.ts +4 -0
  264. package/dist/adapters/sqlite/tools/virtual/vtable/drop.d.ts.map +1 -0
  265. package/dist/adapters/sqlite/tools/virtual/vtable/index.d.ts +6 -0
  266. package/dist/adapters/sqlite/tools/virtual/vtable/index.d.ts.map +1 -0
  267. package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts +4 -0
  268. package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -0
  269. package/dist/adapters/sqlite/tools/virtual/vtable/list.d.ts +4 -0
  270. package/dist/adapters/sqlite/tools/virtual/vtable/list.d.ts.map +1 -0
  271. package/dist/adapters/sqlite/types.d.ts +89 -0
  272. package/dist/adapters/sqlite/types.d.ts.map +1 -0
  273. package/dist/adapters/sqlite-helpers.d.ts +51 -0
  274. package/dist/adapters/sqlite-helpers.d.ts.map +1 -0
  275. package/dist/adapters/sqlite-native/extensions.d.ts +17 -0
  276. package/dist/adapters/sqlite-native/extensions.d.ts.map +1 -0
  277. package/dist/adapters/sqlite-native/index.d.ts +11 -0
  278. package/dist/adapters/sqlite-native/index.d.ts.map +1 -0
  279. package/dist/adapters/sqlite-native/native-query-executor.d.ts +24 -0
  280. package/dist/adapters/sqlite-native/native-query-executor.d.ts.map +1 -0
  281. package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts +160 -0
  282. package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -0
  283. package/dist/adapters/sqlite-native/registration/index.d.ts +12 -0
  284. package/dist/adapters/sqlite-native/registration/index.d.ts.map +1 -0
  285. package/dist/adapters/sqlite-native/tools/spatialite/analysis.d.ts +23 -0
  286. package/dist/adapters/sqlite-native/tools/spatialite/analysis.d.ts.map +1 -0
  287. package/dist/adapters/sqlite-native/tools/spatialite/index.d.ts +15 -0
  288. package/dist/adapters/sqlite-native/tools/spatialite/index.d.ts.map +1 -0
  289. package/dist/adapters/sqlite-native/tools/spatialite/loader.d.ts +22 -0
  290. package/dist/adapters/sqlite-native/tools/spatialite/loader.d.ts.map +1 -0
  291. package/dist/adapters/sqlite-native/tools/spatialite/schemas.d.ts +78 -0
  292. package/dist/adapters/sqlite-native/tools/spatialite/schemas.d.ts.map +1 -0
  293. package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts +30 -0
  294. package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -0
  295. package/dist/adapters/sqlite-native/tools/transactions.d.ts +12 -0
  296. package/dist/adapters/sqlite-native/tools/transactions.d.ts.map +1 -0
  297. package/dist/adapters/sqlite-native/tools/window.d.ts +7 -0
  298. package/dist/adapters/sqlite-native/tools/window.d.ts.map +1 -0
  299. package/dist/adapters/sqlite-native/transaction-methods.d.ts +36 -0
  300. package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -0
  301. package/dist/audit/backup-manager.d.ts +90 -0
  302. package/dist/audit/backup-manager.d.ts.map +1 -0
  303. package/dist/audit/index.d.ts +11 -0
  304. package/dist/audit/index.d.ts.map +1 -0
  305. package/dist/audit/interceptor.d.ts +54 -0
  306. package/dist/audit/interceptor.d.ts.map +1 -0
  307. package/dist/audit/logger.d.ts +62 -0
  308. package/dist/audit/logger.d.ts.map +1 -0
  309. package/dist/audit/types.d.ts +112 -0
  310. package/dist/audit/types.d.ts.map +1 -0
  311. package/dist/auth/auth-context.d.ts +28 -0
  312. package/dist/auth/auth-context.d.ts.map +1 -0
  313. package/dist/auth/authorization-server-discovery.d.ts +90 -0
  314. package/dist/auth/authorization-server-discovery.d.ts.map +1 -0
  315. package/dist/auth/errors.d.ts +74 -0
  316. package/dist/auth/errors.d.ts.map +1 -0
  317. package/dist/auth/middleware/core.d.ts +22 -0
  318. package/dist/auth/middleware/core.d.ts.map +1 -0
  319. package/dist/auth/middleware/express-auth.d.ts +13 -0
  320. package/dist/auth/middleware/express-auth.d.ts.map +1 -0
  321. package/dist/auth/middleware/express-scopes.d.ts +6 -0
  322. package/dist/auth/middleware/express-scopes.d.ts.map +1 -0
  323. package/dist/auth/middleware/extraction.d.ts +2 -0
  324. package/dist/auth/middleware/extraction.d.ts.map +1 -0
  325. package/dist/auth/middleware/index.d.ts +5 -0
  326. package/dist/auth/middleware/index.d.ts.map +1 -0
  327. package/dist/auth/oauth-resource-server.d.ts +74 -0
  328. package/dist/auth/oauth-resource-server.d.ts.map +1 -0
  329. package/dist/auth/scope-map.d.ts +24 -0
  330. package/dist/auth/scope-map.d.ts.map +1 -0
  331. package/dist/auth/scopes/constants.d.ts +40 -0
  332. package/dist/auth/scopes/constants.d.ts.map +1 -0
  333. package/dist/auth/scopes/display.d.ts +5 -0
  334. package/dist/auth/scopes/display.d.ts.map +1 -0
  335. package/dist/auth/scopes/enforcement.d.ts +27 -0
  336. package/dist/auth/scopes/enforcement.d.ts.map +1 -0
  337. package/dist/auth/scopes/index.d.ts +6 -0
  338. package/dist/auth/scopes/index.d.ts.map +1 -0
  339. package/dist/auth/scopes/mapping.d.ts +39 -0
  340. package/dist/auth/scopes/mapping.d.ts.map +1 -0
  341. package/dist/auth/scopes/validation.d.ts +27 -0
  342. package/dist/auth/scopes/validation.d.ts.map +1 -0
  343. package/dist/auth/token-validator.d.ts +63 -0
  344. package/dist/auth/token-validator.d.ts.map +1 -0
  345. package/dist/auth/transport-agnostic.d.ts +11 -0
  346. package/dist/auth/transport-agnostic.d.ts.map +1 -0
  347. package/dist/auth/types.d.ts +257 -0
  348. package/dist/auth/types.d.ts.map +1 -0
  349. package/dist/{chunk-WBER5YY4.js → chunk-37G4DLL6.js} +1010 -409
  350. package/dist/chunk-E5IESRTK.js +489 -0
  351. package/dist/{chunk-645ZEFLA.js → chunk-L552U3QS.js} +887 -309
  352. package/dist/{chunk-5Y42NPBP.js → chunk-NV34JSQM.js} +4656 -1829
  353. package/dist/{chunk-Z7C2TM4L.js → chunk-W5WQVNVX.js} +169 -57
  354. package/dist/cli.d.ts +7 -0
  355. package/dist/cli.d.ts.map +1 -0
  356. package/dist/cli.js +47 -26
  357. package/dist/codemode/api-constants.d.ts +40 -0
  358. package/dist/codemode/api-constants.d.ts.map +1 -0
  359. package/dist/codemode/api.d.ts +70 -0
  360. package/dist/codemode/api.d.ts.map +1 -0
  361. package/dist/codemode/auto-return.d.ts +25 -0
  362. package/dist/codemode/auto-return.d.ts.map +1 -0
  363. package/dist/codemode/index.d.ts +12 -0
  364. package/dist/codemode/index.d.ts.map +1 -0
  365. package/dist/codemode/sandbox-factory.d.ts +72 -0
  366. package/dist/codemode/sandbox-factory.d.ts.map +1 -0
  367. package/dist/codemode/sandbox.d.ts +54 -0
  368. package/dist/codemode/sandbox.d.ts.map +1 -0
  369. package/dist/codemode/security.d.ts +45 -0
  370. package/dist/codemode/security.d.ts.map +1 -0
  371. package/dist/codemode/types.d.ts +167 -0
  372. package/dist/codemode/types.d.ts.map +1 -0
  373. package/dist/constants/server-instructions.d.ts +22 -0
  374. package/dist/constants/server-instructions.d.ts.map +1 -0
  375. package/dist/filtering/tool-constants.d.ts +45 -0
  376. package/dist/filtering/tool-constants.d.ts.map +1 -0
  377. package/dist/filtering/tool-filter.d.ts +82 -0
  378. package/dist/filtering/tool-filter.d.ts.map +1 -0
  379. package/dist/{http-6KF4ULDI.js → http-HWTUVFIA.js} +498 -391
  380. package/dist/index.d.ts +9 -1065
  381. package/dist/index.d.ts.map +1 -0
  382. package/dist/index.js +4 -6
  383. package/dist/server/mcp-server.d.ts +66 -0
  384. package/dist/server/mcp-server.d.ts.map +1 -0
  385. package/dist/server/registration/audit-tools.d.ts +13 -0
  386. package/dist/server/registration/audit-tools.d.ts.map +1 -0
  387. package/dist/server/registration/built-in-tools.d.ts +8 -0
  388. package/dist/server/registration/built-in-tools.d.ts.map +1 -0
  389. package/dist/server/registration/help-resources.d.ts +7 -0
  390. package/dist/server/registration/help-resources.d.ts.map +1 -0
  391. package/dist/server/registration/index.d.ts +4 -0
  392. package/dist/server/registration/index.d.ts.map +1 -0
  393. package/dist/{sqlite-U5KSYQXK.js → sqlite-TB56Z7G3.js} +61 -17
  394. package/dist/{sqlite-native-JXMCFQBA.js → sqlite-native-IF75BB3O.js} +459 -254
  395. package/dist/transports/http/index.d.ts +8 -0
  396. package/dist/transports/http/index.d.ts.map +1 -0
  397. package/dist/transports/http/middleware.d.ts +25 -0
  398. package/dist/transports/http/middleware.d.ts.map +1 -0
  399. package/dist/transports/http/oauth.d.ts +24 -0
  400. package/dist/transports/http/oauth.d.ts.map +1 -0
  401. package/dist/transports/http/session.d.ts +2 -0
  402. package/dist/transports/http/session.d.ts.map +1 -0
  403. package/dist/transports/http/sessions/index.d.ts +4 -0
  404. package/dist/transports/http/sessions/index.d.ts.map +1 -0
  405. package/dist/transports/http/sessions/legacy-sse.d.ts +6 -0
  406. package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -0
  407. package/dist/transports/http/sessions/mutex.d.ts +6 -0
  408. package/dist/transports/http/sessions/mutex.d.ts.map +1 -0
  409. package/dist/transports/http/sessions/stateful.d.ts +12 -0
  410. package/dist/transports/http/sessions/stateful.d.ts.map +1 -0
  411. package/dist/transports/http/sessions/stateless.d.ts +6 -0
  412. package/dist/transports/http/sessions/stateless.d.ts.map +1 -0
  413. package/dist/transports/http/transport.d.ts +65 -0
  414. package/dist/transports/http/transport.d.ts.map +1 -0
  415. package/dist/transports/http/type-adapters.d.ts +20 -0
  416. package/dist/transports/http/type-adapters.d.ts.map +1 -0
  417. package/dist/transports/http/types.d.ts +120 -0
  418. package/dist/transports/http/types.d.ts.map +1 -0
  419. package/dist/types/adapter.d.ts +138 -0
  420. package/dist/types/adapter.d.ts.map +1 -0
  421. package/dist/types/auth.d.ts +79 -0
  422. package/dist/types/auth.d.ts.map +1 -0
  423. package/dist/types/database.d.ts +100 -0
  424. package/dist/types/database.d.ts.map +1 -0
  425. package/dist/types/filtering.d.ts +41 -0
  426. package/dist/types/filtering.d.ts.map +1 -0
  427. package/dist/types/index.d.ts +13 -0
  428. package/dist/types/index.d.ts.map +1 -0
  429. package/dist/types/server.d.ts +48 -0
  430. package/dist/types/server.d.ts.map +1 -0
  431. package/dist/utils/annotations.d.ts +62 -0
  432. package/dist/utils/annotations.d.ts.map +1 -0
  433. package/dist/utils/errors/base.d.ts +33 -0
  434. package/dist/utils/errors/base.d.ts.map +1 -0
  435. package/dist/utils/errors/categories.d.ts +41 -0
  436. package/dist/utils/errors/categories.d.ts.map +1 -0
  437. package/dist/utils/errors/classes.d.ts +124 -0
  438. package/dist/utils/errors/classes.d.ts.map +1 -0
  439. package/dist/utils/errors/error-response-fields.d.ts +24 -0
  440. package/dist/utils/errors/error-response-fields.d.ts.map +1 -0
  441. package/dist/utils/errors/format.d.ts +74 -0
  442. package/dist/utils/errors/format.d.ts.map +1 -0
  443. package/dist/utils/errors/index.d.ts +11 -0
  444. package/dist/utils/errors/index.d.ts.map +1 -0
  445. package/dist/utils/errors/suggestions.d.ts +16 -0
  446. package/dist/utils/errors/suggestions.d.ts.map +1 -0
  447. package/dist/utils/icons.d.ts +19 -0
  448. package/dist/utils/icons.d.ts.map +1 -0
  449. package/dist/utils/identifiers.d.ts +121 -0
  450. package/dist/utils/identifiers.d.ts.map +1 -0
  451. package/dist/utils/index.d.ts +9 -0
  452. package/dist/utils/index.d.ts.map +1 -0
  453. package/dist/utils/insights-manager.d.ts +39 -0
  454. package/dist/utils/insights-manager.d.ts.map +1 -0
  455. package/dist/utils/logger/error-codes.d.ts +48 -0
  456. package/dist/utils/logger/error-codes.d.ts.map +1 -0
  457. package/dist/utils/logger/index.d.ts +22 -0
  458. package/dist/utils/logger/index.d.ts.map +1 -0
  459. package/dist/utils/logger/logger.d.ts +94 -0
  460. package/dist/utils/logger/logger.d.ts.map +1 -0
  461. package/dist/utils/logger/module-logger.d.ts +28 -0
  462. package/dist/utils/logger/module-logger.d.ts.map +1 -0
  463. package/dist/utils/logger/types.d.ts +36 -0
  464. package/dist/utils/logger/types.d.ts.map +1 -0
  465. package/dist/utils/progress-utils.d.ts +54 -0
  466. package/dist/utils/progress-utils.d.ts.map +1 -0
  467. package/dist/utils/redaction.d.ts +4 -0
  468. package/dist/utils/redaction.d.ts.map +1 -0
  469. package/dist/utils/resource-annotations.d.ts +36 -0
  470. package/dist/utils/resource-annotations.d.ts.map +1 -0
  471. package/dist/utils/validate-json-path.d.ts +43 -0
  472. package/dist/utils/validate-json-path.d.ts.map +1 -0
  473. package/dist/utils/validate-path.d.ts +37 -0
  474. package/dist/utils/validate-path.d.ts.map +1 -0
  475. package/dist/utils/where-clause.d.ts +42 -0
  476. package/dist/utils/where-clause.d.ts.map +1 -0
  477. package/dist/version.d.ts +10 -0
  478. package/dist/version.d.ts.map +1 -0
  479. package/package.json +26 -13
  480. package/.gitattributes +0 -2
  481. package/.gitleaks.toml +0 -9
  482. package/.trivyignore +0 -8
  483. package/dist/chunk-OKOVZ5QE.js +0 -28
  484. package/dist/chunk-SFJQCNG7.js +0 -131
  485. package/dist/chunk-VIDSICEL.js +0 -85
  486. package/dist/chunk-X3MUUOWM.js +0 -152
  487. package/dist/worker-script.d.ts +0 -2
  488. package/dist/worker-script.js +0 -150
  489. package/logs/.gitkeep +0 -1
  490. package/mcp-config-example.json +0 -83
  491. package/playwright.config.ts +0 -101
  492. package/scripts/generate-server-instructions.ts +0 -111
  493. package/scripts/update-badges.ts +0 -99
  494. package/server.json +0 -54
  495. package/test-server/README.md +0 -115
  496. package/test-server/code-map.md +0 -421
  497. package/test-server/fixtures/sample.csv +0 -6
  498. package/test-server/reset-database.ps1 +0 -415
  499. package/test-server/sample.csv +0 -11
  500. package/test-server/scripts/README.md +0 -27
  501. package/test-server/scripts/test-help-resources.mjs +0 -245
  502. package/test-server/scripts/test-prompts.mjs +0 -251
  503. package/test-server/scripts/test-tool-annotations.mjs +0 -162
  504. package/test-server/test-advanced/README.md +0 -70
  505. package/test-server/test-advanced/test-codemode-advanced-admin.md +0 -174
  506. package/test-server/test-advanced/test-codemode-advanced-core.md +0 -193
  507. package/test-server/test-advanced/test-codemode-advanced-geo.md +0 -157
  508. package/test-server/test-advanced/test-codemode-advanced-introspection.md +0 -171
  509. package/test-server/test-advanced/test-codemode-advanced-json.md +0 -169
  510. package/test-server/test-advanced/test-codemode-advanced-migration.md +0 -160
  511. package/test-server/test-advanced/test-codemode-advanced-stats.md +0 -185
  512. package/test-server/test-advanced/test-codemode-advanced-text.md +0 -183
  513. package/test-server/test-advanced/test-codemode-advanced-transactions.md +0 -136
  514. package/test-server/test-advanced/test-codemode-advanced-vector.md +0 -141
  515. package/test-server/test-codemode/README.md +0 -121
  516. package/test-server/test-codemode/test-codemode-admin.md +0 -223
  517. package/test-server/test-codemode/test-codemode-core.md +0 -286
  518. package/test-server/test-codemode/test-codemode-geo.md +0 -177
  519. package/test-server/test-codemode/test-codemode-introspection.md +0 -190
  520. package/test-server/test-codemode/test-codemode-json.md +0 -237
  521. package/test-server/test-codemode/test-codemode-migration.md +0 -278
  522. package/test-server/test-codemode/test-codemode-sandbox.md +0 -413
  523. package/test-server/test-codemode/test-codemode-stats.md +0 -232
  524. package/test-server/test-codemode/test-codemode-text.md +0 -237
  525. package/test-server/test-codemode/test-codemode-transactions.md +0 -236
  526. package/test-server/test-codemode/test-codemode-vector.md +0 -244
  527. package/test-server/test-codemode/test-codemode-wasm-degradation.md +0 -394
  528. package/test-server/test-database.sql +0 -424
  529. package/test-server/test-preflight.md +0 -53
  530. package/test-server/test-prompts.md +0 -354
  531. package/test-server/test-resources.md +0 -272
  532. package/test-server/test-tool-groups/README.md +0 -100
  533. package/test-server/test-tool-groups/test-admin-core.md +0 -165
  534. package/test-server/test-tool-groups/test-admin-extensions.md +0 -133
  535. package/test-server/test-tool-groups/test-core-data.md +0 -262
  536. package/test-server/test-tool-groups/test-core-schema.md +0 -240
  537. package/test-server/test-tool-groups/test-geo-haversine.md +0 -130
  538. package/test-server/test-tool-groups/test-geo-spatialite.md +0 -110
  539. package/test-server/test-tool-groups/test-introspection-diagnostics.md +0 -123
  540. package/test-server/test-tool-groups/test-introspection-schema.md +0 -133
  541. package/test-server/test-tool-groups/test-json-read.md +0 -219
  542. package/test-server/test-tool-groups/test-json-write.md +0 -157
  543. package/test-server/test-tool-groups/test-migration.md +0 -193
  544. package/test-server/test-tool-groups/test-stats-advanced.md +0 -118
  545. package/test-server/test-tool-groups/test-stats-basic.md +0 -156
  546. package/test-server/test-tool-groups/test-text-advanced.md +0 -169
  547. package/test-server/test-tool-groups/test-text-basic.md +0 -177
  548. package/test-server/test-tool-groups/test-transactions.md +0 -179
  549. package/test-server/test-tool-groups/test-vector-read.md +0 -130
  550. package/test-server/test-tool-groups/test-vector-write.md +0 -115
  551. package/test-server/tool-reference.md +0 -257
  552. package/tsconfig.build.json +0 -6
  553. package/tsconfig.test.json +0 -9
@@ -1,6 +1,5 @@
1
- import { TOOL_GROUP_SCOPES, getAuthContext, SCOPES } from './chunk-SFJQCNG7.js';
2
- import { VERSION, NAME, READ_ONLY, SERVER_ICONS } from './chunk-VIDSICEL.js';
3
- import { TOOL_GROUPS, parseToolFilter, getToolFilterFromEnv, logger, getFilterSummary, DbMcpError } from './chunk-645ZEFLA.js';
1
+ import { VERSION, NAME, READ_ONLY, SERVER_ICONS, ASSISTANT_FOCUSED, redactObject, getRequiredScope, AuditListBackupsOutputSchema, AuditListBackupsSchema, AuditGetBackupOutputSchema, AuditCleanupOutputSchema, AuditDiffBackupOutputSchema, AuditRestoreBackupOutputSchema } from './chunk-E5IESRTK.js';
2
+ import { parseToolFilter, getToolFilterFromEnv, logger, getFilterSummary, DbMcpError, getAuthContext, scopesGrantToolAccess, registerToolScopes, InsufficientScopeError, sanitizeErrorMessage, formatHandlerError } from './chunk-L552U3QS.js';
4
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
4
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
5
  import { open, stat, mkdir, rename, readdir, unlink, mkdtemp, writeFile, rmdir, readFile, appendFile } from 'fs/promises';
@@ -24,17 +23,17 @@ var INSTRUCTIONS = `# db-mcp (SQLite MCP Server)
24
23
 
25
24
  ## Built-in Tools
26
25
 
27
- \`server_info\`, \`server_health\`, \`list_adapters\` \u2014 always available.
26
+ \`server_info\`, \`server_health\`, \`list_adapters\`, \`sqlite_execute_code\` \u2014 injected into all configurations.
28
27
 
29
28
  ## Help Resources
30
29
 
31
30
  Read \`sqlite://help\` for gotchas and critical usage patterns.
32
- Read \`sqlite://help/{group}\` for group-specific tool reference (json, text, stats, vector, geo, admin, transactions, introspection, migration).
31
+ Read \`sqlite://help/{group}\` for group-specific tool reference (core, json, text, stats, vector, geo, admin, transactions, introspection, migration).
33
32
  Only help resources for your enabled tool groups are registered.`;
34
33
  var HELP_CONTENT = /* @__PURE__ */ new Map([
35
34
  [
36
35
  "admin",
37
- `# db-mcp Help \u2014 Database Administration (29 Native / 29 WASM)
36
+ `# db-mcp Help \u2014 Database Administration (32N/31W tools) + Server Audit (5 tools)
38
37
 
39
38
  ## Maintenance
40
39
 
@@ -44,21 +43,28 @@ sqlite_optimize({ analyze: true, reindex: true }); // optimize performance
44
43
  sqlite_vacuum(); // reclaim space
45
44
  sqlite_analyze({ table: "orders" }); // update statistics for query planner
46
45
  sqlite_dbstat({ summarize: true }); // storage stats (\u26A0\uFE0F summarize native-only; WASM returns counts only)
46
+ sqlite_reindex(); // rebuild all indexes
47
+ sqlite_reindex({ target: "idx_users_email" }); // rebuild specific index
48
+ sqlite_reindex({ target: "orders" }); // rebuild all indexes for a table
47
49
  \`\`\`
48
50
 
49
51
  ## Backup/Restore (Native only)
50
52
 
51
53
  \`\`\`javascript
52
54
  sqlite_backup({ targetPath: "/path/to/backup.db" });
55
+ sqlite_vacuum_into({ outputPath: "/path/to/compact.db" }); // create defragmented copy
56
+ sqlite_dump({ outputPath: "/path/to/dump.sql" }); // export SQL text dump
53
57
  sqlite_verify_backup({ backupPath: "/path/to/backup.db" }); // check integrity without restoring
54
58
  sqlite_restore({ sourcePath: "/path/to/backup.db" }); // \u26A0\uFE0F WARNING: Replaces current database
55
59
  \`\`\`
56
60
 
57
- ## Audit Backups (Requires --audit-backup)
61
+ ## Audit Backups
58
62
 
59
63
  \`\`\`javascript
60
- sqlite_audit_list_backups(); // list pre-mutation DDL snapshots
64
+ sqlite_audit_list_backups({ limit: 10, offset: 0 }); // list pre-mutation DDL snapshots
61
65
  sqlite_audit_get_backup({ filename: "snapshot_123.json" }); // retrieve specific snapshot
66
+ sqlite_audit_diff_backup({ filename: "snapshot_123.json" }); // compare snapshot against live schema
67
+ sqlite_audit_restore_backup({ filename: "snapshot_123.json", dryRun: true }); // restore schema from snapshot
62
68
  sqlite_audit_cleanup(); // apply retention policy and delete old snapshots
63
69
  \`\`\`
64
70
 
@@ -70,9 +76,21 @@ sqlite_pragma_settings({ pragma: "cache_size", value: 10000 }); // set value
70
76
  sqlite_pragma_table_info({ table: "users" }); // column details
71
77
  sqlite_pragma_compile_options({ filter: "FTS" }); // \u26A0\uFE0F WASM may show FTS3, not FTS5
72
78
  sqlite_pragma_database_list(); // list attached databases
79
+ sqlite_attach_database({ filepath: "/path/to/other.db", alias: "archive" }); // attach external DB
80
+ sqlite_detach_database({ alias: "archive" }); // detach DB
73
81
  sqlite_pragma_optimize(); // run PRAGMA optimize
74
82
  \`\`\`
75
83
 
84
+ ## WAL Management
85
+
86
+ \`\`\`javascript
87
+ sqlite_wal({ action: "status" }); // check current journal mode
88
+ sqlite_wal({ action: "enable" }); // switch to WAL mode
89
+ sqlite_wal({ action: "disable" }); // switch back to DELETE journal mode
90
+ sqlite_wal({ action: "checkpoint" }); // run default checkpoint
91
+ sqlite_wal({ action: "checkpoint", checkpointMode: "TRUNCATE" }); // checkpoint and truncate WAL file
92
+ \`\`\`
93
+
76
94
  ## Index & Stats
77
95
 
78
96
  - \`sqlite_index_stats({ table: "orders" })\` \u2014 stats for explicit indexes
@@ -132,19 +150,24 @@ sqlite_append_insight({ insight: "Q4 revenue increased 23% YoY" }); // add to me
132
150
  ],
133
151
  [
134
152
  "core",
135
- `# db-mcp Help \u2014 Core Operations (14 tools)
153
+ `# db-mcp Help \u2014 Core Operations (21 tools)
136
154
 
137
155
  ## Basic Queries
138
156
 
139
157
  - \`sqlite_read_query({ query: "SELECT * FROM users LIMIT 10" })\` \u2014 execute SELECT, PRAGMA, EXPLAIN, or WITH statements
140
- - \`sqlite_write_query({ query: "INSERT INTO users (name) VALUES ('Alice')" })\` \u2014 execute INSERT, UPDATE, DELETE, or DDL statements
158
+ - \`sqlite_write_query({ query: "INSERT INTO users (name) VALUES ('Alice')" })\` \u2014 execute INSERT, UPDATE, DELETE, REPLACE, or trigger DDL (CREATE/DROP TRIGGER)
141
159
 
142
160
  ## Tables & Schema
143
161
 
144
162
  - \`sqlite_list_tables({ excludeSystemTables?: boolean })\` \u2014 list all tables in the database (system tables excluded by default)
145
- - \`sqlite_describe_table({ table: "users" })\` \u2014 get detailed schema, columns, and foreign keys for a specific table
146
- - \`sqlite_create_table({ table: "users", columns: [{ name: "id", type: "INTEGER PRIMARY KEY" }, { name: "email", type: "TEXT UNIQUE" }] })\` \u2014 create a new table
163
+ - \`sqlite_describe_table({ table: "users" })\` \u2014 get detailed schema, columns, and foreign keys for a specific table. Detects generated columns (VIRTUAL/STORED) with expression.
164
+ - \`sqlite_create_table({ table: "users", columns: [{ name: "id", type: "INTEGER PRIMARY KEY" }, { name: "email", type: "TEXT UNIQUE" }], foreignKeys: [{ column: "role_id", targetTable: "roles" }], checkConstraints: ["price > 0"] })\` \u2014 create a new table with optional table-level constraints. Use \`strict: true\` for STRICT mode (SQLite 3.37+) to enforce column type checking.
147
165
  - \`sqlite_drop_table({ table: "users", ifExists?: true })\` \u2014 drop an existing table
166
+ - \`sqlite_alter_table({ table: "users", operation: "add_column", column: "age", type: "INTEGER", nullable: true })\` \u2014 add, rename, or drop columns, or rename a table. Operations: \`add_column\`, \`rename_column\`, \`drop_column\`, \`rename_table\`.
167
+ - \`sqlite_list_triggers({ table?: "users" })\` \u2014 list database triggers, optionally filtered by table
168
+ - \`sqlite_create_trigger({ name: "trg_updated", table: "users", timing: "AFTER", event: "UPDATE", body: "UPDATE users SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id" })\` \u2014 create a trigger with BEFORE/AFTER/INSTEAD OF timing, optional column-specific UPDATE triggers and WHEN conditions
169
+ - \`sqlite_drop_trigger({ name: "trg_updated" })\` \u2014 drop a database trigger
170
+ - \`sqlite_list_constraints({ table: "users" })\` \u2014 list primary key, foreign key, unique, and check constraints for a table
148
171
 
149
172
  ## Indexes
150
173
 
@@ -154,15 +177,17 @@ sqlite_append_insight({ insight: "Q4 revenue increased 23% YoY" }); // add to me
154
177
 
155
178
  ## Convenience Tools (High-Level Data Operations)
156
179
 
157
- - \`sqlite_upsert({ table: "users", data: [{ id: 1, name: "Alice" }], conflictColumns: ["id"], updateColumns: ["name"], returning: true })\` \u2014 insert or update rows using \`ON CONFLICT\` (or \`REPLACE\` fallback). Supports \`returning: true\` or array of columns.
158
- - \`sqlite_batch_insert({ table: "users", data: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }], returning: true })\` \u2014 insert multiple rows in a single batch. Supports \`returning: true\` or array of columns.
159
- - \`sqlite_count({ table: "users", whereClause?: "status = 'active'" })\` \u2014 count rows in a table (faster than a full query)
160
- - \`sqlite_exists({ table: "users", whereClause: "email = 'test@example.com'" })\` \u2014 check if a row exists (stops at first match)
161
- - \`sqlite_truncate({ table: "users" })\` \u2014 quickly delete all rows from a table (executes \`DELETE FROM table\`)`
180
+ - \`sqlite_upsert({ table: "users", data: { id: 1, name: "Alice" }, conflictColumns: ["id"], updateColumns: ["name"], returning: true })\` \u2014 insert or update a row using \`ON CONFLICT\` (or \`REPLACE\` fallback). Supports \`returning: true\` or array of columns.
181
+ - \`sqlite_batch_insert({ table: "users", rows: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }], returning: true })\` \u2014 insert multiple rows in a single batch. Supports \`returning: true\` or array of columns.
182
+ - \`sqlite_count({ table: "users", where?: "status = 'active'" })\` \u2014 count rows in a table (faster than a full query)
183
+ - \`sqlite_exists({ table: "users", where: "email = 'test@example.com'" })\` \u2014 check if a row exists (stops at first match)
184
+ - \`sqlite_truncate({ table: "users" })\` \u2014 quickly delete all rows from a table (executes \`DELETE FROM table\`)
185
+ - \`sqlite_date_add({ table: "users", column: "created_at", amount: 7, unit: "days", whereClause: "id = 1" })\` \u2014 add or subtract time intervals from a date column. By default returns only the computed column; use \`selectColumns\` to return additional context.
186
+ - \`sqlite_date_diff({ table: "users", column1: "ended_at", column2: "started_at", unit: "days", whereClause: "id = 1" })\` \u2014 calculate the difference between two date columns. By default returns only the computed column; use \`selectColumns\` to return additional context.`
162
187
  ],
163
188
  [
164
189
  "geo",
165
- `# db-mcp Help \u2014 Geospatial Operations (4 basic + 7 SpatiaLite)
190
+ `# db-mcp Help \u2014 Geospatial Operations (11N/4W: 4 basic + 7 SpatiaLite [NATIVE ONLY])
166
191
 
167
192
  ## Basic Geo (always available \u2014 Haversine formula)
168
193
 
@@ -275,7 +300,7 @@ sqlite_spatialite_index({
275
300
 
276
301
  ## \u26A0\uFE0F Critical Gotchas
277
302
 
278
- 1. **sqlite_write_query**: \u26D4 Only INSERT/UPDATE/DELETE \u2014 use \`sqlite_read_query\` for SELECT
303
+ 1. **sqlite_write_query**: DML only (INSERT/UPDATE/DELETE/REPLACE) \u2014 use \`sqlite_read_query\` for SELECT, and dedicated DDL tools like \`sqlite_create_table\`, \`sqlite_create_trigger\`, and \`sqlite_drop_trigger\` for schema modifications.
279
304
  2. **Regex patterns**: Double-escape backslashes (\`\\\\\\\\\`) when passing through JSON/MCP
280
305
  3. **FTS5 virtual tables**: \`*_fts\` and shadow tables \`*_fts_*\` are hidden from \`sqlite_list_tables\` for cleaner output
281
306
  4. **FTS5 boolean logic**: Uses AND by default \u2014 \`"machine learning"\` = rows with BOTH words. Use OR explicitly: \`"machine OR learning"\`
@@ -286,13 +311,16 @@ sqlite_spatialite_index({
286
311
  9. **Fuzzy matching tokenization**: Matches WORD TOKENS by default \u2014 \`"laptop"\` matches \`"Laptop Pro 15"\` (distance 0 on first token). Use \`tokenize: false\` for full-string matching
287
312
  10. **SpatiaLite distances**: \`nearest_neighbor\`/\`distance_matrix\` return CARTESIAN distance (degrees), not geodetic (km/miles)
288
313
  11. **SpatiaLite buffer**: Auto-simplifies output by default (tolerance=0.0001). Use \`simplifyTolerance: 0\` to disable
289
- 12. **sqlite_stats_top_n**: Auto-excludes long-content columns (description, body, notes, etc.) when \`selectColumns\` is omitted. Use \`selectColumns\` to override
314
+ 12. **sqlite_stats_top_n**: Returns all columns by default which creates large payloads for wide tables \u2014 always pass \`selectColumns\` to control output size
290
315
  13. **CSV virtual tables**: Require ABSOLUTE file paths
291
316
  14. **sqlite_create_series_table**: Creates a REGULAR table (not virtual) \u2014 use \`sqlite_drop_table\` to remove
292
317
  15. **sqlite_dbstat**: \`summarize\` only works in native; WASM returns counts only
293
318
  16. **PRAGMA compile options**: WASM may show FTS3, not FTS5
294
319
  17. **Vector tool schemas**: Vector tools use distinct schemas for specific operations. E.g., \`sqlite.vector.dimensions\` requires \`vectorColumn\`. Additionally, \`sqlite.vector.get\` wraps metadata inside a \`metadata\` object (e.g., \`metadata.content\`), and \`sqlite.vector.stats\` returns \`sampleSize\` and \`magnitudeStats\` (not \`count\` and \`stats\`).
295
320
  18. **FTS5 trigger cleanup**: Dropping an FTS5 table with \`sqlite_drop_table\` automatically finds and removes the associated \`_ai\`, \`_ad\`, and \`_au\` sync triggers from the source table.
321
+ 19. **sqlite_batch_insert**: All rows must have the same keys \u2014 inconsistent column sets across rows will cause errors or unexpected NULLs
322
+ 20. **sqlite_schema_diff**: \`baseline\` and \`target\` accept either the string \`"current"\` (queries live DB) or an inline snapshot object from a prior \`sqlite_schema_snapshot\` call. At least one side must be \`"current"\` unless doing an offline comparison
323
+ 21. **sqlite_upsert**: Always specify \`conflictColumns\` \u2014 without it, falls back to \`REPLACE\` which deletes and re-inserts the row, potentially losing columns not included in \`data\`
296
324
 
297
325
  ## WASM vs Native
298
326
 
@@ -302,14 +330,14 @@ sqlite_spatialite_index({
302
330
  | Transactions (8 tools) | \u2705 | \u274C | None |
303
331
  | Window functions (6 tools in stats group) | \u2705 | \u274C | None |
304
332
  | SpatiaLite GIS (7 tools; 4 basic geo always work) | \u2705 | \u274C | None |
305
- | Backup/Restore (3 tools) | \u2705 | \u274C | Graceful error |
333
+ | Backup/Restore/Dump/VacuumInto/Verify (5 tools) | \u2705 | \u274C | Graceful error |
306
334
  | R-Tree spatial indexing | \u2705 | \u274C | Graceful error |
307
335
  | CSV virtual tables | \u2705 | \u274C | Graceful error |
308
336
  | generate_series | JS fallback | JS fallback | \u2014 |
309
337
  | dbstat | \u2705 native (per-table) | \u274C | JS (counts only) |
310
338
  | soundex() | \u2705 native | \u274C | JS |
311
339
 
312
- ## Code Mode (1 tool)
340
+ ## Code Mode (Built-in)
313
341
 
314
342
  | Tool | Description |
315
343
  | --------------------- | ----------------------------------------------------------------- |
@@ -317,6 +345,7 @@ sqlite_spatialite_index({
317
345
 
318
346
  **Usage**: \`sqlite_execute_code({ code: "const tables = await sqlite.core.listTables(); return tables;" })\`
319
347
  **Discover**: \`sqlite.help()\` for all groups, \`sqlite.<group>.help()\` for methods.
348
+ **Progress**: Use \`await sqlite.reportProgress(current, total, "Message")\` for custom long-running tasks.
320
349
  **Groups**: \`sqlite.core\`, \`sqlite.json\`, \`sqlite.text\`, \`sqlite.stats\`, \`sqlite.vector\`, \`sqlite.admin\`, \`sqlite.transactions\` (Native-only), \`sqlite.geo\`, \`sqlite.introspection\`, \`sqlite.migration\`
321
350
 
322
351
  > **Note**: Code Mode dynamically filters capabilities. In WASM environments, \`sqlite.help()\` will omit unsupported groups (e.g., \`transactions\`) and tools (e.g., FTS5) to accurately reflect the active runtime.
@@ -324,6 +353,7 @@ sqlite_spatialite_index({
324
353
  ## Code Mode API Mapping
325
354
 
326
355
  \`sqlite_group_action\` \u2192 \`sqlite.group.action()\` (group prefixes dropped: \`sqlite_json_insert\` \u2192 \`sqlite.json.insert()\`)
356
+ **Exception**: \`stats\` and \`migration\` keep their prefix: \`sqlite_stats_basic\` \u2192 \`sqlite.stats.statsBasic()\`, \`sqlite_migration_apply\` \u2192 \`sqlite.migration.migrationApply()\`
327
357
 
328
358
  **Positional args work**: \`sqlite.core.readQuery("SELECT...")\`, \`sqlite.json.insert("docs", "data", {...})\`
329
359
 
@@ -331,7 +361,7 @@ sqlite_spatialite_index({
331
361
  ],
332
362
  [
333
363
  "introspection",
334
- `# db-mcp Help \u2014 Schema Introspection (9 tools)
364
+ `# db-mcp Help \u2014 Schema Introspection (10 tools)
335
365
 
336
366
  All introspection tools are **read-only** \u2014 they query PRAGMAs and sqlite_master, never modify data.
337
367
 
@@ -347,11 +377,11 @@ sqlite_topological_sort({ direction: "create", excludeSystemTables: true });
347
377
  sqlite_topological_sort({ direction: "drop" }); // safe DROP order
348
378
 
349
379
  // Simulate DELETE/DROP/TRUNCATE impact \u2014 shows affected tables, cascade paths, severity scoring
350
- sqlite_cascade_simulator({ table: "users", operation: "delete" });
351
- sqlite_cascade_simulator({ table: "users", operation: "drop", compact: true }); // compact omits path arrays
380
+ sqlite_cascade_simulator({ table: "users", operation: "DELETE" });
381
+ sqlite_cascade_simulator({ table: "users", operation: "DROP", compact: true }); // compact omits path arrays
352
382
  \`\`\`
353
383
 
354
- ## Schema Analysis (3 tools)
384
+ ## Schema Analysis (4 tools)
355
385
 
356
386
  \`\`\`javascript
357
387
  // Full schema in one call \u2014 compact: true omits column details, sections limits scope
@@ -361,6 +391,20 @@ sqlite_schema_snapshot({
361
391
  });
362
392
  sqlite_schema_snapshot({ compact: true }); // lighter payload
363
393
 
394
+ // Compare a saved snapshot against the current live schema \u2014 structured drift analysis
395
+ sqlite_schema_diff({
396
+ baseline: previousSnapshot, // from an earlier sqlite_schema_snapshot call
397
+ target: "current",
398
+ });
399
+ // Compare specific sections only
400
+ sqlite_schema_diff({
401
+ baseline: "current",
402
+ target: modifiedSnapshot,
403
+ sections: ["tables", "indexes"],
404
+ });
405
+ // Both sides inline (offline diff, no DB queries)
406
+ sqlite_schema_diff({ baseline: snapshotA, target: snapshotB });
407
+
364
408
  // Find constraint health issues \u2014 missing PKs, nullable FKs, unindexed FKs
365
409
  sqlite_constraint_analysis({ excludeSystemTables: true });
366
410
  sqlite_constraint_analysis({
@@ -402,13 +446,13 @@ sqlite_query_plan({ sql: "SELECT * FROM orders WHERE status = 'active'" });
402
446
  ],
403
447
  [
404
448
  "json",
405
- `# db-mcp Help \u2014 JSON Operations (24 tools)
449
+ `# db-mcp Help \u2014 JSON Operations (25 tools)
406
450
 
407
451
  ## Collection & CRUD
408
452
 
409
453
  - \`sqlite_create_json_collection({ tableName, indexes: [{ path: "$.type" }, { path: "$.author" }] })\` \u2014 creates table with JSON indexes
410
454
  - \`sqlite_json_insert({ table, column, data: { type: "article", title: "Hello", tags: ["news"] } })\` \u2014 insert JSON document
411
- - \`sqlite_json_select({ table, column, extractPaths? })\` \u2014 select rows, optionally extract specific JSON paths
455
+ - \`sqlite_json_select({ table, column, paths? })\` \u2014 select rows, optionally extract specific JSON paths
412
456
  - \`sqlite_json_update({ table, column, path, value, whereClause })\` \u2014 update value at JSON path
413
457
  - \`sqlite_json_query({ table, column, filterPaths: { "$.type": "article" }, selectPaths: ["$.title"] })\` \u2014 query with path-based filters and projections
414
458
 
@@ -463,9 +507,10 @@ sqlite_json_group_object({
463
507
  \`\`\`
464
508
 
465
509
  - \`sqlite_json_keys({ table, column, path? })\` \u2014 get distinct keys of JSON objects
466
- - \`sqlite_json_pretty({ table, column, whereClause? })\` \u2014 format JSON with indentation
467
- - \`sqlite_json_valid({ table, column })\` \u2014 check if values are valid JSON
510
+ - \`sqlite_json_pretty({ json: "{\\"name\\": \\"Alice\\"}" })\` \u2014 format JSON string with indentation for readability
511
+ - \`sqlite_json_valid({ json: "{\\"name\\": \\"Alice\\"}" })\` \u2014 check if a string is valid JSON
468
512
  - \`sqlite_json_analyze_schema({ table, column })\` \u2014 infer schema types
513
+ - \`sqlite_json_diff({ table, column, path1, path2 })\` \u2014 compare two JSON paths within the same row
469
514
 
470
515
  ## Security
471
516
 
@@ -492,8 +537,7 @@ sqlite_migration_init();
492
537
  sqlite_migration_apply({
493
538
  version: "2024-01-15-add-users",
494
539
  description: "Create users table",
495
- sql:
496
- "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE)",
540
+ sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE)",
497
541
  rollbackSql: "DROP TABLE users",
498
542
  sourceSystem: "agent",
499
543
  appliedBy: "claude",
@@ -522,11 +566,11 @@ sqlite_migration_status();
522
566
  ## \u26A0\uFE0F Gotchas
523
567
 
524
568
  - Rollback requires \`rollbackSql\` to have been provided when the migration was recorded/applied
525
- - Migration group is **opt-in** \u2014 not included in any shortcut except \`dev-schema\` and \`full\``
569
+ - Migration group is **opt-in** \u2014 not included by default. Enable via \`--tool-filter\` flag: use \`dev-schema\` (core+introspection+migration+codemode) or \`full\` (all groups)`
526
570
  ],
527
571
  [
528
572
  "stats",
529
- `# db-mcp Help \u2014 Statistical Analysis (16 core + 6 window)
573
+ `# db-mcp Help \u2014 Statistical Analysis (23N/17W: 17 core + 6 window [NATIVE ONLY])
530
574
 
531
575
  ## Core Statistics (always available)
532
576
 
@@ -542,6 +586,7 @@ sqlite_stats_percentile({
542
586
  sqlite_stats_histogram({ table: "products", column: "price", buckets: 10 });
543
587
  sqlite_stats_correlation({ table: "data", column1: "x", column2: "y" }); // Pearson coefficient
544
588
  sqlite_stats_distinct({ table: "orders", column: "status" }); // distinct values
589
+ sqlite_stats_sample({ table: "orders", sampleSize: 100 }); // random sample
545
590
  sqlite_stats_summary({
546
591
  table: "data",
547
592
  columns: ["price", "quantity", "discount"],
@@ -642,13 +687,13 @@ sqlite_window_moving_avg({
642
687
  column: "close_price",
643
688
  orderBy: "date",
644
689
  windowSize: 7,
645
- selectColumns: ["date"]
690
+ selectColumns: ["date"],
646
691
  });
647
692
  \`\`\``
648
693
  ],
649
694
  [
650
695
  "text",
651
- `# db-mcp Help \u2014 Text Processing & FTS5
696
+ `# db-mcp Help \u2014 Text Processing & FTS5 (19N/14W: 14 text + 5 FTS5 [NATIVE ONLY])
652
697
 
653
698
  ## Full-Text Search / FTS5 (5 tools, Native only)
654
699
 
@@ -775,11 +820,16 @@ sqlite_advanced_search({
775
820
  fuzzyThreshold: 0.4,
776
821
  });
777
822
 
778
- // Sentiment analysis \u2014 pure text analysis, no database query needed
823
+ // Sentiment analysis \u2014 text analysis (can analyze raw text or database columns)
779
824
  sqlite_text_sentiment({ text: "This product is amazing and wonderful!" });
780
825
  // \u2192 { sentiment: "very_positive", score: 2, confidence: "medium" }
781
826
 
782
- sqlite_text_sentiment({ text: "Great service but slow delivery", returnWords: true });
827
+ sqlite_text_sentiment({ table: "articles", column: "body" }); // analyzes all rows in a column
828
+
829
+ sqlite_text_sentiment({
830
+ text: "Great service but slow delivery",
831
+ returnWords: true,
832
+ });
783
833
  // \u2192 { sentiment: "neutral", score: 0, matchedPositive: ["great"], matchedNegative: ["slow"] }
784
834
  \`\`\``
785
835
  ],
@@ -883,11 +933,12 @@ var AuditLogger = class {
883
933
  await this.ensureDirectory();
884
934
  const fh = await open(this.config.logPath, "a");
885
935
  await fh.close();
886
- } catch {
936
+ } catch (err) {
887
937
  process.stderr.write(
888
938
  `[AUDIT] Failed to initialise log file: ${this.config.logPath}
889
939
  `
890
940
  );
941
+ throw err;
891
942
  }
892
943
  }
893
944
  /**
@@ -897,7 +948,8 @@ var AuditLogger = class {
897
948
  */
898
949
  log(entry) {
899
950
  if (this.closed || !this.config.enabled) return;
900
- this.buffer.push(JSON.stringify(entry));
951
+ const safeEntry = redactObject(entry, 0, 5);
952
+ this.buffer.push(JSON.stringify(safeEntry));
901
953
  if (this.buffer.length >= BUFFER_HIGH_WATER) {
902
954
  void this.flush();
903
955
  }
@@ -1033,9 +1085,9 @@ var gzipAsync = promisify(gzip);
1033
1085
  var SNAPSHOT_TOOL_ARGS = {
1034
1086
  sqlite_drop_table: { targetKey: "table" },
1035
1087
  sqlite_drop_index: { targetKey: "index" },
1036
- sqlite_drop_view: { targetKey: "view" },
1088
+ sqlite_drop_view: { targetKey: "viewName" },
1037
1089
  sqlite_import_csv: { targetKey: "table" },
1038
- sqlite_backup: { targetKey: "path" }
1090
+ sqlite_backup: { targetKey: "targetPath" }
1039
1091
  };
1040
1092
  var SNAPSHOT_EXT = ".snapshot.json.gz";
1041
1093
  var SNAPSHOT_EXT_LEGACY = ".snapshot.json";
@@ -1087,14 +1139,18 @@ var BackupManager = class {
1087
1139
  /**
1088
1140
  * List available snapshots with metadata.
1089
1141
  */
1090
- async listSnapshots() {
1142
+ async listSnapshots(limit = 10, offset = 0) {
1091
1143
  try {
1092
1144
  await this.ensureDirectory();
1093
1145
  const files = await readdir(this.snapshotDir);
1146
+ const snapshotFiles = files.filter(
1147
+ (f) => f.endsWith(SNAPSHOT_EXT) || f.endsWith(SNAPSHOT_EXT_LEGACY)
1148
+ );
1149
+ snapshotFiles.sort((a, b) => b.localeCompare(a));
1150
+ const total = snapshotFiles.length;
1151
+ const targetFiles = snapshotFiles.slice(offset, offset + limit);
1094
1152
  const snapshots = [];
1095
- for (const file of files) {
1096
- if (!file.endsWith(SNAPSHOT_EXT) && !file.endsWith(SNAPSHOT_EXT_LEGACY))
1097
- continue;
1153
+ for (const file of targetFiles) {
1098
1154
  try {
1099
1155
  const parsed = await this.readSnapshotFile(file);
1100
1156
  if (parsed) {
@@ -1103,10 +1159,9 @@ var BackupManager = class {
1103
1159
  } catch {
1104
1160
  }
1105
1161
  }
1106
- snapshots.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
1107
- return snapshots;
1162
+ return { snapshots, total };
1108
1163
  } catch {
1109
- return [];
1164
+ return { snapshots: [], total: 0 };
1110
1165
  }
1111
1166
  }
1112
1167
  /**
@@ -1400,32 +1455,57 @@ var BackupManager = class {
1400
1455
  }
1401
1456
  }
1402
1457
  };
1403
-
1404
- // src/auth/scope-map.ts
1405
- var toolScopeMap = /* @__PURE__ */ new Map();
1406
- for (const [group, tools] of Object.entries(TOOL_GROUPS)) {
1407
- const scope = TOOL_GROUP_SCOPES[group];
1408
- if (scope) {
1409
- for (const toolName of tools) {
1410
- toolScopeMap.set(toolName, scope);
1411
- toolScopeMap.set(`sqlite_${toolName}`, scope);
1458
+ var SENSITIVE_KEY_PATTERN = /^(password|passwd|token|secret|authorization|api_?key|credential|private_?key|access_?token|refresh_?token)$/i;
1459
+ var SENSITIVE_VALUE_PATTERN = /(?:sk-|Bearer |token\s*[:=]\s*|password\s*[:=]\s*|secret\s*[:=]\s*|apikey\s*[:=]\s*|api_key\s*[:=]\s*|AWS_SECRET_ACCESS_KEY\s*[:=]\s*|GITHUB_TOKEN\s*[:=]\s*|ghp_|gho_|ghu_|ghs_|xoxb-|xoxp-|xoxs-|AZURE_[A-Z_]*\s*[:=]\s*|DATABASE_URL\s*[:=]\s*|AKIA|sk-ant-api[a-zA-Z0-9_-]+|sk_live_[a-zA-Z0-9_]+|rk_live_[a-zA-Z0-9_]+|SG\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+|npm_[a-zA-Z0-9]{30,}|dpl_[a-zA-Z0-9]{30,}|hvs\.[a-zA-Z0-9_-]+)[^\s'",;)}\]]{4,}/gi;
1460
+ function redactSensitiveKeys(value, depth = 0) {
1461
+ const MAX_DEPTH = 5;
1462
+ if (depth > MAX_DEPTH || value === null || value === void 0) {
1463
+ return value;
1464
+ }
1465
+ if (Array.isArray(value)) {
1466
+ return value.map((item) => redactSensitiveKeys(item, depth + 1));
1467
+ }
1468
+ if (typeof value === "string") {
1469
+ const isSql = /^\s*(?:SELECT|INSERT|UPDATE|DELETE|WITH|CREATE|ALTER|DROP|PRAGMA)\b/i.test(
1470
+ value
1471
+ );
1472
+ const scrubbed = isSql ? value.replace(/'(?:''|[^'])*'/g, "'***'") : value;
1473
+ return scrubbed.replace(SENSITIVE_VALUE_PATTERN, "[REDACTED]");
1474
+ }
1475
+ if (typeof value === "object") {
1476
+ const result = {};
1477
+ for (const [key, val] of Object.entries(value)) {
1478
+ if (SENSITIVE_KEY_PATTERN.test(key)) {
1479
+ result[key] = "[REDACTED]";
1480
+ } else if (typeof val === "object" && val !== null) {
1481
+ result[key] = redactSensitiveKeys(val, depth + 1);
1482
+ } else if (typeof val === "string") {
1483
+ const isSql = key.toLowerCase() === "sql" || key.toLowerCase() === "query" || /^\s*(?:SELECT|INSERT|UPDATE|DELETE|WITH|CREATE|ALTER|DROP|PRAGMA)\b/i.test(
1484
+ val
1485
+ );
1486
+ const scrubbed = isSql ? val.replace(/'(?:''|[^'])*'/g, "'***'") : val;
1487
+ result[key] = scrubbed.replace(SENSITIVE_VALUE_PATTERN, "[REDACTED]");
1488
+ } else {
1489
+ result[key] = val;
1490
+ }
1412
1491
  }
1492
+ return result;
1413
1493
  }
1494
+ return value;
1414
1495
  }
1415
- function getRequiredScope(toolName) {
1416
- return toolScopeMap.get(toolName) ?? SCOPES.READ;
1417
- }
1418
-
1419
- // src/audit/interceptor.ts
1420
1496
  var ALWAYS_AUDITED_SCOPES = /* @__PURE__ */ new Set(["write", "admin"]);
1421
1497
  function scopeToCategory(scope) {
1422
1498
  if (scope === "admin") return "admin";
1423
1499
  if (scope === "read") return "read";
1424
1500
  return "write";
1425
1501
  }
1426
- function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1502
+ function createAuditInterceptor(auditLogger, backupManager) {
1427
1503
  const auditReads = auditLogger.config.auditReads;
1504
+ let currentQueryAdapter;
1428
1505
  return {
1506
+ setQueryAdapter(adapter) {
1507
+ currentQueryAdapter = adapter;
1508
+ },
1429
1509
  async around(toolName, args, requestId, fn, options) {
1430
1510
  const scope = getRequiredScope(toolName);
1431
1511
  if (!ALWAYS_AUDITED_SCOPES.has(scope) && !auditReads) {
@@ -1438,6 +1518,18 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1438
1518
  let error;
1439
1519
  let backupRef;
1440
1520
  let tokenEstimate;
1521
+ if (backupManager !== void 0 && currentQueryAdapter !== void 0 && backupManager.shouldSnapshot(toolName)) {
1522
+ try {
1523
+ backupRef = await backupManager.createSnapshot(
1524
+ toolName,
1525
+ args ?? {},
1526
+ requestId,
1527
+ currentQueryAdapter,
1528
+ options?.logAs
1529
+ );
1530
+ } catch {
1531
+ }
1532
+ }
1441
1533
  try {
1442
1534
  const result = await fn();
1443
1535
  if (typeof result === "object" && result !== null) {
@@ -1455,7 +1547,9 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1455
1547
  return result;
1456
1548
  } catch (err) {
1457
1549
  success = false;
1458
- error = err instanceof Error ? err.message : String(err);
1550
+ error = sanitizeErrorMessage(
1551
+ err instanceof Error ? err.message : String(err)
1552
+ );
1459
1553
  const errorResult = {
1460
1554
  success: false,
1461
1555
  error,
@@ -1495,7 +1589,7 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1495
1589
  durationMs,
1496
1590
  success,
1497
1591
  error,
1498
- args: auditLogger.config.redact ? void 0 : args,
1592
+ args: auditLogger.config.redact ? void 0 : redactSensitiveKeys(args),
1499
1593
  backup: backupRef,
1500
1594
  tokenEstimate
1501
1595
  });
@@ -1504,6 +1598,803 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1504
1598
  }
1505
1599
  };
1506
1600
  }
1601
+
1602
+ // src/server/registration/built-in-tools.ts
1603
+ function registerBuiltInTools(server, adaptersMap, config, toolFilter) {
1604
+ const serverInfoOpts = {
1605
+ title: "Server Info",
1606
+ description: "Get information about the db-mcp server and registered adapters",
1607
+ icons: SERVER_ICONS,
1608
+ annotations: READ_ONLY
1609
+ };
1610
+ server.registerTool("server_info", serverInfoOpts, () => {
1611
+ const authCtx = getAuthContext();
1612
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "server_info")) {
1613
+ throw new InsufficientScopeError(["read"], authCtx.scopes);
1614
+ }
1615
+ const adapterInfo = [];
1616
+ for (const [id, adapter] of adaptersMap) {
1617
+ adapterInfo.push({
1618
+ id,
1619
+ ...adapter.getInfo()
1620
+ });
1621
+ }
1622
+ return {
1623
+ content: [
1624
+ {
1625
+ type: "text",
1626
+ text: JSON.stringify(
1627
+ {
1628
+ name: config.name,
1629
+ version: config.version,
1630
+ transport: config.transport,
1631
+ adapters: adapterInfo,
1632
+ toolFilter: {
1633
+ raw: toolFilter.raw,
1634
+ enabledGroups: [...toolFilter.enabledGroups]
1635
+ }
1636
+ },
1637
+ null,
1638
+ 2
1639
+ )
1640
+ }
1641
+ ]
1642
+ };
1643
+ });
1644
+ const healthOpts = {
1645
+ title: "Server Health",
1646
+ description: "Check health status of all database connections",
1647
+ icons: SERVER_ICONS,
1648
+ annotations: READ_ONLY
1649
+ };
1650
+ server.registerTool("server_health", healthOpts, async () => {
1651
+ const authCtx = getAuthContext();
1652
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "server_health")) {
1653
+ throw new InsufficientScopeError(["read"], authCtx.scopes);
1654
+ }
1655
+ const health = {
1656
+ server: "healthy",
1657
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1658
+ adapters: {}
1659
+ };
1660
+ for (const [id, adapter] of adaptersMap) {
1661
+ try {
1662
+ const adapterHealth = await adapter.getHealth();
1663
+ health["adapters"][id] = adapterHealth;
1664
+ } catch (error) {
1665
+ let errorMsg = error instanceof Error ? error.message : "Unknown error";
1666
+ errorMsg = errorMsg.replace(/(:[^:@/]+@)/g, ":***@");
1667
+ health["adapters"][id] = {
1668
+ connected: false,
1669
+ error: errorMsg
1670
+ };
1671
+ }
1672
+ }
1673
+ return {
1674
+ content: [
1675
+ {
1676
+ type: "text",
1677
+ text: JSON.stringify(health, null, 2)
1678
+ }
1679
+ ]
1680
+ };
1681
+ });
1682
+ const listAdaptersOpts = {
1683
+ title: "List Adapters",
1684
+ description: "List all registered database adapters",
1685
+ icons: SERVER_ICONS,
1686
+ annotations: READ_ONLY
1687
+ };
1688
+ server.registerTool("list_adapters", listAdaptersOpts, () => {
1689
+ const authCtx = getAuthContext();
1690
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "list_adapters")) {
1691
+ throw new InsufficientScopeError(["read"], authCtx.scopes);
1692
+ }
1693
+ const adapters = [];
1694
+ for (const [, adapter] of adaptersMap) {
1695
+ adapters.push({
1696
+ id: `${adapter.type}:default`,
1697
+ type: adapter.type,
1698
+ name: adapter.name,
1699
+ version: adapter.version,
1700
+ connected: adapter.isConnected()
1701
+ });
1702
+ }
1703
+ return {
1704
+ content: [
1705
+ {
1706
+ type: "text",
1707
+ text: JSON.stringify(adapters, null, 2)
1708
+ }
1709
+ ]
1710
+ };
1711
+ });
1712
+ registerToolScopes(
1713
+ /* @__PURE__ */ new Map([
1714
+ ["server_info", ["read"]],
1715
+ ["server_health", ["read"]],
1716
+ ["list_adapters", ["read"]]
1717
+ ])
1718
+ );
1719
+ }
1720
+
1721
+ // src/server/registration/help-resources.ts
1722
+ function registerHelpResources(server, toolFilter) {
1723
+ const gotchasContent = HELP_CONTENT.get("gotchas");
1724
+ if (gotchasContent) {
1725
+ server.registerResource(
1726
+ "sqlite_help",
1727
+ "sqlite://help",
1728
+ {
1729
+ description: "Critical gotchas, WASM vs Native comparison, and Code Mode API reference",
1730
+ mimeType: "text/markdown",
1731
+ annotations: ASSISTANT_FOCUSED
1732
+ },
1733
+ () => ({
1734
+ contents: [
1735
+ {
1736
+ uri: "sqlite://help",
1737
+ mimeType: "text/markdown",
1738
+ text: gotchasContent
1739
+ }
1740
+ ]
1741
+ })
1742
+ );
1743
+ }
1744
+ const groupHelpKeys = [
1745
+ { group: "core", key: "core" },
1746
+ { group: "json", key: "json" },
1747
+ { group: "text", key: "text" },
1748
+ { group: "stats", key: "stats" },
1749
+ { group: "vector", key: "vector" },
1750
+ { group: "geo", key: "geo" },
1751
+ { group: "admin", key: "admin" },
1752
+ { group: "transactions", key: "transactions" },
1753
+ { group: "introspection", key: "introspection" },
1754
+ { group: "migration", key: "migration" }
1755
+ ];
1756
+ for (const { group, key } of groupHelpKeys) {
1757
+ const isCodemodeOnly = toolFilter.enabledGroups.size === 1 && toolFilter.enabledGroups.has("codemode");
1758
+ if (!toolFilter.enabledGroups.has(group) && !isCodemodeOnly) {
1759
+ continue;
1760
+ }
1761
+ const content = HELP_CONTENT.get(key);
1762
+ if (!content) continue;
1763
+ server.registerResource(
1764
+ `sqlite_help_${key}`,
1765
+ `sqlite://help/${key}`,
1766
+ {
1767
+ description: `Tool reference for the ${group} tool group`,
1768
+ mimeType: "text/markdown",
1769
+ annotations: ASSISTANT_FOCUSED
1770
+ },
1771
+ () => ({
1772
+ contents: [
1773
+ {
1774
+ uri: `sqlite://help/${key}`,
1775
+ mimeType: "text/markdown",
1776
+ text: content
1777
+ }
1778
+ ]
1779
+ })
1780
+ );
1781
+ }
1782
+ const registeredHelp = ["sqlite://help"];
1783
+ for (const { group, key } of groupHelpKeys) {
1784
+ if (toolFilter.enabledGroups.has(group)) {
1785
+ registeredHelp.push(`sqlite://help/${key}`);
1786
+ }
1787
+ }
1788
+ logger.info(`Help resources: ${registeredHelp.join(", ")}`, {
1789
+ module: "SERVER"
1790
+ });
1791
+ }
1792
+ function redactSqlLiterals(text) {
1793
+ return text.replace(/'(?:''|[^'])*'/g, "'***'");
1794
+ }
1795
+ function validateDdl(sql) {
1796
+ const cleanSql = sql.replace(/\/\*[\s\S]*?\*\//g, "").replace(/--.*$/gm, "");
1797
+ const upperSql = cleanSql.toUpperCase();
1798
+ if (upperSql.includes("ATTACH ") || upperSql.includes("DETACH ") || upperSql.includes("PRAGMA ") || upperSql.includes("LOAD_EXTENSION(")) {
1799
+ throw new Error(
1800
+ `DDL validation failed: unauthorized command or function call`
1801
+ );
1802
+ }
1803
+ if (upperSql.includes(" ON MAIN.") || upperSql.includes(" ON TEMP.")) {
1804
+ throw new Error(
1805
+ `DDL validation failed: trigger attempts to target a specific database`
1806
+ );
1807
+ }
1808
+ }
1809
+ function registerAuditResource(server, auditLogger, backupManager) {
1810
+ if (!auditLogger) return;
1811
+ server.registerResource(
1812
+ "sqlite_audit",
1813
+ "sqlite://audit",
1814
+ {
1815
+ description: "Recent audit log entries and backup statistics. Shows the last 50 tool invocations with timing, outcomes, and token estimates.",
1816
+ mimeType: "application/json"
1817
+ },
1818
+ async () => {
1819
+ const recent = await auditLogger.recent(50);
1820
+ const backupStats = backupManager ? await backupManager.getStats() : void 0;
1821
+ const payload = {
1822
+ entries: recent,
1823
+ stats: {
1824
+ totalEntries: recent.length,
1825
+ ...backupStats && { backups: backupStats }
1826
+ }
1827
+ };
1828
+ const payloadStr = JSON.stringify(payload, null, 2);
1829
+ return {
1830
+ contents: [
1831
+ {
1832
+ uri: "sqlite://audit",
1833
+ mimeType: "application/json",
1834
+ text: redactSqlLiterals(payloadStr)
1835
+ }
1836
+ ]
1837
+ };
1838
+ }
1839
+ );
1840
+ }
1841
+ function registerAuditBackupTools(server, backupManager, adaptersMap) {
1842
+ if (!backupManager) return;
1843
+ server.registerTool(
1844
+ "sqlite_audit_list_backups",
1845
+ {
1846
+ title: "List Audit Backups",
1847
+ description: "List pre-mutation DDL snapshots captured before destructive operations. Returns metadata for each snapshot including timestamp, tool, target, and size.",
1848
+ inputSchema: AuditListBackupsSchema,
1849
+ outputSchema: AuditListBackupsOutputSchema,
1850
+ annotations: {
1851
+ readOnlyHint: true,
1852
+ destructiveHint: false,
1853
+ idempotentHint: true,
1854
+ openWorldHint: false
1855
+ }
1856
+ },
1857
+ async (args) => {
1858
+ const authCtx = getAuthContext();
1859
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_list_backups")) {
1860
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
1861
+ }
1862
+ let parsed;
1863
+ try {
1864
+ parsed = AuditListBackupsSchema.parse(args ?? {});
1865
+ } catch (error) {
1866
+ const structured = formatHandlerError(error);
1867
+ return {
1868
+ content: [
1869
+ {
1870
+ type: "text",
1871
+ text: JSON.stringify(structured, null, 2)
1872
+ }
1873
+ ],
1874
+ isError: true,
1875
+ structuredContent: structured
1876
+ };
1877
+ }
1878
+ const limit = parsed.limit ?? 10;
1879
+ const offset = parsed.offset ?? 0;
1880
+ const { snapshots, total } = await backupManager.listSnapshots(
1881
+ limit,
1882
+ offset
1883
+ );
1884
+ const result = {
1885
+ success: true,
1886
+ snapshots,
1887
+ count: snapshots.length,
1888
+ totalCount: total
1889
+ };
1890
+ const tokenEstimate = Math.ceil(
1891
+ Buffer.byteLength(JSON.stringify(result), "utf8") / 4
1892
+ );
1893
+ return {
1894
+ content: [
1895
+ {
1896
+ type: "text",
1897
+ text: JSON.stringify(
1898
+ { ...result, _meta: { tokenEstimate } },
1899
+ null,
1900
+ 2
1901
+ )
1902
+ }
1903
+ ],
1904
+ structuredContent: result
1905
+ };
1906
+ }
1907
+ );
1908
+ server.registerTool(
1909
+ "sqlite_audit_get_backup",
1910
+ {
1911
+ title: "Get Audit Backup",
1912
+ description: "Retrieve a specific pre-mutation DDL snapshot by filename. Returns the full snapshot content including DDL and optional data.",
1913
+ inputSchema: z.object({
1914
+ filename: z.string().default("").describe("Snapshot filename from sqlite_audit_list_backups results")
1915
+ }),
1916
+ outputSchema: AuditGetBackupOutputSchema,
1917
+ annotations: {
1918
+ readOnlyHint: true,
1919
+ destructiveHint: false,
1920
+ idempotentHint: true,
1921
+ openWorldHint: false
1922
+ }
1923
+ },
1924
+ async (args) => {
1925
+ const authCtx = getAuthContext();
1926
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_get_backup")) {
1927
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
1928
+ }
1929
+ let filename;
1930
+ try {
1931
+ const parsed = z.object({ filename: z.string().min(1, "filename is required") }).parse(args);
1932
+ filename = parsed.filename;
1933
+ } catch (error) {
1934
+ const structured = formatHandlerError(error);
1935
+ return {
1936
+ content: [
1937
+ {
1938
+ type: "text",
1939
+ text: JSON.stringify(structured, null, 2)
1940
+ }
1941
+ ],
1942
+ isError: true,
1943
+ structuredContent: structured
1944
+ };
1945
+ }
1946
+ const snapshot = await backupManager.getSnapshot(filename);
1947
+ if (!snapshot) {
1948
+ const errRes = {
1949
+ success: false,
1950
+ error: `Snapshot not found: ${filename}`
1951
+ };
1952
+ return {
1953
+ content: [
1954
+ {
1955
+ type: "text",
1956
+ text: JSON.stringify(errRes, null, 2)
1957
+ }
1958
+ ],
1959
+ isError: true,
1960
+ structuredContent: errRes
1961
+ };
1962
+ }
1963
+ const result = { success: true, ...snapshot };
1964
+ const snapshotStr = JSON.stringify(result, null, 2);
1965
+ return {
1966
+ content: [
1967
+ {
1968
+ type: "text",
1969
+ text: redactSqlLiterals(snapshotStr)
1970
+ }
1971
+ ],
1972
+ structuredContent: result
1973
+ };
1974
+ }
1975
+ );
1976
+ server.registerTool(
1977
+ "sqlite_audit_cleanup",
1978
+ {
1979
+ title: "Cleanup Audit Backups",
1980
+ description: "Apply retention policy to audit backup snapshots. Deletes snapshots exceeding age or count limits.",
1981
+ outputSchema: AuditCleanupOutputSchema,
1982
+ annotations: {
1983
+ readOnlyHint: false,
1984
+ destructiveHint: true,
1985
+ idempotentHint: true,
1986
+ openWorldHint: false
1987
+ }
1988
+ },
1989
+ async () => {
1990
+ const authCtx = getAuthContext();
1991
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_cleanup")) {
1992
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
1993
+ }
1994
+ const deleted = await backupManager.cleanup();
1995
+ const result = {
1996
+ success: true,
1997
+ deletedCount: deleted,
1998
+ message: deleted > 0 ? `Cleaned up ${String(deleted)} snapshot(s)` : "No snapshots to clean up"
1999
+ };
2000
+ return {
2001
+ content: [
2002
+ {
2003
+ type: "text",
2004
+ text: JSON.stringify(result, null, 2)
2005
+ }
2006
+ ],
2007
+ structuredContent: result
2008
+ };
2009
+ }
2010
+ );
2011
+ server.registerTool(
2012
+ "sqlite_audit_diff_backup",
2013
+ {
2014
+ title: "Diff Audit Backup",
2015
+ description: "Compare a pre-mutation DDL snapshot against the live database schema. Shows objects that have been added, removed, or modified since the snapshot was taken.",
2016
+ inputSchema: z.object({
2017
+ filename: z.string().default("").describe(
2018
+ "Snapshot filename to compare against the live database schema"
2019
+ )
2020
+ }),
2021
+ outputSchema: AuditDiffBackupOutputSchema,
2022
+ annotations: {
2023
+ readOnlyHint: true,
2024
+ destructiveHint: false,
2025
+ idempotentHint: true,
2026
+ openWorldHint: false
2027
+ }
2028
+ },
2029
+ async (args) => {
2030
+ const authCtx = getAuthContext();
2031
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_diff_backup")) {
2032
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
2033
+ }
2034
+ let filename;
2035
+ try {
2036
+ const parsed = z.object({ filename: z.string().min(1, "filename is required") }).parse(args);
2037
+ filename = parsed.filename;
2038
+ } catch (error) {
2039
+ const structured = formatHandlerError(error);
2040
+ return {
2041
+ content: [
2042
+ {
2043
+ type: "text",
2044
+ text: JSON.stringify(structured, null, 2)
2045
+ }
2046
+ ],
2047
+ isError: true,
2048
+ structuredContent: structured
2049
+ };
2050
+ }
2051
+ const snapshot = await backupManager.getSnapshot(filename);
2052
+ if (!snapshot) {
2053
+ const errRes = {
2054
+ success: false,
2055
+ error: `Snapshot not found: ${filename}`
2056
+ };
2057
+ return {
2058
+ content: [
2059
+ {
2060
+ type: "text",
2061
+ text: JSON.stringify(errRes, null, 2)
2062
+ }
2063
+ ],
2064
+ isError: true,
2065
+ structuredContent: errRes
2066
+ };
2067
+ }
2068
+ const adapter = [...adaptersMap.values()][0];
2069
+ if (!adapter) {
2070
+ const errRes = {
2071
+ success: false,
2072
+ error: "No connected adapter available"
2073
+ };
2074
+ return {
2075
+ content: [
2076
+ {
2077
+ type: "text",
2078
+ text: JSON.stringify(errRes, null, 2)
2079
+ }
2080
+ ],
2081
+ isError: true,
2082
+ structuredContent: errRes
2083
+ };
2084
+ }
2085
+ try {
2086
+ const liveResult = await adapter.executeReadQuery(
2087
+ "SELECT name, type, sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY type, name"
2088
+ );
2089
+ const liveObjects = /* @__PURE__ */ new Map();
2090
+ for (const row of liveResult.rows ?? []) {
2091
+ liveObjects.set(row["name"], {
2092
+ type: row["type"],
2093
+ sql: row["sql"]
2094
+ });
2095
+ }
2096
+ const snapshotDdl = snapshot.ddl ?? "";
2097
+ const snapshotObjects = /* @__PURE__ */ new Map();
2098
+ const statements = snapshotDdl.split(";").map((s) => s.trim()).filter(Boolean);
2099
+ for (const stmt of statements) {
2100
+ const match = /CREATE\s+(?:VIRTUAL\s+)?(?:TEMP(?:ORARY)?\s+)?(TABLE|INDEX|VIEW|TRIGGER)\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"([^"]+)"|(\S+))/i.exec(
2101
+ stmt
2102
+ );
2103
+ if (match) {
2104
+ const type = (match[1] ?? "").toLowerCase();
2105
+ const name = match[2] ?? match[3] ?? "";
2106
+ snapshotObjects.set(name, { type, sql: stmt });
2107
+ }
2108
+ }
2109
+ const diffs = [];
2110
+ const snapshotTarget = snapshot.metadata?.target;
2111
+ for (const [name, live] of liveObjects) {
2112
+ if (name === snapshotTarget || snapshotObjects.has(name)) {
2113
+ if (!snapshotObjects.has(name)) {
2114
+ diffs.push({
2115
+ object: name,
2116
+ type: live.type,
2117
+ status: "added",
2118
+ liveDefinition: live.sql
2119
+ });
2120
+ }
2121
+ }
2122
+ }
2123
+ for (const [name, snap] of snapshotObjects) {
2124
+ if (!liveObjects.has(name)) {
2125
+ diffs.push({
2126
+ object: name,
2127
+ type: snap.type,
2128
+ status: "removed",
2129
+ snapshotDefinition: snap.sql
2130
+ });
2131
+ }
2132
+ }
2133
+ for (const [name, snap] of snapshotObjects) {
2134
+ const live = liveObjects.get(name);
2135
+ if (live && live.sql !== snap.sql) {
2136
+ diffs.push({
2137
+ object: name,
2138
+ type: live.type,
2139
+ status: "modified",
2140
+ liveDefinition: live.sql,
2141
+ snapshotDefinition: snap.sql
2142
+ });
2143
+ }
2144
+ }
2145
+ const result = {
2146
+ success: true,
2147
+ diffs,
2148
+ snapshotTimestamp: snapshot.metadata?.timestamp ?? "",
2149
+ snapshotTarget: snapshot.metadata?.target ?? ""
2150
+ };
2151
+ return {
2152
+ content: [
2153
+ {
2154
+ type: "text",
2155
+ text: JSON.stringify(result, null, 2)
2156
+ }
2157
+ ],
2158
+ structuredContent: result
2159
+ };
2160
+ } catch (error) {
2161
+ const errRes = {
2162
+ success: false,
2163
+ error: error instanceof Error ? error.message : String(error)
2164
+ };
2165
+ return {
2166
+ content: [
2167
+ {
2168
+ type: "text",
2169
+ text: JSON.stringify(errRes, null, 2)
2170
+ }
2171
+ ],
2172
+ isError: true,
2173
+ structuredContent: errRes
2174
+ };
2175
+ }
2176
+ }
2177
+ );
2178
+ server.registerTool(
2179
+ "sqlite_audit_restore_backup",
2180
+ {
2181
+ title: "Restore Audit Backup",
2182
+ description: "Restore a pre-mutation DDL snapshot by executing its DDL statements against the live database. Use dryRun=true to preview the DDL without applying changes.",
2183
+ inputSchema: z.object({
2184
+ filename: z.string().default("").describe("Snapshot filename to restore from"),
2185
+ dryRun: z.unknown().optional().describe("If true, returns the DDL without executing it (boolean)")
2186
+ }),
2187
+ outputSchema: AuditRestoreBackupOutputSchema,
2188
+ annotations: {
2189
+ readOnlyHint: false,
2190
+ destructiveHint: true,
2191
+ idempotentHint: false,
2192
+ openWorldHint: false
2193
+ }
2194
+ },
2195
+ async (args) => {
2196
+ const authCtx = getAuthContext();
2197
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_restore_backup")) {
2198
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
2199
+ }
2200
+ let filename;
2201
+ let dryRun;
2202
+ try {
2203
+ const parsed = z.object({
2204
+ filename: z.string().min(1, "filename is required"),
2205
+ dryRun: z.boolean().optional().default(false)
2206
+ }).parse(args);
2207
+ filename = parsed.filename;
2208
+ dryRun = parsed.dryRun;
2209
+ } catch (error) {
2210
+ const structured = formatHandlerError(error);
2211
+ return {
2212
+ content: [
2213
+ {
2214
+ type: "text",
2215
+ text: JSON.stringify(structured, null, 2)
2216
+ }
2217
+ ],
2218
+ isError: true,
2219
+ structuredContent: structured
2220
+ };
2221
+ }
2222
+ const snapshot = await backupManager.getSnapshot(filename);
2223
+ if (!snapshot) {
2224
+ const errRes = {
2225
+ success: false,
2226
+ error: `Snapshot not found: ${filename}`
2227
+ };
2228
+ return {
2229
+ content: [
2230
+ {
2231
+ type: "text",
2232
+ text: JSON.stringify(errRes, null, 2)
2233
+ }
2234
+ ],
2235
+ isError: true,
2236
+ structuredContent: errRes
2237
+ };
2238
+ }
2239
+ const ddl = snapshot.ddl ?? "";
2240
+ if (!ddl.trim()) {
2241
+ const errRes = {
2242
+ success: false,
2243
+ error: "Snapshot contains no DDL statements"
2244
+ };
2245
+ return {
2246
+ content: [
2247
+ {
2248
+ type: "text",
2249
+ text: JSON.stringify(errRes, null, 2)
2250
+ }
2251
+ ],
2252
+ isError: true,
2253
+ structuredContent: errRes
2254
+ };
2255
+ }
2256
+ const adapter = [...adaptersMap.values()][0];
2257
+ if (!adapter) {
2258
+ const errRes = {
2259
+ success: false,
2260
+ error: "No connected adapter available"
2261
+ };
2262
+ return {
2263
+ content: [
2264
+ {
2265
+ type: "text",
2266
+ text: JSON.stringify(errRes, null, 2)
2267
+ }
2268
+ ],
2269
+ isError: true,
2270
+ structuredContent: errRes
2271
+ };
2272
+ }
2273
+ if (dryRun) {
2274
+ const result = {
2275
+ success: true,
2276
+ message: "Dry run: no changes applied",
2277
+ dryRun: true,
2278
+ ddl: redactSqlLiterals(ddl)
2279
+ };
2280
+ return {
2281
+ content: [
2282
+ {
2283
+ type: "text",
2284
+ text: JSON.stringify(result, null, 2)
2285
+ }
2286
+ ],
2287
+ structuredContent: result
2288
+ };
2289
+ }
2290
+ try {
2291
+ const statements = ddl.split(";").map((s) => s.trim()).filter((s) => {
2292
+ const cleanSql = s.replace(/\/\*[\s\S]*?\*\//g, "").replace(/--.*$/gm, "").trim();
2293
+ return cleanSql.length > 0;
2294
+ });
2295
+ if (statements.length === 0) {
2296
+ const result2 = {
2297
+ success: true,
2298
+ message: "No executable statements found in snapshot (only comments)",
2299
+ changesApplied: 0
2300
+ };
2301
+ return {
2302
+ content: [
2303
+ {
2304
+ type: "text",
2305
+ text: JSON.stringify(result2, null, 2)
2306
+ }
2307
+ ],
2308
+ structuredContent: result2
2309
+ };
2310
+ }
2311
+ await adapter.executeQuery("BEGIN TRANSACTION;");
2312
+ try {
2313
+ for (const stmt of statements) {
2314
+ validateDdl(stmt);
2315
+ await adapter.executeQuery(`${stmt};`);
2316
+ }
2317
+ await adapter.executeQuery("COMMIT;");
2318
+ } catch (e) {
2319
+ await adapter.executeQuery("ROLLBACK;");
2320
+ throw e;
2321
+ }
2322
+ const result = {
2323
+ success: true,
2324
+ message: `Successfully executed ${statements.length} statement(s) from snapshot`,
2325
+ changesApplied: statements.length
2326
+ };
2327
+ return {
2328
+ content: [
2329
+ {
2330
+ type: "text",
2331
+ text: JSON.stringify(result, null, 2)
2332
+ }
2333
+ ],
2334
+ structuredContent: result
2335
+ };
2336
+ } catch (error) {
2337
+ const errRes = {
2338
+ success: false,
2339
+ error: error instanceof Error ? error.message : String(error)
2340
+ };
2341
+ return {
2342
+ content: [
2343
+ {
2344
+ type: "text",
2345
+ text: JSON.stringify(errRes, null, 2)
2346
+ }
2347
+ ],
2348
+ isError: true,
2349
+ structuredContent: errRes
2350
+ };
2351
+ }
2352
+ }
2353
+ );
2354
+ registerToolScopes(
2355
+ /* @__PURE__ */ new Map([
2356
+ ["sqlite_audit_list_backups", ["admin", "full"]],
2357
+ ["sqlite_audit_get_backup", ["admin", "full"]],
2358
+ ["sqlite_audit_cleanup", ["admin", "full"]],
2359
+ ["sqlite_audit_diff_backup", ["admin", "full"]],
2360
+ ["sqlite_audit_restore_backup", ["admin", "full"]]
2361
+ ])
2362
+ );
2363
+ logger.info(
2364
+ "Registered audit backup tools: sqlite_audit_list_backups, sqlite_audit_get_backup, sqlite_audit_cleanup, sqlite_audit_diff_backup, sqlite_audit_restore_backup",
2365
+ { module: "AUDIT" }
2366
+ );
2367
+ }
2368
+
2369
+ // src/server/mcp-server.ts
2370
+ var proto = McpServer.prototype;
2371
+ if (typeof proto["createToolError"] === "function") {
2372
+ const originalCreateToolError = proto["createToolError"];
2373
+ proto["createToolError"] = function(errorMessage) {
2374
+ const result = originalCreateToolError.call(
2375
+ this,
2376
+ errorMessage
2377
+ );
2378
+ if (result.content?.[0]?.type === "text") {
2379
+ const rawError = result.content[0].text;
2380
+ if (rawError.includes("Input validation error")) {
2381
+ const cleanError = rawError.replace(
2382
+ /^MCP error -32602: Input validation error: /,
2383
+ "Validation error: "
2384
+ );
2385
+ const structured = {
2386
+ success: false,
2387
+ error: cleanError,
2388
+ code: "VALIDATION_ERROR",
2389
+ category: "validation" /* VALIDATION */
2390
+ };
2391
+ result.content[0].text = JSON.stringify(structured, null, 2);
2392
+ result.isError = true;
2393
+ }
2394
+ }
2395
+ return result;
2396
+ };
2397
+ }
1507
2398
  var DbMcpServer = class {
1508
2399
  server;
1509
2400
  adapters = /* @__PURE__ */ new Map();
@@ -1536,8 +2427,35 @@ var DbMcpServer = class {
1536
2427
  toolFilter: config.toolFilter ?? "none",
1537
2428
  capabilities: ["logging"]
1538
2429
  });
1539
- this.registerBuiltInTools();
1540
- this.registerHelpResources();
2430
+ registerBuiltInTools(
2431
+ this.server,
2432
+ this.adapters,
2433
+ this.config,
2434
+ this.toolFilter
2435
+ );
2436
+ registerHelpResources(this.server, this.toolFilter);
2437
+ const internalMcp = this.server;
2438
+ const handlers = internalMcp.server._requestHandlers;
2439
+ if (!handlers?.has("tools/list")) {
2440
+ throw new DbMcpError(
2441
+ "Security: SDK _requestHandlers monkey-patch failed. Scope filtering is disabled.",
2442
+ "SERVER_START_FAILED",
2443
+ "internal" /* INTERNAL */
2444
+ );
2445
+ }
2446
+ const originalListToolsHandler = handlers.get("tools/list");
2447
+ if (originalListToolsHandler) {
2448
+ handlers.set("tools/list", async (request, extra) => {
2449
+ const result = await originalListToolsHandler(request, extra);
2450
+ const authCtx = getAuthContext();
2451
+ if (authCtx && Array.isArray(result.tools)) {
2452
+ result.tools = result.tools.filter(
2453
+ (t) => scopesGrantToolAccess(authCtx.scopes, t.name)
2454
+ );
2455
+ }
2456
+ return result;
2457
+ });
2458
+ }
1541
2459
  if (config.audit?.enabled) {
1542
2460
  this.auditInitPromise = this.initializeAudit(config);
1543
2461
  }
@@ -1554,6 +2472,9 @@ var DbMcpServer = class {
1554
2472
  this.adapters.set(adapterId, adapter);
1555
2473
  if (this.auditInterceptor && "setAuditInterceptor" in adapter) {
1556
2474
  adapter.setAuditInterceptor(this.auditInterceptor);
2475
+ this.auditInterceptor.setQueryAdapter({
2476
+ executeQuery: (sql, params) => adapter.executeReadQuery(sql, params)
2477
+ });
1557
2478
  }
1558
2479
  if (this.backupManager && "setBackupManager" in adapter) {
1559
2480
  adapter.setBackupManager(this.backupManager);
@@ -1561,6 +2482,15 @@ var DbMcpServer = class {
1561
2482
  adapter.registerTools(this.server, this.toolFilter);
1562
2483
  adapter.registerResources(this.server);
1563
2484
  adapter.registerPrompts(this.server);
2485
+ const toolDefs = adapter.getToolDefinitions();
2486
+ const scopesMap = /* @__PURE__ */ new Map();
2487
+ for (const tool of toolDefs) {
2488
+ if (tool.requiredScopes) {
2489
+ scopesMap.set(tool.name, tool.requiredScopes);
2490
+ scopesMap.set(`sqlite_${tool.name}`, tool.requiredScopes);
2491
+ }
2492
+ }
2493
+ registerToolScopes(scopesMap);
1564
2494
  logger.info(`Registered adapter: ${adapter.name} (${adapterId})`, {
1565
2495
  module: "SERVER"
1566
2496
  });
@@ -1577,178 +2507,6 @@ var DbMcpServer = class {
1577
2507
  getAdapters() {
1578
2508
  return this.adapters;
1579
2509
  }
1580
- /**
1581
- * Register built-in server tools (health, info, etc.)
1582
- */
1583
- registerBuiltInTools() {
1584
- const serverInfoOpts = {
1585
- title: "Server Info",
1586
- description: "Get information about the db-mcp server and registered adapters",
1587
- icons: SERVER_ICONS,
1588
- annotations: READ_ONLY
1589
- };
1590
- this.server.registerTool("server_info", serverInfoOpts, () => {
1591
- const adapterInfo = [];
1592
- for (const [id, adapter] of this.adapters) {
1593
- adapterInfo.push({
1594
- id,
1595
- ...adapter.getInfo()
1596
- });
1597
- }
1598
- return {
1599
- content: [
1600
- {
1601
- type: "text",
1602
- text: JSON.stringify(
1603
- {
1604
- name: this.config.name,
1605
- version: this.config.version,
1606
- transport: this.config.transport,
1607
- adapters: adapterInfo,
1608
- toolFilter: {
1609
- raw: this.toolFilter.raw,
1610
- enabledGroups: [...this.toolFilter.enabledGroups]
1611
- }
1612
- },
1613
- null,
1614
- 2
1615
- )
1616
- }
1617
- ]
1618
- };
1619
- });
1620
- const healthOpts = {
1621
- title: "Server Health",
1622
- description: "Check health status of all database connections",
1623
- icons: SERVER_ICONS,
1624
- annotations: READ_ONLY
1625
- };
1626
- this.server.registerTool("server_health", healthOpts, async () => {
1627
- const health = {
1628
- server: "healthy",
1629
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1630
- adapters: {}
1631
- };
1632
- for (const [id, adapter] of this.adapters) {
1633
- try {
1634
- const adapterHealth = await adapter.getHealth();
1635
- health["adapters"][id] = adapterHealth;
1636
- } catch (error) {
1637
- health["adapters"][id] = {
1638
- connected: false,
1639
- error: error instanceof Error ? error.message : "Unknown error"
1640
- };
1641
- }
1642
- }
1643
- return {
1644
- content: [
1645
- {
1646
- type: "text",
1647
- text: JSON.stringify(health, null, 2)
1648
- }
1649
- ]
1650
- };
1651
- });
1652
- const listAdaptersOpts = {
1653
- title: "List Adapters",
1654
- description: "List all registered database adapters",
1655
- icons: SERVER_ICONS,
1656
- annotations: READ_ONLY
1657
- };
1658
- this.server.registerTool("list_adapters", listAdaptersOpts, () => {
1659
- const adapters = [];
1660
- for (const [id, adapter] of this.adapters) {
1661
- adapters.push({
1662
- id,
1663
- type: adapter.type,
1664
- name: adapter.name,
1665
- version: adapter.version,
1666
- connected: adapter.isConnected()
1667
- });
1668
- }
1669
- return {
1670
- content: [
1671
- {
1672
- type: "text",
1673
- text: JSON.stringify(adapters, null, 2)
1674
- }
1675
- ]
1676
- };
1677
- });
1678
- }
1679
- /**
1680
- * Register sqlite://help resources for on-demand reference documentation.
1681
- * Always registers sqlite://help (gotchas). Group-specific help is filtered
1682
- * by the tool filter configuration.
1683
- */
1684
- registerHelpResources() {
1685
- const gotchasContent = HELP_CONTENT.get("gotchas");
1686
- if (gotchasContent) {
1687
- this.server.registerResource(
1688
- "sqlite_help",
1689
- "sqlite://help",
1690
- {
1691
- description: "Critical gotchas, WASM vs Native comparison, and Code Mode API reference",
1692
- mimeType: "text/markdown"
1693
- },
1694
- () => ({
1695
- contents: [
1696
- {
1697
- uri: "sqlite://help",
1698
- mimeType: "text/markdown",
1699
- text: gotchasContent
1700
- }
1701
- ]
1702
- })
1703
- );
1704
- }
1705
- const groupHelpKeys = [
1706
- { group: "core", key: "core" },
1707
- { group: "json", key: "json" },
1708
- { group: "text", key: "text" },
1709
- { group: "stats", key: "stats" },
1710
- { group: "vector", key: "vector" },
1711
- { group: "geo", key: "geo" },
1712
- { group: "admin", key: "admin" },
1713
- { group: "transactions", key: "transactions" },
1714
- { group: "introspection", key: "introspection" },
1715
- { group: "migration", key: "migration" }
1716
- ];
1717
- for (const { group, key } of groupHelpKeys) {
1718
- const isCodemodeOnly = this.toolFilter.enabledGroups.size === 1 && this.toolFilter.enabledGroups.has("codemode");
1719
- if (!this.toolFilter.enabledGroups.has(group) && !isCodemodeOnly) {
1720
- continue;
1721
- }
1722
- const content = HELP_CONTENT.get(key);
1723
- if (!content) continue;
1724
- this.server.registerResource(
1725
- `sqlite_help_${key}`,
1726
- `sqlite://help/${key}`,
1727
- {
1728
- description: `Tool reference for the ${group} tool group`,
1729
- mimeType: "text/markdown"
1730
- },
1731
- () => ({
1732
- contents: [
1733
- {
1734
- uri: `sqlite://help/${key}`,
1735
- mimeType: "text/markdown",
1736
- text: content
1737
- }
1738
- ]
1739
- })
1740
- );
1741
- }
1742
- const registeredHelp = ["sqlite://help"];
1743
- for (const { group, key } of groupHelpKeys) {
1744
- if (this.toolFilter.enabledGroups.has(group)) {
1745
- registeredHelp.push(`sqlite://help/${key}`);
1746
- }
1747
- }
1748
- logger.info(`Help resources: ${registeredHelp.join(", ")}`, {
1749
- module: "SERVER"
1750
- });
1751
- }
1752
2510
  /**
1753
2511
  * Start the server with the configured transport
1754
2512
  */
@@ -1777,12 +2535,16 @@ var DbMcpServer = class {
1777
2535
  logger.info(`db-mcp server started (stdio transport)`, {
1778
2536
  module: "SERVER"
1779
2537
  });
2538
+ logger.warning(
2539
+ "SECURITY WARNING: Running in STDIO mode grants blanket 'admin' access to all tools. This implies full trust in the local client/agent. If this server is exposed over SSH or used by an untrusted client, consider using HTTP transport with OAuth (--oauth-enabled) for granular scope enforcement.",
2540
+ { module: "SERVER", code: "STDIO_ADMIN_RISK" }
2541
+ );
1780
2542
  }
1781
2543
  /**
1782
2544
  * Start server with HTTP transport (Streamable HTTP with SSE support)
1783
2545
  */
1784
2546
  async startHttp() {
1785
- const { HttpTransport } = await import('./http-6KF4ULDI.js');
2547
+ const { HttpTransport } = await import('./http-HWTUVFIA.js');
1786
2548
  const oauthConfig = {
1787
2549
  enabled: this.config.oauth?.enabled ?? false,
1788
2550
  authorizationServerUrl: this.config.oauth?.authorizationServerUrl ?? "",
@@ -1810,12 +2572,13 @@ var DbMcpServer = class {
1810
2572
  enableHSTS: this.config.enableHSTS
1811
2573
  },
1812
2574
  oauth: oauthConfig,
1813
- stateless: this.config.statelessHttp ?? false
2575
+ stateless: this.config.statelessHttp ?? false,
2576
+ noAuthEnforcement: this.config.noAuthEnforcement ?? false
1814
2577
  });
1815
2578
  await transport.initialize(this.server);
1816
2579
  await transport.start();
1817
2580
  const mode = this.config.statelessHttp ? "stateless" : "stateful";
1818
- const host = this.config.host ?? "0.0.0.0";
2581
+ const host = this.config.host ?? "127.0.0.1";
1819
2582
  const port = String(this.config.port ?? 3e3);
1820
2583
  logger.info(
1821
2584
  `db-mcp server started (HTTP transport on ${host}:${port}, ${mode} mode)`,
@@ -1866,179 +2629,17 @@ var DbMcpServer = class {
1866
2629
  }
1867
2630
  this.auditInterceptor = createAuditInterceptor(
1868
2631
  this.auditLogger,
1869
- this.backupManager ?? void 0);
1870
- this.registerAuditResource();
2632
+ this.backupManager ?? void 0
2633
+ );
2634
+ registerAuditResource(this.server, this.auditLogger, this.backupManager);
1871
2635
  if (this.backupManager && this.toolFilter.enabledGroups.has("admin")) {
1872
- this.registerAuditBackupTools();
2636
+ registerAuditBackupTools(this.server, this.backupManager, this.adapters);
1873
2637
  }
1874
2638
  logger.info(
1875
2639
  `Audit logging enabled (${auditConfig.logPath}, redact=${String(auditConfig.redact)}, reads=${String(auditConfig.auditReads)}, backup=${String(!!auditConfig.backup?.enabled)})`,
1876
2640
  { module: "AUDIT" }
1877
2641
  );
1878
2642
  }
1879
- /**
1880
- * Register the sqlite://audit resource for agent access to audit log.
1881
- */
1882
- registerAuditResource() {
1883
- if (!this.auditLogger) return;
1884
- const auditLogger = this.auditLogger;
1885
- const backupManager = this.backupManager;
1886
- this.server.registerResource(
1887
- "sqlite_audit",
1888
- "sqlite://audit",
1889
- {
1890
- description: "Recent audit log entries and backup statistics. Shows the last 50 tool invocations with timing, outcomes, and token estimates.",
1891
- mimeType: "application/json"
1892
- },
1893
- async () => {
1894
- const recent = await auditLogger.recent(50);
1895
- const backupStats = backupManager ? await backupManager.getStats() : void 0;
1896
- const payload = {
1897
- entries: recent,
1898
- stats: {
1899
- totalEntries: recent.length,
1900
- ...backupStats && { backups: backupStats }
1901
- }
1902
- };
1903
- return {
1904
- contents: [
1905
- {
1906
- uri: "sqlite://audit",
1907
- mimeType: "application/json",
1908
- text: JSON.stringify(payload, null, 2)
1909
- }
1910
- ]
1911
- };
1912
- }
1913
- );
1914
- }
1915
- /**
1916
- * Register audit backup tools for snapshot management.
1917
- */
1918
- registerAuditBackupTools() {
1919
- const backupManager = this.backupManager;
1920
- if (!backupManager) return;
1921
- this.server.registerTool(
1922
- "sqlite_audit_list_backups",
1923
- {
1924
- title: "List Audit Backups",
1925
- description: "List pre-mutation DDL snapshots captured before destructive operations. Returns metadata for each snapshot including timestamp, tool, target, and size.",
1926
- annotations: {
1927
- readOnlyHint: true,
1928
- destructiveHint: false,
1929
- idempotentHint: true,
1930
- openWorldHint: false
1931
- }
1932
- },
1933
- async () => {
1934
- const snapshots = await backupManager.listSnapshots();
1935
- return {
1936
- content: [
1937
- {
1938
- type: "text",
1939
- text: JSON.stringify(
1940
- {
1941
- snapshots,
1942
- count: snapshots.length,
1943
- _meta: {
1944
- tokenEstimate: Math.ceil(
1945
- Buffer.byteLength(JSON.stringify(snapshots), "utf8") / 4
1946
- )
1947
- }
1948
- },
1949
- null,
1950
- 2
1951
- )
1952
- }
1953
- ]
1954
- };
1955
- }
1956
- );
1957
- this.server.registerTool(
1958
- "sqlite_audit_get_backup",
1959
- {
1960
- title: "Get Audit Backup",
1961
- description: "Retrieve a specific pre-mutation DDL snapshot by filename. Returns the full snapshot content including DDL and optional data.",
1962
- inputSchema: z.object({
1963
- filename: z.string().describe(
1964
- "Snapshot filename from sqlite_audit_list_backups results"
1965
- )
1966
- }),
1967
- annotations: {
1968
- readOnlyHint: true,
1969
- destructiveHint: false,
1970
- idempotentHint: true,
1971
- openWorldHint: false
1972
- }
1973
- },
1974
- async (args) => {
1975
- const { filename } = args;
1976
- const snapshot = await backupManager.getSnapshot(filename);
1977
- if (!snapshot) {
1978
- return {
1979
- content: [
1980
- {
1981
- type: "text",
1982
- text: JSON.stringify(
1983
- {
1984
- success: false,
1985
- error: `Snapshot not found: ${filename}`
1986
- },
1987
- null,
1988
- 2
1989
- )
1990
- }
1991
- ],
1992
- isError: true
1993
- };
1994
- }
1995
- return {
1996
- content: [
1997
- {
1998
- type: "text",
1999
- text: JSON.stringify(snapshot, null, 2)
2000
- }
2001
- ]
2002
- };
2003
- }
2004
- );
2005
- this.server.registerTool(
2006
- "sqlite_audit_cleanup",
2007
- {
2008
- title: "Cleanup Audit Backups",
2009
- description: "Apply retention policy to audit backup snapshots. Deletes snapshots exceeding age or count limits.",
2010
- annotations: {
2011
- readOnlyHint: false,
2012
- destructiveHint: true,
2013
- idempotentHint: true,
2014
- openWorldHint: false
2015
- }
2016
- },
2017
- async () => {
2018
- const deleted = await backupManager.cleanup();
2019
- return {
2020
- content: [
2021
- {
2022
- type: "text",
2023
- text: JSON.stringify(
2024
- {
2025
- success: true,
2026
- deletedCount: deleted,
2027
- message: deleted > 0 ? `Cleaned up ${String(deleted)} snapshot(s)` : "No snapshots to clean up"
2028
- },
2029
- null,
2030
- 2
2031
- )
2032
- }
2033
- ]
2034
- };
2035
- }
2036
- );
2037
- logger.info(
2038
- "Registered audit backup tools: sqlite_audit_list_backups, sqlite_audit_get_backup, sqlite_audit_cleanup",
2039
- { module: "AUDIT" }
2040
- );
2041
- }
2042
2643
  };
2043
2644
  function createServer(config) {
2044
2645
  return new DbMcpServer(config);