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,185 @@
1
+ # db-mcp Advanced Stress Test — [stats]
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
+ **Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
9
+
10
+ **Step 2:** Execute each numbered stress test below using `sqlite_execute_code` (code mode).
11
+
12
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
13
+
14
+ ## WASM Mode
15
+
16
+ > When testing against a **WASM backend** (`--sqlite` / sql.js), apply these adjustments:
17
+
18
+ - **Skip Category 4** entirely (Window Functions — items 19-23) — `[NATIVE ONLY]`.
19
+ - **Category 6** (WASM Boundary Verification) — execute only in WASM mode.
20
+ - All other categories (1-3, 5) are fully WASM-compatible — 16 stats tools work identically.
21
+
22
+ ## Code Mode Execution
23
+
24
+ - **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
25
+
26
+ All tests via `sqlite_execute_code`. Use `sqlite.stats.*` for all stats/window tools.
27
+ State persists across calls. Do NOT pass `readonly: true`. Group related tests into single calls.
28
+
29
+ ## Test Database Schema
30
+
31
+ | Table | Rows | Key Columns |
32
+ | ----------------- | ---- | ---------------------------------------------------- |
33
+ | test_products | 16 | id, name, price (REAL), category (3 values) |
34
+ | test_orders | 20 | id, product_id, total_price, order_date, status |
35
+ | test_measurements | 200 | id, sensor_id (1-5), temperature, humidity, pressure |
36
+
37
+ ## Naming & Cleanup
38
+
39
+ - **Temporary tables**: `stress_*` prefix. Drop at end.
40
+
41
+ ## Reporting Format
42
+
43
+ - ❌ Fail | ⚠️ Issue | 📦 Payload (monitor `metrics.tokenEstimate`) | ✅ Confirmed (inline only)
44
+
45
+ ### Error Message Quality Rating
46
+
47
+ | Level | Verdict |
48
+ | -------------------------------------- | ------- |
49
+ | 5 - Excellent (name + code + context) | ✅ |
50
+ | 4 - Good (name) | ✅ |
51
+ | 3 - Adequate (raw SQLite, informative) | ⚠️ |
52
+ | 2 - Poor (no object name) | ⚠️ |
53
+ | 1 - Useless (generic) | ❌ |
54
+
55
+ ## Structured Error Response Pattern
56
+
57
+ Handler error ✅ = JSON with `success` + `error`. MCP error ❌ = raw text, `isError: true`.
58
+
59
+ ---
60
+
61
+ ## stats Group Tools — Native (22)
62
+
63
+ 1. sqlite_stats_basic
64
+ 2. sqlite_stats_count
65
+ 3. sqlite_stats_group_by
66
+ 4. sqlite_stats_histogram
67
+ 5. sqlite_stats_percentile
68
+ 6. sqlite_stats_correlation
69
+ 7. sqlite_stats_top_n
70
+ 8. sqlite_stats_distinct
71
+ 9. sqlite_stats_summary
72
+ 10. sqlite_stats_frequency
73
+ 11. sqlite_stats_outliers
74
+ 12. sqlite_stats_regression
75
+ 13. sqlite_stats_hypothesis
76
+ 14. sqlite_detect_anomalies
77
+ 15. sqlite_detect_bloat
78
+ 16. sqlite_detect_schema_risks
79
+ 17. sqlite_window_row_number `[NATIVE ONLY]`
80
+ 18. sqlite_window_rank `[NATIVE ONLY]`
81
+ 19. sqlite_window_lag_lead `[NATIVE ONLY]`
82
+ 20. sqlite_window_running_total `[NATIVE ONLY]`
83
+ 21. sqlite_window_moving_avg `[NATIVE ONLY]`
84
+ 22. sqlite_window_ntile `[NATIVE ONLY]`
85
+
86
+ ### WASM (16)
87
+
88
+ Same minus the 6 window function tools (items 17-22).
89
+
90
+ ---
91
+
92
+ ### Category 1: Boundary Values & Empty States
93
+
94
+ Create `stress_stats_table (id INTEGER PRIMARY KEY, value REAL, category TEXT)`:
95
+
96
+ **1.1 Empty Table Statistics**
97
+
98
+ 1. `sqlite.stats.statsBasic({table: "stress_stats_table", column: "value"})` → graceful error or empty stats (not crash)
99
+ 2. `sqlite.stats.statsCount({table: "stress_stats_table"})` → `{count: 0}`
100
+ 3. `sqlite.stats.statsHistogram({table: "stress_stats_table", column: "value", buckets: 5})` → graceful handling
101
+
102
+ **1.2 Single-Row Statistics**
103
+
104
+ Insert one row: `(1, 42.0, 'test')`:
105
+
106
+ 4. `sqlite.stats.statsBasic({table: "stress_stats_table", column: "value"})` → count=1, min=max=avg=42.0
107
+ 5. `sqlite.stats.statsPercentile({table: "stress_stats_table", column: "value", percentiles: [25, 50, 75]})` → all equal 42
108
+ 6. `sqlite.stats.statsRegression({table: "stress_stats_table", xColumn: "id", yColumn: "value", degree: 1})` → graceful handling (regression undefined for n=1)
109
+
110
+ **1.3 NULL-Heavy Data**
111
+
112
+ Insert 5 rows: 3 with `value IS NULL`, 2 with actual values:
113
+
114
+ 7. `sqlite.stats.statsBasic({table: "stress_stats_table", column: "value"})` → only count non-null values (3 total)
115
+ 8. `sqlite.stats.statsCount({table: "stress_stats_table", column: "value"})` → non-null count only
116
+
117
+ **1.4 Extreme Numeric Values**
118
+
119
+ Insert: `(99999999.99)`, `(-99999999.99)`, `(0.0)`, `(0.01)`:
120
+
121
+ 9. `sqlite.stats.statsBasic({table: "stress_stats_table", column: "value"})` → verify min/max/avg handle extreme values
122
+
123
+ ---
124
+
125
+ ### Category 2: Statistical Edge Cases
126
+
127
+ 10. `sqlite.stats.statsCorrelation({table: "test_products", column1: "id", column2: "id"})` → self-correlation = 1.0
128
+ 11. `sqlite.stats.statsHypothesis({table: "test_measurements", column: "temperature", testType: "ttest_one", expectedMean: 999})` → should reject null hypothesis
129
+ 12. `sqlite.stats.statsOutliers({table: "test_measurements", column: "temperature", method: "iqr"})` → IQR-based outliers
130
+ 13. `sqlite.stats.statsOutliers({table: "test_measurements", column: "temperature", method: "zscore"})` → Z-score outliers (compare with IQR)
131
+ 14. `sqlite.stats.statsRegression({table: "test_measurements", xColumn: "temperature", yColumn: "humidity", degree: 2})` → quadratic regression
132
+
133
+ ---
134
+
135
+ ### Category 3: Anomaly Detection Stress
136
+
137
+ 15. `sqlite.stats.detectAnomalies({table: "test_measurements", column: "temperature"})` → anomaly detection result
138
+ 16. `sqlite.stats.detectAnomalies({table: "stress_stats_table", column: "value"})` → graceful handling on mixed NULL/extreme data
139
+ 17. `sqlite.stats.detectBloat()` → bloat detection
140
+ 18. `sqlite.stats.detectSchemaRisks()` → schema risk assessment
141
+
142
+ ---
143
+
144
+ ### Category 4: Window Functions `[NATIVE ONLY]`
145
+
146
+ 19. `sqlite.stats.windowRowNumber({table: "test_products", orderBy: "price DESC"})` → 16 rows, Laptop Pro 15 at #1
147
+ > **Note:** `window_row_number` and `window_rank` do NOT have a `direction` param — embed in `orderBy` string.
148
+ 20. `sqlite.stats.windowRank({table: "test_orders", orderBy: "total_price DESC"})` → ranks with potential ties
149
+ 21. `sqlite.stats.windowRunningTotal({table: "test_orders", valueColumn: "total_price", orderBy: "order_date"})` → monotonically increasing cumulative total
150
+ 22. `sqlite.stats.windowMovingAvg({table: "test_measurements", valueColumn: "temperature", windowSize: 10, orderBy: "measured_at"})` → 10-row moving average
151
+ 23. `sqlite.stats.windowNtile({table: "test_products", buckets: 4, orderBy: "price"})` → 4 groups of ~4 products
152
+
153
+ ---
154
+
155
+ ### Category 5: Error Message Quality
156
+
157
+ 24. `sqlite.stats.statsBasic({table: "nonexistent_table_xyz", column: "x"})` → structured error mentioning table name
158
+ 25. `sqlite.stats.statsBasic({table: "test_products", column: "nonexistent_col"})` → structured error mentioning column
159
+ 26. `sqlite.stats.statsCorrelation({table: "test_products", column1: "name", column2: "description"})` → error about non-numeric columns
160
+ 27. `sqlite.stats.statsHistogram({table: "test_products", column: "price", buckets: 0})` → error (must be > 0)
161
+ 28. `sqlite.stats.statsHistogram({table: "test_products", column: "price", buckets: -1})` → error
162
+
163
+ ---
164
+
165
+ ### Category 6: WASM Boundary Verification
166
+
167
+ For WASM testing only:
168
+
169
+ 29. Confirm window function tools are NOT present in the tool list
170
+ 30. All 16 non-window stats tools should produce identical results in WASM and Native
171
+
172
+ ---
173
+
174
+ ### Final Cleanup
175
+
176
+ Drop `stress_stats_table`. Confirm `test_measurements` (200 rows) and `test_products` (16 rows) unchanged.
177
+
178
+ ## Post-Test Procedures
179
+
180
+ 1. **Cleanup**: Drop all `stress_*` objects
181
+ 2. **Fix EVERY finding** — ❌, ⚠️, 📦
182
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
183
+ 4. **Commit**: Stage and commit — do NOT push
184
+ 5. **Re-test**: After server rebuild
185
+ 6. **Token audit**: Report most expensive block
@@ -0,0 +1,183 @@
1
+ # db-mcp Advanced Stress Test — [text]
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
+ **Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
9
+
10
+ **Step 2:** Execute each numbered stress test below using `sqlite_execute_code` (code mode).
11
+
12
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
13
+
14
+ ## WASM Mode
15
+
16
+ > When testing against a **WASM backend** (`--sqlite` / sql.js), apply these adjustments:
17
+
18
+ - **Skip Category 6** entirely (FTS5 State Integrity — items 21-26) — `[NATIVE ONLY]`.
19
+ - **Category 7** (WASM Boundary Verification) — execute only in WASM mode.
20
+ - **Category 8**: Skip item 32 (`ftsSearch`) — `[NATIVE ONLY]`.
21
+ - **Final Cleanup**: Skip FTS integrity check with `ftsMatchInfo` — `[NATIVE ONLY]`.
22
+ - All other categories (1-5, 7-8) are fully WASM-compatible — 14 text tools work identically.
23
+
24
+ ## Code Mode Execution
25
+
26
+ - **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
27
+
28
+ All tests via `sqlite_execute_code`. Use `sqlite.text.*` for all text/regex/FTS tools.
29
+ State persists across calls. Do NOT pass `readonly: true`. Group related tests into single calls.
30
+
31
+ ## Test Database Schema
32
+
33
+ | Table | Rows | Key Columns |
34
+ | ----------------- | ---- | -------------------------------------------------------- |
35
+ | test_products | 16 | id, name (row 16: `Café Décor Light`), price, category |
36
+ | test_users | 9 | id, username, email, phone, bio |
37
+ | test_articles | 8 | id, title, body, author, category |
38
+ | test_articles_fts | — | FTS5 virtual table (title, body columns) `[NATIVE ONLY]` |
39
+
40
+ **Key data:**
41
+
42
+ - Emails: `@example.com`, `@company.org`, `@gmail.com`; one dotted local: `test.user@gmail.com`
43
+ - Phones: `+1-555-0101`, `+44-20-7123-4567`, `+82-2-1234-5678` (1 NULL)
44
+ - Usernames: lowercase single-word (`johndoe`, `janesmith`, `testuser`, etc.)
45
+
46
+ ## Naming & Cleanup
47
+
48
+ - **Temporary tables/FTS**: `stress_*` prefix. Drop at end.
49
+
50
+ ## Reporting Format
51
+
52
+ - ❌ Fail | ⚠️ Issue | 📦 Payload (monitor `metrics.tokenEstimate`) | ✅ Confirmed (inline only)
53
+
54
+ ### Error Message Quality Rating
55
+
56
+ | Level | Verdict |
57
+ | -------------------------------------- | ------- |
58
+ | 5 - Excellent (name + code + context) | ✅ |
59
+ | 4 - Good (name) | ✅ |
60
+ | 3 - Adequate (raw SQLite, informative) | ⚠️ |
61
+ | 2 - Poor (no object name) | ⚠️ |
62
+ | 1 - Useless (generic) | ❌ |
63
+
64
+ ## Structured Error Response Pattern
65
+
66
+ Handler error ✅ = JSON with `success` + `error`. MCP error ❌ = raw text, `isError: true`.
67
+
68
+ ---
69
+
70
+ ## text Group Tools — Native (19)
71
+
72
+ 1. sqlite_regex_extract
73
+ 2. sqlite_regex_match
74
+ 3. sqlite_text_split
75
+ 4. sqlite_text_concat
76
+ 5. sqlite_text_replace
77
+ 6. sqlite_text_trim
78
+ 7. sqlite_text_case
79
+ 8. sqlite_text_substring
80
+ 9. sqlite_fuzzy_match
81
+ 10. sqlite_phonetic_match
82
+ 11. sqlite_text_normalize
83
+ 12. sqlite_text_validate
84
+ 13. sqlite_advanced_search
85
+ 14. sqlite_text_sentiment
86
+ 15. sqlite_fts_create `[NATIVE ONLY]`
87
+ 16. sqlite_fts_search `[NATIVE ONLY]`
88
+ 17. sqlite_fts_rebuild `[NATIVE ONLY]`
89
+ 18. sqlite_fts_match_info `[NATIVE ONLY]`
90
+ 19. sqlite_fts_headline `[NATIVE ONLY]`
91
+
92
+ ### WASM (14)
93
+
94
+ Same minus the 5 FTS5 tools (items 15-19).
95
+
96
+ ---
97
+
98
+ ### Category 1: Regex Edge Cases
99
+
100
+ 1. `sqlite.text.regexMatch({table: "test_users", column: "email", pattern: "^[a-z]+\\.[a-z]+@"})` → match dotted local parts (test.user)
101
+ 2. `sqlite.text.regexMatch({table: "test_users", column: "phone", pattern: "^\\+1"})` → US phone numbers only (6 users, 1 NULL excluded)
102
+ 3. `sqlite.text.regexExtract({table: "test_users", column: "email", pattern: "@(.+)$", groupIndex: 1})` → full domain extraction
103
+ 4. `sqlite.text.regexMatch({table: "test_users", column: "bio", pattern: ".*"})` → should match all non-NULL bios (all 9 users have bios)
104
+
105
+ ---
106
+
107
+ ### Category 2: Fuzzy/Phonetic Matching Stress
108
+
109
+ 5. `sqlite.text.fuzzyMatch({table: "test_products", column: "name", search: "Keyborad", maxDistance: 3})` → find "Mechanical Keyboard" (Levenshtein)
110
+ 6. `sqlite.text.fuzzyMatch({table: "test_products", column: "name", search: "LAPTOP", maxDistance: 2, tokenize: true})` → match "Laptop" token in "Laptop Pro 15"
111
+ 7. `sqlite.text.fuzzyMatch({table: "test_products", column: "name", search: "xyznonexistent", maxDistance: 1})` → 0 results
112
+ 8. `sqlite.text.phoneticMatch({table: "test_users", column: "username", search: "jon", algorithm: "soundex"})` → 0 results (Soundex: "jon"=J500 ≠ "johndoe"=J530; single-word usernames aren't tokenized)
113
+ 9. `sqlite.text.phoneticMatch({table: "test_users", column: "username", search: "smith", algorithm: "soundex"})` → report behavior (janesmith contains "smith" as suffix)
114
+ 10. `sqlite.text.advancedSearch({table: "test_users", column: "username", searchTerm: "jhn", techniques: ["exact", "fuzzy", "phonetic"], fuzzyThreshold: 0.3})` → should find John via fuzzy/phonetic
115
+
116
+ ---
117
+
118
+ ### Category 3: Text Transformation Edge Cases
119
+
120
+ 11. `sqlite.text.normalize({table: "test_products", column: "name", mode: "strip_accents"})` → `"Café Décor Light"` → `"Cafe Decor Light"` — verify ALL rows returned
121
+ 12. `sqlite.text.normalize({table: "test_products", column: "name", mode: "nfkc"})` → NFKC normalization
122
+ 13. `sqlite.text.case({table: "test_users", column: "username", mode: "upper"})` → verify 9 uppercased usernames
123
+ 14. `sqlite.text.case({table: "test_users", column: "username", mode: "lower"})` → idempotent (already lowercase)
124
+ 15. `sqlite.text.substring({table: "test_users", column: "email", start: 1, length: 3})` → first 3 chars of each email
125
+
126
+ ---
127
+
128
+ ### Category 4: Validation Patterns
129
+
130
+ 16. `sqlite.text.validate({table: "test_users", column: "email", pattern: "email"})` → expect all 9 valid
131
+ 17. `sqlite.text.validate({table: "test_users", column: "phone", pattern: "phone"})` → report valid/invalid/null counts
132
+ 18. `sqlite.text.validate({table: "test_users", column: "email", pattern: "custom", customPattern: "^.+@.+\\..{2,}$"})` → custom regex validation
133
+
134
+ ---
135
+
136
+ ### Category 5: Sentiment Analysis Edge Cases
137
+
138
+ 19. `sqlite.text.sentiment({table: "test_articles", column: "body"})` → sentiment scores for all 8 articles
139
+ 20. Create `stress_sentiment_test` with rows: `"I love this!"` (positive), `"This is terrible"` (negative), `""` (empty), `NULL` → report behavior for edge cases
140
+
141
+ ---
142
+
143
+ ### Category 6: FTS5 State Integrity `[NATIVE ONLY]`
144
+
145
+ 21. `sqlite.text.ftsSearch({table: "test_articles_fts", query: "database"})` → results about databases
146
+ 22. `sqlite.text.ftsRebuild({table: "test_articles_fts"})` → success
147
+ 23. `sqlite.text.ftsSearch({table: "test_articles_fts", query: "database"})` → same results after rebuild (idempotent)
148
+ 24. `sqlite.text.ftsSearch({table: "test_articles_fts", query: "SQLite AND database"})` → boolean operator
149
+ 25. `sqlite.text.ftsSearch({table: "test_articles_fts", query: "\"full-text search\""})` → phrase query
150
+ 26. `sqlite.text.ftsHeadline({table: "test_articles_fts", query: "SQLite"})` → highlighted results
151
+
152
+ ---
153
+
154
+ ### Category 7: WASM Boundary Verification
155
+
156
+ For WASM testing only:
157
+
158
+ 27. Confirm FTS5 tools are NOT present in the tool list (WASM mode excludes them)
159
+ 28. All 14 non-FTS text tools should work identically in WASM and Native
160
+
161
+ ---
162
+
163
+ ### Category 8: Error Message Quality
164
+
165
+ 29. `sqlite.text.regexMatch({table: "nonexistent_table_xyz", column: "x", pattern: "."})` → structured error
166
+ 30. `sqlite.text.fuzzyMatch({table: "test_users", column: "nonexistent_col", search: "test"})` → structured error
167
+ 31. `sqlite.text.validate({table: "test_users", column: "email", pattern: "custom"})` → error about missing `customPattern`
168
+ 32. `sqlite.text.ftsSearch({table: "nonexistent_fts_xyz", query: "test"})` `[NATIVE ONLY]` → structured error
169
+
170
+ ---
171
+
172
+ ### Final Cleanup
173
+
174
+ Drop `stress_*` tables. Confirm `test_articles` row count is still 8. Verify FTS index integrity with `sqlite.text.ftsMatchInfo` `[NATIVE ONLY]`.
175
+
176
+ ## Post-Test Procedures
177
+
178
+ 1. **Cleanup**: Drop all `stress_*` objects
179
+ 2. **Fix EVERY finding** — ❌, ⚠️, 📦
180
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
181
+ 4. **Commit**: Stage and commit — do NOT push
182
+ 5. **Re-test**: After server rebuild
183
+ 6. **Token audit**: Report most expensive block
@@ -0,0 +1,136 @@
1
+ # db-mcp Advanced Stress Test — [transactions]
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
+ **Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
9
+
10
+ **Step 2:** Execute each numbered stress test below using `sqlite_execute_code` (code mode).
11
+
12
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
13
+
14
+ > **Note:** All 8 transaction tools are **`[NATIVE ONLY]`** — they are not available in WASM mode.
15
+
16
+ ## WASM Mode
17
+
18
+ > [!CAUTION]
19
+ > **Skip this entire prompt in WASM mode.** All 8 transaction tools are `[NATIVE ONLY]` — they are not registered in the WASM adapter. The `sqlite.transactions` namespace exists but contains 0 methods. Use `test-tool-group-codemode-wasm-degradation.md` to verify this behavior.
20
+
21
+ ## Code Mode Execution
22
+
23
+ - **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
24
+
25
+ All tests via `sqlite_execute_code`. Use `sqlite.transactions.*` for transaction tools, `sqlite.core.*` for read/write.
26
+ State persists across calls. Do NOT pass `readonly: true`.
27
+
28
+ > **⚠️ Transaction tests are sequential** — each depends on state from the previous. Run lifecycle tests individually, not batched.
29
+
30
+ ## Test Database Schema
31
+
32
+ | Table | Rows | Key Columns |
33
+ | ------------- | ---- | ---------------------------------------- |
34
+ | test_products | 16 | id, name, price, category |
35
+ | test_orders | 20 | id, product_id (FK), total_price, status |
36
+
37
+ ## Naming & Cleanup
38
+
39
+ - **Temporary tables**: `stress_*` prefix. Drop at end.
40
+ - If an active transaction is left open, roll it back before cleanup.
41
+
42
+ ## Reporting Format
43
+
44
+ - ❌ Fail | ⚠️ Issue | 📦 Payload (monitor `metrics.tokenEstimate`) | ✅ Confirmed (inline only)
45
+
46
+ ## Structured Error Response Pattern
47
+
48
+ Handler error ✅ = JSON with `success` + `error`. MCP error ❌ = raw text, `isError: true`.
49
+
50
+ ---
51
+
52
+ ## transactions Group Tools — Native Only (8)
53
+
54
+ 1. sqlite_transaction_begin
55
+ 2. sqlite_transaction_commit
56
+ 3. sqlite_transaction_rollback
57
+ 4. sqlite_transaction_savepoint
58
+ 5. sqlite_transaction_release
59
+ 6. sqlite_transaction_rollback_to
60
+ 7. sqlite_transaction_execute
61
+ 8. sqlite_transaction_status
62
+
63
+ ---
64
+
65
+ ### Category 1: Aborted Transaction Recovery
66
+
67
+ 15. `sqlite.transactions.begin()` → get transaction ID
68
+ 16. `sqlite.transactions.execute({statements: ["INSERT INTO nonexistent_table VALUES (1)"]})` → should fail
69
+ 17. Start new transaction → verify it works normally (no lingering aborted state)
70
+
71
+ ---
72
+
73
+ ### Category 2: Savepoint Stress Test
74
+
75
+ 18. `sqlite.transactions.begin()` → begin
76
+ 19. Create savepoint `sp1`
77
+ 20. `sqlite.core.writeQuery("INSERT INTO stress_tx_sp (id, val) VALUES (1, 'a')")` → insert within transaction (create `stress_tx_sp` first)
78
+ 21. Create savepoint `sp2`
79
+ 22. `sqlite.core.writeQuery("INSERT INTO stress_tx_sp (id, val) VALUES (2, 'b')")` → insert
80
+ 23. `sqlite.transactions.rollbackTo({name: "sp2"})` → should undo sp2's insert
81
+ 24. `sqlite.transactions.rollbackTo({name: "sp1"})` → should undo all inserts
82
+ 25. `sqlite.transactions.commit()` → only pre-sp1 state persists
83
+
84
+ ---
85
+
86
+ ### Category 3: Transaction Execute — Mixed Statements
87
+
88
+ 26. `sqlite.transactions.execute({statements: ["CREATE TABLE stress_tx_test (id INTEGER PRIMARY KEY, name TEXT)", "INSERT INTO stress_tx_test VALUES (1, 'alpha')", "INSERT INTO stress_tx_test VALUES (2, 'beta')"]})` → success, 3 statements
89
+ 27. Verify `stress_tx_test` exists with 2 rows
90
+
91
+ ---
92
+
93
+ ### Category 4: Transaction Execute — Failure Rollback
94
+
95
+ 28. `sqlite.transactions.execute({statements: ["CREATE TABLE stress_tx_fail (id INT)", "INSERT INTO nonexistent_xyz VALUES (1)", "CREATE TABLE stress_tx_fail2 (id INT)"]})` → failure
96
+ 29. Verify: `stress_tx_fail` does NOT exist (atomic rollback worked)
97
+
98
+ ---
99
+
100
+ ### Category 5: Rapid State Transitions
101
+
102
+ 30. Begin → commit immediately (empty transaction)
103
+ 31. Begin → rollback immediately (empty transaction)
104
+ 32. `sqlite.transactions.status()` → verify `{active: false}` after both
105
+ 33. Begin → savepoint → release → commit (minimal lifecycle)
106
+
107
+ ---
108
+
109
+ ### Category 6: Error Message Quality
110
+
111
+ 34. `sqlite.transactions.rollback()` with no active transaction → report behavior
112
+ 35. `sqlite.transactions.release({name: "nonexistent_sp_xyz"})` → structured error
113
+ 36. `sqlite.transactions.execute({statements: []})` → report behavior for empty array
114
+
115
+ ---
116
+
117
+ ### Category 7: WASM Boundary Verification
118
+
119
+ For WASM testing only:
120
+
121
+ 37. Confirm all 8 transaction tools are NOT present in the tool list
122
+
123
+ ---
124
+
125
+ ### Final Cleanup
126
+
127
+ Drop `stress_tx_sp`, `stress_tx_test`, `stress_tx_fail` if they exist. Confirm `test_products` (16 rows) and `test_orders` (20 rows) unchanged.
128
+
129
+ ## Post-Test Procedures
130
+
131
+ 1. **Cleanup**: Roll back any active transaction, drop all `stress_*` objects
132
+ 2. **Fix EVERY finding** — ❌, ⚠️, 📦
133
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
134
+ 4. **Commit**: Stage and commit — do NOT push
135
+ 5. **Re-test**: After server rebuild
136
+ 6. **Token audit**: Report most expensive block
@@ -0,0 +1,141 @@
1
+ # db-mcp Advanced Stress Test — [vector]
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
+ **Step 1:** Read `C:\Users\chris\Desktop\db-mcp\src\constants\server-instructions\gotchas.md` using `view_file`.
9
+
10
+ **Step 2:** Execute each numbered stress test below using `sqlite_execute_code` (code mode).
11
+
12
+ **Step 3:** The agent should update C:\Users\chris\Desktop\db-mcp\UNRELEASED.md with any/all changes/fixes.
13
+
14
+ ## WASM Mode
15
+
16
+ > When testing against a **WASM backend** (`--sqlite` / sql.js): All 11 vector tools are fully WASM-compatible. No categories to skip or adjust.
17
+
18
+ ## Code Mode Execution
19
+
20
+ - **Code Over Docs**: Fix the handler code if standards (Structured Errors/Zod) are violated. Do NOT change docs/prompts to accommodate broken code.
21
+
22
+ All tests via `sqlite_execute_code`. Use `sqlite.vector.*` for vector tools, `sqlite.core.*` for read/write.
23
+ State persists across calls. Do NOT pass `readonly: true`. Group related tests into single calls.
24
+
25
+ ## Test Database Schema
26
+
27
+ | Table | Rows | Key Columns |
28
+ | --------------- | ---- | --------------------------------------------------------- |
29
+ | test_embeddings | 20 | id, content, category, embedding (8-dim JSON float array) |
30
+
31
+ **Categories**: database, fitness, food, tech, travel (each ~4 rows)
32
+ **Row 1**: content="Machine learning fundamentals", embedding=[0.12, 0.45, -0.23, 0.78, 0.34, -0.56, 0.89, 0.01]
33
+
34
+ > Vector tools use pure JS computations with JSON-stored vectors — all 11 tools work identically in WASM and Native.
35
+
36
+ ## Naming & Cleanup
37
+
38
+ - **Temporary tables**: `stress_*` prefix. Drop at end.
39
+
40
+ ## Reporting Format
41
+
42
+ - ❌ Fail | ⚠️ Issue | 📦 Payload (monitor `metrics.tokenEstimate`) | ✅ Confirmed (inline only)
43
+
44
+ ## Structured Error Response Pattern
45
+
46
+ Handler error ✅ = JSON with `success` + `error`. MCP error ❌ = raw text, `isError: true`.
47
+
48
+ ---
49
+
50
+ ## vector Group Tools (11)
51
+
52
+ 1. sqlite_vector_create_table
53
+ 2. sqlite_vector_store
54
+ 3. sqlite_vector_batch_store
55
+ 4. sqlite_vector_search
56
+ 5. sqlite_vector_get
57
+ 6. sqlite_vector_delete
58
+ 7. sqlite_vector_count
59
+ 8. sqlite_vector_stats
60
+ 9. sqlite_vector_dimensions
61
+ 10. sqlite_vector_normalize
62
+ 11. sqlite_vector_distance
63
+
64
+ ---
65
+
66
+ ### Category 1: Boundary Values
67
+
68
+ > **Note:** `createTable` uses `tableName`, other ops use `table`. Store/batch-store require `idColumn` and `vectorColumn`.
69
+
70
+ **1.1 Empty Vector Table**
71
+
72
+ 1. `sqlite.vector.createTable({tableName: "stress_vec_empty", dimensions: 4})` → success
73
+ 2. `sqlite.vector.count({table: "stress_vec_empty"})` → `{count: 0}`
74
+ 3. `sqlite.vector.search({table: "stress_vec_empty", vectorColumn: "vector", queryVector: [1, 2, 3, 4], metric: "cosine", limit: 5})` → empty results (not error)
75
+ 4. `sqlite.vector.stats({table: "stress_vec_empty", vectorColumn: "vector"})` → graceful: `{count: 0, message: "No valid vectors found"}`
76
+ 5. `sqlite.vector.dimensions({table: "stress_vec_empty", vectorColumn: "vector"})` → `{dimensions: null, message: "No vectors found"}` (inferred from data)
77
+
78
+ **1.2 Single-Vector Table**
79
+
80
+ 6. `sqlite.vector.store({table: "stress_vec_empty", idColumn: "id", vectorColumn: "vector", id: 1, vector: [1, 0, 0, 0]})` → success
81
+ 7. `sqlite.vector.search({table: "stress_vec_empty", vectorColumn: "vector", queryVector: [1, 0, 0, 0], metric: "cosine", limit: 5})` → 1 result, similarity ≈ 1
82
+
83
+ ---
84
+
85
+ ### Category 2: Distance Metric Verification
86
+
87
+ 8. `sqlite.vector.distance({vector1: [1, 0, 0], vector2: [0, 1, 0], metric: "cosine"})` → ≈ 1.0 (orthogonal)
88
+ 9. `sqlite.vector.distance({vector1: [1, 0, 0], vector2: [1, 0, 0], metric: "cosine"})` → ≈ 0.0 (identical)
89
+ 10. `sqlite.vector.distance({vector1: [1, 0, 0], vector2: [-1, 0, 0], metric: "cosine"})` → ≈ 2.0 (opposite)
90
+ 11. `sqlite.vector.distance({vector1: [3, 4], vector2: [0, 0], metric: "euclidean"})` → exactly 5.0
91
+ 12. `sqlite.vector.distance({vector1: [1, 2, 3], vector2: [1, 2, 3], metric: "euclidean"})` → exactly 0.0
92
+ 13. `sqlite.vector.normalize({vector: [3, 4]})` → `{normalized: [0.6, 0.8], originalMagnitude: 5.0}`
93
+ 14. `sqlite.vector.normalize({vector: [0, 0, 0]})` → `{normalized: [0, 0, 0], originalMagnitude: 0}` (zero vector, no crash)
94
+
95
+ ---
96
+
97
+ ### Category 3: Dimension Mismatch
98
+
99
+ > Dimension validation on store is best-effort. `distance` enforces strictly.
100
+
101
+ 15. `sqlite.vector.store({table: "stress_vec_empty", idColumn: "id", vectorColumn: "vector", id: 2, vector: [1, 2]})` → dimension mismatch error (table has 4-dim rows)
102
+ 16. `sqlite.vector.search({table: "stress_vec_empty", vectorColumn: "vector", queryVector: [1, 2], metric: "cosine"})` → search runs (dimension mismatch silently handled via try/catch)
103
+ 17. `sqlite.vector.distance({vector1: [1, 2, 3], vector2: [1, 2], metric: "cosine"})` → structured error: "Vector dimensions must match"
104
+
105
+ ---
106
+
107
+ ### Category 4: Batch Operations
108
+
109
+ 18. `sqlite.vector.batchStore({table: "stress_vec_empty", idColumn: "id", vectorColumn: "vector", items: []})` → `{stored: 0, message: "No items provided"}`
110
+ 19. `sqlite.vector.batchStore(...)` with 50 vectors into `stress_vec_empty` → `{stored: 50}`
111
+ 20. `sqlite.vector.count({table: "stress_vec_empty"})` → `{count: 51}` (1 from earlier + 50 batch)
112
+
113
+ ---
114
+
115
+ ### Category 5: Category Filtering
116
+
117
+ 21. `sqlite.vector.search({table: "test_embeddings", vectorColumn: "embedding", queryVector: [0.12, 0.45, -0.23, 0.78, 0.34, -0.56, 0.89, 0.01], metric: "cosine", limit: 20, whereClause: "category = 'tech'"})` → only tech results (4 rows)
118
+ 22. `sqlite.vector.search({table: "test_embeddings", vectorColumn: "embedding", queryVector: [0.12, 0.45, -0.23, 0.78, 0.34, -0.56, 0.89, 0.01], metric: "cosine", limit: 20, whereClause: "category = 'nonexistent'"})` → 0 results (not error)
119
+
120
+ ---
121
+
122
+ ### Category 6: Error Message Quality
123
+
124
+ 23. `sqlite.vector.search({table: "nonexistent_table_xyz", vectorColumn: "v", queryVector: [1, 2, 3], metric: "cosine"})` → structured error mentioning table name
125
+ 24. `sqlite.vector.get({table: "test_embeddings", idColumn: "id", vectorColumn: "embedding", id: 99999})` → `{success: false, error: "Vector not found"}`
126
+ 25. `sqlite.vector.delete({table: "test_embeddings", idColumn: "id", ids: [99999]})` → `{success: true, deleted: 0}` (idempotent)
127
+
128
+ ---
129
+
130
+ ### Final Cleanup
131
+
132
+ Drop `stress_vec_empty`. Confirm `test_embeddings` count is still 20.
133
+
134
+ ## Post-Test Procedures
135
+
136
+ 1. **Cleanup**: Drop all `stress_*` objects
137
+ 2. **Fix EVERY finding** — ❌, ⚠️, 📦
138
+ 3. **Validate**: Instruct the user to run the test suite (Vitest/Playwright), lint, and typecheck. Do NOT run them yourself.
139
+ 4. **Commit**: Stage and commit — do NOT push
140
+ 5. **Re-test**: After server rebuild
141
+ 6. **Token audit**: Report most expensive block