db-mcp 1.0.2 → 1.1.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/.gitattributes +2 -0
- package/LICENSE +1 -1
- package/README.md +244 -518
- package/dist/chunk-4IA3DB5C.js +135 -0
- package/dist/chunk-AOUL5SHS.js +930 -0
- package/dist/chunk-DWJXQEFA.js +13759 -0
- package/dist/chunk-DZQLDEQS.js +879 -0
- package/dist/chunk-S5IDDSSB.js +74 -0
- package/dist/chunk-Z2GFQU3G.js +363 -0
- package/dist/cli.d.ts +0 -7
- package/dist/cli.js +227 -183
- package/dist/http-VSB7DBJR.js +1541 -0
- package/dist/index.d.ts +842 -10
- package/dist/index.js +5 -17
- package/dist/sqlite-VHBA4ABV.js +600 -0
- package/dist/sqlite-native-D2LH5ZT7.js +2498 -0
- package/dist/worker-script.d.ts +2 -0
- package/dist/worker-script.js +126 -0
- package/package.json +26 -16
- package/playwright.config.ts +101 -0
- package/scripts/generate-server-instructions.ts +111 -0
- package/server.json +5 -6
- package/test-server/README.md +118 -0
- package/test-server/code-map.md +409 -0
- package/test-server/fixtures/sample.csv +6 -0
- package/test-server/reset-database.ps1 +373 -0
- package/test-server/sample.csv +11 -0
- package/test-server/test-agent-experience.md +243 -0
- package/test-server/test-database.sql +388 -0
- package/test-server/test-group-tools.md +861 -0
- package/test-server/test-help-resources.mjs +238 -0
- package/test-server/test-preflight.md +53 -0
- package/test-server/test-prompts.md +354 -0
- package/test-server/test-resources.md +245 -0
- package/test-server/test-tool-annotations.mjs +157 -0
- package/test-server/test-tools-advanced-1.md +517 -0
- package/test-server/test-tools-advanced-2.md +487 -0
- package/test-server/test-tools-codemode.md +629 -0
- package/test-server/test-tools.md +176 -0
- package/test-server/tool-reference.md +236 -0
- package/tsconfig.test.json +9 -0
- package/dist/adapters/DatabaseAdapter.d.ts +0 -141
- package/dist/adapters/DatabaseAdapter.d.ts.map +0 -1
- package/dist/adapters/DatabaseAdapter.js +0 -131
- package/dist/adapters/DatabaseAdapter.js.map +0 -1
- package/dist/adapters/sqlite/SchemaManager.d.ts +0 -58
- package/dist/adapters/sqlite/SchemaManager.d.ts.map +0 -1
- package/dist/adapters/sqlite/SchemaManager.js +0 -187
- package/dist/adapters/sqlite/SchemaManager.js.map +0 -1
- package/dist/adapters/sqlite/SqliteAdapter.d.ts +0 -161
- package/dist/adapters/sqlite/SqliteAdapter.d.ts.map +0 -1
- package/dist/adapters/sqlite/SqliteAdapter.js +0 -741
- package/dist/adapters/sqlite/SqliteAdapter.js.map +0 -1
- package/dist/adapters/sqlite/index.d.ts +0 -9
- package/dist/adapters/sqlite/index.d.ts.map +0 -1
- package/dist/adapters/sqlite/index.js +0 -8
- package/dist/adapters/sqlite/index.js.map +0 -1
- package/dist/adapters/sqlite/json-utils.d.ts +0 -100
- package/dist/adapters/sqlite/json-utils.d.ts.map +0 -1
- package/dist/adapters/sqlite/json-utils.js +0 -274
- package/dist/adapters/sqlite/json-utils.js.map +0 -1
- package/dist/adapters/sqlite/output-schemas.d.ts +0 -1187
- package/dist/adapters/sqlite/output-schemas.d.ts.map +0 -1
- package/dist/adapters/sqlite/output-schemas.js +0 -1337
- package/dist/adapters/sqlite/output-schemas.js.map +0 -1
- package/dist/adapters/sqlite/prompts.d.ts +0 -13
- package/dist/adapters/sqlite/prompts.d.ts.map +0 -1
- package/dist/adapters/sqlite/prompts.js +0 -605
- package/dist/adapters/sqlite/prompts.js.map +0 -1
- package/dist/adapters/sqlite/resources.d.ts +0 -13
- package/dist/adapters/sqlite/resources.d.ts.map +0 -1
- package/dist/adapters/sqlite/resources.js +0 -251
- package/dist/adapters/sqlite/resources.js.map +0 -1
- package/dist/adapters/sqlite/tools/admin.d.ts +0 -14
- package/dist/adapters/sqlite/tools/admin.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/admin.js +0 -788
- package/dist/adapters/sqlite/tools/admin.js.map +0 -1
- package/dist/adapters/sqlite/tools/core.d.ts +0 -25
- package/dist/adapters/sqlite/tools/core.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/core.js +0 -359
- package/dist/adapters/sqlite/tools/core.js.map +0 -1
- package/dist/adapters/sqlite/tools/fts.d.ts +0 -13
- package/dist/adapters/sqlite/tools/fts.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/fts.js +0 -347
- package/dist/adapters/sqlite/tools/fts.js.map +0 -1
- package/dist/adapters/sqlite/tools/geo.d.ts +0 -14
- package/dist/adapters/sqlite/tools/geo.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/geo.js +0 -252
- package/dist/adapters/sqlite/tools/geo.js.map +0 -1
- package/dist/adapters/sqlite/tools/index.d.ts +0 -30
- package/dist/adapters/sqlite/tools/index.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/index.js +0 -61
- package/dist/adapters/sqlite/tools/index.js.map +0 -1
- package/dist/adapters/sqlite/tools/json-helpers.d.ts +0 -14
- package/dist/adapters/sqlite/tools/json-helpers.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/json-helpers.js +0 -477
- package/dist/adapters/sqlite/tools/json-helpers.js.map +0 -1
- package/dist/adapters/sqlite/tools/json-operations.d.ts +0 -14
- package/dist/adapters/sqlite/tools/json-operations.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/json-operations.js +0 -839
- package/dist/adapters/sqlite/tools/json-operations.js.map +0 -1
- package/dist/adapters/sqlite/tools/stats.d.ts +0 -15
- package/dist/adapters/sqlite/tools/stats.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/stats.js +0 -1219
- package/dist/adapters/sqlite/tools/stats.js.map +0 -1
- package/dist/adapters/sqlite/tools/text.d.ts +0 -14
- package/dist/adapters/sqlite/tools/text.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/text.js +0 -1141
- package/dist/adapters/sqlite/tools/text.js.map +0 -1
- package/dist/adapters/sqlite/tools/vector.d.ts +0 -14
- package/dist/adapters/sqlite/tools/vector.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/vector.js +0 -613
- package/dist/adapters/sqlite/tools/vector.js.map +0 -1
- package/dist/adapters/sqlite/tools/virtual.d.ts +0 -13
- package/dist/adapters/sqlite/tools/virtual.d.ts.map +0 -1
- package/dist/adapters/sqlite/tools/virtual.js +0 -930
- package/dist/adapters/sqlite/tools/virtual.js.map +0 -1
- package/dist/adapters/sqlite/types.d.ts +0 -207
- package/dist/adapters/sqlite/types.d.ts.map +0 -1
- package/dist/adapters/sqlite/types.js +0 -186
- package/dist/adapters/sqlite/types.js.map +0 -1
- package/dist/adapters/sqlite-native/NativeSqliteAdapter.d.ts +0 -163
- package/dist/adapters/sqlite-native/NativeSqliteAdapter.d.ts.map +0 -1
- package/dist/adapters/sqlite-native/NativeSqliteAdapter.js +0 -748
- package/dist/adapters/sqlite-native/NativeSqliteAdapter.js.map +0 -1
- package/dist/adapters/sqlite-native/index.d.ts +0 -11
- package/dist/adapters/sqlite-native/index.d.ts.map +0 -1
- package/dist/adapters/sqlite-native/index.js +0 -11
- package/dist/adapters/sqlite-native/index.js.map +0 -1
- package/dist/adapters/sqlite-native/tools/spatialite.d.ts +0 -19
- package/dist/adapters/sqlite-native/tools/spatialite.d.ts.map +0 -1
- package/dist/adapters/sqlite-native/tools/spatialite.js +0 -628
- package/dist/adapters/sqlite-native/tools/spatialite.js.map +0 -1
- package/dist/adapters/sqlite-native/tools/transactions.d.ts +0 -12
- package/dist/adapters/sqlite-native/tools/transactions.d.ts.map +0 -1
- package/dist/adapters/sqlite-native/tools/transactions.js +0 -255
- package/dist/adapters/sqlite-native/tools/transactions.js.map +0 -1
- package/dist/adapters/sqlite-native/tools/window.d.ts +0 -12
- package/dist/adapters/sqlite-native/tools/window.d.ts.map +0 -1
- package/dist/adapters/sqlite-native/tools/window.js +0 -370
- package/dist/adapters/sqlite-native/tools/window.js.map +0 -1
- package/dist/auth/AuthorizationServerDiscovery.d.ts +0 -90
- package/dist/auth/AuthorizationServerDiscovery.d.ts.map +0 -1
- package/dist/auth/AuthorizationServerDiscovery.js +0 -204
- package/dist/auth/AuthorizationServerDiscovery.js.map +0 -1
- package/dist/auth/OAuthResourceServer.d.ts +0 -65
- package/dist/auth/OAuthResourceServer.d.ts.map +0 -1
- package/dist/auth/OAuthResourceServer.js +0 -121
- package/dist/auth/OAuthResourceServer.js.map +0 -1
- package/dist/auth/TokenValidator.d.ts +0 -60
- package/dist/auth/TokenValidator.d.ts.map +0 -1
- package/dist/auth/TokenValidator.js +0 -235
- package/dist/auth/TokenValidator.js.map +0 -1
- package/dist/auth/errors.d.ts +0 -74
- package/dist/auth/errors.d.ts.map +0 -1
- package/dist/auth/errors.js +0 -133
- package/dist/auth/errors.js.map +0 -1
- package/dist/auth/index.d.ts +0 -13
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -15
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/middleware.d.ts +0 -81
- package/dist/auth/middleware.d.ts.map +0 -1
- package/dist/auth/middleware.js +0 -291
- package/dist/auth/middleware.js.map +0 -1
- package/dist/auth/scopes.d.ts +0 -136
- package/dist/auth/scopes.d.ts.map +0 -1
- package/dist/auth/scopes.js +0 -349
- package/dist/auth/scopes.js.map +0 -1
- package/dist/auth/types.d.ts +0 -257
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js +0 -8
- package/dist/auth/types.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/constants/ServerInstructions.d.ts +0 -45
- package/dist/constants/ServerInstructions.d.ts.map +0 -1
- package/dist/constants/ServerInstructions.js +0 -356
- package/dist/constants/ServerInstructions.js.map +0 -1
- package/dist/filtering/ToolConstants.d.ts +0 -34
- package/dist/filtering/ToolConstants.d.ts.map +0 -1
- package/dist/filtering/ToolConstants.js +0 -174
- package/dist/filtering/ToolConstants.js.map +0 -1
- package/dist/filtering/ToolFilter.d.ts +0 -82
- package/dist/filtering/ToolFilter.d.ts.map +0 -1
- package/dist/filtering/ToolFilter.js +0 -296
- package/dist/filtering/ToolFilter.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/server/McpServer.d.ts +0 -61
- package/dist/server/McpServer.d.ts.map +0 -1
- package/dist/server/McpServer.js +0 -270
- package/dist/server/McpServer.js.map +0 -1
- package/dist/transports/http.d.ts +0 -134
- package/dist/transports/http.d.ts.map +0 -1
- package/dist/transports/http.js +0 -516
- package/dist/transports/http.js.map +0 -1
- package/dist/transports/index.d.ts +0 -5
- package/dist/transports/index.d.ts.map +0 -1
- package/dist/transports/index.js +0 -5
- package/dist/transports/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -380
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -68
- package/dist/types/index.js.map +0 -1
- package/dist/utils/annotations.d.ts +0 -44
- package/dist/utils/annotations.d.ts.map +0 -1
- package/dist/utils/annotations.js +0 -77
- package/dist/utils/annotations.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -155
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -329
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/identifiers.d.ts +0 -121
- package/dist/utils/identifiers.d.ts.map +0 -1
- package/dist/utils/identifiers.js +0 -319
- package/dist/utils/identifiers.js.map +0 -1
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -7
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/insightsManager.d.ts +0 -39
- package/dist/utils/insightsManager.d.ts.map +0 -1
- package/dist/utils/insightsManager.js +0 -63
- package/dist/utils/insightsManager.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -189
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -394
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/progress-utils.d.ts +0 -54
- package/dist/utils/progress-utils.d.ts.map +0 -1
- package/dist/utils/progress-utils.js +0 -74
- package/dist/utils/progress-utils.js.map +0 -1
- package/dist/utils/resourceAnnotations.d.ts +0 -36
- package/dist/utils/resourceAnnotations.d.ts.map +0 -1
- package/dist/utils/resourceAnnotations.js +0 -57
- package/dist/utils/resourceAnnotations.js.map +0 -1
- package/dist/utils/where-clause.d.ts +0 -41
- package/dist/utils/where-clause.d.ts.map +0 -1
- package/dist/utils/where-clause.js +0 -116
- package/dist/utils/where-clause.js.map +0 -1
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
import { READ_ONLY, SERVER_ICONS } from './chunk-S5IDDSSB.js';
|
|
2
|
+
import { parseToolFilter, getToolFilterFromEnv, logger, getFilterSummary, DbMcpError } from './chunk-AOUL5SHS.js';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
6
|
+
|
|
7
|
+
var _require = createRequire(import.meta.url);
|
|
8
|
+
var pkg = _require("../package.json");
|
|
9
|
+
var VERSION = pkg.version;
|
|
10
|
+
var NAME = pkg.name;
|
|
11
|
+
|
|
12
|
+
// src/constants/server-instructions.ts
|
|
13
|
+
var INSTRUCTIONS = `# db-mcp (SQLite MCP Server)
|
|
14
|
+
|
|
15
|
+
## Quick Access
|
|
16
|
+
|
|
17
|
+
| Purpose | Action |
|
|
18
|
+
| --------------- | -------------------------- |
|
|
19
|
+
| Health check | \`server_health\` tool |
|
|
20
|
+
| Server info | \`server_info\` tool |
|
|
21
|
+
| Database schema | \`sqlite://schema\` resource |
|
|
22
|
+
| Tool help | \`sqlite://help\` resource |
|
|
23
|
+
|
|
24
|
+
## Built-in Tools
|
|
25
|
+
|
|
26
|
+
\`server_info\`, \`server_health\`, \`list_adapters\` \u2014 always available.
|
|
27
|
+
|
|
28
|
+
## Help Resources
|
|
29
|
+
|
|
30
|
+
Read \`sqlite://help\` for gotchas and critical usage patterns.
|
|
31
|
+
Read \`sqlite://help/{group}\` for group-specific tool reference (json, text, stats, vector, geo, admin, introspection, migration).
|
|
32
|
+
Only help resources for your enabled tool groups are registered.`;
|
|
33
|
+
var HELP_CONTENT = /* @__PURE__ */ new Map([
|
|
34
|
+
[
|
|
35
|
+
"admin",
|
|
36
|
+
`# db-mcp Help \u2014 Database Administration (33 Native / 26 WASM)
|
|
37
|
+
|
|
38
|
+
## Transactions (7 tools, Native only)
|
|
39
|
+
|
|
40
|
+
\`\`\`javascript
|
|
41
|
+
// Atomic multi-statement execution (preferred for simple cases)
|
|
42
|
+
sqlite_transaction_execute({ statements: ["UPDATE a SET x=1", "UPDATE b SET y=2"] });
|
|
43
|
+
|
|
44
|
+
// Manual transaction control
|
|
45
|
+
sqlite_transaction_begin({ mode: "immediate" }); // or "deferred", "exclusive"
|
|
46
|
+
sqlite_transaction_savepoint({ name: "checkpoint" });
|
|
47
|
+
sqlite_transaction_rollback_to({ name: "checkpoint" });
|
|
48
|
+
sqlite_transaction_release({ name: "checkpoint" });
|
|
49
|
+
sqlite_transaction_commit();
|
|
50
|
+
sqlite_transaction_rollback();
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
## Maintenance
|
|
54
|
+
|
|
55
|
+
\`\`\`javascript
|
|
56
|
+
sqlite_integrity_check({ maxErrors: 10 }); // check for corruption
|
|
57
|
+
sqlite_optimize({ analyze: true, reindex: true }); // optimize performance
|
|
58
|
+
sqlite_vacuum(); // reclaim space
|
|
59
|
+
sqlite_analyze({ table: "orders" }); // update statistics for query planner
|
|
60
|
+
sqlite_dbstat({ summarize: true }); // storage stats (\u26A0\uFE0F summarize native-only; WASM returns counts only)
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
## Backup/Restore (Native only)
|
|
64
|
+
|
|
65
|
+
\`\`\`javascript
|
|
66
|
+
sqlite_backup({ targetPath: "/path/to/backup.db" });
|
|
67
|
+
sqlite_verify_backup({ backupPath: "/path/to/backup.db" }); // check integrity without restoring
|
|
68
|
+
sqlite_restore({ sourcePath: "/path/to/backup.db" }); // \u26A0\uFE0F WARNING: Replaces current database
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
## PRAGMA
|
|
72
|
+
|
|
73
|
+
\`\`\`javascript
|
|
74
|
+
sqlite_pragma_settings({ pragma: "journal_mode" }); // get value
|
|
75
|
+
sqlite_pragma_settings({ pragma: "cache_size", value: 10000 }); // set value
|
|
76
|
+
sqlite_pragma_table_info({ table: "users" }); // column details
|
|
77
|
+
sqlite_pragma_compile_options({ filter: "FTS" }); // \u26A0\uFE0F WASM may show FTS3, not FTS5
|
|
78
|
+
sqlite_pragma_database_list(); // list attached databases
|
|
79
|
+
sqlite_pragma_optimize(); // run PRAGMA optimize
|
|
80
|
+
\`\`\`
|
|
81
|
+
|
|
82
|
+
## Index & Stats
|
|
83
|
+
|
|
84
|
+
- \`sqlite_index_stats({ table: "orders" })\` \u2014 stats for explicit indexes
|
|
85
|
+
|
|
86
|
+
## Views
|
|
87
|
+
|
|
88
|
+
\`\`\`javascript
|
|
89
|
+
sqlite_create_view({ viewName: "active_orders", selectQuery: "SELECT * FROM orders WHERE status = 'active'" });
|
|
90
|
+
sqlite_create_view({ viewName: "v", selectQuery: "...", replace: true }); // CREATE OR REPLACE
|
|
91
|
+
sqlite_list_views(); // list all views
|
|
92
|
+
sqlite_drop_view({ viewName: "active_orders" });
|
|
93
|
+
\`\`\`
|
|
94
|
+
|
|
95
|
+
## Virtual Tables
|
|
96
|
+
|
|
97
|
+
\`\`\`javascript
|
|
98
|
+
sqlite_list_virtual_tables(); // list FTS5, R-Tree, CSV tables
|
|
99
|
+
sqlite_virtual_table_info({ tableName: "articles_fts" }); // module and column info
|
|
100
|
+
sqlite_drop_virtual_table({ tableName: "old_fts", ifExists: true });
|
|
101
|
+
\`\`\`
|
|
102
|
+
|
|
103
|
+
## Generate Series (pure JS)
|
|
104
|
+
|
|
105
|
+
\`\`\`javascript
|
|
106
|
+
sqlite_generate_series({ start: 1, stop: 100, step: 5 }); // returns array of values
|
|
107
|
+
// \u26A0\uFE0F Creates a REGULAR table (not virtual) \u2014 use sqlite_drop_table to remove
|
|
108
|
+
sqlite_create_series_table({ tableName: "numbers", start: 1, stop: 1000 });
|
|
109
|
+
\`\`\`
|
|
110
|
+
|
|
111
|
+
## R-Tree (Native only)
|
|
112
|
+
|
|
113
|
+
\`\`\`javascript
|
|
114
|
+
sqlite_create_rtree_table({ tableName: "locations_idx", dimensions: 2 }); // 2D: minX, maxX, minY, maxY
|
|
115
|
+
// Returns graceful error with wasmLimitation: true in WASM
|
|
116
|
+
\`\`\`
|
|
117
|
+
|
|
118
|
+
## CSV Virtual Tables (Native only)
|
|
119
|
+
|
|
120
|
+
\u26A0\uFE0F Requires ABSOLUTE file paths
|
|
121
|
+
|
|
122
|
+
\`\`\`javascript
|
|
123
|
+
sqlite_analyze_csv_schema({ filePath: "/absolute/path/to/data.csv" }); // analyze CSV structure
|
|
124
|
+
sqlite_create_csv_table({ tableName: "csv_data", filePath: "/absolute/path/to/data.csv" });
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
## Business Insights
|
|
128
|
+
|
|
129
|
+
\`\`\`javascript
|
|
130
|
+
sqlite_append_insight({ insight: "Q4 revenue increased 23% YoY" }); // add to memo://insights
|
|
131
|
+
\`\`\``
|
|
132
|
+
],
|
|
133
|
+
[
|
|
134
|
+
"geo",
|
|
135
|
+
`# db-mcp Help \u2014 Geospatial Operations (4 basic + 7 SpatiaLite)
|
|
136
|
+
|
|
137
|
+
## Basic Geo (always available \u2014 Haversine formula)
|
|
138
|
+
|
|
139
|
+
\`\`\`javascript
|
|
140
|
+
sqlite_geo_distance({ lat1: 40.7128, lon1: -74.006, lat2: 34.0522, lon2: -118.2437 }); // returns km
|
|
141
|
+
sqlite_geo_bounding_box({
|
|
142
|
+
table: "stores", latColumn: "lat", lonColumn: "lon",
|
|
143
|
+
minLat: 40, maxLat: 41, minLon: -75, maxLon: -73,
|
|
144
|
+
});
|
|
145
|
+
sqlite_geo_nearby({
|
|
146
|
+
table: "stores", latColumn: "lat", lonColumn: "lon",
|
|
147
|
+
centerLat: 40.7, centerLon: -74, radius: 10, unit: "km",
|
|
148
|
+
});
|
|
149
|
+
sqlite_geo_cluster({ table: "customers", latColumn: "lat", lonColumn: "lon", gridSize: 0.1 });
|
|
150
|
+
\`\`\`
|
|
151
|
+
|
|
152
|
+
## SpatiaLite (7 tools, Native only)
|
|
153
|
+
|
|
154
|
+
\`\`\`javascript
|
|
155
|
+
// Load extension first
|
|
156
|
+
sqlite_spatialite_load(); // \u26A0\uFE0F Required before using other spatial tools
|
|
157
|
+
|
|
158
|
+
// Create spatial table with geometry column
|
|
159
|
+
sqlite_spatialite_create_table({ tableName: "places", geometryColumn: "geom", geometryType: "POINT", srid: 4326 });
|
|
160
|
+
|
|
161
|
+
// Import data (WKT or GeoJSON)
|
|
162
|
+
sqlite_spatialite_import({ tableName: "places", format: "wkt", data: "POINT(-73.99 40.75)", additionalData: { name: "NYC" } });
|
|
163
|
+
sqlite_spatialite_import({ tableName: "places", format: "geojson", data: '{"type":"Point","coordinates":[-73.99,40.75]}' });
|
|
164
|
+
|
|
165
|
+
// Spatial queries (SELECT only)
|
|
166
|
+
sqlite_spatialite_query({ query: "SELECT name, AsText(geom) FROM places WHERE ST_Within(geom, ...)" });
|
|
167
|
+
|
|
168
|
+
// Spatial analysis
|
|
169
|
+
// analysisType: "spatial_extent" | "point_in_polygon" | "nearest_neighbor" | "distance_matrix"
|
|
170
|
+
// \u26A0\uFE0F nearest_neighbor/distance_matrix return CARTESIAN distance (degrees), not geodetic (km/miles)
|
|
171
|
+
// For same source/target table, use excludeSelf: true to avoid self-matches
|
|
172
|
+
sqlite_spatialite_analyze({ analysisType: "spatial_extent", sourceTable: "places", geometryColumn: "geom" });
|
|
173
|
+
sqlite_spatialite_analyze({ analysisType: "nearest_neighbor", sourceTable: "pts", targetTable: "pts", excludeSelf: true });
|
|
174
|
+
|
|
175
|
+
// Geometry transforms
|
|
176
|
+
// buffer: 'distance' = radius; simplify: 'distance' = tolerance (0.0001 for lat/lon)
|
|
177
|
+
// \u26A0\uFE0F Buffer auto-simplifies output by default (tolerance=0.0001). Use simplifyTolerance: 0 to disable
|
|
178
|
+
sqlite_spatialite_transform({ operation: "buffer", geometry1: "POINT(-73.99 40.75)", distance: 0.01 });
|
|
179
|
+
sqlite_spatialite_transform({ operation: "simplify", geometry1: "...", distance: 0.001 });
|
|
180
|
+
|
|
181
|
+
// Spatial index (R-Tree)
|
|
182
|
+
sqlite_spatialite_index({ tableName: "places", geometryColumn: "geom", action: "create" }); // create, drop, or check
|
|
183
|
+
\`\`\``
|
|
184
|
+
],
|
|
185
|
+
[
|
|
186
|
+
"gotchas",
|
|
187
|
+
`# db-mcp Help \u2014 Gotchas & Code Mode
|
|
188
|
+
|
|
189
|
+
## \u26A0\uFE0F Critical Gotchas
|
|
190
|
+
|
|
191
|
+
1. **sqlite_write_query**: \u26D4 Only INSERT/UPDATE/DELETE \u2014 use \`sqlite_read_query\` for SELECT
|
|
192
|
+
2. **Regex patterns**: Double-escape backslashes (\`\\\\\\\\\`) when passing through JSON/MCP
|
|
193
|
+
3. **FTS5 virtual tables**: \`*_fts\` and shadow tables \`*_fts_*\` are hidden from \`sqlite_list_tables\` for cleaner output
|
|
194
|
+
4. **FTS5 boolean logic**: Uses AND by default \u2014 \`"machine learning"\` = rows with BOTH words. Use OR explicitly: \`"machine OR learning"\`
|
|
195
|
+
5. **FTS5 rebuild**: After \`sqlite_fts_create\`, must call \`sqlite_fts_rebuild\` to populate index with existing data
|
|
196
|
+
6. **json_each row multiplication**: Expands arrays to rows \u2014 use \`limit\` param for large arrays
|
|
197
|
+
7. **json_group_object without groupByColumn**: Each row creates a key-value pair; duplicate keys result if key values aren't unique
|
|
198
|
+
8. **allowExpressions**: For column extraction ONLY (e.g., \`json_extract\`), NOT aggregate functions \u2014 use \`aggregateFunction\` param instead
|
|
199
|
+
9. **sqlite_json_normalize_column**: Defaults to \`preserve\` (maintains original format); use \`outputFormat: 'text'\` to force text
|
|
200
|
+
10. **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
|
|
201
|
+
11. **SpatiaLite distances**: \`nearest_neighbor\`/\`distance_matrix\` return CARTESIAN distance (degrees), not geodetic (km/miles)
|
|
202
|
+
12. **SpatiaLite buffer**: Auto-simplifies output by default (tolerance=0.0001). Use \`simplifyTolerance: 0\` to disable
|
|
203
|
+
13. **sqlite_stats_top_n**: Auto-excludes long-content columns (description, body, notes, etc.) when \`selectColumns\` is omitted. Use \`selectColumns\` to override
|
|
204
|
+
14. **CSV virtual tables**: Require ABSOLUTE file paths
|
|
205
|
+
15. **sqlite_create_series_table**: Creates a REGULAR table (not virtual) \u2014 use \`sqlite_drop_table\` to remove
|
|
206
|
+
16. **sqlite_dbstat**: \`summarize\` only works in native; WASM returns counts only
|
|
207
|
+
17. **PRAGMA compile options**: WASM may show FTS3, not FTS5
|
|
208
|
+
|
|
209
|
+
## WASM vs Native
|
|
210
|
+
|
|
211
|
+
| Feature | Native | WASM | Fallback |
|
|
212
|
+
| ------------------------------------------------- | --------------------- | ----------- | ---------------- |
|
|
213
|
+
| FTS5 full-text search | \u2705 | \u274C | None |
|
|
214
|
+
| Transactions (7 tools) | \u2705 | \u274C | None |
|
|
215
|
+
| Window functions (6 tools in stats group) | \u2705 | \u274C | None |
|
|
216
|
+
| SpatiaLite GIS (7 tools; 4 basic geo always work) | \u2705 | \u274C | None |
|
|
217
|
+
| Backup/Restore (3 tools) | \u2705 | \u274C | Graceful error |
|
|
218
|
+
| R-Tree spatial indexing | \u2705 | \u274C | Graceful error |
|
|
219
|
+
| CSV virtual tables | \u2705 | \u274C | Graceful error |
|
|
220
|
+
| generate_series | JS fallback | JS fallback | \u2014 |
|
|
221
|
+
| dbstat | \u2705 native (per-table) | \u274C | JS (counts only) |
|
|
222
|
+
| soundex() | \u2705 native | \u274C | JS |
|
|
223
|
+
|
|
224
|
+
## Code Mode (1 tool)
|
|
225
|
+
|
|
226
|
+
| Tool | Description |
|
|
227
|
+
| --------------------- | ----------------------------------------------------------------- |
|
|
228
|
+
| \`sqlite_execute_code\` | Execute JavaScript in a sandboxed environment with \`sqlite.*\` API |
|
|
229
|
+
|
|
230
|
+
**Usage**: \`sqlite_execute_code({ code: "const tables = await sqlite.core.listTables(); return tables;" })\`
|
|
231
|
+
**Discover**: \`sqlite.help()\` for all groups, \`sqlite.<group>.help()\` for methods.
|
|
232
|
+
**Groups**: \`sqlite.core\`, \`sqlite.json\`, \`sqlite.text\`, \`sqlite.stats\`, \`sqlite.vector\`, \`sqlite.admin\`, \`sqlite.geo\`, \`sqlite.introspection\`, \`sqlite.migration\`
|
|
233
|
+
|
|
234
|
+
## Code Mode API Mapping
|
|
235
|
+
|
|
236
|
+
\`sqlite_group_action\` \u2192 \`sqlite.group.action()\` (group prefixes dropped: \`sqlite_json_insert\` \u2192 \`sqlite.json.insert()\`)
|
|
237
|
+
|
|
238
|
+
**Positional args work**: \`sqlite.core.readQuery("SELECT...")\`, \`sqlite.json.insert("docs", "data", {...})\`
|
|
239
|
+
|
|
240
|
+
**Discovery**: \`sqlite.help()\` returns all groups and methods. \`sqlite.core.help()\`, \`sqlite.json.help()\` for group-specific methods.`
|
|
241
|
+
],
|
|
242
|
+
[
|
|
243
|
+
"introspection",
|
|
244
|
+
`# db-mcp Help \u2014 Schema Introspection (9 tools)
|
|
245
|
+
|
|
246
|
+
All introspection tools are **read-only** \u2014 they query PRAGMAs and sqlite_master, never modify data.
|
|
247
|
+
|
|
248
|
+
## Graph Analysis (3 tools)
|
|
249
|
+
|
|
250
|
+
\`\`\`javascript
|
|
251
|
+
// Build FK dependency graph \u2014 nodesOnly: true for lightweight response (nodes without edges)
|
|
252
|
+
sqlite_dependency_graph({ includeRowCounts: true, excludeSystemTables: true });
|
|
253
|
+
sqlite_dependency_graph({ nodesOnly: true }); // lighter payload
|
|
254
|
+
|
|
255
|
+
// Safe DDL execution order \u2014 "create" = parents first (default), "drop" = children first
|
|
256
|
+
sqlite_topological_sort({ direction: "create", excludeSystemTables: true });
|
|
257
|
+
sqlite_topological_sort({ direction: "drop" }); // safe DROP order
|
|
258
|
+
|
|
259
|
+
// Simulate DELETE/DROP/TRUNCATE impact \u2014 shows affected tables, cascade paths, severity scoring
|
|
260
|
+
sqlite_cascade_simulator({ table: "users", operation: "delete" });
|
|
261
|
+
sqlite_cascade_simulator({ table: "users", operation: "drop", compact: true }); // compact omits path arrays
|
|
262
|
+
\`\`\`
|
|
263
|
+
|
|
264
|
+
## Schema Analysis (3 tools)
|
|
265
|
+
|
|
266
|
+
\`\`\`javascript
|
|
267
|
+
// Full schema in one call \u2014 compact: true omits column details, sections limits scope
|
|
268
|
+
sqlite_schema_snapshot({ sections: ["tables", "indexes"], excludeSystemTables: true });
|
|
269
|
+
sqlite_schema_snapshot({ compact: true }); // lighter payload
|
|
270
|
+
|
|
271
|
+
// Find constraint health issues \u2014 missing PKs, nullable FKs, unindexed FKs
|
|
272
|
+
sqlite_constraint_analysis({ excludeSystemTables: true });
|
|
273
|
+
sqlite_constraint_analysis({ table: "orders", checks: ["missing_pk", "unindexed_fk"] }); // limit scope
|
|
274
|
+
|
|
275
|
+
// Analyze DDL for SQLite-specific risks \u2014 does NOT execute the statements
|
|
276
|
+
sqlite_migration_risks({ statements: ["ALTER TABLE users ADD COLUMN email TEXT", "DROP TABLE old_logs"] });
|
|
277
|
+
\`\`\`
|
|
278
|
+
|
|
279
|
+
## Diagnostics (3 tools)
|
|
280
|
+
|
|
281
|
+
\`\`\`javascript
|
|
282
|
+
// Fragmentation, per-table size breakdown, optimization recommendations
|
|
283
|
+
sqlite_storage_analysis({ includeTableDetails: true, excludeSystemTables: true });
|
|
284
|
+
sqlite_storage_analysis({ limit: 10 }); // top 10 tables only
|
|
285
|
+
|
|
286
|
+
// Audit index effectiveness \u2014 find redundant, missing FK, unindexed large tables
|
|
287
|
+
sqlite_index_audit({ excludeSystemTables: true });
|
|
288
|
+
sqlite_index_audit({ table: "orders", minSeverity: "warning" }); // reduce payload
|
|
289
|
+
|
|
290
|
+
// EXPLAIN QUERY PLAN with scan-type classification and optimization suggestions (SELECT/WITH only)
|
|
291
|
+
sqlite_query_plan({ sql: "SELECT * FROM orders WHERE status = 'active'" });
|
|
292
|
+
\`\`\`
|
|
293
|
+
|
|
294
|
+
## \u26A0\uFE0F Gotchas
|
|
295
|
+
|
|
296
|
+
- \`excludeSystemTables\` defaults to \`true\` \u2014 SpatiaLite system tables are hidden for cleaner output. Pass \`false\` to include them
|
|
297
|
+
- \`sqlite_migration_risks\` analyzes DDL text statically \u2014 it does NOT execute the statements`
|
|
298
|
+
],
|
|
299
|
+
[
|
|
300
|
+
"json",
|
|
301
|
+
`# db-mcp Help \u2014 JSON Operations (23 tools)
|
|
302
|
+
|
|
303
|
+
## Collection & CRUD
|
|
304
|
+
|
|
305
|
+
- \`sqlite_create_json_collection({ tableName, indexes: [{ path: "$.type" }, { path: "$.author" }] })\` \u2014 creates table with JSON indexes
|
|
306
|
+
- \`sqlite_json_insert({ table, column, data: { type: "article", title: "Hello", tags: ["news"] } })\` \u2014 insert JSON document
|
|
307
|
+
- \`sqlite_json_select({ table, column, extractPaths? })\` \u2014 select rows, optionally extract specific JSON paths
|
|
308
|
+
- \`sqlite_json_update({ table, column, path, value, whereClause })\` \u2014 update value at JSON path
|
|
309
|
+
- \`sqlite_json_query({ table, column, filterPaths: { "$.type": "article" }, selectPaths: ["$.title"] })\` \u2014 query with path-based filters and projections
|
|
310
|
+
|
|
311
|
+
## Path Operations
|
|
312
|
+
|
|
313
|
+
- \`sqlite_json_extract({ table, column, path: "$.title" })\` \u2014 extract value at path. Returns null if path doesn't exist
|
|
314
|
+
- \`sqlite_json_set({ table, column, path: "$.views", value: 100, whereClause: "id = 1" })\` \u2014 set value at path (creates if missing)
|
|
315
|
+
- \`sqlite_json_merge({ table, column, mergeData: { featured: true }, whereClause: "id = 1" })\` \u2014 merge object into existing JSON
|
|
316
|
+
- \`sqlite_json_remove({ table, column, path, whereClause })\` \u2014 remove key at path
|
|
317
|
+
- \`sqlite_json_validate_path({ path: "$.store.books[0].title" })\` \u2014 validate JSON path syntax without executing a query
|
|
318
|
+
- \`sqlite_json_type({ table, column, path })\` \u2014 get JSON type (null, true, false, integer, real, text, array, object)
|
|
319
|
+
|
|
320
|
+
## Array Operations
|
|
321
|
+
|
|
322
|
+
\u26A0\uFE0F \`json_each\` multiplies output rows \u2014 use \`limit\` param for large arrays
|
|
323
|
+
|
|
324
|
+
- \`sqlite_json_array_append({ table, column, path: "$.tags", value: "featured", whereClause: "id = 1" })\` \u2014 append to array
|
|
325
|
+
- \`sqlite_json_array_length({ table, column, path })\` \u2014 get array length
|
|
326
|
+
- \`sqlite_json_each({ table, column, path: "$.tags", limit: 50 })\` \u2014 expand array to rows
|
|
327
|
+
|
|
328
|
+
## Aggregation & Analysis
|
|
329
|
+
|
|
330
|
+
\`\`\`javascript
|
|
331
|
+
// Regular tables: use column names directly
|
|
332
|
+
sqlite_json_group_array({ table: "events", valueColumn: "user_id", groupByColumn: "event_type" });
|
|
333
|
+
|
|
334
|
+
// JSON collections: use allowExpressions with json_extract for both columns
|
|
335
|
+
// \u26A0\uFE0F allowExpressions is for column extraction ONLY, NOT aggregate functions
|
|
336
|
+
// \u26A0\uFE0F Without groupByColumn, each row creates a key-value pair; duplicate keys if values aren't unique
|
|
337
|
+
sqlite_json_group_array({
|
|
338
|
+
table: "docs",
|
|
339
|
+
valueColumn: "json_extract(data, '$.author')",
|
|
340
|
+
groupByColumn: "json_extract(data, '$.type')",
|
|
341
|
+
allowExpressions: true,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// For aggregate values (COUNT, SUM, AVG), use aggregateFunction parameter instead
|
|
345
|
+
sqlite_json_group_object({ table: "events", keyColumn: "event_type", aggregateFunction: "COUNT(*)" });
|
|
346
|
+
sqlite_json_group_object({ table: "orders", keyColumn: "status", aggregateFunction: "SUM(total)" });
|
|
347
|
+
\`\`\`
|
|
348
|
+
|
|
349
|
+
- \`sqlite_json_keys({ table, column, path? })\` \u2014 get distinct keys of JSON objects
|
|
350
|
+
- \`sqlite_json_pretty({ table, column, whereClause? })\` \u2014 format JSON with indentation
|
|
351
|
+
- \`sqlite_json_valid({ table, column })\` \u2014 check if values are valid JSON
|
|
352
|
+
- \`sqlite_json_analyze_schema({ table, column })\` \u2014 infer schema types
|
|
353
|
+
|
|
354
|
+
## JSONB Optimization (SQLite 3.45+)
|
|
355
|
+
|
|
356
|
+
- \`sqlite_json_storage_info({ table, column })\` \u2014 check text vs JSONB format
|
|
357
|
+
- \`sqlite_jsonb_convert({ table, column })\` \u2014 convert to JSONB for faster queries
|
|
358
|
+
- \`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`
|
|
359
|
+
],
|
|
360
|
+
[
|
|
361
|
+
"migration",
|
|
362
|
+
`# db-mcp Help \u2014 Migration Tracking (6 tools)
|
|
363
|
+
|
|
364
|
+
\u26A0\uFE0F Must call \`sqlite_migration_init()\` before using any other migration tool \u2014 it creates the tracking table.
|
|
365
|
+
|
|
366
|
+
\`\`\`javascript
|
|
367
|
+
// Initialize tracking table (idempotent \u2014 safe to call multiple times)
|
|
368
|
+
sqlite_migration_init();
|
|
369
|
+
|
|
370
|
+
// Apply migration: executes SQL and records atomically. If SQL fails, no record is created
|
|
371
|
+
// SHA-256 dedup \u2014 submitting the same SQL twice is rejected as a duplicate
|
|
372
|
+
sqlite_migration_apply({
|
|
373
|
+
version: "2024-01-15-add-users",
|
|
374
|
+
description: "Create users table",
|
|
375
|
+
migrationSql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE)",
|
|
376
|
+
rollbackSql: "DROP TABLE users",
|
|
377
|
+
sourceSystem: "agent",
|
|
378
|
+
appliedBy: "claude",
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Record externally-applied migration (does NOT execute the SQL)
|
|
382
|
+
sqlite_migration_record({
|
|
383
|
+
version: "2024-01-10-initial",
|
|
384
|
+
description: "Initial schema (pre-existing)",
|
|
385
|
+
migrationSql: "CREATE TABLE orders (...)",
|
|
386
|
+
sourceSystem: "manual",
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// Rollback by ID or version \u2014 requires rollbackSql to have been recorded
|
|
390
|
+
sqlite_migration_rollback({ version: "2024-01-15-add-users" });
|
|
391
|
+
sqlite_migration_rollback({ id: 3, dryRun: true }); // preview SQL without executing
|
|
392
|
+
|
|
393
|
+
// Query history with filters and pagination
|
|
394
|
+
sqlite_migration_history({ status: "applied", limit: 10 });
|
|
395
|
+
sqlite_migration_history({ sourceSystem: "agent", compact: true }); // compact omits hash and source system
|
|
396
|
+
|
|
397
|
+
// Summary: latest version, counts by status, unique source systems
|
|
398
|
+
sqlite_migration_status();
|
|
399
|
+
\`\`\`
|
|
400
|
+
|
|
401
|
+
## \u26A0\uFE0F Gotchas
|
|
402
|
+
|
|
403
|
+
- Rollback requires \`rollbackSql\` to have been provided when the migration was recorded/applied
|
|
404
|
+
- Migration group is **opt-in** \u2014 not included in any shortcut except \`dev-schema\` and \`full\``
|
|
405
|
+
],
|
|
406
|
+
[
|
|
407
|
+
"stats",
|
|
408
|
+
`# db-mcp Help \u2014 Statistical Analysis (13 core + 6 window)
|
|
409
|
+
|
|
410
|
+
## Core Statistics (always available)
|
|
411
|
+
|
|
412
|
+
\`\`\`javascript
|
|
413
|
+
sqlite_stats_basic({ table: "employees", column: "salary" }); // count, sum, avg, min, max
|
|
414
|
+
sqlite_stats_count({ table: "orders", column: "status", distinct: true }); // count rows, optionally distinct
|
|
415
|
+
sqlite_stats_group_by({ table: "orders", column: "total", groupBy: "status" }); // aggregate by group
|
|
416
|
+
sqlite_stats_percentile({ table: "sales", column: "revenue", percentiles: [25, 50, 75, 90] });
|
|
417
|
+
sqlite_stats_histogram({ table: "products", column: "price", buckets: 10 });
|
|
418
|
+
sqlite_stats_correlation({ table: "data", column1: "x", column2: "y" }); // Pearson coefficient
|
|
419
|
+
sqlite_stats_distinct({ table: "orders", column: "status" }); // distinct values
|
|
420
|
+
sqlite_stats_summary({ table: "data", columns: ["price", "quantity", "discount"] }); // multi-column summary
|
|
421
|
+
sqlite_stats_frequency({ table: "orders", column: "status" }); // frequency distribution
|
|
422
|
+
sqlite_stats_regression({ table: "data", xColumn: "year", yColumn: "revenue" }); // linear
|
|
423
|
+
sqlite_stats_regression({ table: "data", xColumn: "year", yColumn: "revenue", degree: 2 }); // quadratic
|
|
424
|
+
sqlite_stats_outliers({ table: "sales", column: "amount", method: "iqr" }); // or "zscore". Use maxOutliers to limit payload
|
|
425
|
+
sqlite_stats_hypothesis({ table: "samples", column: "value", testType: "ttest_one", expectedMean: 100 });
|
|
426
|
+
\`\`\`
|
|
427
|
+
|
|
428
|
+
\u26A0\uFE0F \`sqlite_stats_top_n\` \u2014 always use \`selectColumns\` to avoid returning all columns (large payloads with text fields):
|
|
429
|
+
|
|
430
|
+
\`\`\`javascript
|
|
431
|
+
sqlite_stats_top_n({
|
|
432
|
+
table: "products",
|
|
433
|
+
column: "price",
|
|
434
|
+
n: 10,
|
|
435
|
+
selectColumns: ["id", "name", "price"],
|
|
436
|
+
});
|
|
437
|
+
\`\`\`
|
|
438
|
+
|
|
439
|
+
## Window Functions (6 tools, Native only)
|
|
440
|
+
|
|
441
|
+
\`\`\`javascript
|
|
442
|
+
sqlite_window_row_number({ table: "employees", orderBy: "hire_date", partitionBy: "department" });
|
|
443
|
+
sqlite_window_rank({ table: "sales", orderBy: "revenue DESC", partitionBy: "region", rankType: "dense_rank" });
|
|
444
|
+
sqlite_window_lag_lead({ table: "sales", orderBy: "date", column: "revenue", partitionBy: "region" }); // access previous/next row values
|
|
445
|
+
sqlite_window_running_total({ table: "transactions", column: "amount", orderBy: "date" });
|
|
446
|
+
sqlite_window_moving_avg({ table: "stock_prices", column: "close_price", orderBy: "date", windowSize: 7 });
|
|
447
|
+
sqlite_window_ntile({ table: "employees", orderBy: "salary DESC", buckets: 4, partitionBy: "department" }); // quartiles
|
|
448
|
+
\`\`\``
|
|
449
|
+
],
|
|
450
|
+
[
|
|
451
|
+
"text",
|
|
452
|
+
`# db-mcp Help \u2014 Text Processing & FTS5
|
|
453
|
+
|
|
454
|
+
## Full-Text Search / FTS5 (4 tools, Native only)
|
|
455
|
+
|
|
456
|
+
\`\`\`javascript
|
|
457
|
+
// Create FTS5 table with triggers for auto-sync on future changes
|
|
458
|
+
sqlite_fts_create({ tableName: "articles_fts", sourceTable: "articles", columns: ["title", "content"] });
|
|
459
|
+
sqlite_fts_rebuild({ table: "articles_fts" }); // \u26A0\uFE0F Required: populate index with existing data
|
|
460
|
+
|
|
461
|
+
// FTS5 uses AND by default: "machine learning" = rows containing BOTH words
|
|
462
|
+
// Use OR explicitly: "machine OR learning" for rows containing EITHER word
|
|
463
|
+
sqlite_fts_search({ table: "articles_fts", query: "machine learning", limit: 10 });
|
|
464
|
+
sqlite_fts_match_info({ table: "articles_fts", query: "machine learning" }); // bm25 ranking info
|
|
465
|
+
\`\`\`
|
|
466
|
+
|
|
467
|
+
\u26A0\uFE0F FTS5 virtual tables (\`*_fts\`) and shadow tables (\`*_fts_*\`) are hidden from \`sqlite_list_tables\` for cleaner output
|
|
468
|
+
|
|
469
|
+
## Text Processing (13 tools)
|
|
470
|
+
|
|
471
|
+
\`\`\`javascript
|
|
472
|
+
// Regex patterns: \u26A0\uFE0F Double-escape backslashes (\\\\) when passing through JSON/MCP
|
|
473
|
+
sqlite_regex_match({ table: "logs", column: "message", pattern: "ERROR:\\\\\\\\s+(\\\\\\\\w+)" });
|
|
474
|
+
sqlite_regex_extract({ table: "users", column: "email", pattern: "@([a-zA-Z0-9.-]+)", groupIndex: 1 });
|
|
475
|
+
|
|
476
|
+
// Text manipulation
|
|
477
|
+
sqlite_text_split({ table: "users", column: "email", delimiter: "@" }); // split into parts array
|
|
478
|
+
sqlite_text_concat({ table: "users", columns: ["first_name", "last_name"], separator: " " });
|
|
479
|
+
sqlite_text_replace({ table: "docs", column: "content", search: "old", replacement: "new" });
|
|
480
|
+
sqlite_text_trim({ table: "users", column: "name" }); // trim whitespace
|
|
481
|
+
sqlite_text_case({ table: "products", column: "name", mode: "upper" }); // or "lower"
|
|
482
|
+
sqlite_text_substring({ table: "codes", column: "value", start: 1, length: 3 }); // extract substring
|
|
483
|
+
sqlite_text_normalize({ table: "docs", column: "content", mode: "strip_accents" }); // or nfc, nfd, nfkc, nfkd
|
|
484
|
+
|
|
485
|
+
// Validation patterns: email, phone, url, uuid, ipv4, custom
|
|
486
|
+
sqlite_text_validate({ table: "users", column: "email", pattern: "email" });
|
|
487
|
+
sqlite_text_validate({ table: "data", column: "field", pattern: "custom", customPattern: "^[A-Z]{2}[0-9]{4}$" });
|
|
488
|
+
|
|
489
|
+
// Fuzzy matching \u2014 matches WORD TOKENS by default (not entire value)
|
|
490
|
+
// "laptop" matches "Laptop Pro 15" (distance 0 on first token). Use tokenize: false for full-string matching.
|
|
491
|
+
sqlite_fuzzy_match({ table: "products", column: "name", search: "laptop", maxDistance: 2 });
|
|
492
|
+
sqlite_fuzzy_match({ table: "products", column: "name", search: "laptob", maxDistance: 2, tokenize: false }); // full value
|
|
493
|
+
|
|
494
|
+
// Phonetic matching \u2014 finds words that sound alike (matches against any word in value)
|
|
495
|
+
// Use includeRowData: false for lighter payloads when only matching values are needed
|
|
496
|
+
sqlite_phonetic_match({ table: "products", column: "name", search: "laptop", algorithm: "soundex" });
|
|
497
|
+
sqlite_phonetic_match({ table: "products", column: "name", search: "laptop", includeRowData: false }); // lighter
|
|
498
|
+
|
|
499
|
+
// Advanced search \u2014 combines exact, fuzzy, and phonetic techniques
|
|
500
|
+
// fuzzyThreshold: 0.3-0.4 = loose matching (more results), 0.6-0.8 = strict matching (fewer results)
|
|
501
|
+
sqlite_advanced_search({
|
|
502
|
+
table: "products", column: "name", searchTerm: "laptop",
|
|
503
|
+
techniques: ["exact", "fuzzy", "phonetic"], fuzzyThreshold: 0.4,
|
|
504
|
+
});
|
|
505
|
+
\`\`\``
|
|
506
|
+
],
|
|
507
|
+
[
|
|
508
|
+
"vector",
|
|
509
|
+
`# db-mcp Help \u2014 Vector/Semantic Search (11 tools)
|
|
510
|
+
|
|
511
|
+
\`\`\`javascript
|
|
512
|
+
// Create vector table with metadata columns
|
|
513
|
+
sqlite_vector_create_table({ tableName: "docs", dimensions: 384, additionalColumns: [{ name: "content", type: "TEXT" }] });
|
|
514
|
+
|
|
515
|
+
// Store vectors (single and batch)
|
|
516
|
+
sqlite_vector_store({ table: "docs", idColumn: "id", vectorColumn: "emb", id: 1, vector: [...] });
|
|
517
|
+
sqlite_vector_batch_store({ table: "docs", idColumn: "id", vectorColumn: "emb", items: [{ id: 1, vector: [...] }, { id: 2, vector: [...] }] });
|
|
518
|
+
|
|
519
|
+
// Search vectors (returnColumns omits vector data from results for smaller payloads)
|
|
520
|
+
sqlite_vector_search({ table: "docs", vectorColumn: "emb", queryVector: [...], limit: 10, returnColumns: ["id", "title"] });
|
|
521
|
+
|
|
522
|
+
// Retrieve and delete vectors
|
|
523
|
+
// Note: sqlite_vector_get returns parsed 'vector' array + raw JSON string in 'metadata' for flexibility
|
|
524
|
+
sqlite_vector_get({ table: "docs", idColumn: "id", vectorColumn: "emb", id: 1 });
|
|
525
|
+
sqlite_vector_delete({ table: "docs", idColumn: "id", ids: [1, 2, 3] });
|
|
526
|
+
|
|
527
|
+
// Vector metadata
|
|
528
|
+
sqlite_vector_count({ table: "docs" }); // or with dimensions filter: { table: "docs", dimensions: 384 }
|
|
529
|
+
sqlite_vector_dimensions({ table: "docs", vectorColumn: "emb" });
|
|
530
|
+
sqlite_vector_stats({ table: "docs", vectorColumn: "emb" }); // magnitude min/max/avg
|
|
531
|
+
|
|
532
|
+
// Utility tools for preprocessing
|
|
533
|
+
sqlite_vector_normalize({ vector: [3, 4, 0, 0] }); // returns unit vector [0.6, 0.8, 0, 0]
|
|
534
|
+
sqlite_vector_distance({ vector1: [...], vector2: [...], metric: "cosine" }); // or "euclidean", "dot"
|
|
535
|
+
\`\`\``
|
|
536
|
+
]
|
|
537
|
+
]);
|
|
538
|
+
|
|
539
|
+
// src/server/mcp-server.ts
|
|
540
|
+
var DbMcpServer = class {
|
|
541
|
+
server;
|
|
542
|
+
adapters = /* @__PURE__ */ new Map();
|
|
543
|
+
toolFilter;
|
|
544
|
+
config;
|
|
545
|
+
constructor(config) {
|
|
546
|
+
this.config = config;
|
|
547
|
+
this.toolFilter = config.toolFilter ? parseToolFilter(config.toolFilter) : getToolFilterFromEnv();
|
|
548
|
+
this.server = new McpServer(
|
|
549
|
+
{
|
|
550
|
+
name: config.name,
|
|
551
|
+
version: config.version
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
capabilities: {
|
|
555
|
+
logging: {}
|
|
556
|
+
},
|
|
557
|
+
instructions: INSTRUCTIONS
|
|
558
|
+
}
|
|
559
|
+
);
|
|
560
|
+
logger.info(getFilterSummary(this.toolFilter), { module: "FILTER" });
|
|
561
|
+
logger.info("MCP Server initialized", {
|
|
562
|
+
module: "SERVER",
|
|
563
|
+
name: config.name,
|
|
564
|
+
version: config.version,
|
|
565
|
+
toolFilter: config.toolFilter ?? "none",
|
|
566
|
+
capabilities: ["logging"]
|
|
567
|
+
});
|
|
568
|
+
this.registerBuiltInTools();
|
|
569
|
+
this.registerHelpResources();
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Register a database adapter
|
|
573
|
+
*/
|
|
574
|
+
async registerAdapter(adapter, config) {
|
|
575
|
+
const adapterId = `${adapter.type}:${config.connectionString ?? "default"}`;
|
|
576
|
+
await adapter.connect(config);
|
|
577
|
+
this.adapters.set(adapterId, adapter);
|
|
578
|
+
adapter.registerTools(this.server, this.toolFilter);
|
|
579
|
+
adapter.registerResources(this.server);
|
|
580
|
+
adapter.registerPrompts(this.server);
|
|
581
|
+
logger.info(`Registered adapter: ${adapter.name} (${adapterId})`, {
|
|
582
|
+
module: "SERVER"
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Get an adapter by ID
|
|
587
|
+
*/
|
|
588
|
+
getAdapter(adapterId) {
|
|
589
|
+
return this.adapters.get(adapterId);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Get all registered adapters
|
|
593
|
+
*/
|
|
594
|
+
getAdapters() {
|
|
595
|
+
return this.adapters;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Register built-in server tools (health, info, etc.)
|
|
599
|
+
*/
|
|
600
|
+
registerBuiltInTools() {
|
|
601
|
+
const serverInfoOpts = {
|
|
602
|
+
title: "Server Info",
|
|
603
|
+
description: "Get information about the db-mcp server and registered adapters",
|
|
604
|
+
icons: SERVER_ICONS,
|
|
605
|
+
annotations: READ_ONLY
|
|
606
|
+
};
|
|
607
|
+
this.server.registerTool(
|
|
608
|
+
"server_info",
|
|
609
|
+
serverInfoOpts,
|
|
610
|
+
() => {
|
|
611
|
+
const adapterInfo = [];
|
|
612
|
+
for (const [id, adapter] of this.adapters) {
|
|
613
|
+
adapterInfo.push({
|
|
614
|
+
id,
|
|
615
|
+
...adapter.getInfo()
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
content: [
|
|
620
|
+
{
|
|
621
|
+
type: "text",
|
|
622
|
+
text: JSON.stringify(
|
|
623
|
+
{
|
|
624
|
+
name: this.config.name,
|
|
625
|
+
version: this.config.version,
|
|
626
|
+
transport: this.config.transport,
|
|
627
|
+
adapters: adapterInfo,
|
|
628
|
+
toolFilter: {
|
|
629
|
+
raw: this.toolFilter.raw,
|
|
630
|
+
enabledGroups: [...this.toolFilter.enabledGroups]
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
null,
|
|
634
|
+
2
|
|
635
|
+
)
|
|
636
|
+
}
|
|
637
|
+
]
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
const healthOpts = {
|
|
642
|
+
title: "Server Health",
|
|
643
|
+
description: "Check health status of all database connections",
|
|
644
|
+
icons: SERVER_ICONS,
|
|
645
|
+
annotations: READ_ONLY
|
|
646
|
+
};
|
|
647
|
+
this.server.registerTool(
|
|
648
|
+
"server_health",
|
|
649
|
+
healthOpts,
|
|
650
|
+
async () => {
|
|
651
|
+
const health = {
|
|
652
|
+
server: "healthy",
|
|
653
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
654
|
+
adapters: {}
|
|
655
|
+
};
|
|
656
|
+
for (const [id, adapter] of this.adapters) {
|
|
657
|
+
try {
|
|
658
|
+
const adapterHealth = await adapter.getHealth();
|
|
659
|
+
health["adapters"][id] = adapterHealth;
|
|
660
|
+
} catch (error) {
|
|
661
|
+
health["adapters"][id] = {
|
|
662
|
+
connected: false,
|
|
663
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
content: [
|
|
669
|
+
{
|
|
670
|
+
type: "text",
|
|
671
|
+
text: JSON.stringify(health, null, 2)
|
|
672
|
+
}
|
|
673
|
+
]
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
);
|
|
677
|
+
const listAdaptersOpts = {
|
|
678
|
+
title: "List Adapters",
|
|
679
|
+
description: "List all registered database adapters",
|
|
680
|
+
icons: SERVER_ICONS,
|
|
681
|
+
annotations: READ_ONLY
|
|
682
|
+
};
|
|
683
|
+
this.server.registerTool(
|
|
684
|
+
"list_adapters",
|
|
685
|
+
listAdaptersOpts,
|
|
686
|
+
() => {
|
|
687
|
+
const adapters = [];
|
|
688
|
+
for (const [id, adapter] of this.adapters) {
|
|
689
|
+
adapters.push({
|
|
690
|
+
id,
|
|
691
|
+
type: adapter.type,
|
|
692
|
+
name: adapter.name,
|
|
693
|
+
version: adapter.version,
|
|
694
|
+
connected: adapter.isConnected()
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
return {
|
|
698
|
+
content: [
|
|
699
|
+
{
|
|
700
|
+
type: "text",
|
|
701
|
+
text: JSON.stringify(adapters, null, 2)
|
|
702
|
+
}
|
|
703
|
+
]
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Register sqlite://help resources for on-demand reference documentation.
|
|
710
|
+
* Always registers sqlite://help (gotchas). Group-specific help is filtered
|
|
711
|
+
* by the tool filter configuration.
|
|
712
|
+
*/
|
|
713
|
+
registerHelpResources() {
|
|
714
|
+
const gotchasContent = HELP_CONTENT.get("gotchas");
|
|
715
|
+
if (gotchasContent) {
|
|
716
|
+
this.server.registerResource(
|
|
717
|
+
"sqlite_help",
|
|
718
|
+
"sqlite://help",
|
|
719
|
+
{
|
|
720
|
+
description: "Critical gotchas, WASM vs Native comparison, and Code Mode API reference",
|
|
721
|
+
mimeType: "text/markdown"
|
|
722
|
+
},
|
|
723
|
+
() => ({
|
|
724
|
+
contents: [
|
|
725
|
+
{
|
|
726
|
+
uri: "sqlite://help",
|
|
727
|
+
mimeType: "text/markdown",
|
|
728
|
+
text: gotchasContent
|
|
729
|
+
}
|
|
730
|
+
]
|
|
731
|
+
})
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
const groupHelpKeys = [
|
|
735
|
+
{ group: "json", key: "json" },
|
|
736
|
+
{ group: "text", key: "text" },
|
|
737
|
+
{ group: "stats", key: "stats" },
|
|
738
|
+
{ group: "vector", key: "vector" },
|
|
739
|
+
{ group: "geo", key: "geo" },
|
|
740
|
+
{ group: "admin", key: "admin" },
|
|
741
|
+
{ group: "introspection", key: "introspection" },
|
|
742
|
+
{ group: "migration", key: "migration" }
|
|
743
|
+
];
|
|
744
|
+
for (const { group, key } of groupHelpKeys) {
|
|
745
|
+
if (!this.toolFilter.enabledGroups.has(group)) continue;
|
|
746
|
+
const content = HELP_CONTENT.get(key);
|
|
747
|
+
if (!content) continue;
|
|
748
|
+
this.server.registerResource(
|
|
749
|
+
`sqlite_help_${key}`,
|
|
750
|
+
`sqlite://help/${key}`,
|
|
751
|
+
{
|
|
752
|
+
description: `Tool reference for the ${group} tool group`,
|
|
753
|
+
mimeType: "text/markdown"
|
|
754
|
+
},
|
|
755
|
+
() => ({
|
|
756
|
+
contents: [
|
|
757
|
+
{
|
|
758
|
+
uri: `sqlite://help/${key}`,
|
|
759
|
+
mimeType: "text/markdown",
|
|
760
|
+
text: content
|
|
761
|
+
}
|
|
762
|
+
]
|
|
763
|
+
})
|
|
764
|
+
);
|
|
765
|
+
}
|
|
766
|
+
const registeredHelp = ["sqlite://help"];
|
|
767
|
+
for (const { group, key } of groupHelpKeys) {
|
|
768
|
+
if (this.toolFilter.enabledGroups.has(group)) {
|
|
769
|
+
registeredHelp.push(`sqlite://help/${key}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
logger.info(`Help resources: ${registeredHelp.join(", ")}`, {
|
|
773
|
+
module: "SERVER"
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Start the server with the configured transport
|
|
778
|
+
*/
|
|
779
|
+
async start() {
|
|
780
|
+
switch (this.config.transport) {
|
|
781
|
+
case "stdio":
|
|
782
|
+
await this.startStdio();
|
|
783
|
+
break;
|
|
784
|
+
case "http":
|
|
785
|
+
await this.startHttp();
|
|
786
|
+
break;
|
|
787
|
+
default:
|
|
788
|
+
throw new DbMcpError(
|
|
789
|
+
`Unsupported transport: ${this.config.transport}`,
|
|
790
|
+
"SERVER_START_FAILED",
|
|
791
|
+
"config" /* CONFIGURATION */
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Start server with stdio transport
|
|
797
|
+
*/
|
|
798
|
+
async startStdio() {
|
|
799
|
+
const transport = new StdioServerTransport();
|
|
800
|
+
await this.server.connect(transport);
|
|
801
|
+
logger.info(`db-mcp server started (stdio transport)`, {
|
|
802
|
+
module: "SERVER"
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Start server with HTTP transport (Streamable HTTP with SSE support)
|
|
807
|
+
*/
|
|
808
|
+
async startHttp() {
|
|
809
|
+
const { HttpTransport } = await import('./http-VSB7DBJR.js');
|
|
810
|
+
const oauthConfig = {
|
|
811
|
+
enabled: this.config.oauth?.enabled ?? false,
|
|
812
|
+
authorizationServerUrl: this.config.oauth?.authorizationServerUrl ?? "",
|
|
813
|
+
audience: this.config.oauth?.audience ?? this.config.name
|
|
814
|
+
};
|
|
815
|
+
if (this.config.oauth?.issuer !== void 0) {
|
|
816
|
+
oauthConfig.issuer = this.config.oauth.issuer;
|
|
817
|
+
}
|
|
818
|
+
if (this.config.oauth?.jwksUri !== void 0) {
|
|
819
|
+
oauthConfig.jwksUri = this.config.oauth.jwksUri;
|
|
820
|
+
}
|
|
821
|
+
if (this.config.oauth?.clockTolerance !== void 0) {
|
|
822
|
+
oauthConfig.clockTolerance = this.config.oauth.clockTolerance;
|
|
823
|
+
}
|
|
824
|
+
if (this.config.oauth?.publicPaths !== void 0) {
|
|
825
|
+
oauthConfig.publicPaths = this.config.oauth.publicPaths;
|
|
826
|
+
}
|
|
827
|
+
const transport = new HttpTransport({
|
|
828
|
+
port: this.config.port ?? 3e3,
|
|
829
|
+
...this.config.host !== void 0 && { host: this.config.host },
|
|
830
|
+
...this.config.authToken !== void 0 && {
|
|
831
|
+
authToken: this.config.authToken
|
|
832
|
+
},
|
|
833
|
+
...this.config.enableHSTS !== void 0 && {
|
|
834
|
+
enableHSTS: this.config.enableHSTS
|
|
835
|
+
},
|
|
836
|
+
oauth: oauthConfig,
|
|
837
|
+
stateless: this.config.statelessHttp ?? false
|
|
838
|
+
});
|
|
839
|
+
await transport.initialize(this.server);
|
|
840
|
+
await transport.start();
|
|
841
|
+
const mode = this.config.statelessHttp ? "stateless" : "stateful";
|
|
842
|
+
const host = this.config.host ?? "0.0.0.0";
|
|
843
|
+
const port = String(this.config.port ?? 3e3);
|
|
844
|
+
logger.info(
|
|
845
|
+
`db-mcp server started (HTTP transport on ${host}:${port}, ${mode} mode)`,
|
|
846
|
+
{ module: "TRANSPORT", mode }
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Gracefully shut down the server
|
|
851
|
+
*/
|
|
852
|
+
async shutdown() {
|
|
853
|
+
logger.info("Shutting down db-mcp server...", { module: "SERVER" });
|
|
854
|
+
for (const [id, adapter] of this.adapters) {
|
|
855
|
+
try {
|
|
856
|
+
await adapter.disconnect();
|
|
857
|
+
logger.info(`Disconnected adapter: ${id}`, { module: "SERVER" });
|
|
858
|
+
} catch (error) {
|
|
859
|
+
logger.error(`Error disconnecting adapter ${id}`, {
|
|
860
|
+
module: "SERVER",
|
|
861
|
+
error: error instanceof Error ? error : void 0
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
await this.server.close();
|
|
866
|
+
logger.info("Server shutdown complete", { module: "SERVER" });
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
function createServer(config) {
|
|
870
|
+
return new DbMcpServer(config);
|
|
871
|
+
}
|
|
872
|
+
var DEFAULT_CONFIG = {
|
|
873
|
+
name: NAME,
|
|
874
|
+
version: VERSION,
|
|
875
|
+
transport: "stdio",
|
|
876
|
+
databases: []
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
export { DEFAULT_CONFIG, DbMcpServer, NAME, VERSION, createServer };
|