db-mcp 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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-E5IESRTK.js +489 -0
  350. package/dist/{chunk-5Y42NPBP.js → chunk-FR65YPAH.js} +4657 -1830
  351. package/dist/{chunk-645ZEFLA.js → chunk-L552U3QS.js} +887 -309
  352. package/dist/{chunk-WBER5YY4.js → chunk-THATOQRT.js} +1026 -455
  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-6C3AJI4I.js} +61 -17
  394. package/dist/{sqlite-native-JXMCFQBA.js → sqlite-native-ZSSWCTYC.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 +25 -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,15 @@ 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
- [
36
- "admin",
37
- `# db-mcp Help \u2014 Database Administration (29 Native / 29 WASM)
34
+ ["admin", `# db-mcp Help \u2014 Database Administration (32N/31W tools) + Server Audit (5 tools)
38
35
 
39
36
  ## Maintenance
40
37
 
@@ -44,21 +41,28 @@ sqlite_optimize({ analyze: true, reindex: true }); // optimize performance
44
41
  sqlite_vacuum(); // reclaim space
45
42
  sqlite_analyze({ table: "orders" }); // update statistics for query planner
46
43
  sqlite_dbstat({ summarize: true }); // storage stats (\u26A0\uFE0F summarize native-only; WASM returns counts only)
44
+ sqlite_reindex(); // rebuild all indexes
45
+ sqlite_reindex({ target: "idx_users_email" }); // rebuild specific index
46
+ sqlite_reindex({ target: "orders" }); // rebuild all indexes for a table
47
47
  \`\`\`
48
48
 
49
49
  ## Backup/Restore (Native only)
50
50
 
51
51
  \`\`\`javascript
52
52
  sqlite_backup({ targetPath: "/path/to/backup.db" });
53
+ sqlite_vacuum_into({ outputPath: "/path/to/compact.db" }); // create defragmented copy
54
+ sqlite_dump({ outputPath: "/path/to/dump.sql" }); // export SQL text dump
53
55
  sqlite_verify_backup({ backupPath: "/path/to/backup.db" }); // check integrity without restoring
54
56
  sqlite_restore({ sourcePath: "/path/to/backup.db" }); // \u26A0\uFE0F WARNING: Replaces current database
55
57
  \`\`\`
56
58
 
57
- ## Audit Backups (Requires --audit-backup)
59
+ ## Audit Backups
58
60
 
59
61
  \`\`\`javascript
60
- sqlite_audit_list_backups(); // list pre-mutation DDL snapshots
62
+ sqlite_audit_list_backups({ limit: 10, offset: 0 }); // list pre-mutation DDL snapshots
61
63
  sqlite_audit_get_backup({ filename: "snapshot_123.json" }); // retrieve specific snapshot
64
+ sqlite_audit_diff_backup({ filename: "snapshot_123.json" }); // compare snapshot against live schema
65
+ sqlite_audit_restore_backup({ filename: "snapshot_123.json", dryRun: true }); // restore schema from snapshot
62
66
  sqlite_audit_cleanup(); // apply retention policy and delete old snapshots
63
67
  \`\`\`
64
68
 
@@ -70,9 +74,21 @@ sqlite_pragma_settings({ pragma: "cache_size", value: 10000 }); // set value
70
74
  sqlite_pragma_table_info({ table: "users" }); // column details
71
75
  sqlite_pragma_compile_options({ filter: "FTS" }); // \u26A0\uFE0F WASM may show FTS3, not FTS5
72
76
  sqlite_pragma_database_list(); // list attached databases
77
+ sqlite_attach_database({ filepath: "/path/to/other.db", alias: "archive" }); // attach external DB
78
+ sqlite_detach_database({ alias: "archive" }); // detach DB
73
79
  sqlite_pragma_optimize(); // run PRAGMA optimize
74
80
  \`\`\`
75
81
 
82
+ ## WAL Management
83
+
84
+ \`\`\`javascript
85
+ sqlite_wal({ action: "status" }); // check current journal mode
86
+ sqlite_wal({ action: "enable" }); // switch to WAL mode
87
+ sqlite_wal({ action: "disable" }); // switch back to DELETE journal mode
88
+ sqlite_wal({ action: "checkpoint" }); // run default checkpoint
89
+ sqlite_wal({ action: "checkpoint", checkpointMode: "TRUNCATE" }); // checkpoint and truncate WAL file
90
+ \`\`\`
91
+
76
92
  ## Index & Stats
77
93
 
78
94
  - \`sqlite_index_stats({ table: "orders" })\` \u2014 stats for explicit indexes
@@ -128,23 +144,25 @@ sqlite_create_csv_table({
128
144
 
129
145
  \`\`\`javascript
130
146
  sqlite_append_insight({ insight: "Q4 revenue increased 23% YoY" }); // add to memo://insights
131
- \`\`\``
132
- ],
133
- [
134
- "core",
135
- `# db-mcp Help \u2014 Core Operations (14 tools)
147
+ \`\`\``],
148
+ ["core", `# db-mcp Help \u2014 Core Operations (21 tools)
136
149
 
137
150
  ## Basic Queries
138
151
 
139
152
  - \`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
153
+ - \`sqlite_write_query({ query: "INSERT INTO users (name) VALUES ('Alice')" })\` \u2014 execute INSERT, UPDATE, DELETE, REPLACE, or trigger DDL (CREATE/DROP TRIGGER)
141
154
 
142
155
  ## Tables & Schema
143
156
 
144
157
  - \`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
158
+ - \`sqlite_describe_table({ table: "users" })\` \u2014 get detailed schema, columns, and foreign keys for a specific table. Detects generated columns (VIRTUAL/STORED) with expression.
159
+ - \`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
160
  - \`sqlite_drop_table({ table: "users", ifExists?: true })\` \u2014 drop an existing table
161
+ - \`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\`.
162
+ - \`sqlite_list_triggers({ table?: "users" })\` \u2014 list database triggers, optionally filtered by table
163
+ - \`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
164
+ - \`sqlite_drop_trigger({ name: "trg_updated" })\` \u2014 drop a database trigger
165
+ - \`sqlite_list_constraints({ table: "users" })\` \u2014 list primary key, foreign key, unique, and check constraints for a table
148
166
 
149
167
  ## Indexes
150
168
 
@@ -154,15 +172,14 @@ sqlite_append_insight({ insight: "Q4 revenue increased 23% YoY" }); // add to me
154
172
 
155
173
  ## Convenience Tools (High-Level Data Operations)
156
174
 
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\`)`
162
- ],
163
- [
164
- "geo",
165
- `# db-mcp Help \u2014 Geospatial Operations (4 basic + 7 SpatiaLite)
175
+ - \`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.
176
+ - \`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.
177
+ - \`sqlite_count({ table: "users", where?: "status = 'active'" })\` \u2014 count rows in a table (faster than a full query)
178
+ - \`sqlite_exists({ table: "users", where: "email = 'test@example.com'" })\` \u2014 check if a row exists (stops at first match)
179
+ - \`sqlite_truncate({ table: "users" })\` \u2014 quickly delete all rows from a table (executes \`DELETE FROM table\`)
180
+ - \`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.
181
+ - \`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.`],
182
+ ["geo", `# db-mcp Help \u2014 Geospatial Operations (11N/4W: 4 basic + 7 SpatiaLite [NATIVE ONLY])
166
183
 
167
184
  ## Basic Geo (always available \u2014 Haversine formula)
168
185
 
@@ -267,15 +284,12 @@ sqlite_spatialite_index({
267
284
  geometryColumn: "geom",
268
285
  action: "create",
269
286
  }); // create, drop, or check
270
- \`\`\``
271
- ],
272
- [
273
- "gotchas",
274
- `# db-mcp Help \u2014 Gotchas & Code Mode
287
+ \`\`\``],
288
+ ["gotchas", `# db-mcp Help \u2014 Gotchas & Code Mode
275
289
 
276
290
  ## \u26A0\uFE0F Critical Gotchas
277
291
 
278
- 1. **sqlite_write_query**: \u26D4 Only INSERT/UPDATE/DELETE \u2014 use \`sqlite_read_query\` for SELECT
292
+ 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
293
  2. **Regex patterns**: Double-escape backslashes (\`\\\\\\\\\`) when passing through JSON/MCP
280
294
  3. **FTS5 virtual tables**: \`*_fts\` and shadow tables \`*_fts_*\` are hidden from \`sqlite_list_tables\` for cleaner output
281
295
  4. **FTS5 boolean logic**: Uses AND by default \u2014 \`"machine learning"\` = rows with BOTH words. Use OR explicitly: \`"machine OR learning"\`
@@ -286,13 +300,16 @@ sqlite_spatialite_index({
286
300
  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
301
  10. **SpatiaLite distances**: \`nearest_neighbor\`/\`distance_matrix\` return CARTESIAN distance (degrees), not geodetic (km/miles)
288
302
  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
303
+ 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
304
  13. **CSV virtual tables**: Require ABSOLUTE file paths
291
305
  14. **sqlite_create_series_table**: Creates a REGULAR table (not virtual) \u2014 use \`sqlite_drop_table\` to remove
292
306
  15. **sqlite_dbstat**: \`summarize\` only works in native; WASM returns counts only
293
307
  16. **PRAGMA compile options**: WASM may show FTS3, not FTS5
294
308
  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
309
  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.
310
+ 19. **sqlite_batch_insert**: All rows must have the same keys \u2014 inconsistent column sets across rows will cause errors or unexpected NULLs
311
+ 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
312
+ 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
313
 
297
314
  ## WASM vs Native
298
315
 
@@ -302,14 +319,14 @@ sqlite_spatialite_index({
302
319
  | Transactions (8 tools) | \u2705 | \u274C | None |
303
320
  | Window functions (6 tools in stats group) | \u2705 | \u274C | None |
304
321
  | SpatiaLite GIS (7 tools; 4 basic geo always work) | \u2705 | \u274C | None |
305
- | Backup/Restore (3 tools) | \u2705 | \u274C | Graceful error |
322
+ | Backup/Restore/Dump/VacuumInto/Verify (5 tools) | \u2705 | \u274C | Graceful error |
306
323
  | R-Tree spatial indexing | \u2705 | \u274C | Graceful error |
307
324
  | CSV virtual tables | \u2705 | \u274C | Graceful error |
308
325
  | generate_series | JS fallback | JS fallback | \u2014 |
309
326
  | dbstat | \u2705 native (per-table) | \u274C | JS (counts only) |
310
327
  | soundex() | \u2705 native | \u274C | JS |
311
328
 
312
- ## Code Mode (1 tool)
329
+ ## Code Mode (Built-in)
313
330
 
314
331
  | Tool | Description |
315
332
  | --------------------- | ----------------------------------------------------------------- |
@@ -317,6 +334,7 @@ sqlite_spatialite_index({
317
334
 
318
335
  **Usage**: \`sqlite_execute_code({ code: "const tables = await sqlite.core.listTables(); return tables;" })\`
319
336
  **Discover**: \`sqlite.help()\` for all groups, \`sqlite.<group>.help()\` for methods.
337
+ **Progress**: Use \`await sqlite.reportProgress(current, total, "Message")\` for custom long-running tasks.
320
338
  **Groups**: \`sqlite.core\`, \`sqlite.json\`, \`sqlite.text\`, \`sqlite.stats\`, \`sqlite.vector\`, \`sqlite.admin\`, \`sqlite.transactions\` (Native-only), \`sqlite.geo\`, \`sqlite.introspection\`, \`sqlite.migration\`
321
339
 
322
340
  > **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,14 +342,12 @@ sqlite_spatialite_index({
324
342
  ## Code Mode API Mapping
325
343
 
326
344
  \`sqlite_group_action\` \u2192 \`sqlite.group.action()\` (group prefixes dropped: \`sqlite_json_insert\` \u2192 \`sqlite.json.insert()\`)
345
+ **Exception**: \`stats\` and \`migration\` keep their prefix: \`sqlite_stats_basic\` \u2192 \`sqlite.stats.statsBasic()\`, \`sqlite_migration_apply\` \u2192 \`sqlite.migration.migrationApply()\`
327
346
 
328
347
  **Positional args work**: \`sqlite.core.readQuery("SELECT...")\`, \`sqlite.json.insert("docs", "data", {...})\`
329
348
 
330
- **Discovery**: \`sqlite.help()\` returns all groups and methods. \`sqlite.core.help()\`, \`sqlite.json.help()\` for group-specific methods.`
331
- ],
332
- [
333
- "introspection",
334
- `# db-mcp Help \u2014 Schema Introspection (9 tools)
349
+ **Discovery**: \`sqlite.help()\` returns all groups and methods. \`sqlite.core.help()\`, \`sqlite.json.help()\` for group-specific methods.`],
350
+ ["introspection", `# db-mcp Help \u2014 Schema Introspection (10 tools)
335
351
 
336
352
  All introspection tools are **read-only** \u2014 they query PRAGMAs and sqlite_master, never modify data.
337
353
 
@@ -347,11 +363,11 @@ sqlite_topological_sort({ direction: "create", excludeSystemTables: true });
347
363
  sqlite_topological_sort({ direction: "drop" }); // safe DROP order
348
364
 
349
365
  // 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
366
+ sqlite_cascade_simulator({ table: "users", operation: "DELETE" });
367
+ sqlite_cascade_simulator({ table: "users", operation: "DROP", compact: true }); // compact omits path arrays
352
368
  \`\`\`
353
369
 
354
- ## Schema Analysis (3 tools)
370
+ ## Schema Analysis (4 tools)
355
371
 
356
372
  \`\`\`javascript
357
373
  // Full schema in one call \u2014 compact: true omits column details, sections limits scope
@@ -361,6 +377,20 @@ sqlite_schema_snapshot({
361
377
  });
362
378
  sqlite_schema_snapshot({ compact: true }); // lighter payload
363
379
 
380
+ // Compare a saved snapshot against the current live schema \u2014 structured drift analysis
381
+ sqlite_schema_diff({
382
+ baseline: previousSnapshot, // from an earlier sqlite_schema_snapshot call
383
+ target: "current",
384
+ });
385
+ // Compare specific sections only
386
+ sqlite_schema_diff({
387
+ baseline: "current",
388
+ target: modifiedSnapshot,
389
+ sections: ["tables", "indexes"],
390
+ });
391
+ // Both sides inline (offline diff, no DB queries)
392
+ sqlite_schema_diff({ baseline: snapshotA, target: snapshotB });
393
+
364
394
  // Find constraint health issues \u2014 missing PKs, nullable FKs, unindexed FKs
365
395
  sqlite_constraint_analysis({ excludeSystemTables: true });
366
396
  sqlite_constraint_analysis({
@@ -398,17 +428,14 @@ sqlite_query_plan({ sql: "SELECT * FROM orders WHERE status = 'active'" });
398
428
  ## \u26A0\uFE0F Gotchas
399
429
 
400
430
  - \`excludeSystemTables\` defaults to \`true\` \u2014 SpatiaLite system tables are hidden for cleaner output. Pass \`false\` to include them
401
- - \`sqlite_migration_risks\` analyzes DDL text statically \u2014 it does NOT execute the statements`
402
- ],
403
- [
404
- "json",
405
- `# db-mcp Help \u2014 JSON Operations (24 tools)
431
+ - \`sqlite_migration_risks\` analyzes DDL text statically \u2014 it does NOT execute the statements`],
432
+ ["json", `# db-mcp Help \u2014 JSON Operations (25 tools)
406
433
 
407
434
  ## Collection & CRUD
408
435
 
409
436
  - \`sqlite_create_json_collection({ tableName, indexes: [{ path: "$.type" }, { path: "$.author" }] })\` \u2014 creates table with JSON indexes
410
437
  - \`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
438
+ - \`sqlite_json_select({ table, column, paths? })\` \u2014 select rows, optionally extract specific JSON paths
412
439
  - \`sqlite_json_update({ table, column, path, value, whereClause })\` \u2014 update value at JSON path
413
440
  - \`sqlite_json_query({ table, column, filterPaths: { "$.type": "article" }, selectPaths: ["$.title"] })\` \u2014 query with path-based filters and projections
414
441
 
@@ -463,9 +490,10 @@ sqlite_json_group_object({
463
490
  \`\`\`
464
491
 
465
492
  - \`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
493
+ - \`sqlite_json_pretty({ json: "{\\"name\\": \\"Alice\\"}" })\` \u2014 format JSON string with indentation for readability
494
+ - \`sqlite_json_valid({ json: "{\\"name\\": \\"Alice\\"}" })\` \u2014 check if a string is valid JSON
468
495
  - \`sqlite_json_analyze_schema({ table, column })\` \u2014 infer schema types
496
+ - \`sqlite_json_diff({ table, column, path1, path2 })\` \u2014 compare two JSON paths within the same row
469
497
 
470
498
  ## Security
471
499
 
@@ -475,11 +503,8 @@ sqlite_json_group_object({
475
503
 
476
504
  - \`sqlite_json_storage_info({ table, column })\` \u2014 check text vs JSONB format
477
505
  - \`sqlite_jsonb_convert({ table, column })\` \u2014 convert to JSONB for faster queries
478
- - \`sqlite_json_normalize_column({ table, column, outputFormat? })\` \u2014 normalize JSON (sort keys, compact). \u26A0\uFE0F Defaults to \`"preserve"\` (maintains original format); use \`outputFormat: "text"\` to force text output`
479
- ],
480
- [
481
- "migration",
482
- `# db-mcp Help \u2014 Migration Tracking (6 tools)
506
+ - \`sqlite_json_normalize_column({ table, column, outputFormat? })\` \u2014 normalize JSON (sort keys, compact). \u26A0\uFE0F Defaults to \`"preserve"\` (maintains original format); use \`outputFormat: "text"\` to force text output`],
507
+ ["migration", `# db-mcp Help \u2014 Migration Tracking (6 tools)
483
508
 
484
509
  \u26A0\uFE0F Must call \`sqlite_migration_init()\` before using any other migration tool \u2014 it creates the tracking table.
485
510
 
@@ -492,8 +517,7 @@ sqlite_migration_init();
492
517
  sqlite_migration_apply({
493
518
  version: "2024-01-15-add-users",
494
519
  description: "Create users table",
495
- sql:
496
- "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE)",
520
+ sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE)",
497
521
  rollbackSql: "DROP TABLE users",
498
522
  sourceSystem: "agent",
499
523
  appliedBy: "claude",
@@ -522,11 +546,8 @@ sqlite_migration_status();
522
546
  ## \u26A0\uFE0F Gotchas
523
547
 
524
548
  - 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\``
526
- ],
527
- [
528
- "stats",
529
- `# db-mcp Help \u2014 Statistical Analysis (16 core + 6 window)
549
+ - 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)`],
550
+ ["stats", `# db-mcp Help \u2014 Statistical Analysis (23N/17W: 17 core + 6 window [NATIVE ONLY])
530
551
 
531
552
  ## Core Statistics (always available)
532
553
 
@@ -542,6 +563,7 @@ sqlite_stats_percentile({
542
563
  sqlite_stats_histogram({ table: "products", column: "price", buckets: 10 });
543
564
  sqlite_stats_correlation({ table: "data", column1: "x", column2: "y" }); // Pearson coefficient
544
565
  sqlite_stats_distinct({ table: "orders", column: "status" }); // distinct values
566
+ sqlite_stats_sample({ table: "orders", sampleSize: 100 }); // random sample
545
567
  sqlite_stats_summary({
546
568
  table: "data",
547
569
  columns: ["price", "quantity", "discount"],
@@ -642,13 +664,10 @@ sqlite_window_moving_avg({
642
664
  column: "close_price",
643
665
  orderBy: "date",
644
666
  windowSize: 7,
645
- selectColumns: ["date"]
667
+ selectColumns: ["date"],
646
668
  });
647
- \`\`\``
648
- ],
649
- [
650
- "text",
651
- `# db-mcp Help \u2014 Text Processing & FTS5
669
+ \`\`\``],
670
+ ["text", `# db-mcp Help \u2014 Text Processing & FTS5 (19N/14W: 14 text + 5 FTS5 [NATIVE ONLY])
652
671
 
653
672
  ## Full-Text Search / FTS5 (5 tools, Native only)
654
673
 
@@ -775,17 +794,19 @@ sqlite_advanced_search({
775
794
  fuzzyThreshold: 0.4,
776
795
  });
777
796
 
778
- // Sentiment analysis \u2014 pure text analysis, no database query needed
797
+ // Sentiment analysis \u2014 text analysis (can analyze raw text or database columns)
779
798
  sqlite_text_sentiment({ text: "This product is amazing and wonderful!" });
780
799
  // \u2192 { sentiment: "very_positive", score: 2, confidence: "medium" }
781
800
 
782
- sqlite_text_sentiment({ text: "Great service but slow delivery", returnWords: true });
801
+ sqlite_text_sentiment({ table: "articles", column: "body" }); // analyzes all rows in a column
802
+
803
+ sqlite_text_sentiment({
804
+ text: "Great service but slow delivery",
805
+ returnWords: true,
806
+ });
783
807
  // \u2192 { sentiment: "neutral", score: 0, matchedPositive: ["great"], matchedNegative: ["slow"] }
784
- \`\`\``
785
- ],
786
- [
787
- "transactions",
788
- `# db-mcp Help \u2014 Transactions (8 tools, Native only)
808
+ \`\`\``],
809
+ ["transactions", `# db-mcp Help \u2014 Transactions (8 tools, Native only)
789
810
 
790
811
  ## Atomic Execution (preferred for simple cases)
791
812
 
@@ -816,11 +837,8 @@ sqlite_transaction_status(); // \u2192 { status: "active" | "none", active: true
816
837
 
817
838
  - Transaction tools are **Native only** \u2014 WASM adapter does not support transactions
818
839
  - Use \`sqlite_transaction_execute\` for simple multi-statement operations; manual \`begin\`/\`commit\` for complex flows with savepoints
819
- - \`sqlite_transaction_status\` is read-only and requires only \`read\` scope; all other transaction tools require \`write\` scope`
820
- ],
821
- [
822
- "vector",
823
- `# db-mcp Help \u2014 Vector/Semantic Search (11 tools)
840
+ - \`sqlite_transaction_status\` is read-only and requires only \`read\` scope; all other transaction tools require \`write\` scope`],
841
+ ["vector", `# db-mcp Help \u2014 Vector/Semantic Search (11 tools)
824
842
 
825
843
  \`\`\`javascript
826
844
  // Create vector table with metadata columns
@@ -846,8 +864,7 @@ sqlite_vector_stats({ table: "docs", vectorColumn: "emb" }); // returns sampleSi
846
864
  // Utility tools for preprocessing
847
865
  sqlite_vector_normalize({ vector: [3, 4, 0, 0] }); // returns unit vector [0.6, 0.8, 0, 0]
848
866
  sqlite_vector_distance({ vector1: [...], vector2: [...], metric: "cosine" }); // returns { value: <number> }
849
- \`\`\``
850
- ]
867
+ \`\`\``]
851
868
  ]);
852
869
  var BUFFER_HIGH_WATER = 50;
853
870
  var FLUSH_INTERVAL_MS = 100;
@@ -883,11 +900,12 @@ var AuditLogger = class {
883
900
  await this.ensureDirectory();
884
901
  const fh = await open(this.config.logPath, "a");
885
902
  await fh.close();
886
- } catch {
903
+ } catch (err) {
887
904
  process.stderr.write(
888
905
  `[AUDIT] Failed to initialise log file: ${this.config.logPath}
889
906
  `
890
907
  );
908
+ throw err;
891
909
  }
892
910
  }
893
911
  /**
@@ -897,7 +915,8 @@ var AuditLogger = class {
897
915
  */
898
916
  log(entry) {
899
917
  if (this.closed || !this.config.enabled) return;
900
- this.buffer.push(JSON.stringify(entry));
918
+ const safeEntry = redactObject(entry, 0, 5);
919
+ this.buffer.push(JSON.stringify(safeEntry));
901
920
  if (this.buffer.length >= BUFFER_HIGH_WATER) {
902
921
  void this.flush();
903
922
  }
@@ -1033,9 +1052,9 @@ var gzipAsync = promisify(gzip);
1033
1052
  var SNAPSHOT_TOOL_ARGS = {
1034
1053
  sqlite_drop_table: { targetKey: "table" },
1035
1054
  sqlite_drop_index: { targetKey: "index" },
1036
- sqlite_drop_view: { targetKey: "view" },
1055
+ sqlite_drop_view: { targetKey: "viewName" },
1037
1056
  sqlite_import_csv: { targetKey: "table" },
1038
- sqlite_backup: { targetKey: "path" }
1057
+ sqlite_backup: { targetKey: "targetPath" }
1039
1058
  };
1040
1059
  var SNAPSHOT_EXT = ".snapshot.json.gz";
1041
1060
  var SNAPSHOT_EXT_LEGACY = ".snapshot.json";
@@ -1087,14 +1106,18 @@ var BackupManager = class {
1087
1106
  /**
1088
1107
  * List available snapshots with metadata.
1089
1108
  */
1090
- async listSnapshots() {
1109
+ async listSnapshots(limit = 10, offset = 0) {
1091
1110
  try {
1092
1111
  await this.ensureDirectory();
1093
1112
  const files = await readdir(this.snapshotDir);
1113
+ const snapshotFiles = files.filter(
1114
+ (f) => f.endsWith(SNAPSHOT_EXT) || f.endsWith(SNAPSHOT_EXT_LEGACY)
1115
+ );
1116
+ snapshotFiles.sort((a, b) => b.localeCompare(a));
1117
+ const total = snapshotFiles.length;
1118
+ const targetFiles = snapshotFiles.slice(offset, offset + limit);
1094
1119
  const snapshots = [];
1095
- for (const file of files) {
1096
- if (!file.endsWith(SNAPSHOT_EXT) && !file.endsWith(SNAPSHOT_EXT_LEGACY))
1097
- continue;
1120
+ for (const file of targetFiles) {
1098
1121
  try {
1099
1122
  const parsed = await this.readSnapshotFile(file);
1100
1123
  if (parsed) {
@@ -1103,10 +1126,9 @@ var BackupManager = class {
1103
1126
  } catch {
1104
1127
  }
1105
1128
  }
1106
- snapshots.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
1107
- return snapshots;
1129
+ return { snapshots, total };
1108
1130
  } catch {
1109
- return [];
1131
+ return { snapshots: [], total: 0 };
1110
1132
  }
1111
1133
  }
1112
1134
  /**
@@ -1400,32 +1422,57 @@ var BackupManager = class {
1400
1422
  }
1401
1423
  }
1402
1424
  };
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);
1425
+ var SENSITIVE_KEY_PATTERN = /^(password|passwd|token|secret|authorization|api_?key|credential|private_?key|access_?token|refresh_?token)$/i;
1426
+ 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;
1427
+ function redactSensitiveKeys(value, depth = 0) {
1428
+ const MAX_DEPTH = 5;
1429
+ if (depth > MAX_DEPTH || value === null || value === void 0) {
1430
+ return value;
1431
+ }
1432
+ if (Array.isArray(value)) {
1433
+ return value.map((item) => redactSensitiveKeys(item, depth + 1));
1434
+ }
1435
+ if (typeof value === "string") {
1436
+ const isSql = /^\s*(?:SELECT|INSERT|UPDATE|DELETE|WITH|CREATE|ALTER|DROP|PRAGMA)\b/i.test(
1437
+ value
1438
+ );
1439
+ const scrubbed = isSql ? value.replace(/'(?:''|[^'])*'/g, "'***'") : value;
1440
+ return scrubbed.replace(SENSITIVE_VALUE_PATTERN, "[REDACTED]");
1441
+ }
1442
+ if (typeof value === "object") {
1443
+ const result = {};
1444
+ for (const [key, val] of Object.entries(value)) {
1445
+ if (SENSITIVE_KEY_PATTERN.test(key)) {
1446
+ result[key] = "[REDACTED]";
1447
+ } else if (typeof val === "object" && val !== null) {
1448
+ result[key] = redactSensitiveKeys(val, depth + 1);
1449
+ } else if (typeof val === "string") {
1450
+ const isSql = key.toLowerCase() === "sql" || key.toLowerCase() === "query" || /^\s*(?:SELECT|INSERT|UPDATE|DELETE|WITH|CREATE|ALTER|DROP|PRAGMA)\b/i.test(
1451
+ val
1452
+ );
1453
+ const scrubbed = isSql ? val.replace(/'(?:''|[^'])*'/g, "'***'") : val;
1454
+ result[key] = scrubbed.replace(SENSITIVE_VALUE_PATTERN, "[REDACTED]");
1455
+ } else {
1456
+ result[key] = val;
1457
+ }
1412
1458
  }
1459
+ return result;
1413
1460
  }
1461
+ return value;
1414
1462
  }
1415
- function getRequiredScope(toolName) {
1416
- return toolScopeMap.get(toolName) ?? SCOPES.READ;
1417
- }
1418
-
1419
- // src/audit/interceptor.ts
1420
1463
  var ALWAYS_AUDITED_SCOPES = /* @__PURE__ */ new Set(["write", "admin"]);
1421
1464
  function scopeToCategory(scope) {
1422
1465
  if (scope === "admin") return "admin";
1423
1466
  if (scope === "read") return "read";
1424
1467
  return "write";
1425
1468
  }
1426
- function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1469
+ function createAuditInterceptor(auditLogger, backupManager) {
1427
1470
  const auditReads = auditLogger.config.auditReads;
1471
+ let currentQueryAdapter;
1428
1472
  return {
1473
+ setQueryAdapter(adapter) {
1474
+ currentQueryAdapter = adapter;
1475
+ },
1429
1476
  async around(toolName, args, requestId, fn, options) {
1430
1477
  const scope = getRequiredScope(toolName);
1431
1478
  if (!ALWAYS_AUDITED_SCOPES.has(scope) && !auditReads) {
@@ -1438,6 +1485,18 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1438
1485
  let error;
1439
1486
  let backupRef;
1440
1487
  let tokenEstimate;
1488
+ if (backupManager !== void 0 && currentQueryAdapter !== void 0 && backupManager.shouldSnapshot(toolName)) {
1489
+ try {
1490
+ backupRef = await backupManager.createSnapshot(
1491
+ toolName,
1492
+ args ?? {},
1493
+ requestId,
1494
+ currentQueryAdapter,
1495
+ options?.logAs
1496
+ );
1497
+ } catch {
1498
+ }
1499
+ }
1441
1500
  try {
1442
1501
  const result = await fn();
1443
1502
  if (typeof result === "object" && result !== null) {
@@ -1455,7 +1514,9 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1455
1514
  return result;
1456
1515
  } catch (err) {
1457
1516
  success = false;
1458
- error = err instanceof Error ? err.message : String(err);
1517
+ error = sanitizeErrorMessage(
1518
+ err instanceof Error ? err.message : String(err)
1519
+ );
1459
1520
  const errorResult = {
1460
1521
  success: false,
1461
1522
  error,
@@ -1495,7 +1556,7 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1495
1556
  durationMs,
1496
1557
  success,
1497
1558
  error,
1498
- args: auditLogger.config.redact ? void 0 : args,
1559
+ args: auditLogger.config.redact ? void 0 : redactSensitiveKeys(args),
1499
1560
  backup: backupRef,
1500
1561
  tokenEstimate
1501
1562
  });
@@ -1504,6 +1565,806 @@ function createAuditInterceptor(auditLogger, backupManager, queryAdapter) {
1504
1565
  }
1505
1566
  };
1506
1567
  }
1568
+
1569
+ // src/server/registration/built-in-tools.ts
1570
+ function registerBuiltInTools(server, adaptersMap, config, toolFilter) {
1571
+ const serverInfoOpts = {
1572
+ title: "Server Info",
1573
+ description: "Get information about the db-mcp server and registered adapters",
1574
+ icons: SERVER_ICONS,
1575
+ annotations: READ_ONLY
1576
+ };
1577
+ server.registerTool("server_info", serverInfoOpts, () => {
1578
+ const authCtx = getAuthContext();
1579
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "server_info")) {
1580
+ throw new InsufficientScopeError(["read"], authCtx.scopes);
1581
+ }
1582
+ const adapterInfo = [];
1583
+ for (const [id, adapter] of adaptersMap) {
1584
+ adapterInfo.push({
1585
+ id,
1586
+ ...adapter.getInfo()
1587
+ });
1588
+ }
1589
+ return {
1590
+ content: [
1591
+ {
1592
+ type: "text",
1593
+ text: JSON.stringify(
1594
+ {
1595
+ name: config.name,
1596
+ version: config.version,
1597
+ transport: config.transport,
1598
+ adapters: adapterInfo,
1599
+ toolFilter: {
1600
+ raw: toolFilter.raw,
1601
+ enabledGroups: [...toolFilter.enabledGroups]
1602
+ }
1603
+ },
1604
+ null,
1605
+ 2
1606
+ )
1607
+ }
1608
+ ]
1609
+ };
1610
+ });
1611
+ const healthOpts = {
1612
+ title: "Server Health",
1613
+ description: "Check health status of all database connections",
1614
+ icons: SERVER_ICONS,
1615
+ annotations: READ_ONLY
1616
+ };
1617
+ server.registerTool("server_health", healthOpts, async () => {
1618
+ const authCtx = getAuthContext();
1619
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "server_health")) {
1620
+ throw new InsufficientScopeError(["read"], authCtx.scopes);
1621
+ }
1622
+ const health = {
1623
+ server: "healthy",
1624
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1625
+ adapters: {}
1626
+ };
1627
+ for (const [id, adapter] of adaptersMap) {
1628
+ try {
1629
+ const adapterHealth = await adapter.getHealth();
1630
+ health["adapters"][id] = adapterHealth;
1631
+ } catch (error) {
1632
+ let errorMsg = error instanceof Error ? error.message : "Unknown error";
1633
+ errorMsg = errorMsg.replace(/(:[^:@/]+@)/g, ":***@");
1634
+ health["adapters"][id] = {
1635
+ connected: false,
1636
+ error: errorMsg
1637
+ };
1638
+ }
1639
+ }
1640
+ return {
1641
+ content: [
1642
+ {
1643
+ type: "text",
1644
+ text: JSON.stringify(health, null, 2)
1645
+ }
1646
+ ]
1647
+ };
1648
+ });
1649
+ const listAdaptersOpts = {
1650
+ title: "List Adapters",
1651
+ description: "List all registered database adapters",
1652
+ icons: SERVER_ICONS,
1653
+ annotations: READ_ONLY
1654
+ };
1655
+ server.registerTool("list_adapters", listAdaptersOpts, () => {
1656
+ const authCtx = getAuthContext();
1657
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "list_adapters")) {
1658
+ throw new InsufficientScopeError(["read"], authCtx.scopes);
1659
+ }
1660
+ const adapters = [];
1661
+ for (const [, adapter] of adaptersMap) {
1662
+ adapters.push({
1663
+ id: `${adapter.type}:default`,
1664
+ type: adapter.type,
1665
+ name: adapter.name,
1666
+ version: adapter.version,
1667
+ connected: adapter.isConnected()
1668
+ });
1669
+ }
1670
+ return {
1671
+ content: [
1672
+ {
1673
+ type: "text",
1674
+ text: JSON.stringify(adapters, null, 2)
1675
+ }
1676
+ ]
1677
+ };
1678
+ });
1679
+ registerToolScopes(
1680
+ /* @__PURE__ */ new Map([
1681
+ ["server_info", ["read"]],
1682
+ ["server_health", ["read"]],
1683
+ ["list_adapters", ["read"]]
1684
+ ])
1685
+ );
1686
+ }
1687
+
1688
+ // src/server/registration/help-resources.ts
1689
+ function registerHelpResources(server, toolFilter) {
1690
+ const gotchasContent = HELP_CONTENT.get("gotchas");
1691
+ if (gotchasContent) {
1692
+ server.registerResource(
1693
+ "sqlite_help",
1694
+ "sqlite://help",
1695
+ {
1696
+ description: "Critical gotchas, WASM vs Native comparison, and Code Mode API reference",
1697
+ mimeType: "text/markdown",
1698
+ annotations: ASSISTANT_FOCUSED
1699
+ },
1700
+ () => ({
1701
+ contents: [
1702
+ {
1703
+ uri: "sqlite://help",
1704
+ mimeType: "text/markdown",
1705
+ text: gotchasContent
1706
+ }
1707
+ ]
1708
+ })
1709
+ );
1710
+ }
1711
+ const groupHelpKeys = [
1712
+ { group: "core", key: "core" },
1713
+ { group: "json", key: "json" },
1714
+ { group: "text", key: "text" },
1715
+ { group: "stats", key: "stats" },
1716
+ { group: "vector", key: "vector" },
1717
+ { group: "geo", key: "geo" },
1718
+ { group: "admin", key: "admin" },
1719
+ { group: "transactions", key: "transactions" },
1720
+ { group: "introspection", key: "introspection" },
1721
+ { group: "migration", key: "migration" }
1722
+ ];
1723
+ for (const { group, key } of groupHelpKeys) {
1724
+ const isCodemodeOnly = toolFilter.enabledGroups.size === 1 && toolFilter.enabledGroups.has("codemode");
1725
+ if (!toolFilter.enabledGroups.has(group) && !isCodemodeOnly) {
1726
+ continue;
1727
+ }
1728
+ const content = HELP_CONTENT.get(key);
1729
+ if (!content) continue;
1730
+ server.registerResource(
1731
+ `sqlite_help_${key}`,
1732
+ `sqlite://help/${key}`,
1733
+ {
1734
+ description: `Tool reference for the ${group} tool group`,
1735
+ mimeType: "text/markdown",
1736
+ annotations: ASSISTANT_FOCUSED
1737
+ },
1738
+ () => ({
1739
+ contents: [
1740
+ {
1741
+ uri: `sqlite://help/${key}`,
1742
+ mimeType: "text/markdown",
1743
+ text: content
1744
+ }
1745
+ ]
1746
+ })
1747
+ );
1748
+ }
1749
+ const registeredHelp = ["sqlite://help"];
1750
+ for (const { group, key } of groupHelpKeys) {
1751
+ if (toolFilter.enabledGroups.has(group)) {
1752
+ registeredHelp.push(`sqlite://help/${key}`);
1753
+ }
1754
+ }
1755
+ logger.info(`Help resources: ${registeredHelp.join(", ")}`, {
1756
+ module: "SERVER"
1757
+ });
1758
+ }
1759
+ function redactSqlLiterals(text) {
1760
+ return text.replace(/'(?:''|[^'])*'/g, "'***'");
1761
+ }
1762
+ function validateDdl(sql) {
1763
+ const cleanSql = sql.replace(/\/\*[\s\S]*?\*\//g, "").replace(/--.*$/gm, "");
1764
+ const upperSql = cleanSql.toUpperCase();
1765
+ if (upperSql.includes("ATTACH ") || upperSql.includes("DETACH ") || upperSql.includes("PRAGMA ") || upperSql.includes("LOAD_EXTENSION(")) {
1766
+ throw new Error(
1767
+ `DDL validation failed: unauthorized command or function call`
1768
+ );
1769
+ }
1770
+ if (upperSql.includes(" ON MAIN.") || upperSql.includes(" ON TEMP.")) {
1771
+ throw new Error(
1772
+ `DDL validation failed: trigger attempts to target a specific database`
1773
+ );
1774
+ }
1775
+ }
1776
+ function registerAuditResource(server, auditLogger, backupManager) {
1777
+ if (!auditLogger) return;
1778
+ server.registerResource(
1779
+ "sqlite_audit",
1780
+ "sqlite://audit",
1781
+ {
1782
+ description: "Recent audit log entries and backup statistics. Shows the last 50 tool invocations with timing, outcomes, and token estimates.",
1783
+ mimeType: "application/json"
1784
+ },
1785
+ async () => {
1786
+ const recent = await auditLogger.recent(50);
1787
+ const backupStats = backupManager ? await backupManager.getStats() : void 0;
1788
+ const payload = {
1789
+ entries: recent,
1790
+ stats: {
1791
+ totalEntries: recent.length,
1792
+ ...backupStats && { backups: backupStats }
1793
+ }
1794
+ };
1795
+ const payloadStr = JSON.stringify(payload, null, 2);
1796
+ return {
1797
+ contents: [
1798
+ {
1799
+ uri: "sqlite://audit",
1800
+ mimeType: "application/json",
1801
+ text: redactSqlLiterals(payloadStr)
1802
+ }
1803
+ ]
1804
+ };
1805
+ }
1806
+ );
1807
+ }
1808
+ function registerAuditBackupTools(server, backupManager, adaptersMap) {
1809
+ if (!backupManager) return;
1810
+ server.registerTool(
1811
+ "sqlite_audit_list_backups",
1812
+ {
1813
+ title: "List Audit Backups",
1814
+ description: "List pre-mutation DDL snapshots captured before destructive operations. Returns metadata for each snapshot including timestamp, tool, target, and size.",
1815
+ inputSchema: AuditListBackupsSchema,
1816
+ outputSchema: AuditListBackupsOutputSchema,
1817
+ annotations: {
1818
+ readOnlyHint: true,
1819
+ destructiveHint: false,
1820
+ idempotentHint: true,
1821
+ openWorldHint: false
1822
+ // Requires admin scope
1823
+ }
1824
+ },
1825
+ async (args) => {
1826
+ const authCtx = getAuthContext();
1827
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_list_backups")) {
1828
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
1829
+ }
1830
+ let parsed;
1831
+ try {
1832
+ parsed = AuditListBackupsSchema.parse(args ?? {});
1833
+ } catch (error) {
1834
+ const structured = formatHandlerError(error);
1835
+ return {
1836
+ content: [
1837
+ {
1838
+ type: "text",
1839
+ text: JSON.stringify(structured, null, 2)
1840
+ }
1841
+ ],
1842
+ isError: true,
1843
+ structuredContent: structured
1844
+ };
1845
+ }
1846
+ const limit = parsed.limit ?? 10;
1847
+ const offset = parsed.offset ?? 0;
1848
+ const { snapshots, total } = await backupManager.listSnapshots(
1849
+ limit,
1850
+ offset
1851
+ );
1852
+ const result = {
1853
+ success: true,
1854
+ snapshots,
1855
+ count: snapshots.length,
1856
+ totalCount: total
1857
+ };
1858
+ const tokenEstimate = Math.ceil(
1859
+ Buffer.byteLength(JSON.stringify(result), "utf8") / 4
1860
+ );
1861
+ return {
1862
+ content: [
1863
+ {
1864
+ type: "text",
1865
+ text: JSON.stringify(
1866
+ { ...result, _meta: { tokenEstimate } },
1867
+ null,
1868
+ 2
1869
+ )
1870
+ }
1871
+ ],
1872
+ structuredContent: result
1873
+ };
1874
+ }
1875
+ );
1876
+ server.registerTool(
1877
+ "sqlite_audit_get_backup",
1878
+ {
1879
+ title: "Get Audit Backup",
1880
+ description: "Retrieve a specific pre-mutation DDL snapshot by filename. Returns the full snapshot content including DDL and optional data.",
1881
+ inputSchema: z.object({
1882
+ filename: z.string().default("").describe("Snapshot filename from sqlite_audit_list_backups results")
1883
+ }),
1884
+ outputSchema: AuditGetBackupOutputSchema,
1885
+ annotations: {
1886
+ readOnlyHint: true,
1887
+ destructiveHint: false,
1888
+ idempotentHint: true,
1889
+ openWorldHint: false
1890
+ // Requires admin scope
1891
+ }
1892
+ },
1893
+ async (args) => {
1894
+ const authCtx = getAuthContext();
1895
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_get_backup")) {
1896
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
1897
+ }
1898
+ let filename;
1899
+ try {
1900
+ const parsed = z.object({ filename: z.string().min(1, "filename is required") }).parse(args);
1901
+ filename = parsed.filename;
1902
+ } catch (error) {
1903
+ const structured = formatHandlerError(error);
1904
+ return {
1905
+ content: [
1906
+ {
1907
+ type: "text",
1908
+ text: JSON.stringify(structured, null, 2)
1909
+ }
1910
+ ],
1911
+ isError: true,
1912
+ structuredContent: structured
1913
+ };
1914
+ }
1915
+ const snapshot = await backupManager.getSnapshot(filename);
1916
+ if (!snapshot) {
1917
+ const errRes = {
1918
+ success: false,
1919
+ error: `Snapshot not found: ${filename}`
1920
+ };
1921
+ return {
1922
+ content: [
1923
+ {
1924
+ type: "text",
1925
+ text: JSON.stringify(errRes, null, 2)
1926
+ }
1927
+ ],
1928
+ isError: true,
1929
+ structuredContent: errRes
1930
+ };
1931
+ }
1932
+ const result = { success: true, ...snapshot };
1933
+ const snapshotStr = JSON.stringify(result, null, 2);
1934
+ return {
1935
+ content: [
1936
+ {
1937
+ type: "text",
1938
+ text: redactSqlLiterals(snapshotStr)
1939
+ }
1940
+ ],
1941
+ structuredContent: result
1942
+ };
1943
+ }
1944
+ );
1945
+ server.registerTool(
1946
+ "sqlite_audit_cleanup",
1947
+ {
1948
+ title: "Cleanup Audit Backups",
1949
+ description: "Apply retention policy to audit backup snapshots. Deletes snapshots exceeding age or count limits.",
1950
+ outputSchema: AuditCleanupOutputSchema,
1951
+ annotations: {
1952
+ readOnlyHint: false,
1953
+ destructiveHint: true,
1954
+ idempotentHint: true,
1955
+ openWorldHint: false
1956
+ }
1957
+ },
1958
+ async () => {
1959
+ const authCtx = getAuthContext();
1960
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_cleanup")) {
1961
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
1962
+ }
1963
+ const deleted = await backupManager.cleanup();
1964
+ const result = {
1965
+ success: true,
1966
+ deletedCount: deleted,
1967
+ message: deleted > 0 ? `Cleaned up ${String(deleted)} snapshot(s)` : "No snapshots to clean up"
1968
+ };
1969
+ return {
1970
+ content: [
1971
+ {
1972
+ type: "text",
1973
+ text: JSON.stringify(result, null, 2)
1974
+ }
1975
+ ],
1976
+ structuredContent: result
1977
+ };
1978
+ }
1979
+ );
1980
+ server.registerTool(
1981
+ "sqlite_audit_diff_backup",
1982
+ {
1983
+ title: "Diff Audit Backup",
1984
+ 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.",
1985
+ inputSchema: z.object({
1986
+ filename: z.string().default("").describe(
1987
+ "Snapshot filename to compare against the live database schema"
1988
+ )
1989
+ }),
1990
+ outputSchema: AuditDiffBackupOutputSchema,
1991
+ annotations: {
1992
+ readOnlyHint: true,
1993
+ destructiveHint: false,
1994
+ idempotentHint: true,
1995
+ openWorldHint: false
1996
+ // Requires admin scope
1997
+ }
1998
+ },
1999
+ async (args) => {
2000
+ const authCtx = getAuthContext();
2001
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_diff_backup")) {
2002
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
2003
+ }
2004
+ let filename;
2005
+ try {
2006
+ const parsed = z.object({ filename: z.string().min(1, "filename is required") }).parse(args);
2007
+ filename = parsed.filename;
2008
+ } catch (error) {
2009
+ const structured = formatHandlerError(error);
2010
+ return {
2011
+ content: [
2012
+ {
2013
+ type: "text",
2014
+ text: JSON.stringify(structured, null, 2)
2015
+ }
2016
+ ],
2017
+ isError: true,
2018
+ structuredContent: structured
2019
+ };
2020
+ }
2021
+ const snapshot = await backupManager.getSnapshot(filename);
2022
+ if (!snapshot) {
2023
+ const errRes = {
2024
+ success: false,
2025
+ error: `Snapshot not found: ${filename}`
2026
+ };
2027
+ return {
2028
+ content: [
2029
+ {
2030
+ type: "text",
2031
+ text: JSON.stringify(errRes, null, 2)
2032
+ }
2033
+ ],
2034
+ isError: true,
2035
+ structuredContent: errRes
2036
+ };
2037
+ }
2038
+ const adapter = [...adaptersMap.values()][0];
2039
+ if (!adapter) {
2040
+ const errRes = {
2041
+ success: false,
2042
+ error: "No connected adapter available"
2043
+ };
2044
+ return {
2045
+ content: [
2046
+ {
2047
+ type: "text",
2048
+ text: JSON.stringify(errRes, null, 2)
2049
+ }
2050
+ ],
2051
+ isError: true,
2052
+ structuredContent: errRes
2053
+ };
2054
+ }
2055
+ try {
2056
+ const liveResult = await adapter.executeReadQuery(
2057
+ "SELECT name, type, sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY type, name"
2058
+ );
2059
+ const liveObjects = /* @__PURE__ */ new Map();
2060
+ for (const row of liveResult.rows ?? []) {
2061
+ liveObjects.set(row["name"], {
2062
+ type: row["type"],
2063
+ sql: row["sql"]
2064
+ });
2065
+ }
2066
+ const snapshotDdl = snapshot.ddl ?? "";
2067
+ const snapshotObjects = /* @__PURE__ */ new Map();
2068
+ const statements = snapshotDdl.split(";").map((s) => s.trim()).filter(Boolean);
2069
+ for (const stmt of statements) {
2070
+ const match = /CREATE\s+(?:VIRTUAL\s+)?(?:TEMP(?:ORARY)?\s+)?(TABLE|INDEX|VIEW|TRIGGER)\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"([^"]+)"|(\S+))/i.exec(
2071
+ stmt
2072
+ );
2073
+ if (match) {
2074
+ const type = (match[1] ?? "").toLowerCase();
2075
+ const name = match[2] ?? match[3] ?? "";
2076
+ snapshotObjects.set(name, { type, sql: stmt });
2077
+ }
2078
+ }
2079
+ const diffs = [];
2080
+ const snapshotTarget = snapshot.metadata?.target;
2081
+ for (const [name, live] of liveObjects) {
2082
+ if (name === snapshotTarget || snapshotObjects.has(name)) {
2083
+ if (!snapshotObjects.has(name)) {
2084
+ diffs.push({
2085
+ object: name,
2086
+ type: live.type,
2087
+ status: "added",
2088
+ liveDefinition: live.sql
2089
+ });
2090
+ }
2091
+ }
2092
+ }
2093
+ for (const [name, snap] of snapshotObjects) {
2094
+ if (!liveObjects.has(name)) {
2095
+ diffs.push({
2096
+ object: name,
2097
+ type: snap.type,
2098
+ status: "removed",
2099
+ snapshotDefinition: snap.sql
2100
+ });
2101
+ }
2102
+ }
2103
+ for (const [name, snap] of snapshotObjects) {
2104
+ const live = liveObjects.get(name);
2105
+ if (live && live.sql !== snap.sql) {
2106
+ diffs.push({
2107
+ object: name,
2108
+ type: live.type,
2109
+ status: "modified",
2110
+ liveDefinition: live.sql,
2111
+ snapshotDefinition: snap.sql
2112
+ });
2113
+ }
2114
+ }
2115
+ const result = {
2116
+ success: true,
2117
+ diffs,
2118
+ snapshotTimestamp: snapshot.metadata?.timestamp ?? "",
2119
+ snapshotTarget: snapshot.metadata?.target ?? ""
2120
+ };
2121
+ return {
2122
+ content: [
2123
+ {
2124
+ type: "text",
2125
+ text: JSON.stringify(result, null, 2)
2126
+ }
2127
+ ],
2128
+ structuredContent: result
2129
+ };
2130
+ } catch (error) {
2131
+ const errRes = {
2132
+ success: false,
2133
+ error: error instanceof Error ? error.message : String(error)
2134
+ };
2135
+ return {
2136
+ content: [
2137
+ {
2138
+ type: "text",
2139
+ text: JSON.stringify(errRes, null, 2)
2140
+ }
2141
+ ],
2142
+ isError: true,
2143
+ structuredContent: errRes
2144
+ };
2145
+ }
2146
+ }
2147
+ );
2148
+ server.registerTool(
2149
+ "sqlite_audit_restore_backup",
2150
+ {
2151
+ title: "Restore Audit Backup",
2152
+ 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.",
2153
+ inputSchema: z.object({
2154
+ filename: z.string().default("").describe("Snapshot filename to restore from"),
2155
+ dryRun: z.unknown().optional().describe("If true, returns the DDL without executing it (boolean)")
2156
+ }),
2157
+ outputSchema: AuditRestoreBackupOutputSchema,
2158
+ annotations: {
2159
+ readOnlyHint: false,
2160
+ destructiveHint: true,
2161
+ idempotentHint: false,
2162
+ openWorldHint: false
2163
+ }
2164
+ },
2165
+ async (args) => {
2166
+ const authCtx = getAuthContext();
2167
+ if (authCtx && !scopesGrantToolAccess(authCtx.scopes, "sqlite_audit_restore_backup")) {
2168
+ throw new InsufficientScopeError(["admin", "full"], authCtx.scopes);
2169
+ }
2170
+ let filename;
2171
+ let dryRun;
2172
+ try {
2173
+ const parsed = z.object({
2174
+ filename: z.string().min(1, "filename is required"),
2175
+ dryRun: z.boolean().optional().default(false)
2176
+ }).parse(args);
2177
+ filename = parsed.filename;
2178
+ dryRun = parsed.dryRun;
2179
+ } catch (error) {
2180
+ const structured = formatHandlerError(error);
2181
+ return {
2182
+ content: [
2183
+ {
2184
+ type: "text",
2185
+ text: JSON.stringify(structured, null, 2)
2186
+ }
2187
+ ],
2188
+ isError: true,
2189
+ structuredContent: structured
2190
+ };
2191
+ }
2192
+ const snapshot = await backupManager.getSnapshot(filename);
2193
+ if (!snapshot) {
2194
+ const errRes = {
2195
+ success: false,
2196
+ error: `Snapshot not found: ${filename}`
2197
+ };
2198
+ return {
2199
+ content: [
2200
+ {
2201
+ type: "text",
2202
+ text: JSON.stringify(errRes, null, 2)
2203
+ }
2204
+ ],
2205
+ isError: true,
2206
+ structuredContent: errRes
2207
+ };
2208
+ }
2209
+ const ddl = snapshot.ddl ?? "";
2210
+ if (!ddl.trim()) {
2211
+ const errRes = {
2212
+ success: false,
2213
+ error: "Snapshot contains no DDL statements"
2214
+ };
2215
+ return {
2216
+ content: [
2217
+ {
2218
+ type: "text",
2219
+ text: JSON.stringify(errRes, null, 2)
2220
+ }
2221
+ ],
2222
+ isError: true,
2223
+ structuredContent: errRes
2224
+ };
2225
+ }
2226
+ const adapter = [...adaptersMap.values()][0];
2227
+ if (!adapter) {
2228
+ const errRes = {
2229
+ success: false,
2230
+ error: "No connected adapter available"
2231
+ };
2232
+ return {
2233
+ content: [
2234
+ {
2235
+ type: "text",
2236
+ text: JSON.stringify(errRes, null, 2)
2237
+ }
2238
+ ],
2239
+ isError: true,
2240
+ structuredContent: errRes
2241
+ };
2242
+ }
2243
+ if (dryRun) {
2244
+ const result = {
2245
+ success: true,
2246
+ message: "Dry run: no changes applied",
2247
+ dryRun: true,
2248
+ ddl: redactSqlLiterals(ddl)
2249
+ };
2250
+ return {
2251
+ content: [
2252
+ {
2253
+ type: "text",
2254
+ text: JSON.stringify(result, null, 2)
2255
+ }
2256
+ ],
2257
+ structuredContent: result
2258
+ };
2259
+ }
2260
+ try {
2261
+ const statements = ddl.split(";").map((s) => s.trim()).filter((s) => {
2262
+ const cleanSql = s.replace(/\/\*[\s\S]*?\*\//g, "").replace(/--.*$/gm, "").trim();
2263
+ return cleanSql.length > 0;
2264
+ });
2265
+ if (statements.length === 0) {
2266
+ const result2 = {
2267
+ success: true,
2268
+ message: "No executable statements found in snapshot (only comments)",
2269
+ changesApplied: 0
2270
+ };
2271
+ return {
2272
+ content: [
2273
+ {
2274
+ type: "text",
2275
+ text: JSON.stringify(result2, null, 2)
2276
+ }
2277
+ ],
2278
+ structuredContent: result2
2279
+ };
2280
+ }
2281
+ await adapter.executeQuery("BEGIN TRANSACTION;");
2282
+ try {
2283
+ for (const stmt of statements) {
2284
+ validateDdl(stmt);
2285
+ await adapter.executeQuery(`${stmt};`);
2286
+ }
2287
+ await adapter.executeQuery("COMMIT;");
2288
+ } catch (e) {
2289
+ await adapter.executeQuery("ROLLBACK;");
2290
+ throw e;
2291
+ }
2292
+ const result = {
2293
+ success: true,
2294
+ message: `Successfully executed ${statements.length} statement(s) from snapshot`,
2295
+ changesApplied: statements.length
2296
+ };
2297
+ return {
2298
+ content: [
2299
+ {
2300
+ type: "text",
2301
+ text: JSON.stringify(result, null, 2)
2302
+ }
2303
+ ],
2304
+ structuredContent: result
2305
+ };
2306
+ } catch (error) {
2307
+ const errRes = {
2308
+ success: false,
2309
+ error: error instanceof Error ? error.message : String(error)
2310
+ };
2311
+ return {
2312
+ content: [
2313
+ {
2314
+ type: "text",
2315
+ text: JSON.stringify(errRes, null, 2)
2316
+ }
2317
+ ],
2318
+ isError: true,
2319
+ structuredContent: errRes
2320
+ };
2321
+ }
2322
+ }
2323
+ );
2324
+ registerToolScopes(
2325
+ /* @__PURE__ */ new Map([
2326
+ ["sqlite_audit_list_backups", ["admin", "full"]],
2327
+ ["sqlite_audit_get_backup", ["admin", "full"]],
2328
+ ["sqlite_audit_cleanup", ["admin", "full"]],
2329
+ ["sqlite_audit_diff_backup", ["admin", "full"]],
2330
+ ["sqlite_audit_restore_backup", ["admin", "full"]]
2331
+ ])
2332
+ );
2333
+ logger.info(
2334
+ "Registered audit backup tools: sqlite_audit_list_backups, sqlite_audit_get_backup, sqlite_audit_cleanup, sqlite_audit_diff_backup, sqlite_audit_restore_backup",
2335
+ { module: "AUDIT" }
2336
+ );
2337
+ }
2338
+
2339
+ // src/server/mcp-server.ts
2340
+ var proto = McpServer.prototype;
2341
+ if (typeof proto["createToolError"] === "function") {
2342
+ const originalCreateToolError = proto["createToolError"];
2343
+ proto["createToolError"] = function(errorMessage) {
2344
+ const result = originalCreateToolError.call(
2345
+ this,
2346
+ errorMessage
2347
+ );
2348
+ if (result.content?.[0]?.type === "text") {
2349
+ const rawError = result.content[0].text;
2350
+ if (rawError.includes("Input validation error")) {
2351
+ const cleanError = rawError.replace(
2352
+ /^MCP error -32602: Input validation error: /,
2353
+ "Validation error: "
2354
+ );
2355
+ const structured = {
2356
+ success: false,
2357
+ error: cleanError,
2358
+ code: "VALIDATION_ERROR",
2359
+ category: "validation" /* VALIDATION */
2360
+ };
2361
+ result.content[0].text = JSON.stringify(structured, null, 2);
2362
+ result.isError = true;
2363
+ }
2364
+ }
2365
+ return result;
2366
+ };
2367
+ }
1507
2368
  var DbMcpServer = class {
1508
2369
  server;
1509
2370
  adapters = /* @__PURE__ */ new Map();
@@ -1536,8 +2397,35 @@ var DbMcpServer = class {
1536
2397
  toolFilter: config.toolFilter ?? "none",
1537
2398
  capabilities: ["logging"]
1538
2399
  });
1539
- this.registerBuiltInTools();
1540
- this.registerHelpResources();
2400
+ registerBuiltInTools(
2401
+ this.server,
2402
+ this.adapters,
2403
+ this.config,
2404
+ this.toolFilter
2405
+ );
2406
+ registerHelpResources(this.server, this.toolFilter);
2407
+ const internalMcp = this.server;
2408
+ const handlers = internalMcp.server._requestHandlers;
2409
+ if (!handlers?.has("tools/list")) {
2410
+ throw new DbMcpError(
2411
+ "Security: SDK _requestHandlers monkey-patch failed. Scope filtering is disabled.",
2412
+ "SERVER_START_FAILED",
2413
+ "internal" /* INTERNAL */
2414
+ );
2415
+ }
2416
+ const originalListToolsHandler = handlers.get("tools/list");
2417
+ if (originalListToolsHandler) {
2418
+ handlers.set("tools/list", async (request, extra) => {
2419
+ const result = await originalListToolsHandler(request, extra);
2420
+ const authCtx = getAuthContext();
2421
+ if (authCtx && Array.isArray(result.tools)) {
2422
+ result.tools = result.tools.filter(
2423
+ (t) => scopesGrantToolAccess(authCtx.scopes, t.name)
2424
+ );
2425
+ }
2426
+ return result;
2427
+ });
2428
+ }
1541
2429
  if (config.audit?.enabled) {
1542
2430
  this.auditInitPromise = this.initializeAudit(config);
1543
2431
  }
@@ -1554,6 +2442,9 @@ var DbMcpServer = class {
1554
2442
  this.adapters.set(adapterId, adapter);
1555
2443
  if (this.auditInterceptor && "setAuditInterceptor" in adapter) {
1556
2444
  adapter.setAuditInterceptor(this.auditInterceptor);
2445
+ this.auditInterceptor.setQueryAdapter({
2446
+ executeQuery: (sql, params) => adapter.executeReadQuery(sql, params)
2447
+ });
1557
2448
  }
1558
2449
  if (this.backupManager && "setBackupManager" in adapter) {
1559
2450
  adapter.setBackupManager(this.backupManager);
@@ -1561,6 +2452,15 @@ var DbMcpServer = class {
1561
2452
  adapter.registerTools(this.server, this.toolFilter);
1562
2453
  adapter.registerResources(this.server);
1563
2454
  adapter.registerPrompts(this.server);
2455
+ const toolDefs = adapter.getToolDefinitions();
2456
+ const scopesMap = /* @__PURE__ */ new Map();
2457
+ for (const tool of toolDefs) {
2458
+ if (tool.requiredScopes) {
2459
+ scopesMap.set(tool.name, tool.requiredScopes);
2460
+ scopesMap.set(`sqlite_${tool.name}`, tool.requiredScopes);
2461
+ }
2462
+ }
2463
+ registerToolScopes(scopesMap);
1564
2464
  logger.info(`Registered adapter: ${adapter.name} (${adapterId})`, {
1565
2465
  module: "SERVER"
1566
2466
  });
@@ -1577,178 +2477,6 @@ var DbMcpServer = class {
1577
2477
  getAdapters() {
1578
2478
  return this.adapters;
1579
2479
  }
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
2480
  /**
1753
2481
  * Start the server with the configured transport
1754
2482
  */
@@ -1777,12 +2505,16 @@ var DbMcpServer = class {
1777
2505
  logger.info(`db-mcp server started (stdio transport)`, {
1778
2506
  module: "SERVER"
1779
2507
  });
2508
+ logger.warning(
2509
+ "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.",
2510
+ { module: "SERVER", code: "STDIO_ADMIN_RISK" }
2511
+ );
1780
2512
  }
1781
2513
  /**
1782
2514
  * Start server with HTTP transport (Streamable HTTP with SSE support)
1783
2515
  */
1784
2516
  async startHttp() {
1785
- const { HttpTransport } = await import('./http-6KF4ULDI.js');
2517
+ const { HttpTransport } = await import('./http-HWTUVFIA.js');
1786
2518
  const oauthConfig = {
1787
2519
  enabled: this.config.oauth?.enabled ?? false,
1788
2520
  authorizationServerUrl: this.config.oauth?.authorizationServerUrl ?? "",
@@ -1810,12 +2542,13 @@ var DbMcpServer = class {
1810
2542
  enableHSTS: this.config.enableHSTS
1811
2543
  },
1812
2544
  oauth: oauthConfig,
1813
- stateless: this.config.statelessHttp ?? false
2545
+ stateless: this.config.statelessHttp ?? false,
2546
+ noAuthEnforcement: this.config.noAuthEnforcement ?? false
1814
2547
  });
1815
2548
  await transport.initialize(this.server);
1816
2549
  await transport.start();
1817
2550
  const mode = this.config.statelessHttp ? "stateless" : "stateful";
1818
- const host = this.config.host ?? "0.0.0.0";
2551
+ const host = this.config.host ?? "127.0.0.1";
1819
2552
  const port = String(this.config.port ?? 3e3);
1820
2553
  logger.info(
1821
2554
  `db-mcp server started (HTTP transport on ${host}:${port}, ${mode} mode)`,
@@ -1866,179 +2599,17 @@ var DbMcpServer = class {
1866
2599
  }
1867
2600
  this.auditInterceptor = createAuditInterceptor(
1868
2601
  this.auditLogger,
1869
- this.backupManager ?? void 0);
1870
- this.registerAuditResource();
2602
+ this.backupManager ?? void 0
2603
+ );
2604
+ registerAuditResource(this.server, this.auditLogger, this.backupManager);
1871
2605
  if (this.backupManager && this.toolFilter.enabledGroups.has("admin")) {
1872
- this.registerAuditBackupTools();
2606
+ registerAuditBackupTools(this.server, this.backupManager, this.adapters);
1873
2607
  }
1874
2608
  logger.info(
1875
2609
  `Audit logging enabled (${auditConfig.logPath}, redact=${String(auditConfig.redact)}, reads=${String(auditConfig.auditReads)}, backup=${String(!!auditConfig.backup?.enabled)})`,
1876
2610
  { module: "AUDIT" }
1877
2611
  );
1878
2612
  }
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
2613
  };
2043
2614
  function createServer(config) {
2044
2615
  return new DbMcpServer(config);