@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
@@ -15,6 +15,7 @@ import type {
15
15
  } from "../../../types/index.js";
16
16
  import type { MySQLAdapter } from "../MySQLAdapter.js";
17
17
  import https from "node:https";
18
+ import { ZodError } from "zod";
18
19
  import {
19
20
  RouterBaseInputSchema,
20
21
  RouteNameInputSchema,
@@ -22,6 +23,15 @@ import {
22
23
  ConnectionPoolNameInputSchema,
23
24
  } from "../types/router-types.js";
24
25
 
26
+ // =============================================================================
27
+ // Helpers
28
+ // =============================================================================
29
+
30
+ /** Extract human-readable messages from a ZodError instead of raw JSON array */
31
+ function formatZodError(error: ZodError): string {
32
+ return error.issues.map((i) => i.message).join("; ");
33
+ }
34
+
25
35
  // =============================================================================
26
36
  // Router HTTP Client Helper
27
37
  // =============================================================================
@@ -31,7 +41,7 @@ import {
31
41
  */
32
42
  interface RouterUnavailableResponse {
33
43
  available: false;
34
- reason: string;
44
+ error: string;
35
45
  }
36
46
 
37
47
  /**
@@ -120,11 +130,11 @@ async function routerFetch(
120
130
  reject(new Error(`Invalid JSON response: ${data}`));
121
131
  }
122
132
  } else {
123
- reject(
124
- new Error(
125
- `Router API error: ${statusCode} ${res.statusMessage ?? "Unknown"}`,
126
- ),
133
+ const err = new Error(
134
+ `Router API error: ${statusCode} ${res.statusMessage ?? "Unknown"}`,
127
135
  );
136
+ (err as Error & { statusCode: number }).statusCode = statusCode;
137
+ reject(err);
128
138
  }
129
139
  });
130
140
  });
@@ -166,22 +176,38 @@ async function routerFetch(
166
176
 
167
177
  /**
168
178
  * Safe wrapper for routerFetch that returns graceful responses instead of throwing.
169
- * Returns { success: true, data } on success or { success: false, response: { available: false, reason } } on failure.
179
+ * Returns { success: true, data } on success or { success: false, response: { available: false, error } } on failure.
180
+ * 404 responses (nonexistent route/metadata/pool) return { success: false, error } matching the standard error convention.
170
181
  */
171
182
  async function safeRouterFetch<T>(path: string): Promise<SafeRouterResult<T>> {
172
183
  try {
173
184
  const data = (await routerFetch(path)) as T;
174
185
  return { success: true, data };
175
186
  } catch (error) {
176
- const reason =
187
+ const msg =
177
188
  error instanceof Error
178
189
  ? error.message
179
190
  : "Unknown error connecting to Router API";
191
+ // 404 = valid Router response for nonexistent route/metadata/pool
192
+ // Return { success: false, error } instead of { available: false } to
193
+ // distinguish "not found" from "Router is down"
194
+ if (
195
+ error instanceof Error &&
196
+ (error as Error & { statusCode?: number }).statusCode === 404
197
+ ) {
198
+ return {
199
+ success: false,
200
+ response: {
201
+ success: false,
202
+ error: msg,
203
+ } as unknown as RouterUnavailableResponse,
204
+ };
205
+ }
180
206
  return {
181
207
  success: false,
182
208
  response: {
183
209
  available: false,
184
- reason,
210
+ error: msg,
185
211
  },
186
212
  };
187
213
  }
@@ -294,18 +320,28 @@ function createRouterRouteStatusTool(): ToolDefinition {
294
320
  openWorldHint: true,
295
321
  },
296
322
  handler: async (params: unknown, _context: RequestContext) => {
297
- const { routeName } = RouteNameInputSchema.parse(params);
298
- const result = await safeRouterFetch<unknown>(
299
- `/routes/${encodeURIComponent(routeName)}/status`,
300
- );
301
- if (!result.success) {
302
- return result.response;
323
+ try {
324
+ const { routeName } = RouteNameInputSchema.parse(params);
325
+ const result = await safeRouterFetch<unknown>(
326
+ `/routes/${encodeURIComponent(routeName)}/status`,
327
+ );
328
+ if (!result.success) {
329
+ return result.response;
330
+ }
331
+ return {
332
+ success: true,
333
+ routeName,
334
+ status: result.data,
335
+ };
336
+ } catch (error) {
337
+ if (error instanceof ZodError) {
338
+ return { success: false, error: formatZodError(error) };
339
+ }
340
+ return {
341
+ success: false,
342
+ error: error instanceof Error ? error.message : String(error),
343
+ };
303
344
  }
304
- return {
305
- success: true,
306
- routeName,
307
- status: result.data,
308
- };
309
345
  },
310
346
  };
311
347
  }
@@ -328,18 +364,28 @@ function createRouterRouteHealthTool(): ToolDefinition {
328
364
  openWorldHint: true,
329
365
  },
330
366
  handler: async (params: unknown, _context: RequestContext) => {
331
- const { routeName } = RouteNameInputSchema.parse(params);
332
- const result = await safeRouterFetch<unknown>(
333
- `/routes/${encodeURIComponent(routeName)}/health`,
334
- );
335
- if (!result.success) {
336
- return result.response;
367
+ try {
368
+ const { routeName } = RouteNameInputSchema.parse(params);
369
+ const result = await safeRouterFetch<unknown>(
370
+ `/routes/${encodeURIComponent(routeName)}/health`,
371
+ );
372
+ if (!result.success) {
373
+ return result.response;
374
+ }
375
+ return {
376
+ success: true,
377
+ routeName,
378
+ health: result.data,
379
+ };
380
+ } catch (error) {
381
+ if (error instanceof ZodError) {
382
+ return { success: false, error: formatZodError(error) };
383
+ }
384
+ return {
385
+ success: false,
386
+ error: error instanceof Error ? error.message : String(error),
387
+ };
337
388
  }
338
- return {
339
- success: true,
340
- routeName,
341
- health: result.data,
342
- };
343
389
  },
344
390
  };
345
391
  }
@@ -362,18 +408,28 @@ function createRouterRouteConnectionsTool(): ToolDefinition {
362
408
  openWorldHint: true,
363
409
  },
364
410
  handler: async (params: unknown, _context: RequestContext) => {
365
- const { routeName } = RouteNameInputSchema.parse(params);
366
- const result = await safeRouterFetch<unknown>(
367
- `/routes/${encodeURIComponent(routeName)}/connections`,
368
- );
369
- if (!result.success) {
370
- return result.response;
411
+ try {
412
+ const { routeName } = RouteNameInputSchema.parse(params);
413
+ const result = await safeRouterFetch<unknown>(
414
+ `/routes/${encodeURIComponent(routeName)}/connections`,
415
+ );
416
+ if (!result.success) {
417
+ return result.response;
418
+ }
419
+ return {
420
+ success: true,
421
+ routeName,
422
+ connections: result.data,
423
+ };
424
+ } catch (error) {
425
+ if (error instanceof ZodError) {
426
+ return { success: false, error: formatZodError(error) };
427
+ }
428
+ return {
429
+ success: false,
430
+ error: error instanceof Error ? error.message : String(error),
431
+ };
371
432
  }
372
- return {
373
- success: true,
374
- routeName,
375
- connections: result.data,
376
- };
377
433
  },
378
434
  };
379
435
  }
@@ -396,18 +452,28 @@ function createRouterRouteDestinationsTool(): ToolDefinition {
396
452
  openWorldHint: true,
397
453
  },
398
454
  handler: async (params: unknown, _context: RequestContext) => {
399
- const { routeName } = RouteNameInputSchema.parse(params);
400
- const result = await safeRouterFetch<unknown>(
401
- `/routes/${encodeURIComponent(routeName)}/destinations`,
402
- );
403
- if (!result.success) {
404
- return result.response;
455
+ try {
456
+ const { routeName } = RouteNameInputSchema.parse(params);
457
+ const result = await safeRouterFetch<unknown>(
458
+ `/routes/${encodeURIComponent(routeName)}/destinations`,
459
+ );
460
+ if (!result.success) {
461
+ return result.response;
462
+ }
463
+ return {
464
+ success: true,
465
+ routeName,
466
+ destinations: result.data,
467
+ };
468
+ } catch (error) {
469
+ if (error instanceof ZodError) {
470
+ return { success: false, error: formatZodError(error) };
471
+ }
472
+ return {
473
+ success: false,
474
+ error: error instanceof Error ? error.message : String(error),
475
+ };
405
476
  }
406
- return {
407
- success: true,
408
- routeName,
409
- destinations: result.data,
410
- };
411
477
  },
412
478
  };
413
479
  }
@@ -430,18 +496,28 @@ function createRouterRouteBlockedHostsTool(): ToolDefinition {
430
496
  openWorldHint: true,
431
497
  },
432
498
  handler: async (params: unknown, _context: RequestContext) => {
433
- const { routeName } = RouteNameInputSchema.parse(params);
434
- const result = await safeRouterFetch<unknown>(
435
- `/routes/${encodeURIComponent(routeName)}/blockedHosts`,
436
- );
437
- if (!result.success) {
438
- return result.response;
499
+ try {
500
+ const { routeName } = RouteNameInputSchema.parse(params);
501
+ const result = await safeRouterFetch<unknown>(
502
+ `/routes/${encodeURIComponent(routeName)}/blockedHosts`,
503
+ );
504
+ if (!result.success) {
505
+ return result.response;
506
+ }
507
+ return {
508
+ success: true,
509
+ routeName,
510
+ blockedHosts: result.data,
511
+ };
512
+ } catch (error) {
513
+ if (error instanceof ZodError) {
514
+ return { success: false, error: formatZodError(error) };
515
+ }
516
+ return {
517
+ success: false,
518
+ error: error instanceof Error ? error.message : String(error),
519
+ };
439
520
  }
440
- return {
441
- success: true,
442
- routeName,
443
- blockedHosts: result.data,
444
- };
445
521
  },
446
522
  };
447
523
  }
@@ -468,18 +544,28 @@ function createRouterMetadataStatusTool(): ToolDefinition {
468
544
  openWorldHint: true,
469
545
  },
470
546
  handler: async (params: unknown, _context: RequestContext) => {
471
- const { metadataName } = MetadataNameInputSchema.parse(params);
472
- const result = await safeRouterFetch<unknown>(
473
- `/metadata/${encodeURIComponent(metadataName)}/status`,
474
- );
475
- if (!result.success) {
476
- return result.response;
547
+ try {
548
+ const { metadataName } = MetadataNameInputSchema.parse(params);
549
+ const result = await safeRouterFetch<unknown>(
550
+ `/metadata/${encodeURIComponent(metadataName)}/status`,
551
+ );
552
+ if (!result.success) {
553
+ return result.response;
554
+ }
555
+ return {
556
+ success: true,
557
+ metadataName,
558
+ status: result.data,
559
+ };
560
+ } catch (error) {
561
+ if (error instanceof ZodError) {
562
+ return { success: false, error: formatZodError(error) };
563
+ }
564
+ return {
565
+ success: false,
566
+ error: error instanceof Error ? error.message : String(error),
567
+ };
477
568
  }
478
- return {
479
- success: true,
480
- metadataName,
481
- status: result.data,
482
- };
483
569
  },
484
570
  };
485
571
  }
@@ -506,18 +592,28 @@ function createRouterPoolStatusTool(): ToolDefinition {
506
592
  openWorldHint: true,
507
593
  },
508
594
  handler: async (params: unknown, _context: RequestContext) => {
509
- const { poolName } = ConnectionPoolNameInputSchema.parse(params);
510
- const result = await safeRouterFetch<unknown>(
511
- `/connection_pool/${encodeURIComponent(poolName)}/status`,
512
- );
513
- if (!result.success) {
514
- return result.response;
595
+ try {
596
+ const { poolName } = ConnectionPoolNameInputSchema.parse(params);
597
+ const result = await safeRouterFetch<unknown>(
598
+ `/connection_pool/${encodeURIComponent(poolName)}/status`,
599
+ );
600
+ if (!result.success) {
601
+ return result.response;
602
+ }
603
+ return {
604
+ success: true,
605
+ poolName,
606
+ status: result.data,
607
+ };
608
+ } catch (error) {
609
+ if (error instanceof ZodError) {
610
+ return { success: false, error: formatZodError(error) };
611
+ }
612
+ return {
613
+ success: false,
614
+ error: error instanceof Error ? error.message : String(error),
615
+ };
515
616
  }
516
- return {
517
- success: true,
518
- poolName,
519
- status: result.data,
520
- };
521
617
  },
522
618
  };
523
619
  }
@@ -162,5 +162,18 @@ describe("Schema Constraint Tools", () => {
162
162
  // Should only call once (existence check), not the main query
163
163
  expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(1);
164
164
  });
165
+ it("should return structured error for invalid constraint type", async () => {
166
+ const tool = createListConstraintsTool(
167
+ mockAdapter as unknown as MySQLAdapter,
168
+ );
169
+ const result = (await tool.handler(
170
+ { table: "users", type: "INVALID_TYPE" },
171
+ mockContext,
172
+ )) as { success: boolean; error: string };
173
+
174
+ expect(result.success).toBe(false);
175
+ expect(result.error).toBeDefined();
176
+ expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
177
+ });
165
178
  });
166
179
  });
@@ -78,13 +78,43 @@ describe("Schema Management Tools", () => {
78
78
  expect(result).toHaveProperty("success", true);
79
79
  });
80
80
 
81
- it("should reject invalid schema names", async () => {
81
+ it("should return structured error for invalid schema names", async () => {
82
82
  const tool = createCreateSchemaTool(
83
83
  mockAdapter as unknown as MySQLAdapter,
84
84
  );
85
- await expect(
86
- tool.handler({ name: "invalid-name" }, mockContext),
87
- ).rejects.toThrow("Invalid schema name");
85
+ const result = (await tool.handler(
86
+ { name: "invalid-name" },
87
+ mockContext,
88
+ )) as { success: boolean; error: string };
89
+
90
+ expect(result.success).toBe(false);
91
+ expect(result.error).toBe("Invalid schema name");
92
+ });
93
+
94
+ it("should return structured error for invalid charset", async () => {
95
+ const tool = createCreateSchemaTool(
96
+ mockAdapter as unknown as MySQLAdapter,
97
+ );
98
+ const result = (await tool.handler(
99
+ { name: "valid_db", charset: "bad; DROP DATABASE" },
100
+ mockContext,
101
+ )) as { success: boolean; error: string };
102
+
103
+ expect(result.success).toBe(false);
104
+ expect(result.error).toContain("Invalid charset");
105
+ });
106
+
107
+ it("should return structured error for invalid collation", async () => {
108
+ const tool = createCreateSchemaTool(
109
+ mockAdapter as unknown as MySQLAdapter,
110
+ );
111
+ const result = (await tool.handler(
112
+ { name: "valid_db", collation: "bad; DROP DATABASE" },
113
+ mockContext,
114
+ )) as { success: boolean; error: string };
115
+
116
+ expect(result.success).toBe(false);
117
+ expect(result.error).toContain("Invalid collation");
88
118
  });
89
119
 
90
120
  it("should use custom charset and collation", async () => {
@@ -120,10 +150,10 @@ describe("Schema Management Tools", () => {
120
150
  const result = (await tool.handler(
121
151
  { name: "existing_db", ifNotExists: false },
122
152
  mockContext,
123
- )) as { success: boolean; reason: string };
153
+ )) as { success: boolean; error: string };
124
154
 
125
155
  expect(result.success).toBe(false);
126
- expect(result.reason).toContain("already exists");
156
+ expect(result.error).toContain("already exists");
127
157
  });
128
158
 
129
159
  it("should return skipped when schema already exists with ifNotExists", async () => {
@@ -172,28 +202,33 @@ describe("Schema Management Tools", () => {
172
202
  expect(result).toHaveProperty("success", true);
173
203
  });
174
204
 
175
- it("should fail if attempting to drop system schema", async () => {
205
+ it("should return structured error for system schemas", async () => {
176
206
  const tool = createDropSchemaTool(mockAdapter as unknown as MySQLAdapter);
177
207
 
178
- await expect(
179
- tool.handler({ name: "mysql" }, mockContext),
180
- ).rejects.toThrow("Cannot drop system schema");
181
- await expect(
182
- tool.handler({ name: "information_schema" }, mockContext),
183
- ).rejects.toThrow("Cannot drop system schema");
184
- await expect(
185
- tool.handler({ name: "performance_schema" }, mockContext),
186
- ).rejects.toThrow("Cannot drop system schema");
187
- await expect(tool.handler({ name: "sys" }, mockContext)).rejects.toThrow(
188
- "Cannot drop system schema",
189
- );
208
+ for (const name of [
209
+ "mysql",
210
+ "information_schema",
211
+ "performance_schema",
212
+ "sys",
213
+ ]) {
214
+ const result = (await tool.handler({ name }, mockContext)) as {
215
+ success: boolean;
216
+ error: string;
217
+ };
218
+ expect(result.success).toBe(false);
219
+ expect(result.error).toBe("Cannot drop system schema");
220
+ }
190
221
  });
191
222
 
192
- it("should reject invalid schema names", async () => {
223
+ it("should return structured error for invalid schema names", async () => {
193
224
  const tool = createDropSchemaTool(mockAdapter as unknown as MySQLAdapter);
194
- await expect(
195
- tool.handler({ name: "invalid-db" }, mockContext),
196
- ).rejects.toThrow("Invalid schema name");
225
+ const result = (await tool.handler(
226
+ { name: "invalid-db" },
227
+ mockContext,
228
+ )) as { success: boolean; error: string };
229
+
230
+ expect(result.success).toBe(false);
231
+ expect(result.error).toBe("Invalid schema name");
197
232
  });
198
233
 
199
234
  it("should drop schema without IF EXISTS if requested", async () => {
@@ -215,10 +250,10 @@ describe("Schema Management Tools", () => {
215
250
  const result = (await tool.handler(
216
251
  { name: "gone_db", ifExists: false },
217
252
  mockContext,
218
- )) as { success: boolean; reason: string };
253
+ )) as { success: boolean; error: string };
219
254
 
220
255
  expect(result.success).toBe(false);
221
- expect(result.reason).toContain("does not exist");
256
+ expect(result.error).toContain("does not exist");
222
257
  });
223
258
 
224
259
  it("should return skipped when schema does not exist with ifExists", async () => {
@@ -59,5 +59,16 @@ describe("Schema Event Tools", () => {
59
59
  const params = mockAdapter.executeQuery.mock.calls[0][1] as unknown[];
60
60
  expect(params).toContain("ENABLED");
61
61
  });
62
+ it("should return structured error for invalid status", async () => {
63
+ const tool = createListEventsTool(mockAdapter as unknown as MySQLAdapter);
64
+ const result = (await tool.handler(
65
+ { status: "INVALID_STATUS" },
66
+ mockContext,
67
+ )) as { success: boolean; error: string };
68
+
69
+ expect(result.success).toBe(false);
70
+ expect(result.error).toBeDefined();
71
+ expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
72
+ });
62
73
  });
63
74
  });
@@ -51,18 +51,39 @@ describe("Schema Trigger Tools", () => {
51
51
  expect(result.schema).toBe("nonexistent_db");
52
52
  });
53
53
 
54
+ it("should return exists false for nonexistent table", async () => {
55
+ // Table existence check returns empty
56
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
57
+
58
+ const tool = createListTriggersTool(
59
+ mockAdapter as unknown as MySQLAdapter,
60
+ );
61
+ const result = (await tool.handler(
62
+ { table: "nonexistent_table" },
63
+ mockContext,
64
+ )) as { exists: boolean; table: string };
65
+
66
+ expect(result.exists).toBe(false);
67
+ expect(result.table).toBe("nonexistent_table");
68
+ });
69
+
54
70
  it("should filter by table when provided", async () => {
55
- mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([]));
71
+ // Table existence check returns a row
72
+ mockAdapter.executeQuery.mockResolvedValueOnce(
73
+ createMockQueryResult([{ TABLE_NAME: "users" }]),
74
+ );
75
+ // Triggers query returns empty
76
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
56
77
 
57
78
  const tool = createListTriggersTool(
58
79
  mockAdapter as unknown as MySQLAdapter,
59
80
  );
60
81
  await tool.handler({ table: "users" }, mockContext);
61
82
 
62
- expect(mockAdapter.executeQuery).toHaveBeenCalled();
63
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
83
+ expect(mockAdapter.executeQuery).toHaveBeenCalledTimes(2);
84
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
64
85
  expect(call).toContain("EVENT_OBJECT_TABLE = ?");
65
- const params = mockAdapter.executeQuery.mock.calls[0][1] as unknown[];
86
+ const params = mockAdapter.executeQuery.mock.calls[1][1] as unknown[];
66
87
  expect(params).toContain("users");
67
88
  });
68
89
  });
@@ -85,17 +85,18 @@ describe("Schema View Tools", () => {
85
85
  expect(call).toContain("OR REPLACE");
86
86
  });
87
87
 
88
- it("should validate view name", async () => {
88
+ it("should return structured error for invalid view name", async () => {
89
89
  const tool = createCreateViewTool(mockAdapter as unknown as MySQLAdapter);
90
- await expect(
91
- tool.handler(
92
- {
93
- name: "invalid-name",
94
- definition: "SELECT 1",
95
- },
96
- mockContext,
97
- ),
98
- ).rejects.toThrow("Invalid view name");
90
+ const result = (await tool.handler(
91
+ {
92
+ name: "invalid-name",
93
+ definition: "SELECT 1",
94
+ },
95
+ mockContext,
96
+ )) as { success: boolean; error: string };
97
+
98
+ expect(result.success).toBe(false);
99
+ expect(result.error).toContain("Invalid view name");
99
100
  });
100
101
 
101
102
  it("should include WITH CHECK OPTION when specified", async () => {
@@ -127,10 +128,10 @@ describe("Schema View Tools", () => {
127
128
  definition: "SELECT 1",
128
129
  },
129
130
  mockContext,
130
- )) as { success: boolean; reason: string };
131
+ )) as { success: boolean; error: string };
131
132
 
132
133
  expect(result.success).toBe(false);
133
- expect(result.reason).toContain("already exists");
134
+ expect(result.error).toContain("already exists");
134
135
  });
135
136
 
136
137
  it("should return success false for invalid SQL definition", async () => {
@@ -145,10 +146,41 @@ describe("Schema View Tools", () => {
145
146
  definition: "SELECT * FROM nonexistent_table",
146
147
  },
147
148
  mockContext,
148
- )) as { success: boolean; reason: string };
149
+ )) as { success: boolean; error: string };
150
+
151
+ expect(result.success).toBe(false);
152
+ expect(result.error).toContain("doesn't exist");
153
+ });
154
+ it("should return structured error for invalid algorithm", async () => {
155
+ const tool = createCreateViewTool(mockAdapter as unknown as MySQLAdapter);
156
+ const result = (await tool.handler(
157
+ {
158
+ name: "test_view",
159
+ definition: "SELECT 1",
160
+ algorithm: "INVALID",
161
+ },
162
+ mockContext,
163
+ )) as { success: boolean; error: string };
164
+
165
+ expect(result.success).toBe(false);
166
+ expect(result.error).toBeDefined();
167
+ expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
168
+ });
169
+
170
+ it("should return structured error for invalid checkOption", async () => {
171
+ const tool = createCreateViewTool(mockAdapter as unknown as MySQLAdapter);
172
+ const result = (await tool.handler(
173
+ {
174
+ name: "test_view",
175
+ definition: "SELECT 1",
176
+ checkOption: "BAD",
177
+ },
178
+ mockContext,
179
+ )) as { success: boolean; error: string };
149
180
 
150
181
  expect(result.success).toBe(false);
151
- expect(result.reason).toContain("doesn't exist");
182
+ expect(result.error).toBeDefined();
183
+ expect(mockAdapter.executeQuery).not.toHaveBeenCalled();
152
184
  });
153
185
  });
154
186
  });