@neverinfamous/mysql-mcp 2.2.0 → 2.3.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 (213) hide show
  1. package/.github/workflows/docker-publish.yml +1 -2
  2. package/CHANGELOG.md +85 -0
  3. package/CODE_MODE.md +245 -0
  4. package/DOCKER_README.md +59 -36
  5. package/README.md +65 -42
  6. package/VERSION +1 -1
  7. package/dist/adapters/mysql/MySQLAdapter.d.ts +4 -0
  8. package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
  9. package/dist/adapters/mysql/MySQLAdapter.js +9 -0
  10. package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
  11. package/dist/adapters/mysql/prompts/index.d.ts +8 -1
  12. package/dist/adapters/mysql/prompts/index.d.ts.map +1 -1
  13. package/dist/adapters/mysql/prompts/index.js +8 -1
  14. package/dist/adapters/mysql/prompts/index.js.map +1 -1
  15. package/dist/adapters/mysql/prompts/routerSetup.d.ts.map +1 -1
  16. package/dist/adapters/mysql/prompts/routerSetup.js +5 -0
  17. package/dist/adapters/mysql/prompts/routerSetup.js.map +1 -1
  18. package/dist/adapters/mysql/resources/capabilities.d.ts.map +1 -1
  19. package/dist/adapters/mysql/resources/capabilities.js +6 -5
  20. package/dist/adapters/mysql/resources/capabilities.js.map +1 -1
  21. package/dist/adapters/mysql/resources/index.d.ts +9 -1
  22. package/dist/adapters/mysql/resources/index.d.ts.map +1 -1
  23. package/dist/adapters/mysql/resources/index.js +9 -1
  24. package/dist/adapters/mysql/resources/index.js.map +1 -1
  25. package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
  26. package/dist/adapters/mysql/tools/admin/backup.js +3 -3
  27. package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
  28. package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
  29. package/dist/adapters/mysql/tools/admin/maintenance.js +5 -5
  30. package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
  31. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
  32. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +26 -5
  33. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
  34. package/dist/adapters/mysql/tools/codemode/index.d.ts +38 -0
  35. package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -0
  36. package/dist/adapters/mysql/tools/codemode/index.js +203 -0
  37. package/dist/adapters/mysql/tools/codemode/index.js.map +1 -0
  38. package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
  39. package/dist/adapters/mysql/tools/core.js +32 -20
  40. package/dist/adapters/mysql/tools/core.js.map +1 -1
  41. package/dist/adapters/mysql/tools/events.js +18 -6
  42. package/dist/adapters/mysql/tools/events.js.map +1 -1
  43. package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
  44. package/dist/adapters/mysql/tools/json/core.js +5 -5
  45. package/dist/adapters/mysql/tools/json/core.js.map +1 -1
  46. package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
  47. package/dist/adapters/mysql/tools/json/helpers.js +9 -3
  48. package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
  49. package/dist/adapters/mysql/tools/partitioning.d.ts.map +1 -1
  50. package/dist/adapters/mysql/tools/partitioning.js +38 -6
  51. package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
  52. package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
  53. package/dist/adapters/mysql/tools/performance/analysis.js +67 -20
  54. package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
  55. package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
  56. package/dist/adapters/mysql/tools/performance/optimization.js +36 -6
  57. package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
  58. package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
  59. package/dist/adapters/mysql/tools/security/data-protection.js +9 -4
  60. package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
  61. package/dist/adapters/mysql/tools/shell/common.d.ts.map +1 -1
  62. package/dist/adapters/mysql/tools/shell/common.js +28 -2
  63. package/dist/adapters/mysql/tools/shell/common.js.map +1 -1
  64. package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
  65. package/dist/adapters/mysql/tools/shell/restore.js +54 -4
  66. package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
  67. package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
  68. package/dist/adapters/mysql/tools/spatial/operations.js +10 -2
  69. package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
  70. package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
  71. package/dist/adapters/mysql/tools/spatial/setup.js +18 -0
  72. package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
  73. package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
  74. package/dist/adapters/mysql/tools/sysschema/resources.js +5 -0
  75. package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
  76. package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
  77. package/dist/adapters/mysql/tools/text/fulltext.js +6 -4
  78. package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
  79. package/dist/adapters/mysql/tools/text/processing.d.ts.map +1 -1
  80. package/dist/adapters/mysql/tools/text/processing.js +10 -45
  81. package/dist/adapters/mysql/tools/text/processing.js.map +1 -1
  82. package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
  83. package/dist/adapters/mysql/tools/transactions.js +8 -8
  84. package/dist/adapters/mysql/tools/transactions.js.map +1 -1
  85. package/dist/adapters/mysql/types.d.ts +968 -78
  86. package/dist/adapters/mysql/types.d.ts.map +1 -1
  87. package/dist/adapters/mysql/types.js +1084 -78
  88. package/dist/adapters/mysql/types.js.map +1 -1
  89. package/dist/auth/scopes.d.ts.map +1 -1
  90. package/dist/auth/scopes.js +1 -0
  91. package/dist/auth/scopes.js.map +1 -1
  92. package/dist/cli/args.d.ts.map +1 -1
  93. package/dist/cli/args.js +12 -0
  94. package/dist/cli/args.js.map +1 -1
  95. package/dist/codemode/api.d.ts +69 -0
  96. package/dist/codemode/api.d.ts.map +1 -0
  97. package/dist/codemode/api.js +1035 -0
  98. package/dist/codemode/api.js.map +1 -0
  99. package/dist/codemode/index.d.ts +13 -0
  100. package/dist/codemode/index.d.ts.map +1 -0
  101. package/dist/codemode/index.js +17 -0
  102. package/dist/codemode/index.js.map +1 -0
  103. package/dist/codemode/sandbox-factory.d.ts +72 -0
  104. package/dist/codemode/sandbox-factory.d.ts.map +1 -0
  105. package/dist/codemode/sandbox-factory.js +88 -0
  106. package/dist/codemode/sandbox-factory.js.map +1 -0
  107. package/dist/codemode/sandbox.d.ts +96 -0
  108. package/dist/codemode/sandbox.d.ts.map +1 -0
  109. package/dist/codemode/sandbox.js +345 -0
  110. package/dist/codemode/sandbox.js.map +1 -0
  111. package/dist/codemode/security.d.ts +44 -0
  112. package/dist/codemode/security.d.ts.map +1 -0
  113. package/dist/codemode/security.js +149 -0
  114. package/dist/codemode/security.js.map +1 -0
  115. package/dist/codemode/types.d.ts +137 -0
  116. package/dist/codemode/types.d.ts.map +1 -0
  117. package/dist/codemode/types.js +46 -0
  118. package/dist/codemode/types.js.map +1 -0
  119. package/dist/codemode/worker-sandbox.d.ts +82 -0
  120. package/dist/codemode/worker-sandbox.d.ts.map +1 -0
  121. package/dist/codemode/worker-sandbox.js +244 -0
  122. package/dist/codemode/worker-sandbox.js.map +1 -0
  123. package/dist/codemode/worker-script.d.ts +8 -0
  124. package/dist/codemode/worker-script.d.ts.map +1 -0
  125. package/dist/codemode/worker-script.js +113 -0
  126. package/dist/codemode/worker-script.js.map +1 -0
  127. package/dist/constants/ServerInstructions.d.ts +1 -1
  128. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  129. package/dist/constants/ServerInstructions.js +33 -9
  130. package/dist/constants/ServerInstructions.js.map +1 -1
  131. package/dist/filtering/ToolConstants.d.ts +11 -11
  132. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  133. package/dist/filtering/ToolConstants.js +37 -19
  134. package/dist/filtering/ToolConstants.js.map +1 -1
  135. package/dist/filtering/ToolFilter.d.ts.map +1 -1
  136. package/dist/filtering/ToolFilter.js +12 -0
  137. package/dist/filtering/ToolFilter.js.map +1 -1
  138. package/dist/server/McpServer.js +1 -1
  139. package/dist/server/McpServer.js.map +1 -1
  140. package/dist/types/modules/server.d.ts +2 -0
  141. package/dist/types/modules/server.d.ts.map +1 -1
  142. package/dist/types/modules/tools.d.ts +1 -1
  143. package/dist/types/modules/tools.d.ts.map +1 -1
  144. package/dist/utils/logger.d.ts +1 -1
  145. package/dist/utils/logger.d.ts.map +1 -1
  146. package/dist/utils/logger.js.map +1 -1
  147. package/package.json +12 -7
  148. package/releases/v2.2.0-release-notes.md +18 -18
  149. package/releases/v2.3.0-release-notes.md +191 -0
  150. package/src/__tests__/perf.test.ts +12 -12
  151. package/src/adapters/mysql/MySQLAdapter.ts +10 -0
  152. package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +1 -1
  153. package/src/adapters/mysql/prompts/index.ts +8 -1
  154. package/src/adapters/mysql/prompts/routerSetup.ts +5 -0
  155. package/src/adapters/mysql/resources/__tests__/capabilities.test.ts +50 -1
  156. package/src/adapters/mysql/resources/capabilities.ts +6 -4
  157. package/src/adapters/mysql/resources/index.ts +9 -1
  158. package/src/adapters/mysql/tools/__tests__/core.test.ts +68 -0
  159. package/src/adapters/mysql/tools/__tests__/events.test.ts +56 -2
  160. package/src/adapters/mysql/tools/__tests__/json_core.test.ts +1 -1
  161. package/src/adapters/mysql/tools/__tests__/json_helpers.test.ts +46 -4
  162. package/src/adapters/mysql/tools/__tests__/replication.test.ts +144 -42
  163. package/src/adapters/mysql/tools/__tests__/security.test.ts +39 -0
  164. package/src/adapters/mysql/tools/__tests__/spatial.test.ts +39 -7
  165. package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +35 -3
  166. package/src/adapters/mysql/tools/__tests__/transactions.test.ts +3 -5
  167. package/src/adapters/mysql/tools/admin/backup.ts +8 -3
  168. package/src/adapters/mysql/tools/admin/maintenance.ts +8 -4
  169. package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +35 -0
  170. package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +26 -5
  171. package/src/adapters/mysql/tools/codemode/index.ts +249 -0
  172. package/src/adapters/mysql/tools/core.ts +44 -27
  173. package/src/adapters/mysql/tools/events.ts +23 -7
  174. package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +59 -14
  175. package/src/adapters/mysql/tools/json/core.ts +8 -4
  176. package/src/adapters/mysql/tools/json/helpers.ts +13 -3
  177. package/src/adapters/mysql/tools/partitioning.ts +53 -6
  178. package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +227 -4
  179. package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +35 -0
  180. package/src/adapters/mysql/tools/performance/analysis.ts +75 -21
  181. package/src/adapters/mysql/tools/performance/optimization.ts +44 -6
  182. package/src/adapters/mysql/tools/security/data-protection.ts +10 -4
  183. package/src/adapters/mysql/tools/shell/__tests__/common.test.ts +46 -0
  184. package/src/adapters/mysql/tools/shell/__tests__/restore.test.ts +28 -1
  185. package/src/adapters/mysql/tools/shell/common.ts +34 -2
  186. package/src/adapters/mysql/tools/shell/restore.ts +70 -7
  187. package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +29 -0
  188. package/src/adapters/mysql/tools/spatial/operations.ts +13 -2
  189. package/src/adapters/mysql/tools/spatial/setup.ts +23 -0
  190. package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +21 -0
  191. package/src/adapters/mysql/tools/sysschema/resources.ts +5 -0
  192. package/src/adapters/mysql/tools/text/fulltext.ts +13 -5
  193. package/src/adapters/mysql/tools/text/processing.ts +20 -49
  194. package/src/adapters/mysql/tools/transactions.ts +11 -7
  195. package/src/adapters/mysql/types.ts +1241 -87
  196. package/src/auth/scopes.ts +1 -0
  197. package/src/cli/args.ts +14 -0
  198. package/src/codemode/api.ts +1224 -0
  199. package/src/codemode/index.ts +51 -0
  200. package/src/codemode/sandbox-factory.ts +146 -0
  201. package/src/codemode/sandbox.ts +450 -0
  202. package/src/codemode/security.ts +188 -0
  203. package/src/codemode/types.ts +194 -0
  204. package/src/codemode/worker-sandbox.ts +326 -0
  205. package/src/codemode/worker-script.ts +144 -0
  206. package/src/constants/ServerInstructions.ts +33 -9
  207. package/src/filtering/ToolConstants.ts +37 -19
  208. package/src/filtering/ToolFilter.ts +15 -0
  209. package/src/filtering/__tests__/ToolFilter.test.ts +65 -38
  210. package/src/server/McpServer.ts +1 -1
  211. package/src/types/modules/server.ts +3 -0
  212. package/src/types/modules/tools.ts +2 -1
  213. package/src/utils/logger.ts +2 -1
@@ -2,7 +2,6 @@ name: Build and Push Docker Images
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [master]
6
5
  tags: ["v*"]
7
6
  pull_request:
8
7
  branches: [master]
@@ -311,7 +310,7 @@ jobs:
311
310
  password: ${{ secrets.DOCKER_PASSWORD }}
312
311
  repository: ${{ env.IMAGE_NAME }}
313
312
  readme-filepath: ./DOCKER_README.md
314
- short-description: "MySQL MCP with 191 tools, OAuth 2.1, HTTP Streamable, Smart Tool Filtering & Connection Pooling."
313
+ short-description: "MySQL MCP Server: 193 tools, Code Mode, Tool Filtering, Connection Pooling, HTTP/SSE & OAuth 2.1"
315
314
 
316
315
  - name: Deployment Summary
317
316
  if: github.ref == 'refs/heads/master'
package/CHANGELOG.md CHANGED
@@ -7,6 +7,89 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.3.0] - 2026-02-18
11
+
12
+ ### Fixed
13
+
14
+ - **`mysql://capabilities` Feature Flags on MySQL 9.x+** — `json` and `gtid` feature flags incorrectly reported `false` on MySQL 9.6.0 because detection used `startsWith("8.")` prefix matching, which doesn't match version strings like `"9.6.0"`. Replaced with `parseInt`-based major version comparison (`>= 8`) that handles 9.x, 10.x, and all future versions while preserving legacy 5.6/5.7 fallbacks.
15
+
16
+ - **README / DOCKER_README Documentation Audit** — Corrected multiple stale numerical claims across both READMEs: meta-group/shortcut count (7→11), ecosystem Option 3 tool count (41→42), cluster Option 2 tool count (10→11, reflects codemode auto-injection), test badge (1794→1833), coverage badge (94%→86%), test runtime (~62s→~80s), and branch coverage (~81%→~72%). Also fixed stale JSDoc comments in `prompts/index.ts` (14→19 total) and `resources/index.ts` (12→18 total) to match actual function return counts.
17
+
18
+ - **`mysqlsh_export_table` / Shell Dump Specific Error Extraction** — When `util.exportTable()` or other dump utilities fail with "Fatal error during dump", the error message now extracts specific MySQL `ERROR:` lines from stderr (e.g., `"Unknown column 'x' in 'where clause'"`) instead of returning the generic privilege-hint message. The generic message is retained as a fallback only when no specific `ERROR:` lines are found in stderr.
19
+ - **Code Mode Backup `help()` Examples** — `mysql.backup.help()` examples contained two inaccuracies: `importData` used `filePath` (a string path) instead of `data` (an array of row objects), and `restoreDump` used `filePath` instead of `filename`. Also fixed `POSITIONAL_PARAM_MAP` entry for `restoreDump` (`filePath` → `filename`).
20
+ - **Code Mode Security `passwordValidate` Positional Shorthand** — `mysql.security.passwordValidate("weak")` failed with a ZodError because `passwordValidate` was missing from `POSITIONAL_PARAM_MAP`. The string argument fell through to the generic fallback (`{ sql, query, table, name }`), leaving `password` undefined. Added `passwordValidate: "password"` entry so single-string positional calls work correctly.
21
+ - **Code Mode Optimization `help()` Examples** — `mysql.optimization.help()` examples contained three inaccuracies: `indexRecommendation` used `sql` instead of `table`, `indexUsage` was listed (belongs to performance group, not optimization), and `forceIndex` used `sql`/`index` instead of `query`/`indexName`. Also removed broken `usage: "indexUsage"` alias from `METHOD_ALIASES.optimization` — `indexUsage` is a performance method, so this alias could not resolve.
22
+ - **Code Mode Security `help()` Alias Misclassification** — `mysql.security.help()` listed `audit` and `firewallRules` as aliases-only instead of primary methods (7 methods + 9 aliases instead of 9 + 7). Caused by self-referential entries in `METHOD_ALIASES.security` (`audit: "audit"`, `firewallRules: "firewallRules"`) — `createSandboxBindings` excludes alias keys from the canonical methods list, so matching names were filtered out. Fix: removed both self-referential entries.
23
+ - **Text Tool Split Schema Violations (`mysql_substring`, `mysql_concat`, `mysql_collation_convert`)** — All three tools used inline Zod schemas without parameter alias support, causing `tableName`/`name` aliases for `table` and the `filter` alias for `where` to be silently ignored. Replaced inline schemas with proper Dual-Schema definitions (`SubstringSchemaBase`/`SubstringSchema`, `ConcatSchemaBase`/`ConcatSchema`, `CollationConvertSchemaBase`/`CollationConvertSchema`) in `types.ts`, matching the pattern used by `mysql_regexp_match`, `mysql_like_search`, and `mysql_soundex`. `mysql_collation_convert` also gained `col` alias support for `column`.
24
+ - **`mysql_security_mask_data` Credit Card Warning Accuracy** — Warning message for short credit card values said "expected at least 8 digits" but the guard (`<= 8`) correctly fully-masks 8-digit values since showing first 4 + last 4 would expose all digits with zero masking. Updated warning to "expected more than 8 digits" to match actual behavior.
25
+ - **`ServerInstructions.ts` Credit Card Masking Threshold Wording** — Documentation said "requires at least 8 digits" but the guard (`<= 8`) fully-masks values with 8 or fewer digits. Updated to "requires more than 8 digits; values with 8 or fewer digits are fully masked" to match actual behavior.
26
+ - **`mysql_security_mask_data` Partial Masking Silent No-Op** — Partial masking silently returned the original value unchanged when `keepFirst + keepLast >= value.length`, with no indication that masking was ineffective. Now returns a `warning` field ("Masking ineffective: keepFirst + keepLast covers entire value length; returned unchanged"), matching the warning pattern used by credit card short-value masking.
27
+ - **Code Mode Security Group Registration** — All 9 security tools (`sslStatus`, `encryptionStatus`, `userPrivileges`, `sensitiveTables`, `audit`, `firewallStatus`, `firewallRules`, `maskData`, `passwordValidate`) were inaccessible in code mode, returning `TypeError: ... is not a function`. Root cause: `security` was in the `keepPrefix` set in `toolNameToMethodName`, so `mysql_security_ssl_status` → `securitySslStatus`. But `METHOD_ALIASES.security` and `GROUP_EXAMPLES.security` used stripped names (`sslStatus`, `audit`, etc.), causing all alias registrations and help examples to fail. Fix: removed `security` from `keepPrefix` so tools resolve directly to short names.
28
+ - **`mysql_security_mask_data` Credit Card 8-Digit Masking** — Credit card masking returned all 8 digits unmasked when the input contained exactly 8 digits. The guard `ccDigits.length < 8` missed the boundary case where `slice(0, 4)` + `slice(-4)` = all 8 digits with zero mask characters in between. Changed to `ccDigits.length <= 8` so 8-digit values are fully masked with a warning, consistent with shorter inputs.
29
+ - **Code Mode Stats Group Registration** — All 8 stats tools (`descriptive`, `percentiles`, `correlation`, `distribution`, `timeSeries`, `regression`, `sampling`, `histogram`) were inaccessible in code mode, returning `TypeError: ... is not a function`. Root cause: `stats` was in the `keepPrefix` set in `toolNameToMethodName`, so `mysql_stats_descriptive` → `statsDescriptive`. But `METHOD_ALIASES.stats` listed every `statsXxx` name as an alias key pointing to the short form (`descriptive`), which never existed as a canonical method. This caused `createGroupApi` to skip all alias registrations and `createSandboxBindings` to filter all methods out of `canonicalMethodNames`. Fix: removed `stats` from `keepPrefix` so tools resolve directly to short names (`descriptive`, `percentiles`, etc.), and removed the 8 now-redundant `statsXxx` prefix aliases.
30
+ - **Code Mode Stats `help()` Examples** — `mysql.stats.help()` examples contained two inaccuracies: `percentiles` example used fractional values (`[0.5, 0.95, 0.99]`) instead of the expected integer percentiles (`[50, 95, 99]`), and `timeSeries` example used `interval: '1 HOUR'` instead of the valid enum value `interval: 'hour'`.
31
+ - **Code Mode Spatial `help()` Examples** — `mysql.spatial.help()` examples used incorrect parameter names: `distance`/`distanceSphere` used `column` instead of `spatialColumn` and `{ x, y }` / `{ lat, lng }` instead of `{ longitude, latitude }` for the `point` object; `point` used `{ x, y }` instead of `{ longitude, latitude }`; `buffer` used `{ table, column }` instead of `{ geometry, distance }`. Also fixed `POSITIONAL_PARAM_MAP` entries for `distance`/`distanceSphere` (`column` → `spatialColumn`) and `point` (`x`/`y` → `longitude`/`latitude`).
32
+ - **Code Mode Spatial Group Registration** — All 12 spatial tools (`createColumn`, `createIndex`, `distance`, `distanceSphere`, `point`, `polygon`, `contains`, `within`, `intersection`, `buffer`, `transform`, `geojson`) were inaccessible in code mode, returning `TypeError: ... is not a function`. Root cause: `spatial` was in the `keepPrefix` set in `toolNameToMethodName`, so `mysql_spatial_distance` → `spatialDistance`. But `METHOD_ALIASES.spatial`, `GROUP_EXAMPLES.spatial`, and `POSITIONAL_PARAM_MAP` all used stripped names (`distance`, `point`, etc.), causing all alias registrations and method lookups to fail. Fix: removed `spatial` from `keepPrefix` so tools resolve directly to short names. Also removed the redundant `geojson` → `geojson` self-alias.
33
+ - **`mysql_spatial_create_index` Duplicate Index Error Consistency** — Tool returned `{ success: false, error: "Query failed: Execute failed: Duplicate key name '...'" }` for duplicate indexes — a raw MySQL error in the generic `error` field. Now returns `{ success: false, reason: "Index '...' already exists on table '...'" }` with a user-friendly message, consistent with `mysql_spatial_create_column` (duplicate column) and `mysql_fulltext_create` (duplicate index) error handling.
34
+ - **Code Mode JSON `help()` Examples** — `mysql.json.help()` examples contained inaccuracies: `contains` example used `candidate` instead of `value`, and `merge` example used `base`/`overlay` with raw objects instead of `json1`/`json2` with JSON strings. Also fixed `POSITIONAL_PARAM_MAP` entries: `contains` (`candidate` → `value`), `merge` (`base`/`overlay` → `json1`/`json2`), and `diff` (`doc1`/`doc2` → `json1`/`json2`).
35
+ - **`mysql_spatial_create_index` Duplicate Column Index Detection** — Tool allowed creating a second spatial index on a column that already had one (e.g., creating `idx_spatial_test_locations_geom` alongside the seeded `idx_locations_geom` on the same `geom` column). Now pre-checks `information_schema.STATISTICS` for existing `SPATIAL` indexes on the target column before attempting creation. Returns `{ success: false, reason: "Spatial index '...' already exists on column '...' of table '...'" }` when a duplicate is found.
36
+ - **`mysql_spatial_buffer` Large GeoJSON Payload with Geographic SRIDs** — Buffering with SRID 4326 produced coordinates with 14+ decimal places (e.g., `-122.41939999999998`), causing unnecessarily large GeoJSON payloads. Added `precision` parameter (default: 6, ~0.11m accuracy) that controls `ST_AsGeoJSON` decimal digit truncation. Lower values (e.g., 2) significantly reduce payload size for geographic buffers where the `segments` parameter is ineffective.
37
+
38
+ - **Code Mode `sysSchemaStats` Help Example** — `mysql.sysschema.help()` listed `sysSchemaStats({ table: 'users' })` as an example, but the tool accepts `schema`, not `table`. Updated to `sysSchemaStats({ schema: 'testdb' })`.
39
+ - **`mysql_sys_memory_summary` Response Consistency** — Tool response lacked count fields, unlike other sysschema tools (e.g., `mysql_sys_innodb_lock_waits` which includes `count`). Added `globalMemoryCount` and `memoryByUserCount` to the response for response shape consistency across the sysschema group.
40
+ - **`mysql_sys_schema_stats` Response Consistency** — Tool response lacked per-array count fields, unlike `mysql_sys_memory_summary` (which includes `globalMemoryCount` and `memoryByUserCount`). Added `tableStatisticsCount`, `indexStatisticsCount`, and `autoIncrementStatusCount` to the response. Also updated `ServerInstructions.ts` to document the count fields for both `mysql_sys_schema_stats` and `mysql_sys_memory_summary`.
41
+
42
+ - **`mysql_event_alter` Clause Ordering** — Tool generated invalid SQL when combining `newName` with other clauses (`comment`, `enabled`, `body`). The handler emitted clauses as `ENABLE/DISABLE → COMMENT → RENAME TO → DO`, but MySQL's `ALTER EVENT` syntax requires `RENAME TO → ENABLE/DISABLE → COMMENT → DO`. Reordered all clause generation to match the MySQL-required syntax order: `ON SCHEDULE → ON COMPLETION → RENAME TO → ENABLE/DISABLE → COMMENT → DO`.
43
+ - **`mysql_event_create` Informative Existing Event Messaging** — When `ifNotExists: true` (default), the tool now pre-checks event existence and returns `{ success: true, skipped: true, reason: "Event already exists", eventName }` when the event was already present, instead of a plain `{ success: true, eventName }` indistinguishable from an actual creation. Matches the informative messaging pattern established by `mysql_event_drop`, `mysql_drop_table`, and `mysql_create_schema`.
44
+ - **Code Mode Shell Tool Naming Inconsistency** — Shell tool methods in code mode used unprefixed-stripping names (e.g., `mysql.shell.mysqlshVersion()`, `mysql.shell.mysqlshRunScript()`) instead of following the prefix-stripping convention used by all other groups. Added `shell: "mysqlsh_"` to `groupPrefixMap` in `api.ts`, so `mysqlsh_version` → `mysql.shell.version()`, `mysqlsh_run_script` → `mysql.shell.runScript()`, etc. Also added shell `METHOD_ALIASES`, `GROUP_EXAMPLES`, and `POSITIONAL_PARAM_MAP` entries.
45
+ - **`mysqlsh_check_upgrade` ServerInstructions Clarification** — Documentation incorrectly stated the tool fails only when `targetVersion` is lower than the server version. Clarified that it also fails when MySQL Shell's version is lower than the server version (Shell cannot analyze a server newer than itself).
46
+ - **`mysqlsh_load_dump` Dry Run Output** — `dryRun: true` previously returned only an opaque `result` field. Now uses `execMySQLShell` directly to capture stderr containing the dry run summary, returning it as a `dryRunOutput` field so the caller can see what schemas/tables would be loaded.
47
+ - **Partitioning Write Tools Missing P154 Existence Check** — `mysql_add_partition`, `mysql_drop_partition`, and `mysql_reorganize_partition` returned raw MySQL errors for nonexistent tables instead of the `{ exists: false, table }` pattern used by `mysql_partition_info` and all other tools. All three write tools now perform an `information_schema.TABLES` pre-check before executing ALTER TABLE.
48
+
49
+ - **`mysql_router_pool_status` Infrastructure & Documentation** — Enabled Router connection pool REST API by adding `[rest_connection_pool]` plugin and `connection_sharing=1` to the Router bootstrap config. Updated `routerSetup.ts` prompt to document the plugin. Corrected `ServerInstructions.ts` — clarified that `pool_status` requires both the REST plugin and `connection_sharing=1` on routes, and the pool name is `main`.
50
+ - **Code Mode Router Alias Inconsistency** — `mysql.router` had intermediate aliases for `routeStatus` and `routeHealth` but not for the other route-specific tools. Added `routeConnections`, `routeDestinations`, and `routeBlockedHosts` as intermediate aliases mapping to `routerRouteConnections`, `routerRouteDestinations`, and `routerRouteBlockedHosts` respectively.
51
+ - **Code Mode Router Group Registration** — All 9 router tools were registered with redundant `router` prefix in code mode (e.g., `routerStatus`, `routerMetadataStatus`), requiring users to call `mysql.router.routerStatus()` instead of the intuitive `mysql.router.status()`. Root cause: `router` was in the `keepPrefix` set in `toolNameToMethodName`, so `mysql_router_status` → `routerStatus`. But `GROUP_EXAMPLES.router` and `METHOD_ALIASES.router` referenced the prefixed names, making `help()` output show `routerStatus()`, `routerRoutes()`, etc. Fix: removed `router` from `keepPrefix` so tools resolve to short names (`status`, `routes`, `metadataStatus`, etc.), updated aliases to point to new canonical names, and removed 7 now-redundant self-aliases.
52
+ - **Code Mode Replication `help()` Examples** — `mysql.replication.help()` listed `replicationStatus()` and `replicationLag()` as examples, neither of which exist as methods (causing `TypeError` when called). Updated examples to use the correct method names: `slaveStatus()` and `lag()`. Also removed the broken `lag → replicationLag` alias (the canonical method name is already `lag`) and fixed `status` alias to point to `slaveStatus` instead of the nonexistent `replicationStatus`.
53
+
54
+ - **`mysql_query_rewrite` / `mysql_optimizer_trace` Missing `sql` Alias** — Both tools did not accept the `sql` parameter alias for `query`, despite being documented in ServerInstructions. Replaced inline Zod schemas with proper Dual-Schema pattern (`schemaBase` + `schema`) using `preprocessQueryOnlyParams`, matching the pattern used by `mysql_explain` and `mysql_explain_analyze`.
55
+ - **`mysql_slow_queries` / `mysql_query_stats` Timer Overflow Detection** — Both tools returned absurdly large `avg_time_ms` / `total_time_ms` / `max_time_ms` values (e.g., ~213 days) for certain queries due to MySQL's `performance_schema` unsigned 64-bit picosecond counter wrapping. Timer values exceeding 24 hours are now clamped to `-1` with `overflow: true` on the row, signaling that the original value was a counter overflow artifact.
56
+ - **`mysql_slow_queries` / `mysql_query_stats` Timer Value Type Consistency** — Both tools returned non-overflowed timer values (`avg_time_ms`, `total_time_ms`, `max_time_ms`) as strings when MySQL's `performance_schema` returned DECIMAL-typed values, while overflow-clamped values were numbers (`-1`). All timer values are now consistently returned as numbers.
57
+ - **`mysql_explain` TRADITIONAL Format Output** — Tool returned TREE format output when TRADITIONAL was requested. The handler used bare `EXPLAIN ${query}` for the TRADITIONAL case, which MySQL 8.0+ defaults to TREE format. Now explicitly uses `EXPLAIN FORMAT=TRADITIONAL ${query}` for all three formats.
58
+ - **`mysql_explain_analyze` Missing `sql` Alias** — Tool did not accept the `sql` parameter alias for `query`, despite being documented in ServerInstructions. Replaced inline Zod schema with proper Dual-Schema pattern (`ExplainAnalyzeSchemaBase` + `ExplainAnalyzeSchema`) using `preprocessQueryOnlyParams`, matching the pattern used by `mysql_explain`.
59
+ - **`mysql_buffer_pool_stats` Payload Reduction (P137)** — Tool returned all 32 columns from `INNODB_BUFFER_POOL_STATS` via `SELECT *`, including many zero-count rate fields. Now returns a curated subset of 23 operationally meaningful columns (pool size, free buffers, database pages, modified pages, hit rate, I/O rates, page activity).
60
+ - **ServerInstructions Parameter Alias Accuracy** — Removed `mysql_explain` and `mysql_explain_analyze` from the table name alias list (they accept `query`/`sql`, not `table`/`tableName`/`name`).
61
+
62
+ - **`mysql_json_update` Missing Reason on No-Match** — Tool returned bare `{ success: false }` without context when the target row ID did not exist. Now returns `{ success: false, reason: "No row found with <idColumn> = <id>" }` matching the descriptive error pattern used by other write tools.
63
+ - **`mysql_json_validate` Auto-Conversion Removed** — Tool previously auto-converted all input (including malformed JSON) to bare JSON strings before calling `JSON_VALID()`, making it impossible to return `valid: false`. Removed auto-conversion — the tool now validates input as-is, correctly returning `valid: false` for malformed JSON and bare strings. Auto-conversion remains in JSON write tools (`json_set`, `json_update`, etc.) where it serves a purpose.
64
+ - **`mysql_read_query` / `mysql_write_query` Uniform Structured Error Handling (P154)** — Both query tools now return `{ success: false, error }` for all query errors (nonexistent table, syntax errors, permission failures, etc.), instead of propagating raw MCP exceptions. Matches the structured error pattern used by all other core tools.
65
+ - **Code Mode Auto-Injection in Tool Filter Whitelist Mode** — `mysql_execute_code` is now automatically included when using raw group filters (e.g., `--tool-filter core`). Previously, only meta-group filters (e.g., `starter`, `essential`) included Code Mode, leaving it inaccessible when a raw group name was used. The auto-injection only applies in whitelist mode (filters not starting with `-`) and respects explicit exclusion via `-codemode` or `-mysql_execute_code`.
66
+ - **Code Mode Negative Memory Metric** — Fixed `mysql_execute_code` returning negative `memoryUsedMb` values (e.g., `-1.09`) in execution metrics when garbage collection reclaims heap between measurement snapshots. Now clamped to `Math.max(0, ...)` in both `CodeModeSandbox` and `WorkerSandbox`.
67
+ - **Code Mode Auto-Rollback on Success** — Fixed `mysql_execute_code` not rolling back uncommitted transactions when user code succeeds but leaves transactions open. The orphaned transaction cleanup previously only ran on execution failure (`!result.success`), causing dangling InnoDB transactions and table locks. Cleanup now runs unconditionally after every execution.
68
+ - **`mysql_transaction_execute` Empty Statements Structured Error** — Fixed `mysql_transaction_execute` throwing a raw Zod validation error when called with an empty `statements` array. Now returns `{ success: false, reason: "No statements provided..." }` matching the structured error pattern used by all other transaction tools. Validation moved from Zod `.refine()` to handler-level guard to prevent unnecessary transaction creation.
69
+ - **Code Mode Cluster `help()` Examples** — `mysql.cluster.help()` examples only showed parameterless calls (`clusterStatus()`, `clusterInstances()`, `grStatus()`). Updated to show the most useful patterns: `clusterStatus({ summary: true })`, `clusterRouterStatus({ summary: true })`, and `clusterSwitchover()`.
70
+ - **`ServerInstructions.ts` Cluster Router Status Documentation** — Documentation for `mysql_cluster_router_status` said only "return only essential router info" for summary mode without listing specific fields. Updated to enumerate all summary fields (routerId, routerName, address, version, lastCheckIn, roPort, rwPort, localCluster) and document the new `isStale`/`staleCount` fields. Also clarified switchover suitability rating thresholds (GOOD/ACCEPTABLE/NOT_RECOMMENDED).
71
+
72
+ ### Added
73
+
74
+ - **`mysql_cluster_router_status` Stale Router Detection** — Router responses now include an `isStale` boolean per router (true when `lastCheckIn` is null or >1 hour old) and a top-level `staleCount` field. Applied in both summary and full modes. Previously, stale/abandoned router entries were indistinguishable from active ones without external timestamp comparison.
75
+ - **Code Mode (`mysql_execute_code`)** — New sandboxed code execution tool enabling LLM agents to compose multi-step MySQL workflows as JavaScript/TypeScript code. Provides the `mysql.*` API namespace with 22 groups (168+ methods) including `mysql.core`, `mysql.json`, `mysql.transactions`, `mysql.spatial`, `mysql.stats`, and more. Features VM-based isolation, security validation, rate limiting, automatic transaction cleanup, and comprehensive help/introspection via `mysql.help()`. Requires `admin` scope.
76
+ - **`--server-host` CLI Option / `MCP_HOST` Environment Variable** — Configurable host binding for HTTP/SSE transport. Defaults to `localhost`. Set to `0.0.0.0` for containerized deployments where the server must accept connections from outside the container. Precedence: CLI flag > environment variable > default.
77
+ - **Parameter Aliases (Split Schema)** — Tools now accept alternative parameter names for commonly used fields, normalized automatically via Zod schema preprocessing. Aliases: `table`/`tableName`/`name` for table parameters (Core, Text, Backup, Partitioning, Performance, Admin tools); `query`/`sql` for SQL parameters (`mysql_read_query`, `mysql_write_query`, `mysql_explain`, `mysql_explain_analyze`, `mysql_query_rewrite`, `mysql_optimizer_trace`); `where`/`filter` for WHERE clause (`mysql_export_table` and all Text tools); `column`/`col` for column parameters (Text tools). Admin maintenance tools also accept singular `table` as an alias for the `tables` array. Schema definitions use a Dual-Schema pattern: `SchemaBase` (with aliases visible to MCP clients) for `inputSchema`, and the runtime `Schema` (with preprocessing + transformation) for handler validation.
78
+
79
+ ### Security
80
+
81
+ - **`mysqlsh_run_script` Secure Temporary File Handling (CodeQL)** — Replaced insecure `os.tmpdir()` + manual filename pattern with `fs.mkdtemp()` for SQL script temp files. The previous approach created predictable files in the shared OS temp directory, flagged by CodeQL as `js/insecure-temporary-file`. Now creates a unique temporary directory with restrictive permissions via `mkdtemp`, writes the script inside it, and recursively removes the directory after execution.
82
+ - **CVE Fix: `ajv` ReDoS via `$data` Option (GHSA-2g4f-4pwh-qvx6)** — Overrode transitive dependency `ajv` (via `@modelcontextprotocol/sdk` → `ajv-formats`) from 8.17.1 to 8.18.0 to fix a ReDoS vulnerability when the `$data` option accepts runtime regex patterns via JSON Pointer.
83
+ - **CVE Fix: `qs` ArrayLimit Bypass (GHSA-w7fw-mjwx-w883)** — Updated transitive dependency `qs` (via `express` → `@modelcontextprotocol/sdk`) from 6.14.1 to 6.14.2 to fix an arrayLimit bypass in comma parsing that allows denial of service.
84
+
85
+ ### Dependencies
86
+
87
+ - Bumped `@eslint/js` from `^9.39.2` to `^10.0.1`
88
+ - Bumped `@types/node` from `^25.2.2` to `^25.2.3`
89
+ - Bumped `eslint` from `^9.39.2` to `^10.0.0`
90
+ - Bumped `mysql2` from `^3.16.3` to `^3.17.2`
91
+ - Bumped `typescript-eslint` from `^8.54.0` to `^8.56.0`
92
+
10
93
  ## [2.2.0] - 2026-02-08
11
94
 
12
95
  ### Fixed
@@ -45,6 +128,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
45
128
  - **`mysql_role_revoke` User Existence Pre-Check** — Fixed `mysql_role_revoke` returning the "not assigned" message for nonexistent users instead of distinguishing them from valid users with unassigned roles. Now pre-checks `mysql.user` before the `role_edges` assignment check and returns `{ success: false, error: "User does not exist" }` for nonexistent users, matching `mysql_role_assign` behavior.
46
129
  - **`mysql_role_revoke` Assignment Pre-Check** — Fixed `mysql_role_revoke` returning `success: true` when revoking a role that was not assigned to the user. Now pre-checks `mysql.role_edges` and returns `{ success: false, reason: "Role '...' is not assigned to user '...'@'...'" }` when the role is not currently assigned.
47
130
  - **`mysql_role_create` / `mysql_role_drop` Informative No-Op Messaging** — When `ifNotExists: true` (default), `mysql_role_create` now pre-checks role existence via `mysql.user` and returns `{ success: true, skipped: true, reason: "Role already exists", roleName }` when the role was already present. Similarly, `mysql_role_drop` with `ifExists: true` (default) returns `{ success: true, skipped: true, reason: "Role did not exist", roleName }` when the role was already absent. Previously both returned a plain `{ success: true, roleName }` indistinguishable from an actual create/drop. Matches the informative messaging pattern established by `mysql_drop_table`, `mysql_create_schema`, and `mysql_event_drop`.
131
+ - **Code Mode Roles `help()` Example Inaccuracy** — `mysql.roles.help()` listed `roleGrant({ role: 'app_reader', privileges: 'SELECT', on: 'mydb.*' })` as an example, but the tool accepts `privileges` as an array (`['SELECT']`) and uses `database`/`table` parameters instead of `on`. Updated to `roleGrant({ role: 'app_reader', privileges: ['SELECT'], database: 'mydb' })`.
132
+ - **Code Mode Docstore `help()` Examples** — `mysql.docstore.help()` examples contained two inaccuracies: `docAdd` example used singular `document` parameter instead of the correct `documents` array, and `docFind` example used `filter: 'price > 5'` (comparison operator) instead of a JSON path existence filter (`$.name`). `doc_find` only supports JSON path existence checks per ServerInstructions.
48
133
  - **`mysql_role_grant` Error Message Sanitization** — Fixed `mysql_role_grant` leaking internal adapter prefix (`Raw query failed: Query failed:`) in error messages for nonexistent tables. Now strips the prefix to return clean MySQL error messages (e.g., `"Table 'testdb.nonexistent' doesn't exist"`).
49
134
  - **Roles Tool Graceful Error Handling** — `mysql_role_create` returns `{ success: false, reason }` for duplicate roles (without `ifNotExists`). `mysql_role_drop` returns `{ success: false, reason }` for nonexistent roles (without `ifExists`). `mysql_role_assign` and `mysql_role_revoke` return `{ success: false, error }` for nonexistent users. `mysql_role_grant` returns `{ success: false, error }` for nonexistent tables. `mysql_user_roles` returns `{ exists: false }` for nonexistent users (P154). Previously all propagated raw MySQL errors.
50
135
  - **Stats Tools Graceful Error Handling (P154)** — All 8 stats tools (`mysql_stats_descriptive`, `mysql_stats_percentiles`, `mysql_stats_correlation`, `mysql_stats_distribution`, `mysql_stats_time_series`, `mysql_stats_regression`, `mysql_stats_sampling`, `mysql_stats_histogram`) now return `{ exists: false, table }` for nonexistent tables and `{ success: false, error }` for other query errors (e.g., unknown column), instead of propagating raw MySQL errors.
package/CODE_MODE.md ADDED
@@ -0,0 +1,245 @@
1
+ # Code Mode
2
+
3
+ **Execute multi-step MySQL workflows in a single tool call.**
4
+
5
+ Code Mode (`mysql_execute_code`) runs JavaScript/TypeScript code in a sandboxed VM with full access to all 192 MySQL tools via the `mysql.*` API namespace. Instead of chaining dozens of sequential tool calls, write a single script that queries, transforms, and acts on your data.
6
+
7
+ ---
8
+
9
+ ## When to Use Code Mode
10
+
11
+ | Scenario | Without Code Mode | With Code Mode |
12
+ | ---------------------------- | ------------------------------------------ | -------------------------------------- |
13
+ | Multi-step data pipeline | 5-10 sequential tool calls | 1 `mysql_execute_code` call |
14
+ | Conditional branching | Agent decides after each tool result | `if/else` logic in one script |
15
+ | Cross-table aggregation | Multiple reads + manual aggregation | Loop and aggregate in JS |
16
+ | Schema migration with checks | Describe → check → alter → verify sequence | Single script with error handling |
17
+ | Batch operations | Repeated tool calls per item | `for` loop over items in one execution |
18
+
19
+ **Rule of thumb**: If a task requires **3+ sequential tool calls** or **conditional logic based on query results**, use Code Mode.
20
+
21
+ ---
22
+
23
+ ## Tool Reference
24
+
25
+ ### `mysql_execute_code`
26
+
27
+ | Parameter | Type | Required | Description |
28
+ | --------- | ------ | -------- | ---------------------------------------- |
29
+ | `code` | string | ✅ | JavaScript/TypeScript code to execute |
30
+ | `timeout` | number | ❌ | Execution timeout in ms (default: 30000) |
31
+
32
+ **Scope**: Requires `admin` scope.
33
+
34
+ **Returns**: The value of the last expression in the code block, wrapped in an execution result with timing and memory metrics.
35
+
36
+ ---
37
+
38
+ ## API Namespace
39
+
40
+ The `mysql` global object exposes **24 tool groups** as sub-objects:
41
+
42
+ | Group | Tools | Description |
43
+ | -------------------- | ----- | ---------------------------------------- |
44
+ | `mysql.core` | 8 | Read/write queries, tables, indexes |
45
+ | `mysql.transactions` | 7 | BEGIN, COMMIT, ROLLBACK, savepoints |
46
+ | `mysql.json` | 17 | JSON functions, merge, diff, stats |
47
+ | `mysql.text` | 6 | REGEXP, LIKE, SOUNDEX |
48
+ | `mysql.fulltext` | 5 | Natural language & boolean search |
49
+ | `mysql.performance` | 8 | EXPLAIN, query analysis, slow queries |
50
+ | `mysql.optimization` | 4 | Index hints, recommendations |
51
+ | `mysql.admin` | 6 | OPTIMIZE, ANALYZE, CHECK |
52
+ | `mysql.monitoring` | 7 | PROCESSLIST, status variables |
53
+ | `mysql.backup` | 4 | Export, import, mysqldump |
54
+ | `mysql.replication` | 5 | Master/slave, binlog |
55
+ | `mysql.partitioning` | 4 | Partition management |
56
+ | `mysql.schema` | 10 | Views, procedures, triggers, constraints |
57
+ | `mysql.shell` | 10 | MySQL Shell utilities |
58
+ | `mysql.events` | 6 | Event Scheduler management |
59
+ | `mysql.sysschema` | 8 | sys schema diagnostics |
60
+ | `mysql.stats` | 8 | Statistical analysis tools |
61
+ | `mysql.spatial` | 12 | Spatial/GIS operations |
62
+ | `mysql.security` | 9 | Audit, SSL, encryption, masking |
63
+ | `mysql.roles` | 8 | MySQL 8.0 role management |
64
+ | `mysql.docstore` | 9 | Document Store collections |
65
+ | `mysql.cluster` | 10 | Group Replication, InnoDB Cluster |
66
+ | `mysql.proxysql` | 12 | ProxySQL management |
67
+ | `mysql.router` | 9 | MySQL Router REST API |
68
+
69
+ ### Method Naming Convention
70
+
71
+ Tool names map to methods by stripping the group prefix and converting to camelCase:
72
+
73
+ ```
74
+ mysql_read_query → mysql.core.readQuery()
75
+ mysql_json_extract → mysql.json.extract()
76
+ mysql_describe_table → mysql.core.describeTable()
77
+ mysql_spatial_point → mysql.spatial.point()
78
+ mysql_show_processlist → mysql.monitoring.showProcesslist()
79
+ ```
80
+
81
+ ### Positional Shorthand
82
+
83
+ Common tools accept positional arguments for convenience:
84
+
85
+ ```javascript
86
+ // Object form
87
+ mysql.core.readQuery({
88
+ query: "SELECT * FROM users WHERE id = ?",
89
+ params: [1],
90
+ });
91
+
92
+ // Positional shorthand
93
+ mysql.core.readQuery("SELECT * FROM users WHERE id = ?", [1]);
94
+ ```
95
+
96
+ ### Discovery
97
+
98
+ ```javascript
99
+ // List all groups and their methods
100
+ mysql.help();
101
+
102
+ // Group-specific help with examples
103
+ mysql.core.help();
104
+ mysql.json.help();
105
+ mysql.transactions.help();
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Usage Examples
111
+
112
+ ### Basic: Multi-Step Data Pipeline
113
+
114
+ ```javascript
115
+ // Get table stats, identify large tables, and analyze their indexes
116
+ const tables = await mysql.core.readQuery(
117
+ "SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema = DATABASE() ORDER BY table_rows DESC LIMIT 5",
118
+ );
119
+
120
+ const results = [];
121
+ for (const table of tables.rows) {
122
+ const indexes = await mysql.core.getIndexes({ table: table.table_name });
123
+ const stats = await mysql.performance.tableStats({ table: table.table_name });
124
+ results.push({
125
+ table: table.table_name,
126
+ rows: table.table_rows,
127
+ indexCount: indexes.indexes?.length || 0,
128
+ stats,
129
+ });
130
+ }
131
+ results;
132
+ ```
133
+
134
+ ### Conditional Logic
135
+
136
+ ```javascript
137
+ // Check if a column exists before adding it
138
+ const desc = await mysql.core.describeTable({ table: "users" });
139
+ const hasEmail = desc.columns.some((c) => c.Field === "email_verified");
140
+
141
+ if (!hasEmail) {
142
+ await mysql.core.writeQuery({
143
+ query: "ALTER TABLE users ADD COLUMN email_verified TINYINT(1) DEFAULT 0",
144
+ });
145
+ ("Column added");
146
+ } else {
147
+ ("Column already exists");
148
+ }
149
+ ```
150
+
151
+ ### Transactions with Error Handling
152
+
153
+ ```javascript
154
+ // Atomic transfer between accounts
155
+ const tx = await mysql.transactions.begin();
156
+ try {
157
+ await mysql.core.writeQuery({
158
+ query: "UPDATE accounts SET balance = balance - ? WHERE id = ?",
159
+ params: [100, 1],
160
+ transactionId: tx.transactionId,
161
+ });
162
+ await mysql.core.writeQuery({
163
+ query: "UPDATE accounts SET balance = balance + ? WHERE id = ?",
164
+ params: [100, 2],
165
+ transactionId: tx.transactionId,
166
+ });
167
+ await mysql.transactions.commit({ transactionId: tx.transactionId });
168
+ ("Transfer complete");
169
+ } catch (e) {
170
+ await mysql.transactions.rollback({ transactionId: tx.transactionId });
171
+ `Transfer failed: ${e.message}`;
172
+ }
173
+ ```
174
+
175
+ ### Cross-Group Aggregation
176
+
177
+ ```javascript
178
+ // Comprehensive database health check
179
+ const [health, pool, processlist, variables] = await Promise.all([
180
+ mysql.monitoring.serverHealth(),
181
+ mysql.monitoring.poolStats(),
182
+ mysql.monitoring.showProcesslist({ full: false }),
183
+ mysql.monitoring.showStatus({ like: "%Threads%" }),
184
+ ]);
185
+
186
+ ({
187
+ serverVersion: health.version,
188
+ uptime: health.uptime,
189
+ activeConnections: pool.active,
190
+ idleConnections: pool.idle,
191
+ runningQueries:
192
+ processlist.processes?.filter((p) => p.Command === "Query").length || 0,
193
+ threadMetrics: variables.variables,
194
+ });
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Security & Sandbox
200
+
201
+ ### Isolation
202
+
203
+ Code runs in an **isolated VM sandbox** (Node.js `vm` module) with no access to:
204
+
205
+ - File system (`fs`, `path`, `os`)
206
+ - Network (`http`, `https`, `net`, `fetch`)
207
+ - Process control (`process`, `child_process`)
208
+ - Module system (`require`, `import`)
209
+
210
+ ### Blocked Patterns
211
+
212
+ The following patterns are detected and rejected **before execution**:
213
+
214
+ | Pattern | Reason |
215
+ | ------------------- | ------------------------- |
216
+ | `require(...)` | Module loading |
217
+ | `import ...` | ES module imports |
218
+ | `process.` | Process access |
219
+ | `eval(...)` | Dynamic code execution |
220
+ | `new Function(...)` | Dynamic function creation |
221
+ | `__dirname` | File system path access |
222
+ | `__filename` | File system path access |
223
+
224
+ ### Rate Limiting
225
+
226
+ Code Mode is rate-limited to prevent abuse. Excessive calls within a short window will return an error with a retry-after suggestion.
227
+
228
+ ### Transaction Cleanup
229
+
230
+ Any transactions opened during code execution but **not explicitly committed** are automatically rolled back when execution completes. This prevents orphaned locks.
231
+
232
+ ### Timeout
233
+
234
+ Default execution timeout is **30 seconds**. Use the `timeout` parameter to adjust for long-running operations.
235
+
236
+ ---
237
+
238
+ ## Tips
239
+
240
+ 1. **Use `await`** — All `mysql.*` methods return Promises.
241
+ 2. **Return values** — The last expression in your code is returned as the result.
242
+ 3. **Error handling** — Wrap operations in `try/catch` for graceful error handling.
243
+ 4. **Parallel queries** — Use `Promise.all()` for independent queries to reduce execution time.
244
+ 5. **Transaction safety** — Always use `try/catch/finally` with transactions to ensure cleanup.
245
+ 6. **Help system** — Call `mysql.help()` or `mysql.<group>.help()` to discover available methods.
package/DOCKER_README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MySQL MCP Server
2
2
 
3
- **Last Updated: February 8, 2026**
3
+ **Last Updated February 18, 2026**
4
4
 
5
5
  [![GitHub](https://img.shields.io/badge/GitHub-neverinfamous/mysql--mcp-blue?logo=github)](https://github.com/neverinfamous/mysql-mcp)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -9,8 +9,8 @@
9
9
  [![Docker Pulls](https://img.shields.io/docker/pulls/writenotenow/mysql-mcp)](https://hub.docker.com/r/writenotenow/mysql-mcp)
10
10
  [![Security](https://img.shields.io/badge/Security-Enhanced-green.svg)](SECURITY.md)
11
11
  ![TypeScript](https://img.shields.io/badge/TypeScript-Strict-blue.svg)
12
- ![Tests](https://img.shields.io/badge/Tests-1794%20passing-brightgreen.svg)
13
- ![Coverage](https://img.shields.io/badge/Coverage-94%25-green.svg)
12
+ ![Tests](https://img.shields.io/badge/Tests-1835%20passing-brightgreen.svg)
13
+ ![Coverage](https://img.shields.io/badge/Coverage-86%25-green.svg)
14
14
 
15
15
  **[📚 Full Documentation (Wiki)](https://github.com/neverinfamous/mysql-mcp/wiki)** • **[Changelog](https://github.com/neverinfamous/mysql-mcp/blob/master/CHANGELOG.md)** • **[Security](https://github.com/neverinfamous/mysql-mcp/blob/master/SECURITY.md)** • **[Release Article](https://adamic.tech/articles/mysql-mcp-server)**
16
16
 
@@ -22,17 +22,17 @@
22
22
 
23
23
  | Feature | Description |
24
24
  | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
25
- | **192 Specialized Tools** | The largest MySQL tool collection for MCP — from core CRUD and native JSON functions (MySQL 5.7+) to advanced spatial/GIS, document store, and cluster management |
25
+ | **193 Specialized Tools** | The largest MySQL tool collection for MCP — from core CRUD and native JSON functions (MySQL 5.7+) to advanced spatial/GIS, document store, and cluster management |
26
26
  | **18 Observability Resources** | Real-time schema, performance metrics, process lists, status variables, replication status, and InnoDB diagnostics |
27
27
  | **19 AI-Powered Prompts** | Guided workflows for query building, schema design, performance tuning, and infrastructure setup |
28
28
  | **OAuth 2.1 + Access Control** | Enterprise-ready security with RFC 9728/8414 compliance, granular scopes (`read`, `write`, `admin`, `full`, `db:*`, `table:*:*`), and Keycloak integration |
29
- | **Smart Tool Filtering** | 24 tool groups + 7 meta-groups let you stay within IDE limits while exposing exactly what you need |
29
+ | **Smart Tool Filtering** | 25 tool groups + 11 shortcuts let you stay within IDE limits while exposing exactly what you need |
30
30
  | **HTTP Streaming Transport** | SSE-based streaming with `/sse`, `/messages`, and `/health` endpoints for remote deployments |
31
31
  | **High-Performance Pooling** | Built-in connection pooling for efficient, concurrent database access |
32
32
  | **Ecosystem Integrations** | First-class support for **MySQL Router**, **ProxySQL**, and **MySQL Shell** utilities |
33
33
  | **Advanced Encryption** | Full TLS/SSL support for secure connections, plus tools for managing data masking, encryption monitoring, and compliance |
34
34
  | **Production-Ready Security** | SQL injection protection, parameterized queries, input validation, and audit capabilities |
35
- | **Strict TypeScript** | 100% type-safe codebase with 1794 tests and 94% coverage |
35
+ | **Strict TypeScript** | 100% type-safe codebase with 1833 tests and 86% coverage |
36
36
  | **MCP 2025-11-25 Compliant** | Full protocol support with tool safety hints, resource priorities, and progress notifications |
37
37
 
38
38
  ---
@@ -118,12 +118,13 @@ mysql-mcp --mysql mysql://root:pass@localhost/db \
118
118
 
119
119
  ```bash
120
120
  # Local installation
121
- node dist/cli.js --transport http --port 3000 --mysql mysql://user:password@localhost:3306/database
121
+ node dist/cli.js --transport http --port 3000 --server-host 0.0.0.0 --mysql mysql://user:password@localhost:3306/database
122
122
 
123
123
  # Docker (expose port 3000)
124
124
  docker run -p 3000:3000 writenotenow/mysql-mcp \
125
125
  --transport http \
126
126
  --port 3000 \
127
+ --server-host 0.0.0.0 \
127
128
  --mysql mysql://user:password@host.docker.internal:3306/database
128
129
  ```
129
130
 
@@ -231,10 +232,26 @@ Use the remote hostname directly:
231
232
 
232
233
  ---
233
234
 
235
+ ## Code Mode: Maximum Efficiency
236
+
237
+ Code Mode (`mysql_execute_code`) dramatically reduces token usage (70–90%) and is included by default in all presets.
238
+
239
+ > [!TIP]
240
+ > **Maximize Token Savings:** For the best results, instruct your AI agent to prefer Code Mode over individual tool calls. Add a rule like this to your agent's prompt or system configuration:
241
+ >
242
+ > _"When using mysql-mcp, prefer `mysql_execute_code` (Code Mode) for multi-step database operations to minimize token usage."_
243
+ >
244
+ > This ensures the agent batches operations into single calls instead of making many individual tool calls. See the [Code Mode wiki](https://github.com/neverinfamous/mysql-mcp/wiki/Code-Mode) for full API documentation.
245
+
246
+ > [!NOTE]
247
+ > **AntiGravity Users:** Server instructions are automatically sent to MCP clients during initialization. However, AntiGravity does not currently support MCP server instructions. For optimal Code Mode usage in AntiGravity, manually provide the contents of [`src/constants/ServerInstructions.ts`](https://github.com/neverinfamous/mysql-mcp/blob/master/src/constants/ServerInstructions.ts) to the agent in your prompt or user rules.
248
+
249
+ ---
250
+
234
251
  ## 🛠️ Tool Filtering
235
252
 
236
253
  > [!IMPORTANT]
237
- > **AI IDEs like Cursor have tool limits (typically 40-50 tools).** With 192 tools available, you MUST use tool filtering to stay within your IDE's limits. We recommend `starter` (38 tools) as a starting point.
254
+ > **AI IDEs like Cursor have tool limits (typically 40-50 tools).** With 193 tools available, you MUST use tool filtering to stay within your IDE's limits. We recommend `starter` (39 tools) as a starting point. Code Mode is included in all presets by default for 70-90% token savings on multi-step operations.
238
255
 
239
256
  ### What Can You Filter?
240
257
 
@@ -242,28 +259,28 @@ The `--tool-filter` argument accepts **shortcuts**, **groups**, or **tool names*
242
259
 
243
260
  | Filter Pattern | Example | Tools | Description |
244
261
  | ---------------- | --------------------------- | ----- | ------------------------- |
245
- | Shortcut only | `starter` | 38 | Use a predefined bundle |
262
+ | Shortcut only | `starter` | 39 | Use a predefined bundle |
246
263
  | Groups only | `core,json,transactions` | 32 | Combine individual groups |
247
- | Shortcut + Group | `starter,spatial` | 50 | Extend a shortcut |
248
- | Shortcut - Tool | `starter,-mysql_drop_table` | 37 | Remove specific tools |
264
+ | Shortcut + Group | `starter,spatial` | 51 | Extend a shortcut |
265
+ | Shortcut - Tool | `starter,-mysql_drop_table` | 38 | Remove specific tools |
249
266
 
250
267
  ### Shortcuts (Predefined Bundles)
251
268
 
252
- | Shortcut | Tools | Use Case | What's Included |
253
- | --------------- | ------ | ------------------ | -------------------------------------------------------- |
254
- | `starter` | **38** | 🌟 **Recommended** | core, json, transactions, text |
255
- | `essential` | 15 | Minimal footprint | core, transactions |
256
- | `dev-power` | 46 | Power Developer | core, schema, performance, stats, fulltext, transactions |
257
- | `ai-data` | 45 | AI Data Analyst | core, json, docstore, text, fulltext |
258
- | `ai-spatial` | 43 | AI Spatial Analyst | core, spatial, stats, performance, transactions |
259
- | `dba-monitor` | 35 | DBA Monitoring | core, monitoring, performance, sysschema, optimization |
260
- | `dba-manage` | 33 | DBA Management | core, admin, backup, replication, partitioning, events |
261
- | `dba-secure` | 32 | DBA Security | core, security, roles, transactions |
262
- | `base-core` | 48 | Base Ops | core, json, transactions, text, schema |
263
- | `base-advanced` | 40 | Advanced Features | docstore, spatial, stats, fulltext, events |
264
- | `ecosystem` | 41 | External Tools | cluster, proxysql, router, shell |
265
-
266
- ### Tool Groups (24 Available)
269
+ | Shortcut | Tools | Use Case | What's Included |
270
+ | --------------- | ------ | ------------------ | ------------------------------------------------------------------ |
271
+ | `starter` | **39** | 🌟 **Recommended** | core, json, transactions, text, codemode |
272
+ | `essential` | 16 | Minimal footprint | core, transactions, codemode |
273
+ | `dev-power` | 47 | Power Developer | core, schema, performance, stats, fulltext, transactions, codemode |
274
+ | `ai-data` | 46 | AI Data Analyst | core, json, docstore, text, fulltext, codemode |
275
+ | `ai-spatial` | 44 | AI Spatial Analyst | core, spatial, stats, performance, transactions, codemode |
276
+ | `dba-monitor` | 36 | DBA Monitoring | core, monitoring, performance, sysschema, optimization, codemode |
277
+ | `dba-manage` | 34 | DBA Management | core, admin, backup, replication, partitioning, events, codemode |
278
+ | `dba-secure` | 33 | DBA Security | core, security, roles, transactions, codemode |
279
+ | `base-core` | 49 | Base Ops | core, json, transactions, text, schema, codemode |
280
+ | `base-advanced` | 41 | Advanced Features | docstore, spatial, stats, fulltext, events, codemode |
281
+ | `ecosystem` | 42 | External Tools | cluster, proxysql, router, shell, codemode |
282
+
283
+ ### Tool Groups (25 Available)
267
284
 
268
285
  | Group | Tools | Description |
269
286
  | -------------- | ----- | ---------------------------------------- |
@@ -291,6 +308,7 @@ The `--tool-filter` argument accepts **shortcuts**, **groups**, or **tool names*
291
308
  | `cluster` | 10 | Group Replication, InnoDB Cluster |
292
309
  | `proxysql` | 12 | ProxySQL management |
293
310
  | `router` | 9 | MySQL Router REST API |
311
+ | `codemode` | 1 | Sandboxed code execution |
294
312
 
295
313
  ---
296
314
 
@@ -298,7 +316,7 @@ The `--tool-filter` argument accepts **shortcuts**, **groups**, or **tool names*
298
316
 
299
317
  Add one of these configurations to your IDE's MCP settings file (e.g., `cline_mcp_settings.json`, `.cursorrules`, or equivalent):
300
318
 
301
- #### Option 1: Starter (38 Essential Tools)
319
+ #### Option 1: Starter (39 Essential Tools)
302
320
 
303
321
  **Best for:** General MySQL database work - CRUD operations, schema management, and monitoring.
304
322
 
@@ -326,7 +344,7 @@ Add one of these configurations to your IDE's MCP settings file (e.g., `cline_mc
326
344
  }
327
345
  ```
328
346
 
329
- #### Option 2: Cluster (10 Tools for InnoDB Cluster Monitoring)
347
+ #### Option 2: Cluster (11 Tools for InnoDB Cluster Monitoring)
330
348
 
331
349
  **Best for:** Monitoring InnoDB Cluster, Group Replication status, and cluster topology.
332
350
 
@@ -361,7 +379,7 @@ Add one of these configurations to your IDE's MCP settings file (e.g., `cline_mc
361
379
  }
362
380
  ```
363
381
 
364
- #### Option 3: Ecosystem (41 Tools for InnoDB Cluster Deployments)
382
+ #### Option 3: Ecosystem (42 Tools for InnoDB Cluster Deployments)
365
383
 
366
384
  **Best for:** MySQL Router, ProxySQL, MySQL Shell, and InnoDB Cluster deployments.
367
385
 
@@ -497,6 +515,8 @@ For specialized setups, see these Wiki pages:
497
515
 
498
516
  ## ⚡ Performance Tuning
499
517
 
518
+ Schema metadata is cached to reduce repeated queries during tool/resource invocations.
519
+
500
520
  | Variable | Default | Description |
501
521
  | ----------------------- | ------- | -------------------------------------------------- |
502
522
  | `METADATA_CACHE_TTL_MS` | `30000` | Cache TTL for schema metadata (milliseconds) |
@@ -504,17 +524,20 @@ For specialized setups, see these Wiki pages:
504
524
 
505
525
  > **Tip:** Lower `METADATA_CACHE_TTL_MS` for development (e.g., `5000`), or increase it for production with stable schemas (e.g., `300000` = 5 min).
506
526
 
527
+ > **Built-in payload optimization:** Many tools support optional `summary: true` for condensed responses and `limit` parameters to cap result sizes. These are particularly useful for cluster status, monitoring, and sys schema tools where full responses can be large. See [`ServerInstructions.ts`](https://github.com/neverinfamous/mysql-mcp/blob/master/src/constants/ServerInstructions.ts) for per-tool details.
528
+
507
529
  ---
508
530
 
509
531
  ### CLI Options
510
532
 
511
- | Option | Environment Variable | Description |
512
- | ------------------------- | ----------------------- | --------------------------- |
513
- | `--oauth-enabled` | `OAUTH_ENABLED` | Enable OAuth authentication |
514
- | `--oauth-issuer` | `OAUTH_ISSUER` | Authorization server URL |
515
- | `--oauth-audience` | `OAUTH_AUDIENCE` | Expected token audience |
516
- | `--oauth-jwks-uri` | `OAUTH_JWKS_URI` | JWKS URI (auto-discovered) |
517
- | `--oauth-clock-tolerance` | `OAUTH_CLOCK_TOLERANCE` | Clock tolerance in seconds |
533
+ | Option | Environment Variable | Description |
534
+ | ------------------------- | ----------------------- | --------------------------------------------------- |
535
+ | `--server-host` | `MCP_HOST` | Host to bind HTTP transport to (default: localhost) |
536
+ | `--oauth-enabled` | `OAUTH_ENABLED` | Enable OAuth authentication |
537
+ | `--oauth-issuer` | `OAUTH_ISSUER` | Authorization server URL |
538
+ | `--oauth-audience` | `OAUTH_AUDIENCE` | Expected token audience |
539
+ | `--oauth-jwks-uri` | `OAUTH_JWKS_URI` | JWKS URI (auto-discovered) |
540
+ | `--oauth-clock-tolerance` | `OAUTH_CLOCK_TOLERANCE` | Clock tolerance in seconds |
518
541
 
519
542
  ### Scopes
520
543