@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,227 @@
1
+ /**
2
+ * mysql-mcp - Code Mode Tool Unit Tests
3
+ *
4
+ * Tests for createExecuteCodeTool, getCodeModeTools, and cleanupCodeMode.
5
+ */
6
+
7
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
8
+ import {
9
+ createExecuteCodeTool,
10
+ getCodeModeTools,
11
+ cleanupCodeMode,
12
+ } from "../index.js";
13
+ import type { MySQLAdapter } from "../../../MySQLAdapter.js";
14
+ import type { ToolDefinition } from "../../../../../types/index.js";
15
+
16
+ // Suppress logger
17
+ vi.mock("../../../../../utils/logger.js", () => ({
18
+ logger: { info: vi.fn(), warning: vi.fn(), error: vi.fn() },
19
+ }));
20
+
21
+ /**
22
+ * Create a mock adapter sufficient for Code Mode usage
23
+ */
24
+ function createCodeModeMockAdapter(): MySQLAdapter {
25
+ const mockTools: ToolDefinition[] = [
26
+ {
27
+ name: "mysql_read_query",
28
+ group: "core",
29
+ title: "Read Query",
30
+ description: "Execute a read query",
31
+ inputSchema: { parse: (v: unknown) => v } as never,
32
+ requiredScopes: ["read"],
33
+ annotations: { readOnlyHint: true },
34
+ handler: vi
35
+ .fn()
36
+ .mockResolvedValue({ rows: [{ id: 1 }], rowsAffected: 0 }),
37
+ },
38
+ {
39
+ name: "mysql_write_query",
40
+ group: "core",
41
+ title: "Write Query",
42
+ description: "Execute a write query",
43
+ inputSchema: { parse: (v: unknown) => v } as never,
44
+ requiredScopes: ["write"],
45
+ annotations: {},
46
+ handler: vi.fn().mockResolvedValue({ rows: [], rowsAffected: 1 }),
47
+ },
48
+ ];
49
+
50
+ return {
51
+ type: "mysql",
52
+ getToolDefinitions: vi.fn().mockReturnValue(mockTools),
53
+ createContext: vi.fn().mockReturnValue({
54
+ timestamp: new Date(),
55
+ requestId: "test-ctx",
56
+ }),
57
+ getActiveTransactionIds: vi.fn().mockReturnValue([]),
58
+ rollbackTransaction: vi.fn().mockResolvedValue(undefined),
59
+ } as unknown as MySQLAdapter;
60
+ }
61
+
62
+ describe("Code Mode Tool", () => {
63
+ let mockAdapter: MySQLAdapter;
64
+
65
+ beforeEach(() => {
66
+ vi.clearAllMocks();
67
+ process.env["CODEMODE_ISOLATION"] = "vm";
68
+ mockAdapter = createCodeModeMockAdapter();
69
+ });
70
+
71
+ afterEach(() => {
72
+ cleanupCodeMode();
73
+ delete process.env["CODEMODE_ISOLATION"];
74
+ });
75
+
76
+ // ===========================================================================
77
+ // createExecuteCodeTool
78
+ // ===========================================================================
79
+ describe("createExecuteCodeTool", () => {
80
+ it("should create tool with correct definition", () => {
81
+ const tool = createExecuteCodeTool(mockAdapter);
82
+ expect(tool.name).toBe("mysql_execute_code");
83
+ expect(tool.group).toBe("codemode");
84
+ expect(tool.requiredScopes).toContain("admin");
85
+ });
86
+
87
+ it("should have proper annotations", () => {
88
+ const tool = createExecuteCodeTool(mockAdapter);
89
+ expect(tool.annotations?.destructiveHint).toBe(true);
90
+ expect(tool.annotations?.readOnlyHint).toBe(false);
91
+ });
92
+
93
+ it("should reject invalid code (blocked patterns)", async () => {
94
+ const tool = createExecuteCodeTool(mockAdapter);
95
+ const result = (await tool.handler(
96
+ { code: 'require("fs")' },
97
+ { timestamp: new Date(), requestId: "test" },
98
+ )) as { success: boolean; error: string };
99
+
100
+ expect(result.success).toBe(false);
101
+ expect(result.error).toContain("validation failed");
102
+ });
103
+
104
+ it("should reject empty code", async () => {
105
+ const tool = createExecuteCodeTool(mockAdapter);
106
+ const result = (await tool.handler(
107
+ { code: "" },
108
+ { timestamp: new Date(), requestId: "test" },
109
+ )) as { success: boolean; error: string };
110
+
111
+ expect(result.success).toBe(false);
112
+ expect(result.error).toContain("validation failed");
113
+ });
114
+
115
+ it("should execute valid code successfully", async () => {
116
+ const tool = createExecuteCodeTool(mockAdapter);
117
+ const result = (await tool.handler(
118
+ { code: "return 42" },
119
+ { timestamp: new Date(), requestId: "test" },
120
+ )) as { success: boolean; result: unknown; hint: string };
121
+
122
+ expect(result.success).toBe(true);
123
+ expect(result.result).toBe(42);
124
+ expect(result.hint).toContain("mysql.help()");
125
+ });
126
+
127
+ it("should handle execution errors gracefully", async () => {
128
+ const tool = createExecuteCodeTool(mockAdapter);
129
+ const result = (await tool.handler(
130
+ { code: 'throw new Error("test fail")' },
131
+ { timestamp: new Date(), requestId: "test" },
132
+ )) as { success: boolean; error: string };
133
+
134
+ expect(result.success).toBe(false);
135
+ expect(result.error).toContain("test fail");
136
+ });
137
+
138
+ it("should cleanup orphaned transactions", async () => {
139
+ // Simulate a transaction that starts during execution
140
+ const getActiveIds = mockAdapter.getActiveTransactionIds as ReturnType<
141
+ typeof vi.fn
142
+ >;
143
+ getActiveIds
144
+ .mockReturnValueOnce([]) // before execution
145
+ .mockReturnValueOnce(["orphan-txn-1"]); // after execution
146
+
147
+ const tool = createExecuteCodeTool(mockAdapter);
148
+ await tool.handler(
149
+ { code: "return 'done'" },
150
+ { timestamp: new Date(), requestId: "test" },
151
+ );
152
+
153
+ expect(mockAdapter.rollbackTransaction).toHaveBeenCalledWith(
154
+ "orphan-txn-1",
155
+ );
156
+ });
157
+
158
+ it("should handle rollback errors gracefully during cleanup", async () => {
159
+ const getActiveIds = mockAdapter.getActiveTransactionIds as ReturnType<
160
+ typeof vi.fn
161
+ >;
162
+ getActiveIds.mockReturnValueOnce([]).mockReturnValueOnce(["bad-txn"]);
163
+
164
+ (
165
+ mockAdapter.rollbackTransaction as ReturnType<typeof vi.fn>
166
+ ).mockRejectedValueOnce(new Error("rollback failed"));
167
+
168
+ const tool = createExecuteCodeTool(mockAdapter);
169
+ // Should not throw even though rollback fails
170
+ const result = (await tool.handler(
171
+ { code: "return 'done'" },
172
+ { timestamp: new Date(), requestId: "test" },
173
+ )) as { success: boolean };
174
+
175
+ expect(result.success).toBe(true);
176
+ });
177
+ });
178
+
179
+ // ===========================================================================
180
+ // getCodeModeTools
181
+ // ===========================================================================
182
+ describe("getCodeModeTools", () => {
183
+ it("should return array with execute code tool", () => {
184
+ const tools = getCodeModeTools(mockAdapter);
185
+ expect(tools).toHaveLength(1);
186
+ expect(tools[0].name).toBe("mysql_execute_code");
187
+ });
188
+ });
189
+
190
+ // ===========================================================================
191
+ // cleanupCodeMode
192
+ // ===========================================================================
193
+ describe("cleanupCodeMode", () => {
194
+ it("should clean up without error when not initialized", () => {
195
+ expect(() => cleanupCodeMode()).not.toThrow();
196
+ });
197
+
198
+ it("should clean up after initialization", async () => {
199
+ // Initialize by executing
200
+ const tool = createExecuteCodeTool(mockAdapter);
201
+ await tool.handler(
202
+ { code: "return 1" },
203
+ { timestamp: new Date(), requestId: "test" },
204
+ );
205
+ // Clean up
206
+ expect(() => cleanupCodeMode()).not.toThrow();
207
+ });
208
+
209
+ it("should allow re-initialization after cleanup", async () => {
210
+ const tool = createExecuteCodeTool(mockAdapter);
211
+ await tool.handler(
212
+ { code: "return 1" },
213
+ { timestamp: new Date(), requestId: "test" },
214
+ );
215
+ cleanupCodeMode();
216
+
217
+ // Re-execute should work
218
+ const result = (await tool.handler(
219
+ { code: "return 2" },
220
+ { timestamp: new Date(), requestId: "test" },
221
+ )) as { success: boolean; result: unknown };
222
+
223
+ expect(result.success).toBe(true);
224
+ expect(result.result).toBe(2);
225
+ });
226
+ });
227
+ });
@@ -13,6 +13,7 @@ import type {
13
13
  } from "../../../../types/index.js";
14
14
  import {
15
15
  createSandboxPool,
16
+ getDefaultSandboxMode,
16
17
  type ISandboxPool,
17
18
  type SandboxMode,
18
19
  } from "../../../../codemode/sandbox-factory.js";
@@ -68,7 +69,8 @@ let securityManager: CodeModeSecurityManager | null = null;
68
69
  function getIsolationMode(): SandboxMode {
69
70
  const envMode = process.env["CODEMODE_ISOLATION"];
70
71
  if (envMode === "worker") return "worker";
71
- return "vm"; // Default
72
+ if (envMode === "vm") return "vm";
73
+ return getDefaultSandboxMode();
72
74
  }
73
75
 
74
76
  /**
@@ -162,8 +164,8 @@ return results;
162
164
  };
163
165
  }
164
166
 
165
- // Create mysql API bindings
166
- const mysqlApi = createMysqlApi(adapter);
167
+ // Create mysql API bindings (readonly filtering applied when readonly: true)
168
+ const mysqlApi = createMysqlApi(adapter, readonly);
167
169
  const bindings = mysqlApi.createSandboxBindings();
168
170
 
169
171
  // Validate bindings are populated
@@ -24,6 +24,14 @@ import {
24
24
  GetIndexesSchemaBase,
25
25
  ListTablesSchema,
26
26
  } from "../types.js";
27
+ import { ZodError } from "zod";
28
+
29
+ /**
30
+ * Extract human-readable messages from a ZodError instead of raw JSON array
31
+ */
32
+ function formatZodError(error: ZodError): string {
33
+ return error.issues.map((i) => i.message).join("; ");
34
+ }
27
35
 
28
36
  /**
29
37
  * Pre-compiled identifier validation patterns (hoisted for performance)
@@ -83,11 +91,15 @@ function createReadQueryTool(adapter: MySQLAdapter): ToolDefinition {
83
91
  idempotentHint: true,
84
92
  },
85
93
  handler: async (params: unknown, _context: RequestContext) => {
86
- const {
87
- query,
88
- params: queryParams,
89
- transactionId,
90
- } = ReadQuerySchema.parse(params);
94
+ let parsed;
95
+ try {
96
+ parsed = ReadQuerySchema.parse(params);
97
+ } catch (err: unknown) {
98
+ if (err instanceof ZodError)
99
+ return { success: false, error: formatZodError(err) };
100
+ throw err;
101
+ }
102
+ const { query, params: queryParams, transactionId } = parsed;
91
103
  try {
92
104
  const result = await adapter.executeReadQuery(
93
105
  query,
@@ -123,11 +135,15 @@ function createWriteQueryTool(adapter: MySQLAdapter): ToolDefinition {
123
135
  readOnlyHint: false,
124
136
  },
125
137
  handler: async (params: unknown, _context: RequestContext) => {
126
- const {
127
- query,
128
- params: queryParams,
129
- transactionId,
130
- } = WriteQuerySchema.parse(params);
138
+ let parsed;
139
+ try {
140
+ parsed = WriteQuerySchema.parse(params);
141
+ } catch (err: unknown) {
142
+ if (err instanceof ZodError)
143
+ return { success: false, error: formatZodError(err) };
144
+ throw err;
145
+ }
146
+ const { query, params: queryParams, transactionId } = parsed;
131
147
  try {
132
148
  const result = await adapter.executeWriteQuery(
133
149
  query,
@@ -163,18 +179,47 @@ function createListTablesTool(adapter: MySQLAdapter): ToolDefinition {
163
179
  idempotentHint: true,
164
180
  },
165
181
  handler: async (params: unknown, _context: RequestContext) => {
166
- const { database } = ListTablesSchema.parse(params);
167
- const tables = await adapter.listTables(database);
168
- return {
169
- tables: tables.map((t) => ({
170
- name: t.name,
171
- type: t.type,
172
- engine: t.engine,
173
- rowCount: t.rowCount,
174
- comment: t.comment,
175
- })),
176
- count: tables.length,
177
- };
182
+ let parsed;
183
+ try {
184
+ parsed = ListTablesSchema.parse(params);
185
+ } catch (err: unknown) {
186
+ if (err instanceof ZodError)
187
+ return { success: false, error: formatZodError(err) };
188
+ throw err;
189
+ }
190
+ const { database } = parsed;
191
+
192
+ // P154: Pre-check database existence when explicitly provided
193
+ if (database) {
194
+ const dbCheck = await adapter.executeReadQuery(
195
+ `SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ?`,
196
+ [database],
197
+ );
198
+ if (!dbCheck.rows || dbCheck.rows.length === 0) {
199
+ return {
200
+ exists: false,
201
+ database,
202
+ message: `Database '${database}' does not exist`,
203
+ };
204
+ }
205
+ }
206
+
207
+ try {
208
+ const tables = await adapter.listTables(database);
209
+ return {
210
+ tables: tables.map((t) => ({
211
+ name: t.name,
212
+ type: t.type,
213
+ engine: t.engine,
214
+ rowCount: t.rowCount,
215
+ comment: t.comment,
216
+ })),
217
+ count: tables.length,
218
+ };
219
+ } catch (err: unknown) {
220
+ const message = err instanceof Error ? err.message : String(err);
221
+ return { success: false, error: message };
222
+ }
178
223
  },
179
224
  };
180
225
  }
@@ -196,7 +241,15 @@ function createDescribeTableTool(adapter: MySQLAdapter): ToolDefinition {
196
241
  idempotentHint: true,
197
242
  },
198
243
  handler: async (params: unknown, _context: RequestContext) => {
199
- const { table } = DescribeTableSchema.parse(params);
244
+ let parsed;
245
+ try {
246
+ parsed = DescribeTableSchema.parse(params);
247
+ } catch (err: unknown) {
248
+ if (err instanceof ZodError)
249
+ return { success: false, error: formatZodError(err) };
250
+ throw err;
251
+ }
252
+ const { table } = parsed;
200
253
  const tableInfo = await adapter.describeTable(table);
201
254
  // Graceful handling for non-existent tables
202
255
  if (!tableInfo.columns || tableInfo.columns.length === 0) {
@@ -227,8 +280,32 @@ function createCreateTableTool(adapter: MySQLAdapter): ToolDefinition {
227
280
  readOnlyHint: false,
228
281
  },
229
282
  handler: async (params: unknown, _context: RequestContext) => {
283
+ let parsed;
284
+ try {
285
+ parsed = CreateTableSchema.parse(params);
286
+ } catch (err: unknown) {
287
+ if (err instanceof ZodError)
288
+ return { success: false, error: formatZodError(err) };
289
+ throw err;
290
+ }
230
291
  const { name, columns, engine, charset, collate, comment, ifNotExists } =
231
- CreateTableSchema.parse(params);
292
+ parsed;
293
+
294
+ // Pre-check existence for skipped indicator when ifNotExists is true
295
+ if (ifNotExists) {
296
+ const checkName = name.includes(".")
297
+ ? (name.split(".")[1] ?? name)
298
+ : name;
299
+ const tableInfo = await adapter.describeTable(checkName);
300
+ if (tableInfo.columns && tableInfo.columns.length > 0) {
301
+ return {
302
+ success: true,
303
+ skipped: true,
304
+ tableName: name,
305
+ reason: "Table already exists",
306
+ };
307
+ }
308
+ }
232
309
 
233
310
  // Build column definitions
234
311
  const columnDefs = columns.map((col) => {
@@ -310,12 +387,13 @@ function createCreateTableTool(adapter: MySQLAdapter): ToolDefinition {
310
387
  if (message.includes("already exists")) {
311
388
  return {
312
389
  success: false,
313
- reason: `Table '${name}' already exists`,
390
+ error: `Table '${name}' already exists`,
314
391
  };
315
392
  }
316
- throw err;
393
+ return { success: false, error: message };
317
394
  }
318
395
 
396
+ adapter.clearSchemaCache();
319
397
  return { success: true, tableName: name };
320
398
  },
321
399
  };
@@ -337,11 +415,19 @@ function createDropTableTool(adapter: MySQLAdapter): ToolDefinition {
337
415
  destructiveHint: true,
338
416
  },
339
417
  handler: async (params: unknown, _context: RequestContext) => {
340
- const { table, ifExists } = DropTableSchema.parse(params);
418
+ let parsed;
419
+ try {
420
+ parsed = DropTableSchema.parse(params);
421
+ } catch (err: unknown) {
422
+ if (err instanceof ZodError)
423
+ return { success: false, error: formatZodError(err) };
424
+ throw err;
425
+ }
426
+ const { table, ifExists } = parsed;
341
427
 
342
428
  // Validate table name
343
429
  if (!isValidId(table)) {
344
- throw new Error("Invalid table name");
430
+ return { success: false, error: "Invalid table name" };
345
431
  }
346
432
 
347
433
  // Pre-check existence for skipped indicator when ifExists is true
@@ -363,12 +449,14 @@ function createDropTableTool(adapter: MySQLAdapter): ToolDefinition {
363
449
  if (message.includes("Unknown table")) {
364
450
  return {
365
451
  success: false,
366
- reason: `Table '${table}' does not exist`,
452
+ error: `Table '${table}' does not exist`,
367
453
  };
368
454
  }
369
- throw err;
455
+ return { success: false, error: message };
370
456
  }
371
457
 
458
+ adapter.clearSchemaCache();
459
+
372
460
  if (tableAbsent) {
373
461
  return {
374
462
  success: true,
@@ -400,7 +488,15 @@ function createGetIndexesTool(adapter: MySQLAdapter): ToolDefinition {
400
488
  idempotentHint: true,
401
489
  },
402
490
  handler: async (params: unknown, _context: RequestContext) => {
403
- const { table } = GetIndexesSchema.parse(params);
491
+ let parsed;
492
+ try {
493
+ parsed = GetIndexesSchema.parse(params);
494
+ } catch (err: unknown) {
495
+ if (err instanceof ZodError)
496
+ return { success: false, error: formatZodError(err) };
497
+ throw err;
498
+ }
499
+ const { table } = parsed;
404
500
  // First check if table exists by describing it
405
501
  const tableInfo = await adapter.describeTable(table);
406
502
  if (!tableInfo.columns || tableInfo.columns.length === 0) {
@@ -433,16 +529,22 @@ function createCreateIndexTool(adapter: MySQLAdapter): ToolDefinition {
433
529
  readOnlyHint: false,
434
530
  },
435
531
  handler: async (params: unknown, _context: RequestContext) => {
436
- const { name, table, columns, unique, type, ifNotExists } =
437
- CreateIndexSchema.parse(params);
532
+ let parsed;
533
+ try {
534
+ parsed = CreateIndexSchema.parse(params);
535
+ } catch (err: unknown) {
536
+ if (err instanceof ZodError)
537
+ return { success: false, error: formatZodError(err) };
538
+ throw err;
539
+ }
540
+ const { name, table, columns, unique, type, ifNotExists } = parsed;
438
541
 
439
542
  // Validate names
440
543
  if (!VALID_INDEX_NAME_PATTERN.test(name)) {
441
- // Index names usually don't have schema prefix
442
- throw new Error("Invalid index name");
544
+ return { success: false, error: "Invalid index name" };
443
545
  }
444
546
  if (!isValidId(table)) {
445
- throw new Error("Invalid table name");
547
+ return { success: false, error: "Invalid table name" };
446
548
  }
447
549
 
448
550
  const columnList = columns.map((c) => `\`${c}\``).join(", ");
@@ -478,15 +580,27 @@ function createCreateIndexTool(adapter: MySQLAdapter): ToolDefinition {
478
580
  if (message.includes("Duplicate key name")) {
479
581
  return {
480
582
  success: false,
481
- reason: `Index '${name}' already exists on table '${table}'`,
583
+ error: `Index '${name}' already exists on table '${table}'`,
584
+ };
585
+ }
586
+ // Distinguish column errors from table errors
587
+ if (message.includes("Key column")) {
588
+ const colMatch = /Key column '([^']+)'/.exec(message);
589
+ return {
590
+ success: false,
591
+ error: colMatch
592
+ ? `Column '${colMatch[1]}' does not exist in table '${table}'`
593
+ : `Column does not exist in table '${table}'`,
482
594
  };
483
595
  }
484
596
  if (message.includes("doesn't exist")) {
485
597
  return { exists: false, table };
486
598
  }
487
- throw err;
599
+ return { success: false, error: message };
488
600
  }
489
601
 
602
+ adapter.clearSchemaCache();
603
+
490
604
  // Warn if HASH was requested on a non-MEMORY engine (InnoDB silently converts to BTREE)
491
605
  if (type === "HASH") {
492
606
  return {