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.
- package/README.md +96 -91
- package/dist/.tsbuildinfo +1 -0
- package/dist/adapters/database-adapter.d.ts +173 -0
- package/dist/adapters/database-adapter.d.ts.map +1 -0
- package/dist/adapters/query-validation.d.ts +20 -0
- package/dist/adapters/query-validation.d.ts.map +1 -0
- package/dist/adapters/registration/index.d.ts +4 -0
- package/dist/adapters/registration/index.d.ts.map +1 -0
- package/dist/adapters/registration/prompts.d.ts +7 -0
- package/dist/adapters/registration/prompts.d.ts.map +1 -0
- package/dist/adapters/registration/resources.d.ts +7 -0
- package/dist/adapters/registration/resources.d.ts.map +1 -0
- package/dist/adapters/registration/tools.d.ts +9 -0
- package/dist/adapters/registration/tools.d.ts.map +1 -0
- package/dist/adapters/sqlite/index.d.ts +9 -0
- package/dist/adapters/sqlite/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/json-utils.d.ts +100 -0
- package/dist/adapters/sqlite/json-utils.d.ts.map +1 -0
- package/dist/adapters/sqlite/prompts/analysis.d.ts +23 -0
- package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -0
- package/dist/adapters/sqlite/prompts/index.d.ts +16 -0
- package/dist/adapters/sqlite/prompts/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/prompts/query.d.ts +19 -0
- package/dist/adapters/sqlite/prompts/query.d.ts.map +1 -0
- package/dist/adapters/sqlite/prompts/schema.d.ts +20 -0
- package/dist/adapters/sqlite/prompts/schema.d.ts.map +1 -0
- package/dist/adapters/sqlite/query-executor.d.ts +38 -0
- package/dist/adapters/sqlite/query-executor.d.ts.map +1 -0
- package/dist/adapters/sqlite/resources.d.ts +13 -0
- package/dist/adapters/sqlite/resources.d.ts.map +1 -0
- package/dist/adapters/sqlite/schema-manager.d.ts +69 -0
- package/dist/adapters/sqlite/schema-manager.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/admin.d.ts +459 -0
- package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/codemode.d.ts +30 -0
- package/dist/adapters/sqlite/schemas/codemode.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/common.d.ts +9 -0
- package/dist/adapters/sqlite/schemas/common.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/core.d.ts +530 -0
- package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/error-mixin.d.ts +10 -0
- package/dist/adapters/sqlite/schemas/error-mixin.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/fts.d.ts +106 -0
- package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/geo.d.ts +135 -0
- package/dist/adapters/sqlite/schemas/geo.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/index.d.ts +23 -0
- package/dist/adapters/sqlite/schemas/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/introspection.d.ts +583 -0
- package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/json.d.ts +849 -0
- package/dist/adapters/sqlite/schemas/json.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/migration.d.ts +220 -0
- package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/native.d.ts +235 -0
- package/dist/adapters/sqlite/schemas/native.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/server.d.ts +13 -0
- package/dist/adapters/sqlite/schemas/server.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/spatialite.d.ts +114 -0
- package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/stats.d.ts +780 -0
- package/dist/adapters/sqlite/schemas/stats.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/text.d.ts +570 -0
- package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/vector.d.ts +252 -0
- package/dist/adapters/sqlite/schemas/vector.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/virtual.d.ts +257 -0
- package/dist/adapters/sqlite/schemas/virtual.d.ts.map +1 -0
- package/dist/adapters/sqlite/schemas/where.d.ts +20 -0
- package/dist/adapters/sqlite/schemas/where.d.ts.map +1 -0
- package/dist/adapters/sqlite/sqlite-adapter/lifecycle.d.ts +13 -0
- package/dist/adapters/sqlite/sqlite-adapter/lifecycle.d.ts.map +1 -0
- package/dist/adapters/sqlite/sqlite-adapter/schema.d.ts +7 -0
- package/dist/adapters/sqlite/sqlite-adapter/schema.d.ts.map +1 -0
- package/dist/adapters/sqlite/sqlite-adapter.d.ts +138 -0
- package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/analyze.d.ts +7 -0
- package/dist/adapters/sqlite/tools/admin/backup/analyze.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/create.d.ts +11 -0
- package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts +7 -0
- package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/index.d.ts +7 -0
- package/dist/adapters/sqlite/tools/admin/backup/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/integrity.d.ts +7 -0
- package/dist/adapters/sqlite/tools/admin/backup/integrity.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/optimize.d.ts +7 -0
- package/dist/adapters/sqlite/tools/admin/backup/optimize.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts +7 -0
- package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/helpers.d.ts +18 -0
- package/dist/adapters/sqlite/tools/admin/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/index.d.ts +10 -0
- package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts +37 -0
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/reindex.d.ts +10 -0
- package/dist/adapters/sqlite/tools/admin/reindex.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/verify.d.ts +13 -0
- package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/admin/wal.d.ts +10 -0
- package/dist/adapters/sqlite/tools/admin/wal.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/codemode.d.ts +22 -0
- package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/column-validation.d.ts +26 -0
- package/dist/adapters/sqlite/tools/column-validation.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/alter-table.d.ts +11 -0
- package/dist/adapters/sqlite/tools/core/alter-table.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/constraints.d.ts +10 -0
- package/dist/adapters/sqlite/tools/core/constraints.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/convenience-helpers.d.ts +20 -0
- package/dist/adapters/sqlite/tools/core/convenience-helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/convenience-schemas.d.ts +20 -0
- package/dist/adapters/sqlite/tools/core/convenience-schemas.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/convenience.d.ts +29 -0
- package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/datetime.d.ts +11 -0
- package/dist/adapters/sqlite/tools/core/datetime.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/index.d.ts +14 -0
- package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/indexes.d.ts +20 -0
- package/dist/adapters/sqlite/tools/core/indexes.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/queries.d.ts +16 -0
- package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/tables.d.ts +37 -0
- package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/core/triggers.d.ts +18 -0
- package/dist/adapters/sqlite/tools/core/triggers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/fts.d.ts +13 -0
- package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/geo.d.ts +14 -0
- package/dist/adapters/sqlite/tools/geo.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/index.d.ts +33 -0
- package/dist/adapters/sqlite/tools/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/constraints.d.ts +10 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/constraints.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/diff.d.ts +11 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/diff.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/index.d.ts +10 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/risks.d.ts +9 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/risks.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/snapshot.d.ts +40 -0
- package/dist/adapters/sqlite/tools/introspection/analysis/snapshot.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/index.d.ts +9 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts +10 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/query-plan.d.ts +10 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/query-plan.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/storage.d.ts +10 -0
- package/dist/adapters/sqlite/tools/introspection/diagnostics/storage.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/graph/helpers.d.ts +44 -0
- package/dist/adapters/sqlite/tools/introspection/graph/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/graph/index.d.ts +9 -0
- package/dist/adapters/sqlite/tools/introspection/graph/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts +12 -0
- package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/introspection/index.d.ts +17 -0
- package/dist/adapters/sqlite/tools/introspection/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-helpers/helpers.d.ts +21 -0
- package/dist/adapters/sqlite/tools/json-helpers/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-helpers/index.d.ts +17 -0
- package/dist/adapters/sqlite/tools/json-helpers/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-helpers/read.d.ts +24 -0
- package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-helpers/write.d.ts +24 -0
- package/dist/adapters/sqlite/tools/json-helpers/write.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/crud.d.ts +39 -0
- package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/diff.d.ts +11 -0
- package/dist/adapters/sqlite/tools/json-operations/diff.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/helpers.d.ts +18 -0
- package/dist/adapters/sqlite/tools/json-operations/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/index.d.ts +10 -0
- package/dist/adapters/sqlite/tools/json-operations/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/query.d.ts +24 -0
- package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/security.d.ts +19 -0
- package/dist/adapters/sqlite/tools/json-operations/security.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/json-operations/transform.d.ts +24 -0
- package/dist/adapters/sqlite/tools/json-operations/transform.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/helpers.d.ts +34 -0
- package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/index.d.ts +15 -0
- package/dist/adapters/sqlite/tools/migration/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/apply.d.ts +4 -0
- package/dist/adapters/sqlite/tools/migration/tracking/apply.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/history.d.ts +4 -0
- package/dist/adapters/sqlite/tools/migration/tracking/history.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/index.d.ts +7 -0
- package/dist/adapters/sqlite/tools/migration/tracking/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/init.d.ts +4 -0
- package/dist/adapters/sqlite/tools/migration/tracking/init.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/record.d.ts +4 -0
- package/dist/adapters/sqlite/tools/migration/tracking/record.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/rollback.d.ts +4 -0
- package/dist/adapters/sqlite/tools/migration/tracking/rollback.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/migration/tracking/status.d.ts +4 -0
- package/dist/adapters/sqlite/tools/migration/tracking/status.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/advanced.d.ts +28 -0
- package/dist/adapters/sqlite/tools/stats/advanced.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/anomaly-detection.d.ts +22 -0
- package/dist/adapters/sqlite/tools/stats/anomaly-detection.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/basic.d.ts +32 -0
- package/dist/adapters/sqlite/tools/stats/basic.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/helpers.d.ts +27 -0
- package/dist/adapters/sqlite/tools/stats/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/index.d.ts +12 -0
- package/dist/adapters/sqlite/tools/stats/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/inference/hypothesis.d.ts +7 -0
- package/dist/adapters/sqlite/tools/stats/inference/hypothesis.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/inference/index.d.ts +4 -0
- package/dist/adapters/sqlite/tools/stats/inference/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/inference/outlier.d.ts +7 -0
- package/dist/adapters/sqlite/tools/stats/inference/outlier.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/inference/regression.d.ts +7 -0
- package/dist/adapters/sqlite/tools/stats/inference/regression.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/math-helpers.d.ts +17 -0
- package/dist/adapters/sqlite/tools/stats/math-helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/stats/schema-risks.d.ts +15 -0
- package/dist/adapters/sqlite/tools/stats/schema-risks.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/formatting.d.ts +48 -0
- package/dist/adapters/sqlite/tools/text/formatting.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/helpers.d.ts +22 -0
- package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/index.d.ts +10 -0
- package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/regex.d.ts +21 -0
- package/dist/adapters/sqlite/tools/text/regex.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/search.d.ts +17 -0
- package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/sentiment.d.ts +13 -0
- package/dist/adapters/sqlite/tools/text/sentiment.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/text/validate.d.ts +11 -0
- package/dist/adapters/sqlite/tools/text/validate.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/vector/helpers.d.ts +11 -0
- package/dist/adapters/sqlite/tools/vector/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/vector/index.d.ts +14 -0
- package/dist/adapters/sqlite/tools/vector/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/vector/metadata.d.ts +28 -0
- package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/vector/search.d.ts +16 -0
- package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/vector/storage.d.ts +24 -0
- package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/vector/tools.d.ts +9 -0
- package/dist/adapters/sqlite/tools/vector/tools.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/analysis.d.ts +24 -0
- package/dist/adapters/sqlite/tools/virtual/analysis.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/extensions.d.ts +13 -0
- package/dist/adapters/sqlite/tools/virtual/extensions.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/helpers.d.ts +18 -0
- package/dist/adapters/sqlite/tools/virtual/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/index.d.ts +10 -0
- package/dist/adapters/sqlite/tools/virtual/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/views.d.ts +21 -0
- package/dist/adapters/sqlite/tools/virtual/views.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts +4 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts +4 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/drop.d.ts +4 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/drop.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/index.d.ts +6 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/index.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts +4 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/list.d.ts +4 -0
- package/dist/adapters/sqlite/tools/virtual/vtable/list.d.ts.map +1 -0
- package/dist/adapters/sqlite/types.d.ts +89 -0
- package/dist/adapters/sqlite/types.d.ts.map +1 -0
- package/dist/adapters/sqlite-helpers.d.ts +51 -0
- package/dist/adapters/sqlite-helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/extensions.d.ts +17 -0
- package/dist/adapters/sqlite-native/extensions.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/index.d.ts +11 -0
- package/dist/adapters/sqlite-native/index.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/native-query-executor.d.ts +24 -0
- package/dist/adapters/sqlite-native/native-query-executor.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts +160 -0
- package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/registration/index.d.ts +12 -0
- package/dist/adapters/sqlite-native/registration/index.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/spatialite/analysis.d.ts +23 -0
- package/dist/adapters/sqlite-native/tools/spatialite/analysis.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/spatialite/index.d.ts +15 -0
- package/dist/adapters/sqlite-native/tools/spatialite/index.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/spatialite/loader.d.ts +22 -0
- package/dist/adapters/sqlite-native/tools/spatialite/loader.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/spatialite/schemas.d.ts +78 -0
- package/dist/adapters/sqlite-native/tools/spatialite/schemas.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts +30 -0
- package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/transactions.d.ts +12 -0
- package/dist/adapters/sqlite-native/tools/transactions.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/transaction-methods.d.ts +36 -0
- package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -0
- package/dist/audit/backup-manager.d.ts +90 -0
- package/dist/audit/backup-manager.d.ts.map +1 -0
- package/dist/audit/index.d.ts +11 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/interceptor.d.ts +54 -0
- package/dist/audit/interceptor.d.ts.map +1 -0
- package/dist/audit/logger.d.ts +62 -0
- package/dist/audit/logger.d.ts.map +1 -0
- package/dist/audit/types.d.ts +112 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/auth/auth-context.d.ts +28 -0
- package/dist/auth/auth-context.d.ts.map +1 -0
- package/dist/auth/authorization-server-discovery.d.ts +90 -0
- package/dist/auth/authorization-server-discovery.d.ts.map +1 -0
- package/dist/auth/errors.d.ts +74 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/middleware/core.d.ts +22 -0
- package/dist/auth/middleware/core.d.ts.map +1 -0
- package/dist/auth/middleware/express-auth.d.ts +13 -0
- package/dist/auth/middleware/express-auth.d.ts.map +1 -0
- package/dist/auth/middleware/express-scopes.d.ts +6 -0
- package/dist/auth/middleware/express-scopes.d.ts.map +1 -0
- package/dist/auth/middleware/extraction.d.ts +2 -0
- package/dist/auth/middleware/extraction.d.ts.map +1 -0
- package/dist/auth/middleware/index.d.ts +5 -0
- package/dist/auth/middleware/index.d.ts.map +1 -0
- package/dist/auth/oauth-resource-server.d.ts +74 -0
- package/dist/auth/oauth-resource-server.d.ts.map +1 -0
- package/dist/auth/scope-map.d.ts +24 -0
- package/dist/auth/scope-map.d.ts.map +1 -0
- package/dist/auth/scopes/constants.d.ts +40 -0
- package/dist/auth/scopes/constants.d.ts.map +1 -0
- package/dist/auth/scopes/display.d.ts +5 -0
- package/dist/auth/scopes/display.d.ts.map +1 -0
- package/dist/auth/scopes/enforcement.d.ts +27 -0
- package/dist/auth/scopes/enforcement.d.ts.map +1 -0
- package/dist/auth/scopes/index.d.ts +6 -0
- package/dist/auth/scopes/index.d.ts.map +1 -0
- package/dist/auth/scopes/mapping.d.ts +39 -0
- package/dist/auth/scopes/mapping.d.ts.map +1 -0
- package/dist/auth/scopes/validation.d.ts +27 -0
- package/dist/auth/scopes/validation.d.ts.map +1 -0
- package/dist/auth/token-validator.d.ts +63 -0
- package/dist/auth/token-validator.d.ts.map +1 -0
- package/dist/auth/transport-agnostic.d.ts +11 -0
- package/dist/auth/transport-agnostic.d.ts.map +1 -0
- package/dist/auth/types.d.ts +257 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/chunk-E5IESRTK.js +489 -0
- package/dist/{chunk-5Y42NPBP.js → chunk-FR65YPAH.js} +4657 -1830
- package/dist/{chunk-645ZEFLA.js → chunk-L552U3QS.js} +887 -309
- package/dist/{chunk-WBER5YY4.js → chunk-THATOQRT.js} +1026 -455
- package/dist/{chunk-Z7C2TM4L.js → chunk-W5WQVNVX.js} +169 -57
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +47 -26
- package/dist/codemode/api-constants.d.ts +40 -0
- package/dist/codemode/api-constants.d.ts.map +1 -0
- package/dist/codemode/api.d.ts +70 -0
- package/dist/codemode/api.d.ts.map +1 -0
- package/dist/codemode/auto-return.d.ts +25 -0
- package/dist/codemode/auto-return.d.ts.map +1 -0
- package/dist/codemode/index.d.ts +12 -0
- package/dist/codemode/index.d.ts.map +1 -0
- package/dist/codemode/sandbox-factory.d.ts +72 -0
- package/dist/codemode/sandbox-factory.d.ts.map +1 -0
- package/dist/codemode/sandbox.d.ts +54 -0
- package/dist/codemode/sandbox.d.ts.map +1 -0
- package/dist/codemode/security.d.ts +45 -0
- package/dist/codemode/security.d.ts.map +1 -0
- package/dist/codemode/types.d.ts +167 -0
- package/dist/codemode/types.d.ts.map +1 -0
- package/dist/constants/server-instructions.d.ts +22 -0
- package/dist/constants/server-instructions.d.ts.map +1 -0
- package/dist/filtering/tool-constants.d.ts +45 -0
- package/dist/filtering/tool-constants.d.ts.map +1 -0
- package/dist/filtering/tool-filter.d.ts +82 -0
- package/dist/filtering/tool-filter.d.ts.map +1 -0
- package/dist/{http-6KF4ULDI.js → http-HWTUVFIA.js} +498 -391
- package/dist/index.d.ts +9 -1065
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -6
- package/dist/server/mcp-server.d.ts +66 -0
- package/dist/server/mcp-server.d.ts.map +1 -0
- package/dist/server/registration/audit-tools.d.ts +13 -0
- package/dist/server/registration/audit-tools.d.ts.map +1 -0
- package/dist/server/registration/built-in-tools.d.ts +8 -0
- package/dist/server/registration/built-in-tools.d.ts.map +1 -0
- package/dist/server/registration/help-resources.d.ts +7 -0
- package/dist/server/registration/help-resources.d.ts.map +1 -0
- package/dist/server/registration/index.d.ts +4 -0
- package/dist/server/registration/index.d.ts.map +1 -0
- package/dist/{sqlite-U5KSYQXK.js → sqlite-6C3AJI4I.js} +61 -17
- package/dist/{sqlite-native-JXMCFQBA.js → sqlite-native-ZSSWCTYC.js} +459 -254
- package/dist/transports/http/index.d.ts +8 -0
- package/dist/transports/http/index.d.ts.map +1 -0
- package/dist/transports/http/middleware.d.ts +25 -0
- package/dist/transports/http/middleware.d.ts.map +1 -0
- package/dist/transports/http/oauth.d.ts +24 -0
- package/dist/transports/http/oauth.d.ts.map +1 -0
- package/dist/transports/http/session.d.ts +2 -0
- package/dist/transports/http/session.d.ts.map +1 -0
- package/dist/transports/http/sessions/index.d.ts +4 -0
- package/dist/transports/http/sessions/index.d.ts.map +1 -0
- package/dist/transports/http/sessions/legacy-sse.d.ts +6 -0
- package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -0
- package/dist/transports/http/sessions/mutex.d.ts +6 -0
- package/dist/transports/http/sessions/mutex.d.ts.map +1 -0
- package/dist/transports/http/sessions/stateful.d.ts +12 -0
- package/dist/transports/http/sessions/stateful.d.ts.map +1 -0
- package/dist/transports/http/sessions/stateless.d.ts +6 -0
- package/dist/transports/http/sessions/stateless.d.ts.map +1 -0
- package/dist/transports/http/transport.d.ts +65 -0
- package/dist/transports/http/transport.d.ts.map +1 -0
- package/dist/transports/http/type-adapters.d.ts +20 -0
- package/dist/transports/http/type-adapters.d.ts.map +1 -0
- package/dist/transports/http/types.d.ts +120 -0
- package/dist/transports/http/types.d.ts.map +1 -0
- package/dist/types/adapter.d.ts +138 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/auth.d.ts +79 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/database.d.ts +100 -0
- package/dist/types/database.d.ts.map +1 -0
- package/dist/types/filtering.d.ts +41 -0
- package/dist/types/filtering.d.ts.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/server.d.ts +48 -0
- package/dist/types/server.d.ts.map +1 -0
- package/dist/utils/annotations.d.ts +62 -0
- package/dist/utils/annotations.d.ts.map +1 -0
- package/dist/utils/errors/base.d.ts +33 -0
- package/dist/utils/errors/base.d.ts.map +1 -0
- package/dist/utils/errors/categories.d.ts +41 -0
- package/dist/utils/errors/categories.d.ts.map +1 -0
- package/dist/utils/errors/classes.d.ts +124 -0
- package/dist/utils/errors/classes.d.ts.map +1 -0
- package/dist/utils/errors/error-response-fields.d.ts +24 -0
- package/dist/utils/errors/error-response-fields.d.ts.map +1 -0
- package/dist/utils/errors/format.d.ts +74 -0
- package/dist/utils/errors/format.d.ts.map +1 -0
- package/dist/utils/errors/index.d.ts +11 -0
- package/dist/utils/errors/index.d.ts.map +1 -0
- package/dist/utils/errors/suggestions.d.ts +16 -0
- package/dist/utils/errors/suggestions.d.ts.map +1 -0
- package/dist/utils/icons.d.ts +19 -0
- package/dist/utils/icons.d.ts.map +1 -0
- package/dist/utils/identifiers.d.ts +121 -0
- package/dist/utils/identifiers.d.ts.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/insights-manager.d.ts +39 -0
- package/dist/utils/insights-manager.d.ts.map +1 -0
- package/dist/utils/logger/error-codes.d.ts +48 -0
- package/dist/utils/logger/error-codes.d.ts.map +1 -0
- package/dist/utils/logger/index.d.ts +22 -0
- package/dist/utils/logger/index.d.ts.map +1 -0
- package/dist/utils/logger/logger.d.ts +94 -0
- package/dist/utils/logger/logger.d.ts.map +1 -0
- package/dist/utils/logger/module-logger.d.ts +28 -0
- package/dist/utils/logger/module-logger.d.ts.map +1 -0
- package/dist/utils/logger/types.d.ts +36 -0
- package/dist/utils/logger/types.d.ts.map +1 -0
- package/dist/utils/progress-utils.d.ts +54 -0
- package/dist/utils/progress-utils.d.ts.map +1 -0
- package/dist/utils/redaction.d.ts +4 -0
- package/dist/utils/redaction.d.ts.map +1 -0
- package/dist/utils/resource-annotations.d.ts +36 -0
- package/dist/utils/resource-annotations.d.ts.map +1 -0
- package/dist/utils/validate-json-path.d.ts +43 -0
- package/dist/utils/validate-json-path.d.ts.map +1 -0
- package/dist/utils/validate-path.d.ts +37 -0
- package/dist/utils/validate-path.d.ts.map +1 -0
- package/dist/utils/where-clause.d.ts +42 -0
- package/dist/utils/where-clause.d.ts.map +1 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +25 -13
- package/.gitattributes +0 -2
- package/.gitleaks.toml +0 -9
- package/.trivyignore +0 -8
- package/dist/chunk-OKOVZ5QE.js +0 -28
- package/dist/chunk-SFJQCNG7.js +0 -131
- package/dist/chunk-VIDSICEL.js +0 -85
- package/dist/chunk-X3MUUOWM.js +0 -152
- package/dist/worker-script.d.ts +0 -2
- package/dist/worker-script.js +0 -150
- package/logs/.gitkeep +0 -1
- package/mcp-config-example.json +0 -83
- package/playwright.config.ts +0 -101
- package/scripts/generate-server-instructions.ts +0 -111
- package/scripts/update-badges.ts +0 -99
- package/server.json +0 -54
- package/test-server/README.md +0 -115
- package/test-server/code-map.md +0 -421
- package/test-server/fixtures/sample.csv +0 -6
- package/test-server/reset-database.ps1 +0 -415
- package/test-server/sample.csv +0 -11
- package/test-server/scripts/README.md +0 -27
- package/test-server/scripts/test-help-resources.mjs +0 -245
- package/test-server/scripts/test-prompts.mjs +0 -251
- package/test-server/scripts/test-tool-annotations.mjs +0 -162
- package/test-server/test-advanced/README.md +0 -70
- package/test-server/test-advanced/test-codemode-advanced-admin.md +0 -174
- package/test-server/test-advanced/test-codemode-advanced-core.md +0 -193
- package/test-server/test-advanced/test-codemode-advanced-geo.md +0 -157
- package/test-server/test-advanced/test-codemode-advanced-introspection.md +0 -171
- package/test-server/test-advanced/test-codemode-advanced-json.md +0 -169
- package/test-server/test-advanced/test-codemode-advanced-migration.md +0 -160
- package/test-server/test-advanced/test-codemode-advanced-stats.md +0 -185
- package/test-server/test-advanced/test-codemode-advanced-text.md +0 -183
- package/test-server/test-advanced/test-codemode-advanced-transactions.md +0 -136
- package/test-server/test-advanced/test-codemode-advanced-vector.md +0 -141
- package/test-server/test-codemode/README.md +0 -121
- package/test-server/test-codemode/test-codemode-admin.md +0 -223
- package/test-server/test-codemode/test-codemode-core.md +0 -286
- package/test-server/test-codemode/test-codemode-geo.md +0 -177
- package/test-server/test-codemode/test-codemode-introspection.md +0 -190
- package/test-server/test-codemode/test-codemode-json.md +0 -237
- package/test-server/test-codemode/test-codemode-migration.md +0 -278
- package/test-server/test-codemode/test-codemode-sandbox.md +0 -413
- package/test-server/test-codemode/test-codemode-stats.md +0 -232
- package/test-server/test-codemode/test-codemode-text.md +0 -237
- package/test-server/test-codemode/test-codemode-transactions.md +0 -236
- package/test-server/test-codemode/test-codemode-vector.md +0 -244
- package/test-server/test-codemode/test-codemode-wasm-degradation.md +0 -394
- package/test-server/test-database.sql +0 -424
- package/test-server/test-preflight.md +0 -53
- package/test-server/test-prompts.md +0 -354
- package/test-server/test-resources.md +0 -272
- package/test-server/test-tool-groups/README.md +0 -100
- package/test-server/test-tool-groups/test-admin-core.md +0 -165
- package/test-server/test-tool-groups/test-admin-extensions.md +0 -133
- package/test-server/test-tool-groups/test-core-data.md +0 -262
- package/test-server/test-tool-groups/test-core-schema.md +0 -240
- package/test-server/test-tool-groups/test-geo-haversine.md +0 -130
- package/test-server/test-tool-groups/test-geo-spatialite.md +0 -110
- package/test-server/test-tool-groups/test-introspection-diagnostics.md +0 -123
- package/test-server/test-tool-groups/test-introspection-schema.md +0 -133
- package/test-server/test-tool-groups/test-json-read.md +0 -219
- package/test-server/test-tool-groups/test-json-write.md +0 -157
- package/test-server/test-tool-groups/test-migration.md +0 -193
- package/test-server/test-tool-groups/test-stats-advanced.md +0 -118
- package/test-server/test-tool-groups/test-stats-basic.md +0 -156
- package/test-server/test-tool-groups/test-text-advanced.md +0 -169
- package/test-server/test-tool-groups/test-text-basic.md +0 -177
- package/test-server/test-tool-groups/test-transactions.md +0 -179
- package/test-server/test-tool-groups/test-vector-read.md +0 -130
- package/test-server/test-tool-groups/test-vector-write.md +0 -115
- package/test-server/tool-reference.md +0 -257
- package/tsconfig.build.json +0 -6
- package/tsconfig.test.json +0 -9
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
158
|
-
- \`sqlite_batch_insert({ table: "users",
|
|
159
|
-
- \`sqlite_count({ table: "users",
|
|
160
|
-
- \`sqlite_exists({ table: "users",
|
|
161
|
-
- \`sqlite_truncate({ table: "users" })\` \u2014 quickly delete all rows from a table (executes \`DELETE FROM table\`)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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**:
|
|
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**:
|
|
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 (
|
|
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 (
|
|
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: "
|
|
351
|
-
sqlite_cascade_simulator({ table: "users", operation: "
|
|
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 (
|
|
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,
|
|
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({
|
|
467
|
-
- \`sqlite_json_valid({
|
|
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
|
|
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
|
|
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({
|
|
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
|
-
|
|
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: "
|
|
1055
|
+
sqlite_drop_view: { targetKey: "viewName" },
|
|
1037
1056
|
sqlite_import_csv: { targetKey: "table" },
|
|
1038
|
-
sqlite_backup: { targetKey: "
|
|
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
|
|
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
|
|
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
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
1540
|
-
|
|
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-
|
|
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 ?? "
|
|
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
|
-
|
|
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.
|
|
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);
|