db-mcp 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.gitleaks.toml +9 -0
  2. package/.trivyignore +8 -0
  3. package/README.md +193 -120
  4. package/dist/{chunk-TVIZ3XJH.js → chunk-5Y42NPBP.js} +4168 -2411
  5. package/dist/{chunk-AOUL5SHS.js → chunk-645ZEFLA.js} +70 -20
  6. package/dist/chunk-OKOVZ5QE.js +28 -0
  7. package/dist/chunk-SFJQCNG7.js +131 -0
  8. package/dist/{chunk-FW7UCRLN.js → chunk-VIDSICEL.js} +3 -0
  9. package/dist/chunk-WBER5YY4.js +2053 -0
  10. package/dist/{chunk-4IA3DB5C.js → chunk-X3MUUOWM.js} +19 -2
  11. package/dist/{chunk-Z2GFQU3G.js → chunk-Z7C2TM4L.js} +114 -21
  12. package/dist/cli.js +79 -5
  13. package/dist/{http-VSB7DBJR.js → http-6KF4ULDI.js} +199 -77
  14. package/dist/index.d.ts +231 -8
  15. package/dist/index.js +6 -5
  16. package/dist/{sqlite-26V3Y4MK.js → sqlite-U5KSYQXK.js} +62 -138
  17. package/dist/{sqlite-native-5O7FZJGB.js → sqlite-native-JXMCFQBA.js} +575 -113
  18. package/dist/worker-script.js +34 -10
  19. package/logs/.gitkeep +1 -0
  20. package/mcp-config-example.json +83 -0
  21. package/package.json +9 -8
  22. package/playwright.config.ts +1 -1
  23. package/scripts/update-badges.ts +99 -0
  24. package/server.json +7 -5
  25. package/test-server/README.md +20 -23
  26. package/test-server/code-map.md +45 -33
  27. package/test-server/reset-database.ps1 +59 -17
  28. package/test-server/scripts/README.md +27 -0
  29. package/test-server/{test-help-resources.mjs → scripts/test-help-resources.mjs} +12 -5
  30. package/test-server/scripts/test-prompts.mjs +251 -0
  31. package/test-server/{test-tool-annotations.mjs → scripts/test-tool-annotations.mjs} +9 -4
  32. package/test-server/test-advanced/README.md +70 -0
  33. package/test-server/test-advanced/test-codemode-advanced-admin.md +174 -0
  34. package/test-server/test-advanced/test-codemode-advanced-core.md +193 -0
  35. package/test-server/test-advanced/test-codemode-advanced-geo.md +157 -0
  36. package/test-server/test-advanced/test-codemode-advanced-introspection.md +171 -0
  37. package/test-server/test-advanced/test-codemode-advanced-json.md +169 -0
  38. package/test-server/test-advanced/test-codemode-advanced-migration.md +160 -0
  39. package/test-server/test-advanced/test-codemode-advanced-stats.md +185 -0
  40. package/test-server/test-advanced/test-codemode-advanced-text.md +183 -0
  41. package/test-server/test-advanced/test-codemode-advanced-transactions.md +136 -0
  42. package/test-server/test-advanced/test-codemode-advanced-vector.md +141 -0
  43. package/test-server/test-codemode/README.md +121 -0
  44. package/test-server/test-codemode/test-codemode-admin.md +223 -0
  45. package/test-server/test-codemode/test-codemode-core.md +286 -0
  46. package/test-server/test-codemode/test-codemode-geo.md +177 -0
  47. package/test-server/test-codemode/test-codemode-introspection.md +190 -0
  48. package/test-server/test-codemode/test-codemode-json.md +237 -0
  49. package/test-server/test-codemode/test-codemode-migration.md +278 -0
  50. package/test-server/test-codemode/test-codemode-sandbox.md +413 -0
  51. package/test-server/test-codemode/test-codemode-stats.md +232 -0
  52. package/test-server/test-codemode/test-codemode-text.md +237 -0
  53. package/test-server/test-codemode/test-codemode-transactions.md +236 -0
  54. package/test-server/test-codemode/test-codemode-vector.md +244 -0
  55. package/test-server/test-codemode/test-codemode-wasm-degradation.md +394 -0
  56. package/test-server/test-database.sql +37 -1
  57. package/test-server/test-resources.md +43 -16
  58. package/test-server/test-tool-groups/README.md +100 -0
  59. package/test-server/test-tool-groups/test-admin-core.md +165 -0
  60. package/test-server/test-tool-groups/test-admin-extensions.md +133 -0
  61. package/test-server/{test-tools.md → test-tool-groups/test-core-data.md} +103 -17
  62. package/test-server/test-tool-groups/test-core-schema.md +240 -0
  63. package/test-server/test-tool-groups/test-geo-haversine.md +130 -0
  64. package/test-server/test-tool-groups/test-geo-spatialite.md +110 -0
  65. package/test-server/test-tool-groups/test-introspection-diagnostics.md +123 -0
  66. package/test-server/test-tool-groups/test-introspection-schema.md +133 -0
  67. package/test-server/test-tool-groups/test-json-read.md +219 -0
  68. package/test-server/test-tool-groups/test-json-write.md +157 -0
  69. package/test-server/test-tool-groups/test-migration.md +193 -0
  70. package/test-server/test-tool-groups/test-stats-advanced.md +118 -0
  71. package/test-server/test-tool-groups/test-stats-basic.md +156 -0
  72. package/test-server/test-tool-groups/test-text-advanced.md +169 -0
  73. package/test-server/test-tool-groups/test-text-basic.md +177 -0
  74. package/test-server/test-tool-groups/test-transactions.md +179 -0
  75. package/test-server/test-tool-groups/test-vector-read.md +130 -0
  76. package/test-server/test-tool-groups/test-vector-write.md +115 -0
  77. package/test-server/tool-reference.md +79 -58
  78. package/tsconfig.build.json +6 -0
  79. package/dist/chunk-RHVEZ42P.js +0 -873
  80. package/test-server/test-agent-experience.md +0 -243
  81. package/test-server/test-group-tools.md +0 -861
  82. package/test-server/test-tools-advanced-1.md +0 -517
  83. package/test-server/test-tools-advanced-2.md +0 -487
  84. package/test-server/test-tools-codemode.md +0 -629
@@ -0,0 +1,240 @@
1
+ # db-mcp Tool Group Testing: [core-schema]
2
+
3
+ > [!IMPORTANT]
4
+ > **Do not track progress in this file.** Track your test progress, coverage matrix, and findings in your internal task tracking system (artifact). However, you SHOULD edit this file to fix any factual errors, broken code, or incorrect assertions in the test prompts.
5
+ > If there is nothing to fix, don't update UNRELEASED.md.
6
+ > We're currently testing Native mode.
7
+
8
+ ## WASM Mode
9
+
10
+ > When testing against a **WASM backend** (`sqlite-wasm` / sql.js): All 8 core schema tools are fully WASM-compatible. No items to skip or adjust.
11
+
12
+ **Step 1:** Confirm you read the server help content sourced from `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file` (not grep or search) — to understand documented behaviors, edge cases, and response structures for this tool group.
13
+
14
+ **Step 2:** Please conduct an exhaustive test of the **core-schema** tool group specified in the group-specific checklist below using live MCP server tool calls directly — not scripts/terminal.
15
+
16
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
17
+
18
+ **Note** If temp tables are present from a previous test pass, it's because the database is locked. Ignore them.
19
+
20
+ ## Reporting Format
21
+
22
+ - ❌ Fail: Tool errors or produces incorrect results (include error message)
23
+ - ⚠️ Issue: Unexpected behavior or improvement opportunity
24
+ - 📦 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).
25
+
26
+ ## Test Database Schema
27
+
28
+ The test database (test-server/test.db) contains these tables with JSON-relevant columns:
29
+
30
+ | Table | Rows | Columns | JSON Columns |
31
+ | ----------------- | ---- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
32
+ | test_products | 16 | id, name, description, price, category, created_at | — |
33
+ | test_orders | 20 | id, product_id (FK), customer_name, quantity, total_price, order_date, status | — |
34
+ | test_jsonb_docs | 6 | id, doc, metadata, tags, created_at | **doc**, **metadata** (nested), **tags** (array) |
35
+ | test_articles | 8 | id, title, body, author, category, published_at | — |
36
+ | test_users | 9 | id, username, email, phone, bio, created_at | — |
37
+ | test_measurements | 200 | id, sensor_id, temperature, humidity, pressure, measured_at | — |
38
+ | test_embeddings | 20 | id, content, category, embedding | **embedding** (8-dim float array); category values: database, fitness, food, tech, travel |
39
+ | test_locations | 15 | id, name, city, latitude, longitude, type | — |
40
+ | test_categories | 17 | id, name, path, level | — |
41
+ | test_events | 100 | id, event_type, user_id (INT, 8 values), payload, event_date | **payload** (JSON) |
42
+
43
+ ## Testing Requirements
44
+
45
+ > [!CAUTION]
46
+ > **Zero tolerance for raw MCP errors.** ANY response that is a raw MCP error (e.g., `-32602`, `isError: true`, no `success` field) is a **bug that must be reported and fixed** — never an acceptable design choice, SDK limitation, or expected behavior. If you see one, report it as ❌ immediately. Do not rationalize it as "the SDK rejecting at the boundary" or "by design for range-constrained params." The handler MUST catch it.
47
+
48
+ 1. Use existing `test_*` tables for read operations (SELECT, COUNT, queries)
49
+ 2. Create temporary tables with `temp_*` prefix for write operations
50
+ 3. Test each tool with realistic inputs based on the schema above
51
+ 4. Report all failures, unexpected behaviors, improvement opportunities, or unnecessarily large payloads
52
+ 5. Do not mention what already works well or issues well documented in help resources and runtime hints which are already optimal
53
+ 6. **Error path testing**: For **every** tool, test at least **two** invalid inputs: (a) a domain error (nonexistent table, invalid column, missing required parameter) and (b) a **Zod validation error** (call the tool with `{}` empty params if it has required parameters, or pass the wrong type). Both must return a **structured handler error** (`{success: false, error: "..."}`) — NOT a raw MCP error frame. See the "Structured Error Response Pattern" section below for how to distinguish the two. This is the most common deficiency found across tool groups.
54
+ 7. **Output schema testing**: For **every** tool that has an `outputSchema`, confirm that at least one valid happy-path call returns a structured JSON response — NOT a raw MCP `-32602` "output schema" error. Output schema mismatches (handler returns fields not declared in the schema) produce the same `-32602` code as input errors but are only caught with valid inputs. See "Output Schema Validation Errors" below. Also check for the inverse: if a schema is **defined** in `src/adapters/sqlite/schemas/` but **not wired** to the tool definition, report as ⚠️ — the schema exists but provides no enforcement.
55
+ 8. **Deterministic checklist first**: Complete ALL items in the group-specific checklist before moving to freeform exploration. The checklist uses exact inputs and expected outputs to ensure reproducible coverage every run.
56
+ 9. **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
57
+
58
+ ## Structured Error Response Pattern
59
+
60
+ All tools should return errors as structured objects instead of throwing. A thrown error propagates as a raw MCP error, which is unhelpful to clients. The expected pattern:
61
+
62
+ ```json
63
+ { "success": false, "error": "Human-readable error message" }
64
+ ```
65
+
66
+ ### Handler Error vs MCP Error — How to Distinguish
67
+
68
+ There are two kinds of error responses. Only one is correct:
69
+
70
+ | Type | Source | What you see | Verdict |
71
+ | -------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ------------------ |
72
+ | **Handler error** ✅ | Handler catches error and returns `{success: false, error: "..."}` | Parseable JSON object with `success` and `error` fields | Correct |
73
+ | **MCP error** ❌ | Uncaught throw propagates to MCP framework | Raw text error string, often prefixed with `Error:`, wrapped in an `isError: true` content block — no `success` field | Bug — report as ❌ |
74
+
75
+ **Concrete examples:**
76
+
77
+ ```
78
+ ✅ Handler error (correct):
79
+ {"success": false, "error": "Table 'nonexistent_xyz' does not exist"}
80
+
81
+ ❌ MCP error (bug — handler threw instead of catching):
82
+ content: [{type: "text", text: "Error: SQLITE_ERROR: no such table: nonexistent_xyz"}]
83
+ isError: true
84
+ ```
85
+
86
+ The MCP error case means the handler is missing a `try/catch` block. When testing, if you see a raw error string (especially one containing `SQLITE_ERROR` without a `success` field), report it as ❌.
87
+
88
+ ### Zod Validation Errors
89
+
90
+ Calling a tool with wrong parameter types or missing required fields triggers a Zod validation error. If the handler has no outer `try/catch`, this surfaces as a raw MCP error (often `-32602`). Test every tool with `{}` (empty params) if it has required parameters — the response must be a handler error, not an MCP error.
91
+
92
+ **Zod refinement leak pattern:** `DatabaseAdapter.registerTool()` uses `.partial()` on input schemas so the SDK accepts `{}`. But `.partial()` only makes keys **optional** — it does NOT strip refinements like `.min(1)`, `.max(90)`, or `.min(-90).max(90)`. This applies to **ALL types** — strings, arrays, AND numbers:
93
+
94
+ - `z.string().min(1)` + empty `""` → SDK rejects with raw MCP `-32602`
95
+ - `z.array().min(1)` + empty `[]` → SDK rejects with raw MCP `-32602`
96
+ - `z.number().min(-90).max(90)` + value `91` → SDK rejects with raw MCP `-32602`
97
+
98
+ **Fix:** Remove ALL `.min(N)` / `.max(N)` refinements from the schema and validate inside the handler instead (see `sqlite_query_plan` in `diagnostics.ts`, `sqlite_append_insight` in `pragma.ts`, and `validateCoordinates()` in `geo.ts` for examples). Optional fields with `.default()` are safe because the default satisfies the constraint.
99
+
100
+ **Required enum coercion pattern:** For **optional** enum params with defaults, `z.preprocess(coercer, z.enum([...]).optional().default(...))` works — the coercer returns `undefined` for invalid values → the `.default()` kicks in. For **required** enum params (no `.optional().default(...)`), this pattern **fails**: the SDK's `.partial()` wraps the preprocess in `.optional()`, but the inner `z.enum()` still rejects `undefined` → raw MCP `-32602`. **Fix:** Use `z.string()` in the schema and validate the enum inside the handler's `try/catch`, returning a structured error (see `VALID_ANALYSIS_TYPES` / `VALID_OPERATIONS` / `VALID_FORMATS` in SpatiaLite `analysis.ts` for examples).
101
+
102
+ **What to report:**
103
+
104
+ - If a tool call returns a raw MCP error (no JSON body with `success` field), report it as ❌ with the tool name and the raw error message
105
+ - If a tool returns `{success: false, error: "..."}`, that is the correct behavior — do not report it as a failure
106
+ - If a tool returns a successful response for an obviously invalid input (e.g., nonexistent table returns `{success: true}`), report it as ⚠️
107
+
108
+ ### Output Schema Validation Errors
109
+
110
+ The MCP SDK enforces `additionalProperties: false` on **output** schemas. If a handler returns fields not declared in its output schema, the SDK rejects the response with a raw `-32602` error — even though the handler logic succeeded. This is a different failure mode from input validation:
111
+
112
+ - **Input `-32602`**: Triggered by sending unrecognized/invalid parameters → caught by the Zod sweep (call with `{}` or `extraParam`)
113
+ - **Output `-32602`**: Triggered by the handler **returning** undeclared fields → caught by a valid happy-path call that still produces a raw MCP error
114
+
115
+ **How to detect:** If a tool call with **correct, valid inputs** returns a raw MCP `-32602` mentioning "does not match the tool's output schema" or "additional properties", the output schema in `src/adapters/sqlite/schemas/` is missing fields that the handler returns. Report as ❌ with both the tool name and the missing field(s).
116
+
117
+ **Fix pattern:** Add the missing fields to the output schema (e.g., `durationMs: z.number().optional()`, `message: z.string().optional()`). Do NOT remove fields from the handler response — the schema must match reality.
118
+
119
+ **Systematic check:** For every tool that has an `outputSchema`, make at least one valid happy-path call and confirm it returns a parseable JSON object with a `success` field — not a raw MCP error. This is separate from (and complementary to) the Zod validation sweep, which tests invalid inputs.
120
+
121
+ ### Error Consistency Audit
122
+
123
+ During testing, check for these inconsistencies across tool groups:
124
+
125
+ 1. **Throw-vs-return**: If a tool throws a raw error instead of returning `{success: false}`, report as ❌. Document which tool groups have raw-error leakage.
126
+ 2. **Error field name**: All `{success: false}` responses should use `error` as the field name. The `reason` field is reserved for `{success: true, skipped: true}` informational responses.
127
+ 3. **Zod validation leaks**: If calling a tool with an invalid enum value or missing required field produces a raw MCP `-32602` error instead of a structured response, report as ❌.
128
+ 4. **Output schema leaks**: If calling a tool with valid inputs produces a raw MCP `-32602` mentioning "output schema" or "additional properties", report as ❌ (see "Output Schema Validation Errors" above).
129
+ 5. **Centralized error formatting**: db-mcp uses `DbMcpError`. If any tool group catches errors but formats them inconsistently (e.g., different message patterns for the same error type), report as ⚠️.
130
+ 6. **Orphaned output schemas**: If a schema is exported from `src/adapters/sqlite/schemas/` (e.g., `TransactionBeginOutputSchema`) but the corresponding tool definition does not reference it via `outputSchema`, report as ⚠️. Use `grep_search` to check whether the schema name appears in any tool file under `src/adapters/`. Defined-but-unwired schemas provide zero enforcement.
131
+ 7. **Inline output schemas**: If any tool defines `outputSchema: z.object({...})` inline in the handler file instead of importing a named schema from `schemas/`, report as ⚠️. All output schemas must live in `src/adapters/sqlite/schemas/` with named exports. Use `grep_search` with pattern `outputSchema: z.object` across `src/adapters/` to detect violations.
132
+
133
+ ## Error Path Testing Checklist
134
+
135
+ For each tool group under test, verify at least one scenario from each applicable row:
136
+
137
+ | Error Scenario | Tool Groups to Test | Example Input |
138
+ | --------------------------------- | ------------------------------------- | ----------------------------------------------------------------------- |
139
+ | Nonexistent table | All table-accepting tools | `table: "nonexistent_xyz"` |
140
+ | Duplicate table/index | Core (`create_table`, `create_index`) | Create existing table |
141
+ | Missing required field | All tools with required params | Omit `table`, `query`, etc. |
142
+ | **Zod validation (empty params)** | **Every tool with required params** | `{}` (empty object — must return handler error, not MCP `-32602` error) |
143
+ | **Zod validation (wrong type)** | **Tools with typed params** | Pass string where number expected, etc. |
144
+
145
+ ### Split Schema Pattern Verification
146
+
147
+ All tools use the Split Schema pattern: a plain `z.object()` Base schema for MCP parameter visibility, and a `z.preprocess()` wrapper for handler parsing. Verify:
148
+
149
+ 1. **Parameter visibility**: For tools with optional parameters (e.g., `limit`, `readonly`), make a direct MCP call using those parameters. If the tool ignores or rejects documented parameters, report as a Split Schema violation.
150
+ 2. **Alias acceptance**: For tools with documented parameter aliases (e.g., `table`/`tableName`, `query`/`sql`, `indexName`/`name`), verify that direct MCP tool calls correctly accept the aliases.
151
+
152
+ ## Cleanup Conventions
153
+
154
+ During testing, use these naming conventions:
155
+
156
+ - **Temporary tables**: Prefix with `temp_` (e.g., `temp_core_test`)
157
+ - **Temporary indexes**: Prefix with `temp_idx_` (e.g., `temp_idx_name`)
158
+
159
+ After testing, clean up:
160
+
161
+ ```sql
162
+ -- List temp tables
163
+ SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'temp_%';
164
+
165
+ -- Drop temp table
166
+ DROP TABLE IF EXISTS temp_core_test;
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Group Focus: core-schema
172
+
173
+ > **Instructions**: Execute every numbered checklist item with the exact inputs shown. Compare responses against the expected results. Report any deviation.
174
+
175
+ ### core-schema Group Tools (8)
176
+
177
+ 1. sqlite_list_tables
178
+ 2. sqlite_describe_table
179
+ 3. sqlite_create_table
180
+ 4. sqlite_drop_table
181
+ 5. sqlite_get_indexes
182
+ 6. sqlite_create_index
183
+ 7. sqlite_drop_index
184
+ 8. sqlite_execute_code
185
+
186
+ **Checklist:**
187
+
188
+ 1. `sqlite_list_tables({excludeSystemTables: true})` → verify `test_products`, `test_orders`, etc. all present, but `sqlite_master` or `sqlite_sequence` absent
189
+ 2. `sqlite_describe_table({table: "test_products"})` → verify columns include `id` (INTEGER), `name` (TEXT), `price` (REAL), `category` (TEXT)
190
+ 3. `sqlite_get_indexes({table: "test_orders", excludeSystemIndexes: true})` → verify `idx_orders_status` and `idx_orders_date` present
191
+ 4. `sqlite_create_table({table: "temp_core_test", columns: [{name: "id", type: "INTEGER", primaryKey: true}, {name: "name", type: "TEXT"}, {name: "value", type: "REAL"}], ifNotExists: true})` → success
192
+ 5. `sqlite_create_table({table: "temp_core_test", columns: [{name: "id", type: "INTEGER", primaryKey: true}], ifNotExists: true})` → success (should not fail if table already exists due to ifNotExists)
193
+ 6. `sqlite_create_index({table: "temp_core_test", columns: ["name"], indexName: "idx_temp_core_name", unique: false, ifNotExists: true})` → success
194
+ 7. `sqlite_drop_index({indexName: "idx_temp_core_name", ifExists: true})` → success
195
+ 8. `sqlite_drop_table({table: "temp_core_test", ifExists: true})` → success
196
+
197
+ **Code mode testing:**
198
+
199
+ 9. `sqlite_execute_code({code: "const tables = await sqlite.core.listTables(); return tables;"})` → returns list of tables including `test_products`, `test_orders`, etc.
200
+ 10. `sqlite_execute_code({code: "const result = await sqlite.core.writeQuery('INSERT INTO test_products VALUES (999, \"x\", \"x\", 0, \"x\", \"x\")'); return result;", readonly: true})` → `result` contains `{success: false, code: "CODEMODE_READONLY_VIOLATION"}` (code mode returns errors as values, not thrown exceptions)
201
+
202
+ **Error path testing:**
203
+
204
+ 🔴 11. `sqlite_describe_table({table: "nonexistent_table_xyz"})` → structured error response, NOT a raw MCP exception
205
+ 🔴 12. `sqlite_drop_table({table: "nonexistent_table_xyz"})` → structured error or `{existed: false}` style response
206
+
207
+ **Zod validation sweep** — call each tool with `{}` (empty params). Every response must be a handler error (`{success: false, error: "Validation error: ..."}`) — NOT a raw MCP error frame:
208
+
209
+ 🔴 13. `sqlite_create_table({})` → handler error
210
+ 🔴 14. `sqlite_describe_table({})` → handler error
211
+ 🔴 15. `sqlite_drop_table({})` → handler error
212
+ 🔴 16. `sqlite_get_indexes({})` → success (returns all indexes, table is optional)
213
+ 🔴 17. `sqlite_create_index({})` → handler error
214
+ 🔴 18. `sqlite_drop_index({})` → handler error
215
+ 🔴 19. `sqlite_execute_code({})` → handler error (has required `code` param)
216
+
217
+ ---
218
+
219
+ ## Post-Test Procedures
220
+
221
+ ### Reporting Rules
222
+
223
+ - Use ✅ only in inline notes during testing; omit from Final Summary
224
+ - Do not mention what already works well or issues already documented in help resources and runtime hints
225
+
226
+ ### After Testing
227
+
228
+ 1. **Triage findings**: If issues were found, create an implementation plan, making sure they are consistent with working patterns in other tools/tool groups. If the plan requires no user decisions, proceed directly to implementation
229
+ 2. **Scope of fixes** includes corrections to any of:
230
+ - Handler code
231
+ - `src/constants/server-instructions/*.md` (per-group help files) — run `npm run generate:instructions` after editing to regenerate `server-instructions.ts`
232
+ - Test database (`test-server/test.db`)
233
+ - This prompt
234
+
235
+ ### After Implementation
236
+
237
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
238
+ 4. **Commit**: Stage and commit all changes — do NOT push
239
+ 5. **Live re-test**: Test fixes with direct MCP tool calls. I will have already rebuilt and restarted the server.
240
+ 6. **Final summary**: If no issues found, provide the final summary after testing. If issues were fixed, provide the summary after live MCP re-testing confirms fixes are working. If the test prompt/database can be improved, make the improvements.
@@ -0,0 +1,130 @@
1
+ # db-mcp Tool Group Testing: [geo-haversine]
2
+
3
+ > [!IMPORTANT]
4
+ > **Do not track progress in this file.** Track your test progress, coverage matrix, and findings in your internal task tracking system (artifact). However, you SHOULD edit this file to fix any factual errors, broken code, or incorrect assertions in the test prompts.
5
+ > If there is nothing to fix, don't update UNRELEASED.md.
6
+ > We're currently testing Native mode.
7
+
8
+ ## WASM Mode
9
+
10
+ > When testing against a **WASM backend** (`sqlite-wasm` / sql.js): All 4 Haversine tools are fully WASM-compatible. No items to skip or adjust.
11
+
12
+ **Step 1:** Confirm you read the server help content sourced from `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file` (not grep or search) — to understand documented behaviors, edge cases, and response structures for this tool group.
13
+
14
+ **Step 2:** Please conduct an exhaustive test of the **geo-haversine** tool group specified in the group-specific checklist below using live MCP server tool calls directly — not scripts/terminal.
15
+
16
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
17
+
18
+ **Note** If temp tables are present from a previous test pass, it's because the database is locked. Ignore them.
19
+
20
+ ## Reporting Format
21
+
22
+ - ❌ Fail: Tool errors or produces incorrect results (include error message)
23
+ - ⚠️ Issue: Unexpected behavior or improvement opportunity
24
+ - 📦 Payload: Unnecessarily large response that should be optimized.
25
+
26
+ ## Test Database Schema
27
+
28
+ | Table | Rows | Columns | JSON Columns |
29
+ | ----------------- | ---- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
30
+ | test_products | 16 | id, name, description, price, category, created_at | — |
31
+ | test_orders | 20 | id, product_id (FK), customer_name, quantity, total_price, order_date, status | — |
32
+ | test_jsonb_docs | 6 | id, doc, metadata, tags, created_at | **doc**, **metadata** (nested), **tags** (array) |
33
+ | test_articles | 8 | id, title, body, author, category, published_at | — |
34
+ | test_users | 9 | id, username, email, phone, bio, created_at | — |
35
+ | test_measurements | 200 | id, sensor_id, temperature, humidity, pressure, measured_at | — |
36
+ | test_embeddings | 20 | id, content, category, embedding | **embedding** (8-dim float array); category values: database, fitness, food, tech, travel |
37
+ | test_locations | 15 | id, name, city, latitude, longitude, type | — |
38
+ | test_categories | 17 | id, name, path, level | — |
39
+ | test_events | 100 | id, event_type, user_id (INT, 8 values), payload, event_date | **payload** (JSON) |
40
+
41
+ ## Testing Requirements
42
+
43
+ > [!CAUTION]
44
+ > **Zero tolerance for raw MCP errors.** ANY response that is a raw MCP error (e.g., `-32602`, `isError: true`, no `success` field) is a **bug that must be reported and fixed**.
45
+
46
+ 1. Use existing `test_*` tables for read operations
47
+ 2. Create temporary tables with `temp_*` prefix for write operations
48
+ 3. **Error path testing**: For **every** tool, test (a) domain error and (b) Zod validation error (`{}`). Both must return `{success: false, error: "..."}`.
49
+ 4. **Output schema testing**: For tools with `outputSchema`, confirm valid calls return structured JSON.
50
+
51
+ ## Structured Error Response Pattern
52
+
53
+ ```json
54
+ { "success": false, "error": "Human-readable error message" }
55
+ ```
56
+
57
+ | Type | Source | What you see | Verdict |
58
+ | -------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------- | ------------------ |
59
+ | **Handler error** ✅ | Handler catches error and returns `{success: false, error: "..."}` | Parseable JSON object with `success` and `error` fields | Correct |
60
+ | **MCP error** ❌ | Uncaught throw propagates to MCP framework | Raw text error string, `isError: true` — no `success` field | Bug — report as ❌ |
61
+
62
+ ### Zod Validation Errors
63
+
64
+ **Zod refinement leak pattern:** `.partial()` does NOT strip `.min(N)` / `.max(N)` refinements. This is **especially important for geo tools** with coordinate params like `.min(-90).max(90)`. **Fix:** Remove refinements from schema, validate inside handler (see `validateCoordinates()` in `geo.ts`).
65
+
66
+ ### Output Schema Validation Errors
67
+
68
+ If valid inputs return raw MCP `-32602` mentioning "output schema", report as ❌.
69
+
70
+ ---
71
+
72
+ ## Group Focus: geo-haversine
73
+
74
+ > **Instructions**: Execute every numbered checklist item with the exact inputs shown. Compare responses against the expected results. Report any deviation.
75
+
76
+ ### geo-haversine Group Tools (5)
77
+
78
+ 1. sqlite_geo_distance
79
+ 2. sqlite_geo_nearby
80
+ 3. sqlite_geo_bounding_box
81
+ 4. sqlite_geo_cluster
82
+ 5. sqlite_execute_code
83
+
84
+ **Test data:** `test_locations` (15 rows). Key coordinates:
85
+
86
+ | Name | City | Lat | Lng |
87
+ | ------------------ | ------------- | -------- | --------- |
88
+ | Central Park | New York | 40.7829 | -73.9654 |
89
+ | Eiffel Tower | Paris | 48.8584 | 2.2945 |
90
+ | Big Ben | London | 51.5007 | -0.1246 |
91
+ | Tokyo Tower | Tokyo | 35.6586 | 139.7454 |
92
+ | Sydney Opera House | Sydney | -33.8568 | 151.2153 |
93
+ | Golden Gate Bridge | San Francisco | 37.8199 | -122.4783 |
94
+
95
+ **Checklist:**
96
+
97
+ 1. `sqlite_geo_distance({lat1: 40.7829, lon1: -73.9654, lat2: 48.8584, lon2: 2.2945})` → NYC to Paris ≈ 5,837 km (verify within ±50 km)
98
+ 2. `sqlite_geo_distance({lat1: 40.7829, lon1: -73.9654, lat2: 37.8199, lon2: -122.4783})` → NYC to SF ≈ 4,130 km
99
+ 3. `sqlite_geo_nearby({table: "test_locations", latColumn: "latitude", lonColumn: "longitude", centerLat: 40.7580, centerLon: -73.9855, radius: 10})` → should find NYC locations (Central Park, Empire State Building, Times Square) — 3 results
100
+ 4. `sqlite_geo_nearby({table: "test_locations", latColumn: "latitude", lonColumn: "longitude", centerLat: 48.8584, centerLon: 2.2945, radius: 10})` → should find Paris locations (Eiffel Tower, Louvre, Notre-Dame) — 3 results
101
+ 5. `sqlite_geo_bounding_box({table: "test_locations", latColumn: "latitude", lonColumn: "longitude", minLat: 35, maxLat: 55, minLon: -130, maxLon: -70})` → US locations (NYC 3 + SF 1 = 4)
102
+ 6. `sqlite_geo_cluster({table: "test_locations", latColumn: "latitude", lonColumn: "longitude", gridSize: 5})` → ~5 clusters grouping by city proximity
103
+
104
+ **Code mode testing:**
105
+
106
+ 7. `sqlite_execute_code({code: "const result = await sqlite.geo.distance({lat1: 40.7829, lon1: -73.9654, lat2: 48.8584, lon2: 2.2945}); return result;"})` → NYC to Paris ≈ 5,837 km
107
+ 8. `sqlite_execute_code({code: "const result = await sqlite.geo.nearby({table: 'test_locations', latColumn: 'latitude', lonColumn: 'longitude', centerLat: 40.758, centerLon: -73.9855, radius: 10}); return result;"})` → NYC locations
108
+
109
+ **Error path testing:**
110
+
111
+ 🔴 9. `sqlite_geo_nearby({table: "nonexistent_table_xyz", latColumn: "lat", lonColumn: "lng", centerLat: 0, centerLon: 0, radius: 100})` → structured error
112
+ 🔴 10. `sqlite_geo_distance({lat1: 91, lon1: 0, lat2: 0, lon2: 0})` → must return `{success: false, error: "Invalid lat1: 91. Must be between -90 and 90."}` — structured handler error, NOT a raw MCP error. If this returns a raw MCP `-32602`, it is a Zod `.min()/.max()` refinement leak bug (see Zod refinement leak pattern above).
113
+
114
+ **Zod validation sweep** — call each tool with `{}` (empty params). Must return handler error, NOT raw MCP error:
115
+
116
+ 🔴 11. `sqlite_geo_distance({})` → handler error
117
+ 🔴 12. `sqlite_geo_nearby({})` → handler error
118
+ 🔴 13. `sqlite_geo_bounding_box({})` → handler error
119
+ 🔴 14. `sqlite_geo_cluster({})` → handler error
120
+
121
+ ---
122
+
123
+ ## Post-Test Procedures
124
+
125
+ 1. **Triage findings**: Create implementation plan if issues found
126
+ 2. **Scope of fixes**: Handler code, server-instructions, test database, this prompt
127
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
128
+ 4. **Commit**: Stage and commit — do NOT push
129
+ 5. **Live re-test**: After server rebuild
130
+ 6. **Final summary**: After testing/re-testing
@@ -0,0 +1,110 @@
1
+ # db-mcp Tool Group Testing: [geo-spatialite]
2
+
3
+ > [!IMPORTANT]
4
+ > **Do not track progress in this file.** Track your test progress, coverage matrix, and findings in your internal task tracking system (artifact). However, you SHOULD edit this file to fix any factual errors, broken code, or incorrect assertions in the test prompts.
5
+ > If there is nothing to fix, don't update UNRELEASED.md.
6
+ > We're currently testing Native mode.
7
+
8
+ ## WASM Mode
9
+
10
+ > When testing against a **WASM backend** (`sqlite-wasm` / sql.js), apply these adjustments:
11
+ >
12
+ > - **Skip SpatiaLite tools** (items 1-7: `sqlite_spatialite_load`, `sqlite_spatialite_create_table`, `sqlite_spatialite_query`, `sqlite_spatialite_analyze`, `sqlite_spatialite_index`, `sqlite_spatialite_transform`, `sqlite_spatialite_import`) — `[NATIVE ONLY]`. These tools are not registered in WASM.
13
+ > - **Skip all checklist items** — all require SpatiaLite.
14
+ > - **Skip all Zod items** (SpatiaLite tools) — `[NATIVE ONLY]`.
15
+
16
+ **Step 1:** Confirm you read the server help content sourced from `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file` (not grep or search) — to understand documented behaviors, edge cases, and response structures for this tool group.
17
+
18
+ **Step 2:** Please conduct an exhaustive test of the **geo-spatialite** tool group specified in the group-specific checklist below using live MCP server tool calls directly — not scripts/terminal.
19
+
20
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
21
+
22
+ **Note** If temp tables are present from a previous test pass, it's because the database is locked. Ignore them.
23
+
24
+ ## Reporting Format
25
+
26
+ - ❌ Fail: Tool errors or produces incorrect results (include error message)
27
+ - ⚠️ Issue: Unexpected behavior or improvement opportunity
28
+ - 📦 Payload: Unnecessarily large response that should be optimized.
29
+
30
+ ## Testing Requirements
31
+
32
+ > [!CAUTION]
33
+ > **Zero tolerance for raw MCP errors.** ANY response that is a raw MCP error (e.g., `-32602`, `isError: true`, no `success` field) is a **bug that must be reported and fixed**.
34
+
35
+ 1. Use existing `test_*` tables for read operations
36
+ 2. Create temporary tables with `temp_*` prefix for write operations
37
+ 3. **Error path testing**: For **every** tool, test (a) domain error and (b) Zod validation error (`{}`). Both must return `{success: false, error: "..."}`.
38
+ 4. **Output schema testing**: For tools with `outputSchema`, confirm valid calls return structured JSON.
39
+
40
+ ## Structured Error Response Pattern
41
+
42
+ ```json
43
+ { "success": false, "error": "Human-readable error message" }
44
+ ```
45
+
46
+ | Type | Source | What you see | Verdict |
47
+ | -------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------- | ------------------ |
48
+ | **Handler error** ✅ | Handler catches error and returns `{success: false, error: "..."}` | Parseable JSON object with `success` and `error` fields | Correct |
49
+ | **MCP error** ❌ | Uncaught throw propagates to MCP framework | Raw text error string, `isError: true` — no `success` field | Bug — report as ❌ |
50
+
51
+ ### Zod Validation Errors
52
+
53
+ **Zod refinement leak pattern:** `.partial()` does NOT strip `.min(N)` / `.max(N)` refinements. **Fix:** Remove refinements from schema, validate inside handler.
54
+
55
+ ### Output Schema Validation Errors
56
+
57
+ If valid inputs return raw MCP `-32602` mentioning "output schema", report as ❌.
58
+
59
+ ---
60
+
61
+ ## Group Focus: geo-spatialite
62
+
63
+ > **Instructions**: Execute every numbered checklist item with the exact inputs shown. Compare responses against the expected results. Report any deviation.
64
+
65
+ ### geo-spatialite Group Tools (7)
66
+
67
+ 1. sqlite_spatialite_load `[NATIVE ONLY]`
68
+ 2. sqlite_spatialite_create_table `[NATIVE ONLY]`
69
+ 3. sqlite_spatialite_query `[NATIVE ONLY]`
70
+ 4. sqlite_spatialite_analyze `[NATIVE ONLY]`
71
+ 5. sqlite_spatialite_index `[NATIVE ONLY]`
72
+ 6. sqlite_spatialite_transform `[NATIVE ONLY]`
73
+ 7. sqlite_spatialite_import `[NATIVE ONLY]`
74
+
75
+ **Checklist:**
76
+
77
+ **SpatiaLite tools `[NATIVE ONLY]`:**
78
+
79
+ 1. `sqlite_spatialite_load` → load SpatiaLite extension, verify version
80
+ 2. `sqlite_spatialite_create_table({tableName: "temp_spatial_test", geometryColumn: "geom", geometryType: "POINT", srid: 4326, additionalColumns: [{name: "name", type: "TEXT"}]})` → success
81
+ 3. `sqlite_spatialite_import({tableName: "temp_spatial_test", format: "wkt", data: "POINT(-73.9654 40.7829)", additionalData: {name: "Test Point"}})` → success
82
+ 4. `sqlite_spatialite_query({query: "SELECT name, AsText(geom) as geom_text FROM temp_spatial_test"})` → WKT geometry returned
83
+ 5. `sqlite_spatialite_transform({operation: "buffer", geometry1: "POINT(-73.9654 40.7829)", distance: 0.01, srid: 4326})` → buffered polygon
84
+ 6. `sqlite_spatialite_index({tableName: "temp_spatial_test", geometryColumn: "geom", action: "create"})` → R-Tree index created
85
+ 7. `sqlite_spatialite_analyze({analysisType: "spatial_extent", sourceTable: "temp_spatial_test", geometryColumn: "geom"})` → spatial extent
86
+ 8. Cleanup: drop R-Tree index (`sqlite_spatialite_index` with `action: "drop"`), then drop `temp_spatial_test`
87
+
88
+ **Error path testing:**
89
+
90
+ 🔴 9. `sqlite_spatialite_query({query: "SELECT name FROM nonexistent_table_xyz"})` `[NATIVE ONLY]` → structured error
91
+
92
+ **Zod validation sweep** — call each tool with `{}` (empty params). Must return handler error, NOT raw MCP error:
93
+
94
+ 🔴 10. `sqlite_spatialite_create_table({})` `[NATIVE ONLY]` → handler error
95
+ 🔴 11. `sqlite_spatialite_query({})` `[NATIVE ONLY]` → handler error
96
+ 🔴 12. `sqlite_spatialite_analyze({})` `[NATIVE ONLY]` → handler error
97
+ 🔴 13. `sqlite_spatialite_index({})` `[NATIVE ONLY]` → handler error
98
+ 🔴 14. `sqlite_spatialite_transform({})` `[NATIVE ONLY]` → handler error
99
+ 🔴 15. `sqlite_spatialite_import({})` `[NATIVE ONLY]` → handler error
100
+
101
+ ---
102
+
103
+ ## Post-Test Procedures
104
+
105
+ 1. **Triage findings**: Create implementation plan if issues found
106
+ 2. **Scope of fixes**: Handler code, server-instructions, test database, this prompt
107
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
108
+ 4. **Commit**: Stage and commit — do NOT push
109
+ 5. **Live re-test**: After server rebuild
110
+ 6. **Final summary**: After testing/re-testing
@@ -0,0 +1,123 @@
1
+ # db-mcp Tool Group Testing: [introspection-diagnostics]
2
+
3
+ > [!IMPORTANT]
4
+ > **Do not track progress in this file.** Track your test progress, coverage matrix, and findings in your internal task tracking system (artifact). However, you SHOULD edit this file to fix any factual errors, broken code, or incorrect assertions in the test prompts.
5
+ > If there is nothing to fix, don't update UNRELEASED.md.
6
+ > We're currently testing Native mode.
7
+
8
+ ## WASM Mode
9
+
10
+ > When testing against a **WASM backend** (`sqlite-wasm` / sql.js): All 3 diagnostics tools are fully WASM-compatible. No items to skip.
11
+
12
+ **Step 1:** Confirm you read the server help content sourced from `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file` (not grep or search) — to understand documented behaviors, edge cases, and response structures for this tool group.
13
+
14
+ **Step 2:** Please conduct an exhaustive test of the **introspection-diagnostics** tool group specified in the group-specific checklist below using live MCP server tool calls directly — not scripts/terminal.
15
+
16
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
17
+
18
+ **Note** If temp tables are present from a previous test pass, it's because the database is locked. Ignore them.
19
+
20
+ ## Reporting Format
21
+
22
+ - ❌ Fail: Tool errors or produces incorrect results (include error message)
23
+ - ⚠️ Issue: Unexpected behavior or improvement opportunity
24
+ - 📦 Payload: Unnecessarily large response that should be optimized.
25
+
26
+ ## Test Database Schema
27
+
28
+ | Table | Rows | Columns | JSON Columns |
29
+ | ----------------- | ---- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
30
+ | test_products | 16 | id, name, description, price, category, created_at | — |
31
+ | test_orders | 20 | id, product_id (FK), customer_name, quantity, total_price, order_date, status | — |
32
+ | test_jsonb_docs | 6 | id, doc, metadata, tags, created_at | **doc**, **metadata** (nested), **tags** (array) |
33
+ | test_articles | 8 | id, title, body, author, category, published_at | — |
34
+ | test_users | 9 | id, username, email, phone, bio, created_at | — |
35
+ | test_measurements | 200 | id, sensor_id, temperature, humidity, pressure, measured_at | — |
36
+ | test_embeddings | 20 | id, content, category, embedding | **embedding** (8-dim float array); category values: database, fitness, food, tech, travel |
37
+ | test_locations | 15 | id, name, city, latitude, longitude, type | — |
38
+ | test_categories | 17 | id, name, path, level | — |
39
+ | test_events | 100 | id, event_type, user_id (INT, 8 values), payload, event_date | **payload** (JSON) |
40
+
41
+ **Redundant index (intentional):** `idx_orders_status` is a prefix of `idx_orders_status_date` — used to test index audit tools.
42
+
43
+ ## Testing Requirements
44
+
45
+ > [!CAUTION]
46
+ > **Zero tolerance for raw MCP errors.** ANY response that is a raw MCP error (e.g., `-32602`, `isError: true`, no `success` field) is a **bug that must be reported and fixed**.
47
+
48
+ 1. Use existing `test_*` tables for read operations
49
+ 2. **Error path testing**: For **every** tool, test (a) domain error and (b) Zod validation error (`{}`). Both must return `{success: false, error: "..."}`.
50
+ 3. **Output schema testing**: For tools with `outputSchema`, confirm valid calls return structured JSON.
51
+
52
+ ## Structured Error Response Pattern
53
+
54
+ ```json
55
+ { "success": false, "error": "Human-readable error message" }
56
+ ```
57
+
58
+ | Type | Source | What you see | Verdict |
59
+ | -------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------- | ------------------ |
60
+ | **Handler error** ✅ | Handler catches error and returns `{success: false, error: "..."}` | Parseable JSON object with `success` and `error` fields | Correct |
61
+ | **MCP error** ❌ | Uncaught throw propagates to MCP framework | Raw text error string, `isError: true` — no `success` field | Bug — report as ❌ |
62
+
63
+ ### Zod Validation Errors
64
+
65
+ **Zod refinement leak pattern:** `.partial()` does NOT strip `.min(N)` / `.max(N)` refinements. **Fix:** Remove refinements from schema, validate inside handler.
66
+
67
+ ### Output Schema Validation Errors
68
+
69
+ If valid inputs return raw MCP `-32602` mentioning "output schema", report as ❌.
70
+
71
+ ---
72
+
73
+ ## Group Focus: introspection-diagnostics
74
+
75
+ > **Instructions**: Execute every numbered checklist item with the exact inputs shown. Compare responses against the expected results. Report any deviation.
76
+
77
+ ### introspection-diagnostics Group Tools (4)
78
+
79
+ 1. sqlite_storage_analysis
80
+ 2. sqlite_index_audit
81
+ 3. sqlite_query_plan
82
+ 4. sqlite_execute_code
83
+
84
+ **Checklist:**
85
+
86
+ **Diagnostics:**
87
+
88
+ 1. `sqlite_storage_analysis({})` → database.pageSize > 0, database.totalPages > 0, database.totalSizeBytes = pageSize × totalPages; recommendations array present
89
+ 2. `sqlite_storage_analysis({})` → tables array contains "test_measurements" (largest by row count); verify each entry has name, sizeBytes, rowCount
90
+ 3. `sqlite_storage_analysis({includeTableDetails: false})` → tables array should be missing or empty
91
+ 4. `sqlite_index_audit({})` → findings array present; summary has redundant, missingFk, total fields
92
+ 5. `sqlite_index_audit({})` → findings includes type="redundant" for `idx_orders_status` (prefix of `idx_orders_status_date`)
93
+ 6. `sqlite_index_audit({table: "test_orders"})` → findings restricted to `test_orders`
94
+ 7. `sqlite_query_plan({sql: "SELECT * FROM test_products WHERE category = 'electronics'"})` → plan array non-empty; analysis.fullScans may or may not include test_products (idx_products_category exists)
95
+ 8. `sqlite_query_plan({sql: "SELECT * FROM test_orders WHERE status = 'completed'"})` → analysis.indexScans present (idx_orders_status exists)
96
+ 9. `sqlite_query_plan({sql: "SELECT * FROM test_products WHERE name = 'Laptop Pro 15'"})` → analysis.fullScans includes test_products (no index on name); suggestions non-empty
97
+ 10. `sqlite_query_plan({sql: "WITH recent AS (SELECT * FROM test_orders ORDER BY order_date DESC LIMIT 5) SELECT * FROM recent"})` → plan contains CTE-related entries
98
+
99
+ **Code mode testing:**
100
+
101
+ 11. `sqlite_execute_code({code: "const result = await sqlite.introspection.queryPlan({sql: 'SELECT * FROM test_products WHERE category = \\u0027electronics\\u0027'}); return result;"})` → plan array present
102
+
103
+ **Error path testing:**
104
+
105
+ 🔴 12. `sqlite_query_plan({sql: "DELETE FROM test_products WHERE id = 1"})` → `{success: false, error: "...only SELECT..."}` (non-SELECT rejected)
106
+ 🔴 13. `sqlite_query_plan({})` → Zod validation error (missing required `sql`). Must be handler error, NOT raw MCP error.
107
+ 🔴 14. `sqlite_storage_analysis({limit: 0})` → Call via direct tool or code mode to verify Zod validation error (min: 1). Must be handler error.
108
+
109
+ **Zod validation sweep** — call each tool with `{}` (empty params). Must return handler error, NOT raw MCP error:
110
+
111
+ 🔴 15. `sqlite_storage_analysis({})` → handler error (or success if no required params)
112
+ 🔴 16. `sqlite_index_audit({})` → handler error (or success if no required params)
113
+
114
+ ---
115
+
116
+ ## Post-Test Procedures
117
+
118
+ 1. **Triage findings**: Create implementation plan if issues found
119
+ 2. **Scope of fixes**: Handler code, server-instructions, test database, this prompt
120
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
121
+ 4. **Commit**: Stage and commit — do NOT push
122
+ 5. **Live re-test**: After server rebuild
123
+ 6. **Final summary**: After testing/re-testing