@neverinfamous/mysql-mcp 2.3.0 → 3.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 (347) hide show
  1. package/.dockerignore +1 -0
  2. package/.gitattributes +18 -0
  3. package/.github/workflows/codeql.yml +2 -10
  4. package/.github/workflows/docker-publish.yml +15 -13
  5. package/CHANGELOG.md +287 -1
  6. package/DOCKER_README.md +100 -265
  7. package/Dockerfile +5 -0
  8. package/README.md +124 -59
  9. package/VERSION +1 -1
  10. package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
  11. package/dist/__tests__/mocks/adapter.js +2 -0
  12. package/dist/__tests__/mocks/adapter.js.map +1 -1
  13. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
  14. package/dist/adapters/DatabaseAdapter.js +50 -9
  15. package/dist/adapters/DatabaseAdapter.js.map +1 -1
  16. package/dist/adapters/mysql/MySQLAdapter.d.ts +6 -0
  17. package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
  18. package/dist/adapters/mysql/MySQLAdapter.js +8 -0
  19. package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
  20. package/dist/adapters/mysql/SchemaManager.js +16 -15
  21. package/dist/adapters/mysql/SchemaManager.js.map +1 -1
  22. package/dist/adapters/mysql/prompts/index.js +10 -20
  23. package/dist/adapters/mysql/prompts/index.js.map +1 -1
  24. package/dist/adapters/mysql/prompts/proxysqlSetup.js +1 -1
  25. package/dist/adapters/mysql/resources/docstore.d.ts.map +1 -1
  26. package/dist/adapters/mysql/resources/docstore.js +10 -7
  27. package/dist/adapters/mysql/resources/docstore.js.map +1 -1
  28. package/dist/adapters/mysql/resources/events.js +11 -8
  29. package/dist/adapters/mysql/resources/events.js.map +1 -1
  30. package/dist/adapters/mysql/resources/indexes.d.ts.map +1 -1
  31. package/dist/adapters/mysql/resources/indexes.js +12 -15
  32. package/dist/adapters/mysql/resources/indexes.js.map +1 -1
  33. package/dist/adapters/mysql/resources/innodb.d.ts.map +1 -1
  34. package/dist/adapters/mysql/resources/innodb.js +20 -17
  35. package/dist/adapters/mysql/resources/innodb.js.map +1 -1
  36. package/dist/adapters/mysql/resources/locks.d.ts.map +1 -1
  37. package/dist/adapters/mysql/resources/locks.js +9 -6
  38. package/dist/adapters/mysql/resources/locks.js.map +1 -1
  39. package/dist/adapters/mysql/resources/performance.d.ts.map +1 -1
  40. package/dist/adapters/mysql/resources/performance.js +15 -15
  41. package/dist/adapters/mysql/resources/performance.js.map +1 -1
  42. package/dist/adapters/mysql/resources/spatial.d.ts.map +1 -1
  43. package/dist/adapters/mysql/resources/spatial.js +9 -6
  44. package/dist/adapters/mysql/resources/spatial.js.map +1 -1
  45. package/dist/adapters/mysql/resources/sysschema.d.ts.map +1 -1
  46. package/dist/adapters/mysql/resources/sysschema.js +12 -9
  47. package/dist/adapters/mysql/resources/sysschema.js.map +1 -1
  48. package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
  49. package/dist/adapters/mysql/tools/admin/backup.js +170 -121
  50. package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
  51. package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
  52. package/dist/adapters/mysql/tools/admin/maintenance.js +106 -57
  53. package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
  54. package/dist/adapters/mysql/tools/admin/monitoring.d.ts.map +1 -1
  55. package/dist/adapters/mysql/tools/admin/monitoring.js +183 -101
  56. package/dist/adapters/mysql/tools/admin/monitoring.js.map +1 -1
  57. package/dist/adapters/mysql/tools/cluster/group-replication.d.ts.map +1 -1
  58. package/dist/adapters/mysql/tools/cluster/group-replication.js +164 -120
  59. package/dist/adapters/mysql/tools/cluster/group-replication.js.map +1 -1
  60. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
  61. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +212 -145
  62. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
  63. package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -1
  64. package/dist/adapters/mysql/tools/codemode/index.js +6 -4
  65. package/dist/adapters/mysql/tools/codemode/index.js.map +1 -1
  66. package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
  67. package/dist/adapters/mysql/tools/core.js +152 -29
  68. package/dist/adapters/mysql/tools/core.js.map +1 -1
  69. package/dist/adapters/mysql/tools/docstore.d.ts.map +1 -1
  70. package/dist/adapters/mysql/tools/docstore.js +340 -163
  71. package/dist/adapters/mysql/tools/docstore.js.map +1 -1
  72. package/dist/adapters/mysql/tools/events.d.ts.map +1 -1
  73. package/dist/adapters/mysql/tools/events.js +284 -198
  74. package/dist/adapters/mysql/tools/events.js.map +1 -1
  75. package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
  76. package/dist/adapters/mysql/tools/json/core.js +11 -39
  77. package/dist/adapters/mysql/tools/json/core.js.map +1 -1
  78. package/dist/adapters/mysql/tools/json/enhanced.d.ts.map +1 -1
  79. package/dist/adapters/mysql/tools/json/enhanced.js +15 -33
  80. package/dist/adapters/mysql/tools/json/enhanced.js.map +1 -1
  81. package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
  82. package/dist/adapters/mysql/tools/json/helpers.js +13 -24
  83. package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
  84. package/dist/adapters/mysql/tools/partitioning.js +3 -0
  85. package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
  86. package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
  87. package/dist/adapters/mysql/tools/performance/analysis.js +89 -60
  88. package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
  89. package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
  90. package/dist/adapters/mysql/tools/performance/optimization.js +151 -127
  91. package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
  92. package/dist/adapters/mysql/tools/proxysql.d.ts +1 -1
  93. package/dist/adapters/mysql/tools/proxysql.d.ts.map +1 -1
  94. package/dist/adapters/mysql/tools/proxysql.js +289 -176
  95. package/dist/adapters/mysql/tools/proxysql.js.map +1 -1
  96. package/dist/adapters/mysql/tools/replication.js +75 -49
  97. package/dist/adapters/mysql/tools/replication.js.map +1 -1
  98. package/dist/adapters/mysql/tools/roles.d.ts.map +1 -1
  99. package/dist/adapters/mysql/tools/roles.js +224 -182
  100. package/dist/adapters/mysql/tools/roles.js.map +1 -1
  101. package/dist/adapters/mysql/tools/router.d.ts.map +1 -1
  102. package/dist/adapters/mysql/tools/router.js +168 -67
  103. package/dist/adapters/mysql/tools/router.js.map +1 -1
  104. package/dist/adapters/mysql/tools/schema/constraints.d.ts.map +1 -1
  105. package/dist/adapters/mysql/tools/schema/constraints.js +21 -3
  106. package/dist/adapters/mysql/tools/schema/constraints.js.map +1 -1
  107. package/dist/adapters/mysql/tools/schema/management.d.ts.map +1 -1
  108. package/dist/adapters/mysql/tools/schema/management.js +61 -14
  109. package/dist/adapters/mysql/tools/schema/management.js.map +1 -1
  110. package/dist/adapters/mysql/tools/schema/routines.d.ts.map +1 -1
  111. package/dist/adapters/mysql/tools/schema/routines.js +27 -4
  112. package/dist/adapters/mysql/tools/schema/routines.js.map +1 -1
  113. package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts.map +1 -1
  114. package/dist/adapters/mysql/tools/schema/scheduled_events.js +24 -3
  115. package/dist/adapters/mysql/tools/schema/scheduled_events.js.map +1 -1
  116. package/dist/adapters/mysql/tools/schema/triggers.d.ts.map +1 -1
  117. package/dist/adapters/mysql/tools/schema/triggers.js +23 -2
  118. package/dist/adapters/mysql/tools/schema/triggers.js.map +1 -1
  119. package/dist/adapters/mysql/tools/schema/views.d.ts.map +1 -1
  120. package/dist/adapters/mysql/tools/schema/views.js +47 -7
  121. package/dist/adapters/mysql/tools/schema/views.js.map +1 -1
  122. package/dist/adapters/mysql/tools/security/audit.d.ts.map +1 -1
  123. package/dist/adapters/mysql/tools/security/audit.js +102 -34
  124. package/dist/adapters/mysql/tools/security/audit.js.map +1 -1
  125. package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
  126. package/dist/adapters/mysql/tools/security/data-protection.js +264 -205
  127. package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
  128. package/dist/adapters/mysql/tools/security/encryption.d.ts.map +1 -1
  129. package/dist/adapters/mysql/tools/security/encryption.js +137 -104
  130. package/dist/adapters/mysql/tools/security/encryption.js.map +1 -1
  131. package/dist/adapters/mysql/tools/shell/backup.d.ts.map +1 -1
  132. package/dist/adapters/mysql/tools/shell/backup.js +71 -59
  133. package/dist/adapters/mysql/tools/shell/backup.js.map +1 -1
  134. package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
  135. package/dist/adapters/mysql/tools/shell/restore.js +61 -47
  136. package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
  137. package/dist/adapters/mysql/tools/spatial/geometry.d.ts.map +1 -1
  138. package/dist/adapters/mysql/tools/spatial/geometry.js +19 -5
  139. package/dist/adapters/mysql/tools/spatial/geometry.js.map +1 -1
  140. package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
  141. package/dist/adapters/mysql/tools/spatial/operations.js +42 -17
  142. package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
  143. package/dist/adapters/mysql/tools/spatial/queries.d.ts.map +1 -1
  144. package/dist/adapters/mysql/tools/spatial/queries.js +109 -57
  145. package/dist/adapters/mysql/tools/spatial/queries.js.map +1 -1
  146. package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
  147. package/dist/adapters/mysql/tools/spatial/setup.js +103 -50
  148. package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
  149. package/dist/adapters/mysql/tools/stats/comparative.d.ts.map +1 -1
  150. package/dist/adapters/mysql/tools/stats/comparative.js +128 -79
  151. package/dist/adapters/mysql/tools/stats/comparative.js.map +1 -1
  152. package/dist/adapters/mysql/tools/stats/descriptive.d.ts.map +1 -1
  153. package/dist/adapters/mysql/tools/stats/descriptive.js +174 -102
  154. package/dist/adapters/mysql/tools/stats/descriptive.js.map +1 -1
  155. package/dist/adapters/mysql/tools/sysschema/activity.d.ts.map +1 -1
  156. package/dist/adapters/mysql/tools/sysschema/activity.js +50 -25
  157. package/dist/adapters/mysql/tools/sysschema/activity.js.map +1 -1
  158. package/dist/adapters/mysql/tools/sysschema/performance.d.ts.map +1 -1
  159. package/dist/adapters/mysql/tools/sysschema/performance.js +121 -66
  160. package/dist/adapters/mysql/tools/sysschema/performance.js.map +1 -1
  161. package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
  162. package/dist/adapters/mysql/tools/sysschema/resources.js +101 -64
  163. package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
  164. package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
  165. package/dist/adapters/mysql/tools/text/fulltext.js +18 -32
  166. package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
  167. package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
  168. package/dist/adapters/mysql/tools/transactions.js +48 -23
  169. package/dist/adapters/mysql/tools/transactions.js.map +1 -1
  170. package/dist/adapters/mysql/types/proxysql-types.d.ts +15 -0
  171. package/dist/adapters/mysql/types/proxysql-types.d.ts.map +1 -1
  172. package/dist/adapters/mysql/types/proxysql-types.js +33 -1
  173. package/dist/adapters/mysql/types/proxysql-types.js.map +1 -1
  174. package/dist/adapters/mysql/types/router-types.d.ts +1 -1
  175. package/dist/adapters/mysql/types/router-types.js +1 -1
  176. package/dist/adapters/mysql/types/router-types.js.map +1 -1
  177. package/dist/adapters/mysql/types/shell-types.js +2 -2
  178. package/dist/adapters/mysql/types/shell-types.js.map +1 -1
  179. package/dist/adapters/mysql/types.d.ts +485 -21
  180. package/dist/adapters/mysql/types.d.ts.map +1 -1
  181. package/dist/adapters/mysql/types.js +546 -19
  182. package/dist/adapters/mysql/types.js.map +1 -1
  183. package/dist/auth/scopes.js +1 -1
  184. package/dist/auth/scopes.js.map +1 -1
  185. package/dist/codemode/api.d.ts +3 -2
  186. package/dist/codemode/api.d.ts.map +1 -1
  187. package/dist/codemode/api.js +80 -5
  188. package/dist/codemode/api.js.map +1 -1
  189. package/dist/codemode/sandbox-factory.js +1 -1
  190. package/dist/codemode/sandbox-factory.js.map +1 -1
  191. package/dist/codemode/types.d.ts +26 -0
  192. package/dist/codemode/types.d.ts.map +1 -1
  193. package/dist/codemode/types.js +2 -0
  194. package/dist/codemode/types.js.map +1 -1
  195. package/dist/codemode/worker-sandbox.d.ts +4 -2
  196. package/dist/codemode/worker-sandbox.d.ts.map +1 -1
  197. package/dist/codemode/worker-sandbox.js +66 -7
  198. package/dist/codemode/worker-sandbox.js.map +1 -1
  199. package/dist/codemode/worker-script.d.ts +3 -0
  200. package/dist/codemode/worker-script.d.ts.map +1 -1
  201. package/dist/codemode/worker-script.js +128 -75
  202. package/dist/codemode/worker-script.js.map +1 -1
  203. package/dist/constants/ServerInstructions.d.ts +1 -1
  204. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  205. package/dist/constants/ServerInstructions.js +37 -31
  206. package/dist/constants/ServerInstructions.js.map +1 -1
  207. package/dist/filtering/ToolConstants.d.ts +1 -1
  208. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  209. package/dist/filtering/ToolConstants.js +1 -2
  210. package/dist/filtering/ToolConstants.js.map +1 -1
  211. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  212. package/dist/pool/ConnectionPool.js.map +1 -1
  213. package/dist/transports/http.d.ts.map +1 -1
  214. package/dist/transports/http.js +6 -0
  215. package/dist/transports/http.js.map +1 -1
  216. package/dist/utils/validators.d.ts +1 -1
  217. package/dist/utils/validators.d.ts.map +1 -1
  218. package/dist/utils/validators.js.map +1 -1
  219. package/package.json +4 -4
  220. package/releases/v2.3.0-release-notes.md +20 -20
  221. package/releases/v2.3.1-release-notes.md +34 -0
  222. package/releases/v3.0.0-release-notes.md +81 -0
  223. package/src/__tests__/mocks/adapter.ts +3 -0
  224. package/src/__tests__/perf.test.ts +6 -6
  225. package/src/adapters/DatabaseAdapter.ts +58 -9
  226. package/src/adapters/__tests__/DatabaseAdapter.test.ts +89 -8
  227. package/src/adapters/mysql/MySQLAdapter.ts +17 -2
  228. package/src/adapters/mysql/SchemaManager.ts +21 -21
  229. package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +1 -1
  230. package/src/adapters/mysql/prompts/index.ts +12 -22
  231. package/src/adapters/mysql/prompts/proxysqlSetup.ts +1 -1
  232. package/src/adapters/mysql/resources/docstore.ts +13 -10
  233. package/src/adapters/mysql/resources/events.ts +12 -12
  234. package/src/adapters/mysql/resources/indexes.ts +17 -19
  235. package/src/adapters/mysql/resources/innodb.ts +23 -22
  236. package/src/adapters/mysql/resources/locks.ts +9 -7
  237. package/src/adapters/mysql/resources/performance.ts +23 -18
  238. package/src/adapters/mysql/resources/spatial.ts +9 -7
  239. package/src/adapters/mysql/resources/sysschema.ts +12 -11
  240. package/src/adapters/mysql/tools/__tests__/core.test.ts +126 -55
  241. package/src/adapters/mysql/tools/__tests__/docstore.test.ts +459 -88
  242. package/src/adapters/mysql/tools/__tests__/events.test.ts +281 -103
  243. package/src/adapters/mysql/tools/__tests__/proxysql.test.ts +128 -28
  244. package/src/adapters/mysql/tools/__tests__/replication.test.ts +48 -2
  245. package/src/adapters/mysql/tools/__tests__/roles.test.ts +15 -18
  246. package/src/adapters/mysql/tools/__tests__/router.test.ts +32 -5
  247. package/src/adapters/mysql/tools/__tests__/security.test.ts +126 -2
  248. package/src/adapters/mysql/tools/__tests__/security_injection.test.ts +84 -76
  249. package/src/adapters/mysql/tools/__tests__/security_integration.test.ts +47 -50
  250. package/src/adapters/mysql/tools/__tests__/spatial.test.ts +11 -10
  251. package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +54 -38
  252. package/src/adapters/mysql/tools/__tests__/stats.test.ts +285 -152
  253. package/src/adapters/mysql/tools/__tests__/transactions.test.ts +13 -13
  254. package/src/adapters/mysql/tools/admin/__tests__/backup.test.ts +171 -25
  255. package/src/adapters/mysql/tools/admin/__tests__/maintenance.test.ts +240 -4
  256. package/src/adapters/mysql/tools/admin/__tests__/monitoring-summary.test.ts +274 -0
  257. package/src/adapters/mysql/tools/admin/__tests__/monitoring.test.ts +94 -5
  258. package/src/adapters/mysql/tools/admin/backup.ts +193 -143
  259. package/src/adapters/mysql/tools/admin/maintenance.ts +118 -69
  260. package/src/adapters/mysql/tools/admin/monitoring.ts +201 -125
  261. package/src/adapters/mysql/tools/cluster/__tests__/group-replication.test.ts +69 -0
  262. package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +141 -0
  263. package/src/adapters/mysql/tools/cluster/group-replication.ts +172 -132
  264. package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +231 -157
  265. package/src/adapters/mysql/tools/codemode/__tests__/codemode-tool.test.ts +227 -0
  266. package/src/adapters/mysql/tools/codemode/index.ts +5 -3
  267. package/src/adapters/mysql/tools/core.ts +152 -38
  268. package/src/adapters/mysql/tools/docstore.ts +422 -205
  269. package/src/adapters/mysql/tools/events.ts +334 -233
  270. package/src/adapters/mysql/tools/json/__tests__/core.test.ts +20 -0
  271. package/src/adapters/mysql/tools/json/__tests__/enhanced.test.ts +82 -50
  272. package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +42 -3
  273. package/src/adapters/mysql/tools/json/core.ts +21 -42
  274. package/src/adapters/mysql/tools/json/enhanced.ts +22 -37
  275. package/src/adapters/mysql/tools/json/helpers.ts +21 -25
  276. package/src/adapters/mysql/tools/partitioning.ts +3 -0
  277. package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +98 -5
  278. package/src/adapters/mysql/tools/performance/__tests__/optimization-coverage.test.ts +515 -0
  279. package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +187 -0
  280. package/src/adapters/mysql/tools/performance/analysis.ts +95 -69
  281. package/src/adapters/mysql/tools/performance/optimization.ts +182 -153
  282. package/src/adapters/mysql/tools/proxysql.ts +314 -209
  283. package/src/adapters/mysql/tools/replication.ts +84 -57
  284. package/src/adapters/mysql/tools/roles.ts +274 -226
  285. package/src/adapters/mysql/tools/router.ts +181 -85
  286. package/src/adapters/mysql/tools/schema/__tests__/constraints.test.ts +13 -0
  287. package/src/adapters/mysql/tools/schema/__tests__/management.test.ts +60 -25
  288. package/src/adapters/mysql/tools/schema/__tests__/scheduled_events.test.ts +11 -0
  289. package/src/adapters/mysql/tools/schema/__tests__/triggers.test.ts +25 -4
  290. package/src/adapters/mysql/tools/schema/__tests__/views.test.ts +46 -14
  291. package/src/adapters/mysql/tools/schema/constraints.ts +22 -3
  292. package/src/adapters/mysql/tools/schema/management.ts +60 -15
  293. package/src/adapters/mysql/tools/schema/routines.ts +26 -4
  294. package/src/adapters/mysql/tools/schema/scheduled_events.ts +25 -3
  295. package/src/adapters/mysql/tools/schema/triggers.ts +27 -2
  296. package/src/adapters/mysql/tools/schema/views.ts +46 -8
  297. package/src/adapters/mysql/tools/security/__tests__/audit.test.ts +90 -4
  298. package/src/adapters/mysql/tools/security/audit.ts +113 -39
  299. package/src/adapters/mysql/tools/security/data-protection.ts +293 -233
  300. package/src/adapters/mysql/tools/security/encryption.ts +172 -139
  301. package/src/adapters/mysql/tools/shell/__tests__/backup.test.ts +29 -0
  302. package/src/adapters/mysql/tools/shell/backup.ts +90 -73
  303. package/src/adapters/mysql/tools/shell/restore.ts +62 -48
  304. package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +22 -14
  305. package/src/adapters/mysql/tools/spatial/__tests__/queries.test.ts +65 -51
  306. package/src/adapters/mysql/tools/spatial/geometry.ts +23 -7
  307. package/src/adapters/mysql/tools/spatial/operations.ts +60 -31
  308. package/src/adapters/mysql/tools/spatial/queries.ts +142 -65
  309. package/src/adapters/mysql/tools/spatial/setup.ts +121 -55
  310. package/src/adapters/mysql/tools/stats/__tests__/comparative.test.ts +12 -10
  311. package/src/adapters/mysql/tools/stats/comparative.ts +150 -98
  312. package/src/adapters/mysql/tools/stats/descriptive.ts +204 -127
  313. package/src/adapters/mysql/tools/sysschema/__tests__/error-paths.test.ts +222 -0
  314. package/src/adapters/mysql/tools/sysschema/__tests__/performance.test.ts +45 -0
  315. package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +6 -3
  316. package/src/adapters/mysql/tools/sysschema/activity.ts +52 -27
  317. package/src/adapters/mysql/tools/sysschema/performance.ts +132 -68
  318. package/src/adapters/mysql/tools/sysschema/resources.ts +105 -67
  319. package/src/adapters/mysql/tools/text/__tests__/fulltext.test.ts +45 -17
  320. package/src/adapters/mysql/tools/text/fulltext.ts +27 -38
  321. package/src/adapters/mysql/tools/transactions.ts +49 -24
  322. package/src/adapters/mysql/types/proxysql-types.ts +38 -1
  323. package/src/adapters/mysql/types/router-types.ts +1 -1
  324. package/src/adapters/mysql/types/shell-types.ts +2 -2
  325. package/src/adapters/mysql/types.ts +632 -19
  326. package/src/auth/__tests__/scopes.test.ts +2 -2
  327. package/src/auth/scopes.ts +1 -1
  328. package/src/codemode/__tests__/api.test.ts +417 -0
  329. package/src/codemode/__tests__/sandbox-factory.test.ts +158 -0
  330. package/src/codemode/__tests__/sandbox.test.ts +301 -0
  331. package/src/codemode/__tests__/security.test.ts +368 -0
  332. package/src/codemode/__tests__/worker-sandbox.test.ts +179 -0
  333. package/src/codemode/__tests__/worker-script.test.ts +226 -0
  334. package/src/codemode/api.ts +89 -5
  335. package/src/codemode/sandbox-factory.ts +1 -1
  336. package/src/codemode/types.ts +34 -0
  337. package/src/codemode/worker-sandbox.ts +74 -7
  338. package/src/codemode/worker-script.ts +157 -86
  339. package/src/constants/ServerInstructions.ts +37 -31
  340. package/src/filtering/ToolConstants.ts +1 -2
  341. package/src/filtering/__tests__/ToolFilter.test.ts +9 -9
  342. package/src/pool/ConnectionPool.ts +4 -1
  343. package/src/transports/__tests__/http.test.ts +15 -3
  344. package/src/transports/http.ts +12 -0
  345. package/src/utils/validators.ts +2 -1
  346. package/vitest.config.ts +3 -1
  347. package/CODE_MODE.md +0 -245
@@ -0,0 +1,81 @@
1
+ # mysql-mcp v3.0.0 Release Notes
2
+
3
+ ## 🚀 Major Release — February 26, 2026
4
+
5
+ **mysql-mcp v3.0.0** is a landmark release delivering **Code Mode with worker-thread sandbox isolation**, **OAuth 2.1 authentication**, **deterministic error handling** across all 192 tools, and hundreds of bug fixes and security hardening improvements.
6
+
7
+ ### ✨ Highlights
8
+
9
+ #### Code Mode (`mysql_execute_code`)
10
+
11
+ New sandboxed code execution tool enabling AI agents to compose multi-step MySQL workflows as JavaScript/TypeScript code. Features:
12
+
13
+ - **Worker-thread isolation** — separate V8 isolate via `worker_threads` with `MessagePort` RPC bridge
14
+ - **Readonly enforcement** — write methods return structured errors when `readonly: true`
15
+ - **Memory limits** — enforced `resourceLimits` (`maxOldGenerationSizeMb`, `maxYoungGenerationSizeMb`)
16
+ - **Full API access** — all 24 tool groups available via `mysql.*` namespace
17
+ - **Auto-injection** — `mysql_execute_code` included in all tool filter presets
18
+
19
+ #### OAuth 2.1 + Configurable Server Host
20
+
21
+ - HTTP/SSE transport with `--server-host` / `MCP_HOST` binding configuration
22
+ - RFC 9728/8414 compliance with granular scopes (`read`, `write`, `admin`, `full`, `db:*`, `table:*:*`)
23
+
24
+ #### Deterministic Error Handling
25
+
26
+ Every tool now returns structured `{success, error}` responses — no raw exceptions, no silent failures. Agents get actionable context instead of cryptic MySQL error codes.
27
+
28
+ #### Parameter Aliases (Split Schema Pattern)
29
+
30
+ Tools accept alternative parameter names automatically normalized via Zod schema preprocessing: `table`/`tableName`/`name`, `query`/`sql`, `where`/`filter`, `column`/`col`.
31
+
32
+ ### 🔒 Security
33
+
34
+ - **Worker sandbox API bridge** — `MessagePort`-based RPC for Code Mode isolation
35
+ - **Code Mode readonly enforcement** — write tools blocked when `readonly: true`
36
+ - **SQL injection fixes** — `mysql_doc_find` filter, `mysql_create_schema` charset/collation, `mysql_security_user_privileges` identifier quoting
37
+ - **ProxySQL credential redaction** — variables containing `password`/`credentials` auto-redacted
38
+ - **CVE patches** — `hono` timing comparison (GHSA-gq3j-xvxp-8hrf), `rollup` path traversal (GHSA-mw96-cpmx-2vgc), `ajv` ReDoS (GHSA-2g4f-4pwh-qvx6), `qs` arrayLimit bypass (GHSA-w7fw-mjwx-w883), `tar` path traversal (CVE-2026-26960)
39
+ - **HTTP security headers** — HSTS, Referrer-Policy, Permissions-Policy
40
+ - **Sandbox pattern hardening** — bracket-notation constructor access and `Reflect.construct` bypass detection
41
+
42
+ ### ⚡ Performance
43
+
44
+ - **Cache invalidation after DDL** — `clearSchemaCache()` on 14 DDL handlers across 7 files
45
+ - **Parallelized queries** — `SchemaManager.describeTable()` and 8 resource handlers use `Promise.all()`
46
+ - **Test suite parallelism** — 4 workers, ~37s total runtime (44% faster)
47
+
48
+ ### 💔 Breaking Changes
49
+
50
+ - **`proxysql_hostgroups` removed** — use `proxysql_connection_pool` (with `hostgroup_id` filtering) instead. Tool count: 193 → 192
51
+ - **`reason` → `error` field normalization** — all `{success: false}` error responses use `error` field; `reason` reserved for informational `{success: true, skipped: true}` responses
52
+ - **`mysql_drop_table` default** — `ifExists` default changed from `true` to `false`
53
+ - **`mysql2` 3.18.0 type** — adjusted `QueryValues` type constraint on `execute()`/`query()`
54
+
55
+ ### 📦 Dependencies
56
+
57
+ - `@modelcontextprotocol/sdk`: 1.26.0 → 1.27.1
58
+ - `@types/node`: 25.2.3 → 25.3.1
59
+ - `eslint`: 10.0.0 → 10.0.2
60
+ - `mysql2`: 3.17.2 → 3.18.1
61
+ - `typescript-eslint`: 8.56.0 → 8.56.1
62
+
63
+ ### 🏗️ Infrastructure
64
+
65
+ - **Default branch** renamed from `master` to `main`
66
+ - **`.gitattributes`** — enforces LF line endings with CRLF exceptions for Windows scripts
67
+ - **Vitest JSON reporter** — `test-results.json` output for agent consumption
68
+
69
+ ---
70
+
71
+ ### Installation
72
+
73
+ ```bash
74
+ # NPM
75
+ npm install -g @neverinfamous/mysql-mcp@3.0.0
76
+
77
+ # Docker
78
+ docker pull writenotenow/mysql-mcp:v3.0.0
79
+ ```
80
+
81
+ **Full Changelog:** [v2.3.1...v3.0.0](https://github.com/neverinfamous/mysql-mcp/compare/v2.3.1...v3.0.0)
@@ -196,6 +196,9 @@ export function createMockMySQLAdapter(): Partial<MySQLAdapter> & {
196
196
 
197
197
  // Pool access
198
198
  getPool: vi.fn().mockReturnValue(null),
199
+
200
+ // Schema cache invalidation
201
+ clearSchemaCache: vi.fn(),
199
202
  };
200
203
  }
201
204
 
@@ -65,9 +65,9 @@ describe("Performance Tests", () => {
65
65
  expect(cachedCallTime.avg).toBeLessThan(0.5);
66
66
  });
67
67
 
68
- it("should return consistent count of 193 tools", () => {
68
+ it("should return consistent count of 192 tools", () => {
69
69
  const tools = getAllToolNames();
70
- expect(tools).toHaveLength(193);
70
+ expect(tools).toHaveLength(192);
71
71
  });
72
72
  });
73
73
 
@@ -165,7 +165,7 @@ describe("Performance Tests", () => {
165
165
  describe("filterTools performance", () => {
166
166
  const mockHandler = async () => ({ result: "ok" });
167
167
 
168
- it("should filter 193 tools efficiently", () => {
168
+ it("should filter 192 tools efficiently", () => {
169
169
  // Create mock tools matching all tool names
170
170
  const allToolNames = getAllToolNames();
171
171
  const mockTools: ToolDefinition[] = allToolNames.map((name) => ({
@@ -198,7 +198,7 @@ describe("Performance Tests", () => {
198
198
 
199
199
  // First call builds the cache
200
200
  const firstCall = adapter.getToolDefinitions();
201
- expect(firstCall).toHaveLength(193);
201
+ expect(firstCall).toHaveLength(192);
202
202
 
203
203
  // Subsequent calls should return same reference (cached)
204
204
  const secondCall = adapter.getToolDefinitions();
@@ -213,7 +213,7 @@ describe("Performance Tests", () => {
213
213
  expect(timing.avg).toBeLessThan(0.5);
214
214
  });
215
215
 
216
- it("should return consistent tool count of 193 regardless of filter default", () => {
216
+ it("should return consistent tool count of 192 regardless of filter default", () => {
217
217
  const adapter = new MySQLAdapter();
218
218
 
219
219
  // getToolDefinitions returns ALL definitions available in the adapter,
@@ -221,7 +221,7 @@ describe("Performance Tests", () => {
221
221
  // Wait, MySQLAdapter.getToolDefinitions() returns all tools?
222
222
  // Yes, checking the implementation... it usually does.
223
223
  const tools = adapter.getToolDefinitions();
224
- expect(tools).toHaveLength(193);
224
+ expect(tools).toHaveLength(192);
225
225
  });
226
226
  });
227
227
  });
@@ -322,26 +322,57 @@ export abstract class DatabaseAdapter {
322
322
  * Register a single prompt with the MCP server
323
323
  */
324
324
  protected registerPrompt(server: McpServer, prompt: PromptDefinition): void {
325
- // Build Zod schema from prompt.arguments definitions
326
- const zodShape: Record<string, z.ZodType> = {};
327
- if (prompt.arguments) {
325
+ // Build a Zod raw shape from prompt.arguments so the SDK can
326
+ // advertise argument metadata in prompts/list via promptArgumentsFromSchema().
327
+ //
328
+ // ALL fields are .optional() because the SDK validates BEFORE our handler
329
+ // runs. If required fields used z.string() (non-optional), clients that
330
+ // invoke prompts without filling in required args would get a raw Zod
331
+ // error instead of our graceful guide message. Required-ness is enforced
332
+ // by the handler-level missing-arg check below.
333
+ let argsSchema: Record<string, z.ZodType> | undefined;
334
+ if (prompt.arguments && prompt.arguments.length > 0) {
335
+ argsSchema = {};
328
336
  for (const arg of prompt.arguments) {
329
- zodShape[arg.name] = arg.required
330
- ? z.string().describe(arg.description)
331
- : z.string().optional().describe(arg.description);
337
+ argsSchema[arg.name] = z.string().optional().describe(arg.description);
332
338
  }
333
339
  }
334
340
 
335
- server.registerPrompt(
341
+ const registered = server.registerPrompt(
336
342
  prompt.name,
337
343
  {
338
344
  description: prompt.description,
339
- argsSchema: zodShape,
345
+ argsSchema,
340
346
  },
341
347
  async (providedArgs) => {
342
348
  const context = this.createContext();
343
349
  // Cast args to Record<string, string> for handler compatibility
344
- const args = providedArgs as Record<string, string>;
350
+ const args = (providedArgs ?? {}) as Record<string, string>;
351
+
352
+ // Check for missing required arguments
353
+ const requiredArgs = prompt.arguments?.filter((a) => a.required) ?? [];
354
+ const missingArgs = requiredArgs.filter((a) => !args[a.name]);
355
+ if (missingArgs.length > 0) {
356
+ // Return a helpful guide listing expected arguments
357
+ const argList = (prompt.arguments ?? [])
358
+ .map(
359
+ (a) =>
360
+ `- **${a.name}**${a.required ? " (required)" : " (optional)"}: ${a.description}`,
361
+ )
362
+ .join("\n");
363
+ return {
364
+ messages: [
365
+ {
366
+ role: "user" as const,
367
+ content: {
368
+ type: "text" as const,
369
+ text: `# ${prompt.name}\n\n${prompt.description}\n\n## Arguments\n\n${argList}\n\nPlease provide the required arguments to use this prompt.`,
370
+ },
371
+ },
372
+ ],
373
+ };
374
+ }
375
+
345
376
  const result = await prompt.handler(args, context);
346
377
  return {
347
378
  messages: [
@@ -359,6 +390,24 @@ export abstract class DatabaseAdapter {
359
390
  };
360
391
  },
361
392
  );
393
+
394
+ // Patch the SDK's stored Zod object schema to accept `undefined` input.
395
+ // The SDK's prompts/get handler calls safeParseAsync(argsSchema, args)
396
+ // where args may be `undefined` when clients omit them. Zod v4's
397
+ // z.object().safeParse(undefined) rejects — but we need it to succeed
398
+ // (coercing to {}) so our handler-level required-arg check can provide
399
+ // a graceful guide message instead of a raw Zod crash.
400
+ // The metadata (shape, type) is preserved for promptArgumentsFromSchema().
401
+ if (registered.argsSchema) {
402
+ const schema = registered.argsSchema as unknown as {
403
+ _zod: { run: (ctx: { value: unknown }) => unknown };
404
+ };
405
+ const originalRun = schema._zod.run.bind(schema._zod);
406
+ schema._zod.run = (ctx: { value: unknown }) => {
407
+ ctx.value ??= {};
408
+ return originalRun(ctx);
409
+ };
410
+ }
362
411
  }
363
412
 
364
413
  // =========================================================================
@@ -370,7 +370,22 @@ describe("DatabaseAdapter", () => {
370
370
  mockServer = {
371
371
  registerTool: vi.fn(),
372
372
  registerResource: vi.fn(),
373
- registerPrompt: vi.fn(),
373
+ // Return a RegisteredPrompt-like object so `registered.argsSchema`
374
+ // is accessible for schema patching in DatabaseAdapter.registerPrompt()
375
+ registerPrompt: vi.fn().mockImplementation((_name, config, _cb) => {
376
+ // Mimic SDK: if argsSchema is provided, create a z.object() from it.
377
+ // Use a mock with _zod.run so the patching code doesn't crash.
378
+ let argsSchema: unknown = undefined;
379
+ if (config?.argsSchema) {
380
+ argsSchema = {
381
+ _zod: {
382
+ def: { type: "object", shape: config.argsSchema },
383
+ run: vi.fn((ctx: { value: unknown }) => ctx),
384
+ },
385
+ };
386
+ }
387
+ return { argsSchema };
388
+ }),
374
389
  };
375
390
  });
376
391
 
@@ -438,7 +453,7 @@ describe("DatabaseAdapter", () => {
438
453
  );
439
454
  });
440
455
 
441
- it("should handle prompts with arguments", () => {
456
+ it("should pass argsSchema for prompts with arguments so SDK advertises them", () => {
442
457
  const promptWithArgs: PromptDefinition = {
443
458
  name: "arg_prompt",
444
459
  description: "desc",
@@ -454,18 +469,84 @@ describe("DatabaseAdapter", () => {
454
469
  ]);
455
470
  adapter.registerPrompts(mockServer as never);
456
471
 
472
+ // argsSchema must be a Zod raw shape so the SDK can:
473
+ // 1. Advertise arguments in prompts/list
474
+ // 2. Validate arguments in prompts/get
475
+ const calledConfig = mockServer.registerPrompt.mock.calls[0][1];
476
+ expect(calledConfig.argsSchema).toBeDefined();
477
+ expect(calledConfig.argsSchema).toHaveProperty("required_arg");
478
+ expect(calledConfig.argsSchema).toHaveProperty("optional_arg");
479
+ });
480
+
481
+ it("should not pass argsSchema for prompts without arguments", () => {
482
+ adapter.registerPrompts(mockServer as never);
483
+
457
484
  expect(mockServer.registerPrompt).toHaveBeenCalledWith(
458
- "arg_prompt",
485
+ "test_prompt",
459
486
  expect.objectContaining({
460
- description: "desc",
461
- argsSchema: expect.objectContaining({
462
- required_arg: expect.anything(),
463
- optional_arg: expect.anything(),
464
- }),
487
+ description: "A test prompt",
488
+ argsSchema: undefined,
465
489
  }),
466
490
  expect.any(Function),
467
491
  );
468
492
  });
493
+
494
+ it("should pass argsSchema for prompts with all-optional arguments", () => {
495
+ const allOptionalPrompt: PromptDefinition = {
496
+ name: "all_optional_prompt",
497
+ description: "All optional args",
498
+ arguments: [
499
+ { name: "opt_a", description: "optional a", required: false },
500
+ { name: "opt_b", description: "optional b", required: false },
501
+ ],
502
+ handler: async () => "result",
503
+ };
504
+
505
+ vi.spyOn(adapter, "getPromptDefinitions").mockReturnValue([
506
+ allOptionalPrompt,
507
+ ]);
508
+ adapter.registerPrompts(mockServer as never);
509
+
510
+ // argsSchema must be a Zod raw shape (even when all optional)
511
+ // so the SDK advertises arguments in prompts/list
512
+ const calledConfig = mockServer.registerPrompt.mock.calls[0][1];
513
+ expect(calledConfig.argsSchema).toBeDefined();
514
+ expect(calledConfig.argsSchema).toHaveProperty("opt_a");
515
+ expect(calledConfig.argsSchema).toHaveProperty("opt_b");
516
+ });
517
+
518
+ it("should return guide message when required args are missing", async () => {
519
+ const promptWithRequired: PromptDefinition = {
520
+ name: "required_prompt",
521
+ description: "Needs args",
522
+ arguments: [
523
+ { name: "operation", description: "The operation", required: true },
524
+ { name: "note", description: "A note", required: false },
525
+ ],
526
+ handler: async () => "should not reach",
527
+ };
528
+
529
+ vi.spyOn(adapter, "getPromptDefinitions").mockReturnValue([
530
+ promptWithRequired,
531
+ ]);
532
+ adapter.registerPrompts(mockServer as never);
533
+
534
+ // Call handler with no args (simulates MCP client sending undefined)
535
+ const handler = mockServer.registerPrompt.mock.calls[0][2] as Function;
536
+ const result = await handler({});
537
+
538
+ // Should return a guide message, not the handler output
539
+ expect(result.messages[0].content.text).toContain("required_prompt");
540
+ expect(result.messages[0].content.text).toContain(
541
+ "**operation** (required)",
542
+ );
543
+ expect(result.messages[0].content.text).toContain(
544
+ "**note** (optional)",
545
+ );
546
+ expect(result.messages[0].content.text).toContain(
547
+ "Please provide the required arguments",
548
+ );
549
+ });
469
550
  });
470
551
 
471
552
  describe("handler execution", () => {
@@ -269,13 +269,19 @@ export class MySQLAdapter extends DatabaseAdapter {
269
269
  const startTime = Date.now();
270
270
 
271
271
  try {
272
- const [results, fields] = await connection.execute(sql, params);
272
+ const [results, fields] = await connection.execute(
273
+ sql,
274
+ params as (string | number | null)[],
275
+ );
273
276
  return this.processExecutionResult(results, fields, startTime);
274
277
  } catch (error) {
275
278
  if (this.isUnsupportedPreparedStatementError(error)) {
276
279
  // Fallback to text protocol
277
280
  try {
278
- const [results, fields] = await connection.query(sql, params);
281
+ const [results, fields] = await connection.query(
282
+ sql,
283
+ params as (string | number | null)[],
284
+ );
279
285
  return this.processExecutionResult(results, fields, startTime);
280
286
  } catch (fallbackError) {
281
287
  const err = fallbackError as Error;
@@ -544,6 +550,15 @@ export class MySQLAdapter extends DatabaseAdapter {
544
550
  return this.pool;
545
551
  }
546
552
 
553
+ /**
554
+ * Clear the schema metadata cache.
555
+ * Should be called after any DDL operation (CREATE/DROP/ALTER TABLE, INDEX, VIEW)
556
+ * to prevent stale metadata from being served during the cache TTL window.
557
+ */
558
+ clearSchemaCache(): void {
559
+ this.schemaManager.clearCache();
560
+ }
561
+
547
562
  /**
548
563
  * Get IDs of all active transactions (for Code Mode cleanup)
549
564
  */
@@ -201,9 +201,10 @@ export class SchemaManager {
201
201
  : "TABLE_SCHEMA = DATABASE()";
202
202
  const params = schemaName ? [schemaName, shortTableName] : [shortTableName];
203
203
 
204
- // Get column information
205
- const columnsResult = await this.executor.executeQuery(
206
- `
204
+ // Performance optimization: run column and table queries in parallel
205
+ const [columnsResult, tableResult] = await Promise.all([
206
+ this.executor.executeQuery(
207
+ `
207
208
  SELECT
208
209
  COLUMN_NAME as name,
209
210
  DATA_TYPE as type,
@@ -219,8 +220,23 @@ export class SchemaManager {
219
220
  AND TABLE_NAME = ?
220
221
  ORDER BY ORDINAL_POSITION
221
222
  `,
222
- params,
223
- );
223
+ params,
224
+ ),
225
+ this.executor.executeQuery(
226
+ `
227
+ SELECT
228
+ TABLE_TYPE as type,
229
+ ENGINE as engine,
230
+ TABLE_ROWS as rowCount,
231
+ TABLE_COLLATION as collation,
232
+ TABLE_COMMENT as comment
233
+ FROM information_schema.TABLES
234
+ WHERE ${schemaClause}
235
+ AND TABLE_NAME = ?
236
+ `,
237
+ params,
238
+ ),
239
+ ]);
224
240
 
225
241
  const columns: ColumnInfo[] = (columnsResult.rows ?? []).map((row) => ({
226
242
  name: row["name"] as string,
@@ -234,22 +250,6 @@ export class SchemaManager {
234
250
  comment: row["comment"] as string | undefined,
235
251
  }));
236
252
 
237
- // Get table info
238
- const tableResult = await this.executor.executeQuery(
239
- `
240
- SELECT
241
- TABLE_TYPE as type,
242
- ENGINE as engine,
243
- TABLE_ROWS as rowCount,
244
- TABLE_COLLATION as collation,
245
- TABLE_COMMENT as comment
246
- FROM information_schema.TABLES
247
- WHERE ${schemaClause}
248
- AND TABLE_NAME = ?
249
- `,
250
- params,
251
- );
252
-
253
253
  const tableRow = tableResult.rows?.[0];
254
254
 
255
255
  const result: TableInfo = {
@@ -606,7 +606,7 @@ describe("MySQLAdapter", () => {
606
606
  const first = adapter.getToolDefinitions();
607
607
  const second = adapter.getToolDefinitions();
608
608
  expect(first).toBe(second); // Same reference = cached
609
- expect(first.length).toBe(193);
609
+ expect(first.length).toBe(192);
610
610
  });
611
611
  });
612
612
 
@@ -256,31 +256,21 @@ function createSchemaDesignPrompt(): PromptDefinition {
256
256
  ],
257
257
  handler: (args: Record<string, string>, _context: RequestContext) => {
258
258
  return Promise.resolve(`
259
- You are a MySQL database architect. Design a schema for: ${args["entity"]}
259
+ Design a MySQL schema for: ${args["entity"]}
260
260
 
261
261
  ${args["requirements"] ? `Requirements: ${args["requirements"]}` : ""}
262
262
 
263
- Please provide:
264
- 1. CREATE TABLE statement with:
265
- - Appropriate data types
266
- - Primary key
267
- - Indexes for common queries
268
- - Foreign key relationships if applicable
269
- - Engine: InnoDB (for transactions)
270
- - Charset: utf8mb4 (for full Unicode support)
271
-
272
- 2. Explanation of design choices
273
-
274
- 3. Sample INSERT statements
275
-
276
- 4. Common SELECT queries with indexes
277
-
278
- Best practices to follow:
279
- - Use underscore_case for column names
280
- - Include created_at and updated_at timestamps
281
- - Use UNSIGNED for positive-only integers
282
- - Consider JSON columns for flexible data
283
- - Add appropriate indexes based on query patterns
263
+ Provide a CREATE TABLE statement with:
264
+ - Appropriate data types
265
+ - Primary key
266
+ - Indexes for common queries
267
+ - Foreign key relationships if applicable
268
+ - Engine: InnoDB (for transactions)
269
+ - Charset: utf8mb4 (for full Unicode support)
270
+
271
+ Follow these conventions: underscore_case columns, created_at/updated_at timestamps, UNSIGNED for positive integers, JSON columns where appropriate.
272
+
273
+ Briefly explain key design decisions.
284
274
  `);
285
275
  },
286
276
  };
@@ -82,7 +82,7 @@ PROXYSQL_PASSWORD=admin
82
82
  Use ProxySQL tools to verify:
83
83
  - \`proxysql_status\` - Check ProxySQL is running
84
84
  - \`proxysql_servers\` - List configured servers
85
- - \`proxysql_hostgroups\` - View hostgroup configuration
85
+ - \`proxysql_connection_pool\` - View connection pool stats (filterable by hostgroup_id)
86
86
  - \`proxysql_query_rules\` - Review routing rules
87
87
  - \`proxysql_query_digest\` - Analyze query patterns
88
88
 
@@ -22,15 +22,14 @@ export function createDocstoreResource(
22
22
  },
23
23
  handler: async (_uri: string, _context: RequestContext) => {
24
24
  try {
25
- // Check if X Plugin is enabled
26
- const pluginResult = await adapter.executeQuery(
27
- "SELECT PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_NAME = 'mysqlx'",
28
- );
29
- const pluginRow = pluginResult.rows?.[0];
30
- const xPluginEnabled = pluginRow?.["PLUGIN_STATUS"] === "ACTIVE";
31
-
32
- // Get collections (tables with _id column and doc JSON column)
33
- const collectionsResult = await adapter.executeQuery(`
25
+ // Performance optimization: run both independent queries in parallel
26
+ const [pluginResult, collectionsResult] = await Promise.all([
27
+ // Check if X Plugin is enabled
28
+ adapter.executeQuery(
29
+ "SELECT PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_NAME = 'mysqlx'",
30
+ ),
31
+ // Get collections (tables with _id column and doc JSON column)
32
+ adapter.executeQuery(`
34
33
  SELECT
35
34
  t.TABLE_NAME as collection_name,
36
35
  t.TABLE_ROWS as row_count,
@@ -51,7 +50,11 @@ export function createDocstoreResource(
51
50
  AND c2.COLUMN_NAME = '_id'
52
51
  )
53
52
  ORDER BY t.TABLE_NAME
54
- `);
53
+ `),
54
+ ]);
55
+
56
+ const pluginRow = pluginResult.rows?.[0];
57
+ const xPluginEnabled = pluginRow?.["PLUGIN_STATUS"] === "ACTIVE";
55
58
 
56
59
  return {
57
60
  xPluginEnabled,
@@ -21,17 +21,12 @@ export function createEventsResource(
21
21
  priority: 0.6,
22
22
  },
23
23
  handler: async (_uri: string, _context: RequestContext) => {
24
- // Get scheduler status
25
- const schedulerResult = await adapter.executeQuery(
26
- "SHOW VARIABLES LIKE 'event_scheduler'",
27
- );
28
- const schedulerRow = schedulerResult.rows?.[0];
29
- const schedulerVal = schedulerRow?.["Value"];
30
- const schedulerStatus =
31
- typeof schedulerVal === "string" ? schedulerVal : "OFF";
32
-
33
- // Get all events
34
- const eventsResult = await adapter.executeQuery(`
24
+ // Performance optimization: run both independent queries in parallel
25
+ const [schedulerResult, eventsResult] = await Promise.all([
26
+ // Get scheduler status
27
+ adapter.executeQuery("SHOW VARIABLES LIKE 'event_scheduler'"),
28
+ // Get all events
29
+ adapter.executeQuery(`
35
30
  SELECT
36
31
  EVENT_SCHEMA as schema_name,
37
32
  EVENT_NAME as name,
@@ -43,7 +38,12 @@ export function createEventsResource(
43
38
  LAST_EXECUTED as last_executed
44
39
  FROM information_schema.EVENTS
45
40
  ORDER BY EVENT_SCHEMA, EVENT_NAME
46
- `);
41
+ `),
42
+ ]);
43
+ const schedulerRow = schedulerResult.rows?.[0];
44
+ const schedulerVal = schedulerRow?.["Value"];
45
+ const schedulerStatus =
46
+ typeof schedulerVal === "string" ? schedulerVal : "OFF";
47
47
 
48
48
  return {
49
49
  schedulerEnabled: schedulerStatus === "ON",
@@ -32,7 +32,7 @@ export function createIndexesResource(
32
32
  return { error: "No database selected" };
33
33
  }
34
34
 
35
- // Get index statistics
35
+ // Get index statistics (required)
36
36
  const indexResult = await adapter.executeQuery(
37
37
  `
38
38
  SELECT
@@ -50,11 +50,15 @@ export function createIndexesResource(
50
50
  [database],
51
51
  );
52
52
 
53
- // Try to get index usage from performance_schema if available
53
+ // Performance optimization: run unused + duplicate queries in parallel
54
+ // Both are optional — they may fail on older MySQL versions
54
55
  let unusedIndexes: unknown[] = [];
56
+ let duplicateIndexes: unknown[] = [];
57
+
55
58
  try {
56
- const unusedResult = await adapter.executeQuery(
57
- `
59
+ const [unusedResult, dupResult] = await Promise.all([
60
+ adapter.executeQuery(
61
+ `
58
62
  SELECT
59
63
  object_schema as schema_name,
60
64
  object_name as table_name,
@@ -65,18 +69,10 @@ export function createIndexesResource(
65
69
  AND index_name != 'PRIMARY'
66
70
  AND count_star = 0
67
71
  `,
68
- [database],
69
- );
70
- unusedIndexes = unusedResult.rows ?? [];
71
- } catch {
72
- // Performance schema may not be available
73
- }
74
-
75
- // Get duplicate/redundant indexes
76
- let duplicateIndexes: unknown[] = [];
77
- try {
78
- const dupResult = await adapter.executeQuery(
79
- `
72
+ [database],
73
+ ),
74
+ adapter.executeQuery(
75
+ `
80
76
  SELECT
81
77
  a.TABLE_NAME as table_name,
82
78
  a.INDEX_NAME as redundant_index,
@@ -94,11 +90,13 @@ export function createIndexesResource(
94
90
  AND (a.INDEX_NAME != 'PRIMARY' AND b.INDEX_NAME != 'PRIMARY')
95
91
  GROUP BY a.TABLE_NAME, a.INDEX_NAME, a.COLUMN_NAME, b.INDEX_NAME
96
92
  `,
97
- [database],
98
- );
93
+ [database],
94
+ ),
95
+ ]);
96
+ unusedIndexes = unusedResult.rows ?? [];
99
97
  duplicateIndexes = dupResult.rows ?? [];
100
98
  } catch {
101
- // May fail on older MySQL versions
99
+ // Performance schema may not be available on older MySQL versions
102
100
  }
103
101
 
104
102
  return {