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.
Files changed (241) hide show
  1. package/.gitattributes +2 -0
  2. package/LICENSE +1 -1
  3. package/README.md +244 -518
  4. package/dist/chunk-4IA3DB5C.js +135 -0
  5. package/dist/chunk-AOUL5SHS.js +930 -0
  6. package/dist/chunk-DWJXQEFA.js +13759 -0
  7. package/dist/chunk-DZQLDEQS.js +879 -0
  8. package/dist/chunk-S5IDDSSB.js +74 -0
  9. package/dist/chunk-Z2GFQU3G.js +363 -0
  10. package/dist/cli.d.ts +0 -7
  11. package/dist/cli.js +227 -183
  12. package/dist/http-VSB7DBJR.js +1541 -0
  13. package/dist/index.d.ts +842 -10
  14. package/dist/index.js +5 -17
  15. package/dist/sqlite-VHBA4ABV.js +600 -0
  16. package/dist/sqlite-native-D2LH5ZT7.js +2498 -0
  17. package/dist/worker-script.d.ts +2 -0
  18. package/dist/worker-script.js +126 -0
  19. package/package.json +26 -16
  20. package/playwright.config.ts +101 -0
  21. package/scripts/generate-server-instructions.ts +111 -0
  22. package/server.json +5 -6
  23. package/test-server/README.md +118 -0
  24. package/test-server/code-map.md +409 -0
  25. package/test-server/fixtures/sample.csv +6 -0
  26. package/test-server/reset-database.ps1 +373 -0
  27. package/test-server/sample.csv +11 -0
  28. package/test-server/test-agent-experience.md +243 -0
  29. package/test-server/test-database.sql +388 -0
  30. package/test-server/test-group-tools.md +861 -0
  31. package/test-server/test-help-resources.mjs +238 -0
  32. package/test-server/test-preflight.md +53 -0
  33. package/test-server/test-prompts.md +354 -0
  34. package/test-server/test-resources.md +245 -0
  35. package/test-server/test-tool-annotations.mjs +157 -0
  36. package/test-server/test-tools-advanced-1.md +517 -0
  37. package/test-server/test-tools-advanced-2.md +487 -0
  38. package/test-server/test-tools-codemode.md +629 -0
  39. package/test-server/test-tools.md +176 -0
  40. package/test-server/tool-reference.md +236 -0
  41. package/tsconfig.test.json +9 -0
  42. package/dist/adapters/DatabaseAdapter.d.ts +0 -141
  43. package/dist/adapters/DatabaseAdapter.d.ts.map +0 -1
  44. package/dist/adapters/DatabaseAdapter.js +0 -131
  45. package/dist/adapters/DatabaseAdapter.js.map +0 -1
  46. package/dist/adapters/sqlite/SchemaManager.d.ts +0 -58
  47. package/dist/adapters/sqlite/SchemaManager.d.ts.map +0 -1
  48. package/dist/adapters/sqlite/SchemaManager.js +0 -187
  49. package/dist/adapters/sqlite/SchemaManager.js.map +0 -1
  50. package/dist/adapters/sqlite/SqliteAdapter.d.ts +0 -161
  51. package/dist/adapters/sqlite/SqliteAdapter.d.ts.map +0 -1
  52. package/dist/adapters/sqlite/SqliteAdapter.js +0 -741
  53. package/dist/adapters/sqlite/SqliteAdapter.js.map +0 -1
  54. package/dist/adapters/sqlite/index.d.ts +0 -9
  55. package/dist/adapters/sqlite/index.d.ts.map +0 -1
  56. package/dist/adapters/sqlite/index.js +0 -8
  57. package/dist/adapters/sqlite/index.js.map +0 -1
  58. package/dist/adapters/sqlite/json-utils.d.ts +0 -100
  59. package/dist/adapters/sqlite/json-utils.d.ts.map +0 -1
  60. package/dist/adapters/sqlite/json-utils.js +0 -274
  61. package/dist/adapters/sqlite/json-utils.js.map +0 -1
  62. package/dist/adapters/sqlite/output-schemas.d.ts +0 -1187
  63. package/dist/adapters/sqlite/output-schemas.d.ts.map +0 -1
  64. package/dist/adapters/sqlite/output-schemas.js +0 -1337
  65. package/dist/adapters/sqlite/output-schemas.js.map +0 -1
  66. package/dist/adapters/sqlite/prompts.d.ts +0 -13
  67. package/dist/adapters/sqlite/prompts.d.ts.map +0 -1
  68. package/dist/adapters/sqlite/prompts.js +0 -605
  69. package/dist/adapters/sqlite/prompts.js.map +0 -1
  70. package/dist/adapters/sqlite/resources.d.ts +0 -13
  71. package/dist/adapters/sqlite/resources.d.ts.map +0 -1
  72. package/dist/adapters/sqlite/resources.js +0 -251
  73. package/dist/adapters/sqlite/resources.js.map +0 -1
  74. package/dist/adapters/sqlite/tools/admin.d.ts +0 -14
  75. package/dist/adapters/sqlite/tools/admin.d.ts.map +0 -1
  76. package/dist/adapters/sqlite/tools/admin.js +0 -788
  77. package/dist/adapters/sqlite/tools/admin.js.map +0 -1
  78. package/dist/adapters/sqlite/tools/core.d.ts +0 -25
  79. package/dist/adapters/sqlite/tools/core.d.ts.map +0 -1
  80. package/dist/adapters/sqlite/tools/core.js +0 -359
  81. package/dist/adapters/sqlite/tools/core.js.map +0 -1
  82. package/dist/adapters/sqlite/tools/fts.d.ts +0 -13
  83. package/dist/adapters/sqlite/tools/fts.d.ts.map +0 -1
  84. package/dist/adapters/sqlite/tools/fts.js +0 -347
  85. package/dist/adapters/sqlite/tools/fts.js.map +0 -1
  86. package/dist/adapters/sqlite/tools/geo.d.ts +0 -14
  87. package/dist/adapters/sqlite/tools/geo.d.ts.map +0 -1
  88. package/dist/adapters/sqlite/tools/geo.js +0 -252
  89. package/dist/adapters/sqlite/tools/geo.js.map +0 -1
  90. package/dist/adapters/sqlite/tools/index.d.ts +0 -30
  91. package/dist/adapters/sqlite/tools/index.d.ts.map +0 -1
  92. package/dist/adapters/sqlite/tools/index.js +0 -61
  93. package/dist/adapters/sqlite/tools/index.js.map +0 -1
  94. package/dist/adapters/sqlite/tools/json-helpers.d.ts +0 -14
  95. package/dist/adapters/sqlite/tools/json-helpers.d.ts.map +0 -1
  96. package/dist/adapters/sqlite/tools/json-helpers.js +0 -477
  97. package/dist/adapters/sqlite/tools/json-helpers.js.map +0 -1
  98. package/dist/adapters/sqlite/tools/json-operations.d.ts +0 -14
  99. package/dist/adapters/sqlite/tools/json-operations.d.ts.map +0 -1
  100. package/dist/adapters/sqlite/tools/json-operations.js +0 -839
  101. package/dist/adapters/sqlite/tools/json-operations.js.map +0 -1
  102. package/dist/adapters/sqlite/tools/stats.d.ts +0 -15
  103. package/dist/adapters/sqlite/tools/stats.d.ts.map +0 -1
  104. package/dist/adapters/sqlite/tools/stats.js +0 -1219
  105. package/dist/adapters/sqlite/tools/stats.js.map +0 -1
  106. package/dist/adapters/sqlite/tools/text.d.ts +0 -14
  107. package/dist/adapters/sqlite/tools/text.d.ts.map +0 -1
  108. package/dist/adapters/sqlite/tools/text.js +0 -1141
  109. package/dist/adapters/sqlite/tools/text.js.map +0 -1
  110. package/dist/adapters/sqlite/tools/vector.d.ts +0 -14
  111. package/dist/adapters/sqlite/tools/vector.d.ts.map +0 -1
  112. package/dist/adapters/sqlite/tools/vector.js +0 -613
  113. package/dist/adapters/sqlite/tools/vector.js.map +0 -1
  114. package/dist/adapters/sqlite/tools/virtual.d.ts +0 -13
  115. package/dist/adapters/sqlite/tools/virtual.d.ts.map +0 -1
  116. package/dist/adapters/sqlite/tools/virtual.js +0 -930
  117. package/dist/adapters/sqlite/tools/virtual.js.map +0 -1
  118. package/dist/adapters/sqlite/types.d.ts +0 -207
  119. package/dist/adapters/sqlite/types.d.ts.map +0 -1
  120. package/dist/adapters/sqlite/types.js +0 -186
  121. package/dist/adapters/sqlite/types.js.map +0 -1
  122. package/dist/adapters/sqlite-native/NativeSqliteAdapter.d.ts +0 -163
  123. package/dist/adapters/sqlite-native/NativeSqliteAdapter.d.ts.map +0 -1
  124. package/dist/adapters/sqlite-native/NativeSqliteAdapter.js +0 -748
  125. package/dist/adapters/sqlite-native/NativeSqliteAdapter.js.map +0 -1
  126. package/dist/adapters/sqlite-native/index.d.ts +0 -11
  127. package/dist/adapters/sqlite-native/index.d.ts.map +0 -1
  128. package/dist/adapters/sqlite-native/index.js +0 -11
  129. package/dist/adapters/sqlite-native/index.js.map +0 -1
  130. package/dist/adapters/sqlite-native/tools/spatialite.d.ts +0 -19
  131. package/dist/adapters/sqlite-native/tools/spatialite.d.ts.map +0 -1
  132. package/dist/adapters/sqlite-native/tools/spatialite.js +0 -628
  133. package/dist/adapters/sqlite-native/tools/spatialite.js.map +0 -1
  134. package/dist/adapters/sqlite-native/tools/transactions.d.ts +0 -12
  135. package/dist/adapters/sqlite-native/tools/transactions.d.ts.map +0 -1
  136. package/dist/adapters/sqlite-native/tools/transactions.js +0 -255
  137. package/dist/adapters/sqlite-native/tools/transactions.js.map +0 -1
  138. package/dist/adapters/sqlite-native/tools/window.d.ts +0 -12
  139. package/dist/adapters/sqlite-native/tools/window.d.ts.map +0 -1
  140. package/dist/adapters/sqlite-native/tools/window.js +0 -370
  141. package/dist/adapters/sqlite-native/tools/window.js.map +0 -1
  142. package/dist/auth/AuthorizationServerDiscovery.d.ts +0 -90
  143. package/dist/auth/AuthorizationServerDiscovery.d.ts.map +0 -1
  144. package/dist/auth/AuthorizationServerDiscovery.js +0 -204
  145. package/dist/auth/AuthorizationServerDiscovery.js.map +0 -1
  146. package/dist/auth/OAuthResourceServer.d.ts +0 -65
  147. package/dist/auth/OAuthResourceServer.d.ts.map +0 -1
  148. package/dist/auth/OAuthResourceServer.js +0 -121
  149. package/dist/auth/OAuthResourceServer.js.map +0 -1
  150. package/dist/auth/TokenValidator.d.ts +0 -60
  151. package/dist/auth/TokenValidator.d.ts.map +0 -1
  152. package/dist/auth/TokenValidator.js +0 -235
  153. package/dist/auth/TokenValidator.js.map +0 -1
  154. package/dist/auth/errors.d.ts +0 -74
  155. package/dist/auth/errors.d.ts.map +0 -1
  156. package/dist/auth/errors.js +0 -133
  157. package/dist/auth/errors.js.map +0 -1
  158. package/dist/auth/index.d.ts +0 -13
  159. package/dist/auth/index.d.ts.map +0 -1
  160. package/dist/auth/index.js +0 -15
  161. package/dist/auth/index.js.map +0 -1
  162. package/dist/auth/middleware.d.ts +0 -81
  163. package/dist/auth/middleware.d.ts.map +0 -1
  164. package/dist/auth/middleware.js +0 -291
  165. package/dist/auth/middleware.js.map +0 -1
  166. package/dist/auth/scopes.d.ts +0 -136
  167. package/dist/auth/scopes.d.ts.map +0 -1
  168. package/dist/auth/scopes.js +0 -349
  169. package/dist/auth/scopes.js.map +0 -1
  170. package/dist/auth/types.d.ts +0 -257
  171. package/dist/auth/types.d.ts.map +0 -1
  172. package/dist/auth/types.js +0 -8
  173. package/dist/auth/types.js.map +0 -1
  174. package/dist/cli.d.ts.map +0 -1
  175. package/dist/cli.js.map +0 -1
  176. package/dist/constants/ServerInstructions.d.ts +0 -45
  177. package/dist/constants/ServerInstructions.d.ts.map +0 -1
  178. package/dist/constants/ServerInstructions.js +0 -356
  179. package/dist/constants/ServerInstructions.js.map +0 -1
  180. package/dist/filtering/ToolConstants.d.ts +0 -34
  181. package/dist/filtering/ToolConstants.d.ts.map +0 -1
  182. package/dist/filtering/ToolConstants.js +0 -174
  183. package/dist/filtering/ToolConstants.js.map +0 -1
  184. package/dist/filtering/ToolFilter.d.ts +0 -82
  185. package/dist/filtering/ToolFilter.d.ts.map +0 -1
  186. package/dist/filtering/ToolFilter.js +0 -296
  187. package/dist/filtering/ToolFilter.js.map +0 -1
  188. package/dist/index.d.ts.map +0 -1
  189. package/dist/index.js.map +0 -1
  190. package/dist/server/McpServer.d.ts +0 -61
  191. package/dist/server/McpServer.d.ts.map +0 -1
  192. package/dist/server/McpServer.js +0 -270
  193. package/dist/server/McpServer.js.map +0 -1
  194. package/dist/transports/http.d.ts +0 -134
  195. package/dist/transports/http.d.ts.map +0 -1
  196. package/dist/transports/http.js +0 -516
  197. package/dist/transports/http.js.map +0 -1
  198. package/dist/transports/index.d.ts +0 -5
  199. package/dist/transports/index.d.ts.map +0 -1
  200. package/dist/transports/index.js +0 -5
  201. package/dist/transports/index.js.map +0 -1
  202. package/dist/types/index.d.ts +0 -380
  203. package/dist/types/index.d.ts.map +0 -1
  204. package/dist/types/index.js +0 -68
  205. package/dist/types/index.js.map +0 -1
  206. package/dist/utils/annotations.d.ts +0 -44
  207. package/dist/utils/annotations.d.ts.map +0 -1
  208. package/dist/utils/annotations.js +0 -77
  209. package/dist/utils/annotations.js.map +0 -1
  210. package/dist/utils/errors.d.ts +0 -155
  211. package/dist/utils/errors.d.ts.map +0 -1
  212. package/dist/utils/errors.js +0 -329
  213. package/dist/utils/errors.js.map +0 -1
  214. package/dist/utils/identifiers.d.ts +0 -121
  215. package/dist/utils/identifiers.d.ts.map +0 -1
  216. package/dist/utils/identifiers.js +0 -319
  217. package/dist/utils/identifiers.js.map +0 -1
  218. package/dist/utils/index.d.ts +0 -7
  219. package/dist/utils/index.d.ts.map +0 -1
  220. package/dist/utils/index.js +0 -7
  221. package/dist/utils/index.js.map +0 -1
  222. package/dist/utils/insightsManager.d.ts +0 -39
  223. package/dist/utils/insightsManager.d.ts.map +0 -1
  224. package/dist/utils/insightsManager.js +0 -63
  225. package/dist/utils/insightsManager.js.map +0 -1
  226. package/dist/utils/logger.d.ts +0 -189
  227. package/dist/utils/logger.d.ts.map +0 -1
  228. package/dist/utils/logger.js +0 -394
  229. package/dist/utils/logger.js.map +0 -1
  230. package/dist/utils/progress-utils.d.ts +0 -54
  231. package/dist/utils/progress-utils.d.ts.map +0 -1
  232. package/dist/utils/progress-utils.js +0 -74
  233. package/dist/utils/progress-utils.js.map +0 -1
  234. package/dist/utils/resourceAnnotations.d.ts +0 -36
  235. package/dist/utils/resourceAnnotations.d.ts.map +0 -1
  236. package/dist/utils/resourceAnnotations.js +0 -57
  237. package/dist/utils/resourceAnnotations.js.map +0 -1
  238. package/dist/utils/where-clause.d.ts +0 -41
  239. package/dist/utils/where-clause.d.ts.map +0 -1
  240. package/dist/utils/where-clause.js +0 -116
  241. package/dist/utils/where-clause.js.map +0 -1
@@ -0,0 +1,629 @@
1
+ # db-mcp Code Mode Test Plan
2
+
3
+ **Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
4
+
5
+ **Step 2:** Conduct an exhaustive test of **Code Mode** (`sqlite_execute_code`) using live MCP tool calls. All tests use the `sqlite_execute_code` tool — never direct tool calls — unless validating a comparison.
6
+
7
+ ## Test Database Schema
8
+
9
+ See [test-tools.md](./test-tools.md#test-server-schema) for full table details (10 tables, ~400 rows).
10
+
11
+ > **Note:** When testing `sqlite_execute_code`, do **not** pass `readonly: true` unless specifically testing read-only filtering. The `readonly` flag makes write methods return `{success: false, code: "CODEMODE_READONLY_VIOLATION"}`.
12
+
13
+ ## Structured Error Response Pattern
14
+
15
+ See [test-tools.md](./test-tools.md#structured-error-response-pattern) — same rules apply. Code Mode errors must return `{success: false, error: "..."}`, never raw MCP errors.
16
+
17
+ ## Reporting Format
18
+
19
+ - ❌ Fail: Tool errors or produces incorrect results (include error message)
20
+ - ⚠️ Issue: Unexpected behavior or improvement opportunity
21
+ - 📦 Payload: Unnecessarily large response that should be optimized — **blocking, equally important as ❌ bugs**. Oversized payloads waste LLM context window tokens and degrade downstream tool-calling quality. Report the response size in KB and suggest a concrete optimization (e.g., filter system tables, add `compact` option, omit empty arrays).
22
+
23
+ ---
24
+
25
+ ## Phase 1: Sandbox Basics (6 tests)
26
+
27
+ Verify the sandbox executes code, returns results, and handles errors correctly.
28
+
29
+ ### 1.1 — Simple return value
30
+
31
+ ```javascript
32
+ // Expected: {success: true, result: 42}
33
+ return 42;
34
+ ```
35
+
36
+ ### 1.2 — String return
37
+
38
+ ```javascript
39
+ return "hello from sandbox";
40
+ ```
41
+
42
+ ### 1.3 — Object return
43
+
44
+ ```javascript
45
+ return { name: "test", values: [1, 2, 3] };
46
+ ```
47
+
48
+ ### 1.4 — Async/await support
49
+
50
+ ```javascript
51
+ const result = await Promise.resolve("async works");
52
+ return result;
53
+ ```
54
+
55
+ ### 1.5 — Runtime error handling
56
+
57
+ ```javascript
58
+ // Expected: {success: false, error containing "not defined" or "not a function"}
59
+ const x = undefinedVariable;
60
+ return x;
61
+ ```
62
+
63
+ ### 1.6 — Empty code
64
+
65
+ Call `sqlite_execute_code` with `code: ""`.
66
+ Expected: `{success: false}` with validation error, not raw MCP error.
67
+
68
+ ---
69
+
70
+ ## Phase 2: API Discoverability (6 tests)
71
+
72
+ Verify `help()` and group-level introspection work correctly.
73
+
74
+ ### 2.1 — Top-level help
75
+
76
+ ```javascript
77
+ return await sqlite.help();
78
+ ```
79
+
80
+ Expected: `{groups: [...], totalMethods: <number>, usage: "..."}` with 9 groups listed.
81
+
82
+ ### 2.2 — Group help (core)
83
+
84
+ ```javascript
85
+ return await sqlite.core.help();
86
+ ```
87
+
88
+ Expected: `{group: "core", methods: [...], examples: [...]}` with methods including `readQuery`, `writeQuery`, `listTables`, `describeTable`, etc.
89
+
90
+ ### 2.3 — Group help (json)
91
+
92
+ ```javascript
93
+ return await sqlite.json.help();
94
+ ```
95
+
96
+ Expected: methods include `extract`, `set`, `insert`, `query`, `analyzeSchema`, etc.
97
+
98
+ ### 2.4 — All groups exist
99
+
100
+ ```javascript
101
+ const groups = [
102
+ "core",
103
+ "json",
104
+ "text",
105
+ "stats",
106
+ "vector",
107
+ "admin",
108
+ "geo",
109
+ "introspection",
110
+ "migration",
111
+ ];
112
+ const results = {};
113
+ for (const g of groups) {
114
+ const h = await sqlite[g].help();
115
+ results[g] = h.methods.length;
116
+ }
117
+ return results;
118
+ ```
119
+
120
+ Expected: All 9 groups return >0 methods.
121
+
122
+ ### 2.5 — Method aliases resolve
123
+
124
+ ```javascript
125
+ // Alias "query" should resolve to "readQuery"
126
+ const r1 = await sqlite.core.query("SELECT 1 AS num");
127
+ const r2 = await sqlite.core.readQuery("SELECT 1 AS num");
128
+ return { aliasResult: r1, canonicalResult: r2 };
129
+ ```
130
+
131
+ Expected: Both return identical results.
132
+
133
+ ### 2.6 — Top-level convenience aliases
134
+
135
+ ```javascript
136
+ // Top-level readQuery, writeQuery, listTables, describeTable should exist
137
+ const tables = await sqlite.listTables();
138
+ return { success: true, tableCount: tables.tables?.length };
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Phase 3: Core Group via Code Mode (6 tests)
144
+
145
+ ### 3.1 — Read query
146
+
147
+ ```javascript
148
+ return await sqlite.core.readQuery({
149
+ query: "SELECT COUNT(*) as cnt FROM test_products",
150
+ });
151
+ ```
152
+
153
+ Expected: `{success: true, rows: [{cnt: 16}]}`
154
+
155
+ ### 3.2 — Positional args
156
+
157
+ ```javascript
158
+ // Positional: readQuery("SELECT ...") should work
159
+ return await sqlite.core.readQuery("SELECT name FROM test_products LIMIT 2");
160
+ ```
161
+
162
+ ### 3.3 — List tables
163
+
164
+ ```javascript
165
+ return await sqlite.core.listTables();
166
+ ```
167
+
168
+ ### 3.4 — Describe table
169
+
170
+ ```javascript
171
+ return await sqlite.core.describeTable("test_products");
172
+ ```
173
+
174
+ ### 3.5 — Write query (temp table)
175
+
176
+ ```javascript
177
+ await sqlite.core.writeQuery(
178
+ "CREATE TABLE temp_cm_test (id INTEGER PRIMARY KEY, value TEXT)",
179
+ );
180
+ await sqlite.core.writeQuery(
181
+ "INSERT INTO temp_cm_test (value) VALUES ('hello')",
182
+ );
183
+ const result = await sqlite.core.readQuery("SELECT * FROM temp_cm_test");
184
+ return result;
185
+ ```
186
+
187
+ ### 3.6 — Get indexes
188
+
189
+ ```javascript
190
+ return await sqlite.core.getIndexes();
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Phase 4: JSON Group via Code Mode (5 tests)
196
+
197
+ ### 4.1 — JSON extract
198
+
199
+ ```javascript
200
+ return await sqlite.json.extract({
201
+ table: "test_jsonb_docs",
202
+ column: "doc",
203
+ path: "$.title",
204
+ });
205
+ ```
206
+
207
+ ### 4.2 — JSON query with filter
208
+
209
+ ```javascript
210
+ return await sqlite.json.query({
211
+ table: "test_jsonb_docs",
212
+ column: "doc",
213
+ filterPaths: { "$.type": "article" },
214
+ });
215
+ ```
216
+
217
+ ### 4.3 — JSON analyze schema
218
+
219
+ ```javascript
220
+ return await sqlite.json.analyzeSchema({
221
+ table: "test_jsonb_docs",
222
+ column: "doc",
223
+ });
224
+ ```
225
+
226
+ ### 4.4 — JSON valid
227
+
228
+ ```javascript
229
+ return await sqlite.json.valid({ json: '{"key": "value"}' });
230
+ ```
231
+
232
+ ### 4.5 — JSON pretty
233
+
234
+ ```javascript
235
+ return await sqlite.json.pretty({ json: '{"a":1,"b":2}' });
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Phase 5: Stats Group via Code Mode (4 tests)
241
+
242
+ ### 5.1 — Basic stats
243
+
244
+ ```javascript
245
+ return await sqlite.stats.statsBasic({
246
+ table: "test_measurements",
247
+ column: "temperature",
248
+ });
249
+ ```
250
+
251
+ ### 5.2 — Histogram
252
+
253
+ ```javascript
254
+ return await sqlite.stats.statsHistogram({
255
+ table: "test_measurements",
256
+ column: "temperature",
257
+ buckets: 5,
258
+ });
259
+ ```
260
+
261
+ ### 5.3 — Correlation
262
+
263
+ ```javascript
264
+ return await sqlite.stats.statsCorrelation({
265
+ table: "test_measurements",
266
+ column1: "temperature",
267
+ column2: "humidity",
268
+ });
269
+ ```
270
+
271
+ ### 5.4 — Top N
272
+
273
+ ```javascript
274
+ return await sqlite.stats.statsTopN({
275
+ table: "test_products",
276
+ column: "price",
277
+ n: 5,
278
+ });
279
+ ```
280
+
281
+ ---
282
+
283
+ ## Phase 6: Text Group via Code Mode (3 tests)
284
+
285
+ ### 6.1 — Regex match
286
+
287
+ ```javascript
288
+ return await sqlite.text.regexMatch({
289
+ table: "test_users",
290
+ column: "email",
291
+ pattern: "@example\\.com$",
292
+ });
293
+ ```
294
+
295
+ ### 6.2 — Fuzzy match
296
+
297
+ ```javascript
298
+ return await sqlite.text.fuzzyMatch({
299
+ table: "test_products",
300
+ column: "name",
301
+ search: "laptop",
302
+ maxDistance: 2,
303
+ });
304
+ ```
305
+
306
+ ### 6.3 — Text case
307
+
308
+ ```javascript
309
+ return await sqlite.text.case({
310
+ table: "test_products",
311
+ column: "name",
312
+ mode: "upper",
313
+ limit: 3,
314
+ });
315
+ ```
316
+
317
+ ---
318
+
319
+ ## Phase 7: Vector Group via Code Mode (4 tests)
320
+
321
+ ### 7.1 — Vector search
322
+
323
+ ```javascript
324
+ // Use first embedding from test_embeddings as query vector
325
+ const first = await sqlite.core.readQuery(
326
+ "SELECT embedding FROM test_embeddings LIMIT 1",
327
+ );
328
+ const vec = JSON.parse(first.rows[0].embedding);
329
+ return await sqlite.vector.search({
330
+ table: "test_embeddings",
331
+ vectorColumn: "embedding",
332
+ queryVector: vec,
333
+ limit: 3,
334
+ });
335
+ ```
336
+
337
+ ### 7.2 — Vector stats
338
+
339
+ ```javascript
340
+ return await sqlite.vector.stats({
341
+ table: "test_embeddings",
342
+ vectorColumn: "embedding",
343
+ });
344
+ ```
345
+
346
+ ### 7.3 — Vector count
347
+
348
+ ```javascript
349
+ return await sqlite.vector.count({ table: "test_embeddings" });
350
+ ```
351
+
352
+ ### 7.4 — Vector dimensions
353
+
354
+ ```javascript
355
+ return await sqlite.vector.dimensions({
356
+ table: "test_embeddings",
357
+ vectorColumn: "embedding",
358
+ });
359
+ ```
360
+
361
+ ---
362
+
363
+ ## Phase 8: Geo, Introspection, Migration via Code Mode (5 tests)
364
+
365
+ ### 8.1 — Geo distance
366
+
367
+ ```javascript
368
+ return await sqlite.geo.distance({
369
+ lat1: 40.7128,
370
+ lon1: -74.006,
371
+ lat2: 34.0522,
372
+ lon2: -118.2437,
373
+ });
374
+ ```
375
+
376
+ ### 8.2 — Geo nearby
377
+
378
+ ```javascript
379
+ return await sqlite.geo.nearby({
380
+ table: "test_locations",
381
+ latColumn: "latitude",
382
+ lonColumn: "longitude",
383
+ centerLat: 40.7,
384
+ centerLon: -74.0,
385
+ radius: 1000,
386
+ });
387
+ ```
388
+
389
+ ### 8.3 — Introspection — dependency graph
390
+
391
+ ```javascript
392
+ return await sqlite.introspection.dependencyGraph();
393
+ ```
394
+
395
+ ### 8.4 — Introspection — schema snapshot
396
+
397
+ ```javascript
398
+ return await sqlite.introspection.schemaSnapshot({ sections: ["tables"] });
399
+ ```
400
+
401
+ ### 8.5 — Migration — init + status
402
+
403
+ ```javascript
404
+ await sqlite.migration.migrationInit();
405
+ return await sqlite.migration.migrationStatus();
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Phase 9: Admin Group via Code Mode (4 tests)
411
+
412
+ ### 9.1 — Integrity check
413
+
414
+ ```javascript
415
+ return await sqlite.admin.integrityCheck({ maxErrors: 5 });
416
+ ```
417
+
418
+ ### 9.2 — Pragma settings
419
+
420
+ ```javascript
421
+ return await sqlite.admin.pragmaSettings({ pragma: "journal_mode" });
422
+ ```
423
+
424
+ ### 9.3 — List views
425
+
426
+ ```javascript
427
+ return await sqlite.admin.listViews();
428
+ ```
429
+
430
+ ### 9.4 — DBSTAT
431
+
432
+ ```javascript
433
+ return await sqlite.admin.dbstat({ table: "test_products" });
434
+ ```
435
+
436
+ ---
437
+
438
+ ## Phase 10: Readonly Mode (5 tests)
439
+
440
+ All tests use `readonly: true`.
441
+
442
+ ### 10.1 — Read operations work in readonly
443
+
444
+ ```javascript
445
+ // readonly: true
446
+ return await sqlite.core.readQuery("SELECT COUNT(*) as cnt FROM test_products");
447
+ ```
448
+
449
+ Expected: `{success: true, rows: [{cnt: 16}]}`
450
+
451
+ ### 10.2 — Write operations blocked in readonly
452
+
453
+ ```javascript
454
+ // readonly: true
455
+ return await sqlite.core.writeQuery(
456
+ "INSERT INTO test_products (name) VALUES ('blocked')",
457
+ );
458
+ ```
459
+
460
+ Expected: `{success: false, code: "CODEMODE_READONLY_VIOLATION"}`
461
+
462
+ ### 10.3 — Read methods still discoverable
463
+
464
+ ```javascript
465
+ // readonly: true
466
+ const help = await sqlite.core.help();
467
+ return {
468
+ hasWriteQuery: help.methods.includes("writeQuery"),
469
+ methods: help.methods,
470
+ };
471
+ ```
472
+
473
+ Expected: `writeQuery` still appears in help (for discoverability) but is guarded.
474
+
475
+ ### 10.4 — Create table blocked
476
+
477
+ ```javascript
478
+ // readonly: true
479
+ return await sqlite.core.writeQuery(
480
+ "CREATE TABLE temp_readonly_test (id INTEGER)",
481
+ );
482
+ ```
483
+
484
+ Expected: `{success: false, code: "CODEMODE_READONLY_VIOLATION"}`
485
+
486
+ ### 10.5 — Stats read-only works
487
+
488
+ ```javascript
489
+ // readonly: true
490
+ return await sqlite.stats.statsBasic({
491
+ table: "test_products",
492
+ column: "price",
493
+ });
494
+ ```
495
+
496
+ Expected: succeeds — stats tools are read-only.
497
+
498
+ ---
499
+
500
+ ## Phase 11: Security & Error Handling (6 tests)
501
+
502
+ ### 11.1 — Blocked pattern (require)
503
+
504
+ ```javascript
505
+ const fs = require("fs");
506
+ return fs.readFileSync("/etc/passwd");
507
+ ```
508
+
509
+ Expected: `{success: false, code: "CODEMODE_VALIDATION_FAILED"}` with suggestion about blocked patterns.
510
+
511
+ ### 11.2 — Blocked pattern (process)
512
+
513
+ ```javascript
514
+ return process.env;
515
+ ```
516
+
517
+ Expected: `{success: false}` — blocked pattern or runtime error.
518
+
519
+ ### 11.3 — Blocked pattern (eval)
520
+
521
+ ```javascript
522
+ return eval("1+1");
523
+ ```
524
+
525
+ Expected: `{success: false, code: "CODEMODE_VALIDATION_FAILED"}`
526
+
527
+ ### 11.4 — Timeout enforcement
528
+
529
+ ```javascript
530
+ // timeout: 2000
531
+ while (true) {}
532
+ ```
533
+
534
+ Call with `timeout: 2000`. Expected: `{success: false}` with timeout error within ~2s.
535
+
536
+ ### 11.5 — Invalid tool call via API
537
+
538
+ ```javascript
539
+ return await sqlite.core.readQuery({ query: "SELECT * FROM nonexistent_xyz" });
540
+ ```
541
+
542
+ Expected: Tool returns `{success: false, error: "..."}` — the sandbox must not crash.
543
+
544
+ ### 11.6 — Empty params to execute_code
545
+
546
+ Call `sqlite_execute_code` with `{}` (no `code` param). Expected: structured handler error, not raw MCP `-32602`.
547
+
548
+ ---
549
+
550
+ ## Phase 12: Multi-Step Workflows (4 tests)
551
+
552
+ ### 12.1 — ETL pipeline
553
+
554
+ ```javascript
555
+ // Create, populate, transform, read
556
+ await sqlite.core.writeQuery(
557
+ "CREATE TABLE temp_cm_etl (id INTEGER PRIMARY KEY, raw TEXT, processed TEXT)",
558
+ );
559
+ for (let i = 1; i <= 5; i++) {
560
+ await sqlite.core.writeQuery({
561
+ query: `INSERT INTO temp_cm_etl (raw) VALUES ('item_${i}')`,
562
+ });
563
+ }
564
+ // Transform
565
+ await sqlite.core.writeQuery("UPDATE temp_cm_etl SET processed = UPPER(raw)");
566
+ return await sqlite.core.readQuery("SELECT * FROM temp_cm_etl");
567
+ ```
568
+
569
+ ### 12.2 — Cross-group analysis
570
+
571
+ ```javascript
572
+ // Use stats + json together
573
+ const stats = await sqlite.stats.statsBasic({
574
+ table: "test_products",
575
+ column: "price",
576
+ });
577
+ const top = await sqlite.stats.statsTopN({
578
+ table: "test_products",
579
+ column: "price",
580
+ n: 3,
581
+ });
582
+ return { priceStats: stats, topProducts: top };
583
+ ```
584
+
585
+ ### 12.3 — Schema introspection + query
586
+
587
+ ```javascript
588
+ // Discover tables, pick first, describe it, query it
589
+ const tables = await sqlite.core.listTables();
590
+ const first = tables.tables[0].name;
591
+ const schema = await sqlite.core.describeTable(first);
592
+ const sample = await sqlite.core.readQuery({
593
+ query: `SELECT * FROM ${first} LIMIT 3`,
594
+ });
595
+ return {
596
+ table: first,
597
+ columnCount: schema.columns?.length,
598
+ sampleRows: sample.rows?.length,
599
+ };
600
+ ```
601
+
602
+ ### 12.4 — Loop with accumulator
603
+
604
+ ```javascript
605
+ const tables = await sqlite.core.listTables();
606
+ const counts = {};
607
+ for (const t of tables.tables.slice(0, 5)) {
608
+ const r = await sqlite.stats.statsCount({ table: t.name });
609
+ counts[t.name] = r.count;
610
+ }
611
+ return counts;
612
+ ```
613
+
614
+ ---
615
+
616
+ ## Cleanup
617
+
618
+ After all phases:
619
+
620
+ ```javascript
621
+ await sqlite.core.writeQuery("DROP TABLE IF EXISTS temp_cm_test");
622
+ await sqlite.core.writeQuery("DROP TABLE IF EXISTS temp_cm_etl");
623
+ ```
624
+
625
+ ---
626
+
627
+ ## Post-Test Procedures
628
+
629
+ See [test-tools.md](./test-tools.md#post-test-procedures) — same workflow: Attempt to remove all `temp_*` tables. If DROP fails due to a database lock, note the leftover tables and move on — they are inert and will be cleaned up on next database regeneration, triage findings, create implementation plan if needed, validate with lint + typecheck, commit without push, live re-test and provide final summary.