@neverinfamous/mysql-mcp 2.1.0 → 2.2.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 (751) hide show
  1. package/.env.example +14 -4
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +7 -1
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +6 -1
  4. package/.github/dependabot.yml +15 -0
  5. package/.github/pull_request_template.md +5 -0
  6. package/.github/workflows/codeql.yml +41 -42
  7. package/.github/workflows/docker-publish.yml +248 -210
  8. package/.github/workflows/publish-npm.yml +16 -6
  9. package/CHANGELOG.md +272 -22
  10. package/CODE_OF_CONDUCT.md +2 -0
  11. package/DOCKER_README.md +222 -156
  12. package/Dockerfile +2 -2
  13. package/README.md +210 -176
  14. package/SECURITY.md +0 -8
  15. package/VERSION +1 -1
  16. package/dist/__tests__/mocks/adapter.d.ts +3 -3
  17. package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
  18. package/dist/__tests__/mocks/adapter.js +51 -35
  19. package/dist/__tests__/mocks/adapter.js.map +1 -1
  20. package/dist/__tests__/mocks/index.d.ts +4 -4
  21. package/dist/__tests__/mocks/index.d.ts.map +1 -1
  22. package/dist/__tests__/mocks/index.js +2 -2
  23. package/dist/__tests__/mocks/index.js.map +1 -1
  24. package/dist/__tests__/mocks/mysql.d.ts +2 -2
  25. package/dist/__tests__/mocks/mysql.d.ts.map +1 -1
  26. package/dist/__tests__/mocks/mysql.js +14 -14
  27. package/dist/__tests__/mocks/mysql.js.map +1 -1
  28. package/dist/__tests__/setup.d.ts.map +1 -1
  29. package/dist/__tests__/setup.js +7 -7
  30. package/dist/__tests__/setup.js.map +1 -1
  31. package/dist/adapters/DatabaseAdapter.d.ts +2 -2
  32. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
  33. package/dist/adapters/DatabaseAdapter.js +69 -40
  34. package/dist/adapters/DatabaseAdapter.js.map +1 -1
  35. package/dist/adapters/mysql/MySQLAdapter.d.ts +10 -4
  36. package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
  37. package/dist/adapters/mysql/MySQLAdapter.js +143 -116
  38. package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
  39. package/dist/adapters/mysql/SchemaManager.d.ts +1 -1
  40. package/dist/adapters/mysql/SchemaManager.d.ts.map +1 -1
  41. package/dist/adapters/mysql/SchemaManager.js +76 -56
  42. package/dist/adapters/mysql/SchemaManager.js.map +1 -1
  43. package/dist/adapters/mysql/index.d.ts +2 -2
  44. package/dist/adapters/mysql/index.js +2 -2
  45. package/dist/adapters/mysql/prompts/backupStrategy.d.ts +1 -1
  46. package/dist/adapters/mysql/prompts/backupStrategy.d.ts.map +1 -1
  47. package/dist/adapters/mysql/prompts/backupStrategy.js +21 -9
  48. package/dist/adapters/mysql/prompts/backupStrategy.js.map +1 -1
  49. package/dist/adapters/mysql/prompts/clusterSetup.d.ts +1 -1
  50. package/dist/adapters/mysql/prompts/clusterSetup.d.ts.map +1 -1
  51. package/dist/adapters/mysql/prompts/clusterSetup.js +3 -3
  52. package/dist/adapters/mysql/prompts/clusterSetup.js.map +1 -1
  53. package/dist/adapters/mysql/prompts/docstoreSetup.d.ts +1 -1
  54. package/dist/adapters/mysql/prompts/docstoreSetup.js +3 -3
  55. package/dist/adapters/mysql/prompts/docstoreSetup.js.map +1 -1
  56. package/dist/adapters/mysql/prompts/eventScheduler.d.ts +1 -1
  57. package/dist/adapters/mysql/prompts/eventScheduler.js +3 -3
  58. package/dist/adapters/mysql/prompts/eventScheduler.js.map +1 -1
  59. package/dist/adapters/mysql/prompts/healthCheck.d.ts +1 -1
  60. package/dist/adapters/mysql/prompts/healthCheck.d.ts.map +1 -1
  61. package/dist/adapters/mysql/prompts/healthCheck.js +10 -6
  62. package/dist/adapters/mysql/prompts/healthCheck.js.map +1 -1
  63. package/dist/adapters/mysql/prompts/index.d.ts +2 -2
  64. package/dist/adapters/mysql/prompts/index.d.ts.map +1 -1
  65. package/dist/adapters/mysql/prompts/index.js +98 -62
  66. package/dist/adapters/mysql/prompts/index.js.map +1 -1
  67. package/dist/adapters/mysql/prompts/indexTuning.d.ts +1 -1
  68. package/dist/adapters/mysql/prompts/indexTuning.d.ts.map +1 -1
  69. package/dist/adapters/mysql/prompts/indexTuning.js +11 -7
  70. package/dist/adapters/mysql/prompts/indexTuning.js.map +1 -1
  71. package/dist/adapters/mysql/prompts/mysqlshSetup.d.ts +1 -1
  72. package/dist/adapters/mysql/prompts/mysqlshSetup.js +4 -4
  73. package/dist/adapters/mysql/prompts/mysqlshSetup.js.map +1 -1
  74. package/dist/adapters/mysql/prompts/proxysqlSetup.d.ts +1 -1
  75. package/dist/adapters/mysql/prompts/proxysqlSetup.js +3 -3
  76. package/dist/adapters/mysql/prompts/proxysqlSetup.js.map +1 -1
  77. package/dist/adapters/mysql/prompts/replicationSetup.d.ts +1 -1
  78. package/dist/adapters/mysql/prompts/replicationSetup.d.ts.map +1 -1
  79. package/dist/adapters/mysql/prompts/replicationSetup.js +13 -7
  80. package/dist/adapters/mysql/prompts/replicationSetup.js.map +1 -1
  81. package/dist/adapters/mysql/prompts/routerSetup.d.ts +1 -1
  82. package/dist/adapters/mysql/prompts/routerSetup.js +3 -3
  83. package/dist/adapters/mysql/prompts/routerSetup.js.map +1 -1
  84. package/dist/adapters/mysql/prompts/spatialSetup.d.ts +1 -1
  85. package/dist/adapters/mysql/prompts/spatialSetup.js +3 -3
  86. package/dist/adapters/mysql/prompts/spatialSetup.js.map +1 -1
  87. package/dist/adapters/mysql/prompts/sysSchema.d.ts +1 -1
  88. package/dist/adapters/mysql/prompts/sysSchema.d.ts.map +1 -1
  89. package/dist/adapters/mysql/prompts/sysSchema.js +3 -3
  90. package/dist/adapters/mysql/prompts/sysSchema.js.map +1 -1
  91. package/dist/adapters/mysql/resources/capabilities.d.ts +2 -2
  92. package/dist/adapters/mysql/resources/capabilities.d.ts.map +1 -1
  93. package/dist/adapters/mysql/resources/capabilities.js +17 -15
  94. package/dist/adapters/mysql/resources/capabilities.js.map +1 -1
  95. package/dist/adapters/mysql/resources/cluster.d.ts +2 -2
  96. package/dist/adapters/mysql/resources/cluster.d.ts.map +1 -1
  97. package/dist/adapters/mysql/resources/cluster.js +17 -15
  98. package/dist/adapters/mysql/resources/cluster.js.map +1 -1
  99. package/dist/adapters/mysql/resources/docstore.d.ts +2 -2
  100. package/dist/adapters/mysql/resources/docstore.d.ts.map +1 -1
  101. package/dist/adapters/mysql/resources/docstore.js +12 -12
  102. package/dist/adapters/mysql/resources/docstore.js.map +1 -1
  103. package/dist/adapters/mysql/resources/events.d.ts +2 -2
  104. package/dist/adapters/mysql/resources/events.d.ts.map +1 -1
  105. package/dist/adapters/mysql/resources/events.js +12 -12
  106. package/dist/adapters/mysql/resources/events.js.map +1 -1
  107. package/dist/adapters/mysql/resources/health.d.ts +2 -2
  108. package/dist/adapters/mysql/resources/health.d.ts.map +1 -1
  109. package/dist/adapters/mysql/resources/health.js +36 -32
  110. package/dist/adapters/mysql/resources/health.js.map +1 -1
  111. package/dist/adapters/mysql/resources/index.d.ts +2 -2
  112. package/dist/adapters/mysql/resources/index.js +19 -19
  113. package/dist/adapters/mysql/resources/index.js.map +1 -1
  114. package/dist/adapters/mysql/resources/indexes.d.ts +2 -2
  115. package/dist/adapters/mysql/resources/indexes.d.ts.map +1 -1
  116. package/dist/adapters/mysql/resources/indexes.js +12 -12
  117. package/dist/adapters/mysql/resources/indexes.js.map +1 -1
  118. package/dist/adapters/mysql/resources/innodb.d.ts +2 -2
  119. package/dist/adapters/mysql/resources/innodb.d.ts.map +1 -1
  120. package/dist/adapters/mysql/resources/innodb.js +37 -36
  121. package/dist/adapters/mysql/resources/innodb.js.map +1 -1
  122. package/dist/adapters/mysql/resources/locks.d.ts +2 -2
  123. package/dist/adapters/mysql/resources/locks.d.ts.map +1 -1
  124. package/dist/adapters/mysql/resources/locks.js +14 -14
  125. package/dist/adapters/mysql/resources/locks.js.map +1 -1
  126. package/dist/adapters/mysql/resources/performance.d.ts +2 -2
  127. package/dist/adapters/mysql/resources/performance.d.ts.map +1 -1
  128. package/dist/adapters/mysql/resources/performance.js +30 -29
  129. package/dist/adapters/mysql/resources/performance.js.map +1 -1
  130. package/dist/adapters/mysql/resources/pool.d.ts +2 -2
  131. package/dist/adapters/mysql/resources/pool.d.ts.map +1 -1
  132. package/dist/adapters/mysql/resources/pool.js +9 -9
  133. package/dist/adapters/mysql/resources/pool.js.map +1 -1
  134. package/dist/adapters/mysql/resources/processlist.d.ts +2 -2
  135. package/dist/adapters/mysql/resources/processlist.d.ts.map +1 -1
  136. package/dist/adapters/mysql/resources/processlist.js +9 -9
  137. package/dist/adapters/mysql/resources/processlist.js.map +1 -1
  138. package/dist/adapters/mysql/resources/replication.d.ts +2 -2
  139. package/dist/adapters/mysql/resources/replication.d.ts.map +1 -1
  140. package/dist/adapters/mysql/resources/replication.js +42 -35
  141. package/dist/adapters/mysql/resources/replication.js.map +1 -1
  142. package/dist/adapters/mysql/resources/schema.d.ts +2 -2
  143. package/dist/adapters/mysql/resources/schema.d.ts.map +1 -1
  144. package/dist/adapters/mysql/resources/schema.js +8 -8
  145. package/dist/adapters/mysql/resources/schema.js.map +1 -1
  146. package/dist/adapters/mysql/resources/spatial.d.ts +2 -2
  147. package/dist/adapters/mysql/resources/spatial.d.ts.map +1 -1
  148. package/dist/adapters/mysql/resources/spatial.js +9 -9
  149. package/dist/adapters/mysql/resources/spatial.js.map +1 -1
  150. package/dist/adapters/mysql/resources/status.d.ts +2 -2
  151. package/dist/adapters/mysql/resources/status.d.ts.map +1 -1
  152. package/dist/adapters/mysql/resources/status.js +10 -10
  153. package/dist/adapters/mysql/resources/status.js.map +1 -1
  154. package/dist/adapters/mysql/resources/sysschema.d.ts +2 -2
  155. package/dist/adapters/mysql/resources/sysschema.d.ts.map +1 -1
  156. package/dist/adapters/mysql/resources/sysschema.js +10 -10
  157. package/dist/adapters/mysql/resources/sysschema.js.map +1 -1
  158. package/dist/adapters/mysql/resources/tables.d.ts +2 -2
  159. package/dist/adapters/mysql/resources/tables.d.ts.map +1 -1
  160. package/dist/adapters/mysql/resources/tables.js +8 -8
  161. package/dist/adapters/mysql/resources/tables.js.map +1 -1
  162. package/dist/adapters/mysql/resources/variables.d.ts +2 -2
  163. package/dist/adapters/mysql/resources/variables.d.ts.map +1 -1
  164. package/dist/adapters/mysql/resources/variables.js +10 -10
  165. package/dist/adapters/mysql/resources/variables.js.map +1 -1
  166. package/dist/adapters/mysql/tools/admin/backup.d.ts +2 -2
  167. package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
  168. package/dist/adapters/mysql/tools/admin/backup.js +191 -99
  169. package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
  170. package/dist/adapters/mysql/tools/admin/index.d.ts +2 -2
  171. package/dist/adapters/mysql/tools/admin/index.js +6 -6
  172. package/dist/adapters/mysql/tools/admin/index.js.map +1 -1
  173. package/dist/adapters/mysql/tools/admin/maintenance.d.ts +2 -2
  174. package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
  175. package/dist/adapters/mysql/tools/admin/maintenance.js +93 -62
  176. package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
  177. package/dist/adapters/mysql/tools/admin/monitoring.d.ts +2 -2
  178. package/dist/adapters/mysql/tools/admin/monitoring.d.ts.map +1 -1
  179. package/dist/adapters/mysql/tools/admin/monitoring.js +215 -79
  180. package/dist/adapters/mysql/tools/admin/monitoring.js.map +1 -1
  181. package/dist/adapters/mysql/tools/cluster/group-replication.d.ts +2 -2
  182. package/dist/adapters/mysql/tools/cluster/group-replication.d.ts.map +1 -1
  183. package/dist/adapters/mysql/tools/cluster/group-replication.js +90 -74
  184. package/dist/adapters/mysql/tools/cluster/group-replication.js.map +1 -1
  185. package/dist/adapters/mysql/tools/cluster/index.d.ts +2 -2
  186. package/dist/adapters/mysql/tools/cluster/index.js +3 -3
  187. package/dist/adapters/mysql/tools/cluster/index.js.map +1 -1
  188. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts +2 -2
  189. package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
  190. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +204 -97
  191. package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
  192. package/dist/adapters/mysql/tools/core.d.ts +2 -2
  193. package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
  194. package/dist/adapters/mysql/tools/core.js +205 -97
  195. package/dist/adapters/mysql/tools/core.js.map +1 -1
  196. package/dist/adapters/mysql/tools/docstore.d.ts +2 -2
  197. package/dist/adapters/mysql/tools/docstore.d.ts.map +1 -1
  198. package/dist/adapters/mysql/tools/docstore.js +252 -117
  199. package/dist/adapters/mysql/tools/docstore.js.map +1 -1
  200. package/dist/adapters/mysql/tools/events.d.ts +2 -2
  201. package/dist/adapters/mysql/tools/events.d.ts.map +1 -1
  202. package/dist/adapters/mysql/tools/events.js +219 -108
  203. package/dist/adapters/mysql/tools/events.js.map +1 -1
  204. package/dist/adapters/mysql/tools/index.d.ts +19 -19
  205. package/dist/adapters/mysql/tools/index.d.ts.map +1 -1
  206. package/dist/adapters/mysql/tools/index.js +19 -19
  207. package/dist/adapters/mysql/tools/index.js.map +1 -1
  208. package/dist/adapters/mysql/tools/json/core.d.ts +2 -2
  209. package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
  210. package/dist/adapters/mysql/tools/json/core.js +221 -127
  211. package/dist/adapters/mysql/tools/json/core.js.map +1 -1
  212. package/dist/adapters/mysql/tools/json/enhanced.d.ts +2 -2
  213. package/dist/adapters/mysql/tools/json/enhanced.d.ts.map +1 -1
  214. package/dist/adapters/mysql/tools/json/enhanced.js +274 -163
  215. package/dist/adapters/mysql/tools/json/enhanced.js.map +1 -1
  216. package/dist/adapters/mysql/tools/json/helpers.d.ts +2 -2
  217. package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
  218. package/dist/adapters/mysql/tools/json/helpers.js +134 -56
  219. package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
  220. package/dist/adapters/mysql/tools/json/index.d.ts +2 -2
  221. package/dist/adapters/mysql/tools/json/index.js +6 -6
  222. package/dist/adapters/mysql/tools/json/index.js.map +1 -1
  223. package/dist/adapters/mysql/tools/partitioning.d.ts +2 -2
  224. package/dist/adapters/mysql/tools/partitioning.js +143 -59
  225. package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
  226. package/dist/adapters/mysql/tools/performance/analysis.d.ts +2 -2
  227. package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
  228. package/dist/adapters/mysql/tools/performance/analysis.js +122 -86
  229. package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
  230. package/dist/adapters/mysql/tools/performance/index.d.ts +2 -2
  231. package/dist/adapters/mysql/tools/performance/index.js +4 -4
  232. package/dist/adapters/mysql/tools/performance/index.js.map +1 -1
  233. package/dist/adapters/mysql/tools/performance/optimization.d.ts +3 -3
  234. package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
  235. package/dist/adapters/mysql/tools/performance/optimization.js +195 -73
  236. package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
  237. package/dist/adapters/mysql/tools/proxysql.d.ts +2 -2
  238. package/dist/adapters/mysql/tools/proxysql.d.ts.map +1 -1
  239. package/dist/adapters/mysql/tools/proxysql.js +213 -125
  240. package/dist/adapters/mysql/tools/proxysql.js.map +1 -1
  241. package/dist/adapters/mysql/tools/replication.d.ts +2 -2
  242. package/dist/adapters/mysql/tools/replication.d.ts.map +1 -1
  243. package/dist/adapters/mysql/tools/replication.js +117 -66
  244. package/dist/adapters/mysql/tools/replication.js.map +1 -1
  245. package/dist/adapters/mysql/tools/roles.d.ts +2 -2
  246. package/dist/adapters/mysql/tools/roles.d.ts.map +1 -1
  247. package/dist/adapters/mysql/tools/roles.js +276 -84
  248. package/dist/adapters/mysql/tools/roles.js.map +1 -1
  249. package/dist/adapters/mysql/tools/router.d.ts +2 -2
  250. package/dist/adapters/mysql/tools/router.d.ts.map +1 -1
  251. package/dist/adapters/mysql/tools/router.js +174 -109
  252. package/dist/adapters/mysql/tools/router.js.map +1 -1
  253. package/dist/adapters/mysql/tools/schema/constraints.d.ts +2 -2
  254. package/dist/adapters/mysql/tools/schema/constraints.d.ts.map +1 -1
  255. package/dist/adapters/mysql/tools/schema/constraints.js +24 -15
  256. package/dist/adapters/mysql/tools/schema/constraints.js.map +1 -1
  257. package/dist/adapters/mysql/tools/schema/index.d.ts +2 -2
  258. package/dist/adapters/mysql/tools/schema/index.d.ts.map +1 -1
  259. package/dist/adapters/mysql/tools/schema/index.js +7 -7
  260. package/dist/adapters/mysql/tools/schema/index.js.map +1 -1
  261. package/dist/adapters/mysql/tools/schema/management.d.ts +2 -2
  262. package/dist/adapters/mysql/tools/schema/management.d.ts.map +1 -1
  263. package/dist/adapters/mysql/tools/schema/management.js +99 -42
  264. package/dist/adapters/mysql/tools/schema/management.js.map +1 -1
  265. package/dist/adapters/mysql/tools/schema/routines.d.ts +2 -2
  266. package/dist/adapters/mysql/tools/schema/routines.d.ts.map +1 -1
  267. package/dist/adapters/mysql/tools/schema/routines.js +36 -19
  268. package/dist/adapters/mysql/tools/schema/routines.js.map +1 -1
  269. package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts +2 -2
  270. package/dist/adapters/mysql/tools/schema/scheduled_events.d.ts.map +1 -1
  271. package/dist/adapters/mysql/tools/schema/scheduled_events.js +26 -13
  272. package/dist/adapters/mysql/tools/schema/scheduled_events.js.map +1 -1
  273. package/dist/adapters/mysql/tools/schema/triggers.d.ts +2 -2
  274. package/dist/adapters/mysql/tools/schema/triggers.d.ts.map +1 -1
  275. package/dist/adapters/mysql/tools/schema/triggers.js +24 -13
  276. package/dist/adapters/mysql/tools/schema/triggers.js.map +1 -1
  277. package/dist/adapters/mysql/tools/schema/views.d.ts +2 -2
  278. package/dist/adapters/mysql/tools/schema/views.d.ts.map +1 -1
  279. package/dist/adapters/mysql/tools/schema/views.js +59 -28
  280. package/dist/adapters/mysql/tools/schema/views.js.map +1 -1
  281. package/dist/adapters/mysql/tools/security/audit.d.ts +2 -2
  282. package/dist/adapters/mysql/tools/security/audit.d.ts.map +1 -1
  283. package/dist/adapters/mysql/tools/security/audit.js +61 -55
  284. package/dist/adapters/mysql/tools/security/audit.js.map +1 -1
  285. package/dist/adapters/mysql/tools/security/data-protection.d.ts +2 -2
  286. package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
  287. package/dist/adapters/mysql/tools/security/data-protection.js +188 -80
  288. package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
  289. package/dist/adapters/mysql/tools/security/encryption.d.ts +2 -2
  290. package/dist/adapters/mysql/tools/security/encryption.d.ts.map +1 -1
  291. package/dist/adapters/mysql/tools/security/encryption.js +86 -67
  292. package/dist/adapters/mysql/tools/security/encryption.js.map +1 -1
  293. package/dist/adapters/mysql/tools/security/index.d.ts +2 -2
  294. package/dist/adapters/mysql/tools/security/index.js +4 -4
  295. package/dist/adapters/mysql/tools/security/index.js.map +1 -1
  296. package/dist/adapters/mysql/tools/shell/backup.d.ts +1 -1
  297. package/dist/adapters/mysql/tools/shell/backup.d.ts.map +1 -1
  298. package/dist/adapters/mysql/tools/shell/backup.js +122 -63
  299. package/dist/adapters/mysql/tools/shell/backup.js.map +1 -1
  300. package/dist/adapters/mysql/tools/shell/common.d.ts.map +1 -1
  301. package/dist/adapters/mysql/tools/shell/common.js +34 -36
  302. package/dist/adapters/mysql/tools/shell/common.js.map +1 -1
  303. package/dist/adapters/mysql/tools/shell/data-transfer.d.ts +1 -1
  304. package/dist/adapters/mysql/tools/shell/data-transfer.d.ts.map +1 -1
  305. package/dist/adapters/mysql/tools/shell/data-transfer.js +125 -69
  306. package/dist/adapters/mysql/tools/shell/data-transfer.js.map +1 -1
  307. package/dist/adapters/mysql/tools/shell/index.d.ts +2 -2
  308. package/dist/adapters/mysql/tools/shell/index.js +6 -6
  309. package/dist/adapters/mysql/tools/shell/index.js.map +1 -1
  310. package/dist/adapters/mysql/tools/shell/info.d.ts +1 -1
  311. package/dist/adapters/mysql/tools/shell/info.d.ts.map +1 -1
  312. package/dist/adapters/mysql/tools/shell/info.js +12 -12
  313. package/dist/adapters/mysql/tools/shell/info.js.map +1 -1
  314. package/dist/adapters/mysql/tools/shell/restore.d.ts +1 -1
  315. package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
  316. package/dist/adapters/mysql/tools/shell/restore.js +77 -42
  317. package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
  318. package/dist/adapters/mysql/tools/shell/utilities.d.ts +1 -1
  319. package/dist/adapters/mysql/tools/shell/utilities.d.ts.map +1 -1
  320. package/dist/adapters/mysql/tools/shell/utilities.js +42 -18
  321. package/dist/adapters/mysql/tools/shell/utilities.js.map +1 -1
  322. package/dist/adapters/mysql/tools/spatial/geometry.d.ts +2 -2
  323. package/dist/adapters/mysql/tools/spatial/geometry.d.ts.map +1 -1
  324. package/dist/adapters/mysql/tools/spatial/geometry.js +85 -46
  325. package/dist/adapters/mysql/tools/spatial/geometry.js.map +1 -1
  326. package/dist/adapters/mysql/tools/spatial/index.d.ts +2 -2
  327. package/dist/adapters/mysql/tools/spatial/index.js +5 -5
  328. package/dist/adapters/mysql/tools/spatial/index.js.map +1 -1
  329. package/dist/adapters/mysql/tools/spatial/operations.d.ts +2 -2
  330. package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
  331. package/dist/adapters/mysql/tools/spatial/operations.js +167 -106
  332. package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
  333. package/dist/adapters/mysql/tools/spatial/queries.d.ts +2 -2
  334. package/dist/adapters/mysql/tools/spatial/queries.d.ts.map +1 -1
  335. package/dist/adapters/mysql/tools/spatial/queries.js +144 -100
  336. package/dist/adapters/mysql/tools/spatial/queries.js.map +1 -1
  337. package/dist/adapters/mysql/tools/spatial/setup.d.ts +2 -2
  338. package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
  339. package/dist/adapters/mysql/tools/spatial/setup.js +104 -34
  340. package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
  341. package/dist/adapters/mysql/tools/stats/comparative.d.ts +2 -2
  342. package/dist/adapters/mysql/tools/stats/comparative.d.ts.map +1 -1
  343. package/dist/adapters/mysql/tools/stats/comparative.js +159 -107
  344. package/dist/adapters/mysql/tools/stats/comparative.js.map +1 -1
  345. package/dist/adapters/mysql/tools/stats/descriptive.d.ts +2 -2
  346. package/dist/adapters/mysql/tools/stats/descriptive.d.ts.map +1 -1
  347. package/dist/adapters/mysql/tools/stats/descriptive.js +268 -205
  348. package/dist/adapters/mysql/tools/stats/descriptive.js.map +1 -1
  349. package/dist/adapters/mysql/tools/stats/index.d.ts +2 -2
  350. package/dist/adapters/mysql/tools/stats/index.js +3 -3
  351. package/dist/adapters/mysql/tools/stats/index.js.map +1 -1
  352. package/dist/adapters/mysql/tools/sysschema/activity.d.ts +2 -2
  353. package/dist/adapters/mysql/tools/sysschema/activity.d.ts.map +1 -1
  354. package/dist/adapters/mysql/tools/sysschema/activity.js +23 -23
  355. package/dist/adapters/mysql/tools/sysschema/activity.js.map +1 -1
  356. package/dist/adapters/mysql/tools/sysschema/index.d.ts +2 -2
  357. package/dist/adapters/mysql/tools/sysschema/index.js +4 -4
  358. package/dist/adapters/mysql/tools/sysschema/index.js.map +1 -1
  359. package/dist/adapters/mysql/tools/sysschema/performance.d.ts +2 -2
  360. package/dist/adapters/mysql/tools/sysschema/performance.d.ts.map +1 -1
  361. package/dist/adapters/mysql/tools/sysschema/performance.js +58 -43
  362. package/dist/adapters/mysql/tools/sysschema/performance.js.map +1 -1
  363. package/dist/adapters/mysql/tools/sysschema/resources.d.ts +2 -2
  364. package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
  365. package/dist/adapters/mysql/tools/sysschema/resources.js +53 -33
  366. package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
  367. package/dist/adapters/mysql/tools/text/fulltext.d.ts +4 -3
  368. package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
  369. package/dist/adapters/mysql/tools/text/fulltext.js +211 -54
  370. package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
  371. package/dist/adapters/mysql/tools/text/index.d.ts +3 -3
  372. package/dist/adapters/mysql/tools/text/index.d.ts.map +1 -1
  373. package/dist/adapters/mysql/tools/text/index.js +6 -5
  374. package/dist/adapters/mysql/tools/text/index.js.map +1 -1
  375. package/dist/adapters/mysql/tools/text/processing.d.ts +2 -2
  376. package/dist/adapters/mysql/tools/text/processing.d.ts.map +1 -1
  377. package/dist/adapters/mysql/tools/text/processing.js +191 -103
  378. package/dist/adapters/mysql/tools/text/processing.js.map +1 -1
  379. package/dist/adapters/mysql/tools/transactions.d.ts +2 -2
  380. package/dist/adapters/mysql/tools/transactions.js +156 -79
  381. package/dist/adapters/mysql/tools/transactions.js.map +1 -1
  382. package/dist/adapters/mysql/types/proxysql-types.d.ts +7 -2
  383. package/dist/adapters/mysql/types/proxysql-types.d.ts.map +1 -1
  384. package/dist/adapters/mysql/types/proxysql-types.js +52 -30
  385. package/dist/adapters/mysql/types/proxysql-types.js.map +1 -1
  386. package/dist/adapters/mysql/types/router-types.d.ts +1 -1
  387. package/dist/adapters/mysql/types/router-types.js +17 -17
  388. package/dist/adapters/mysql/types/router-types.js.map +1 -1
  389. package/dist/adapters/mysql/types/shell-types.d.ts +1 -2
  390. package/dist/adapters/mysql/types/shell-types.d.ts.map +1 -1
  391. package/dist/adapters/mysql/types/shell-types.js +255 -82
  392. package/dist/adapters/mysql/types/shell-types.js.map +1 -1
  393. package/dist/adapters/mysql/types.d.ts +8 -2
  394. package/dist/adapters/mysql/types.d.ts.map +1 -1
  395. package/dist/adapters/mysql/types.js +269 -128
  396. package/dist/adapters/mysql/types.js.map +1 -1
  397. package/dist/auth/AuthorizationServerDiscovery.d.ts +1 -1
  398. package/dist/auth/AuthorizationServerDiscovery.d.ts.map +1 -1
  399. package/dist/auth/AuthorizationServerDiscovery.js +16 -14
  400. package/dist/auth/AuthorizationServerDiscovery.js.map +1 -1
  401. package/dist/auth/OAuthResourceServer.d.ts +1 -1
  402. package/dist/auth/OAuthResourceServer.d.ts.map +1 -1
  403. package/dist/auth/OAuthResourceServer.js +4 -4
  404. package/dist/auth/OAuthResourceServer.js.map +1 -1
  405. package/dist/auth/TokenValidator.d.ts +1 -1
  406. package/dist/auth/TokenValidator.d.ts.map +1 -1
  407. package/dist/auth/TokenValidator.js +30 -20
  408. package/dist/auth/TokenValidator.js.map +1 -1
  409. package/dist/auth/errors.d.ts.map +1 -1
  410. package/dist/auth/errors.js +24 -24
  411. package/dist/auth/errors.js.map +1 -1
  412. package/dist/auth/index.d.ts +7 -7
  413. package/dist/auth/index.d.ts.map +1 -1
  414. package/dist/auth/index.js +6 -6
  415. package/dist/auth/index.js.map +1 -1
  416. package/dist/auth/middleware.d.ts +2 -2
  417. package/dist/auth/middleware.d.ts.map +1 -1
  418. package/dist/auth/middleware.js +28 -24
  419. package/dist/auth/middleware.js.map +1 -1
  420. package/dist/auth/scopes.d.ts +2 -2
  421. package/dist/auth/scopes.d.ts.map +1 -1
  422. package/dist/auth/scopes.js +22 -16
  423. package/dist/auth/scopes.js.map +1 -1
  424. package/dist/auth/types.d.ts +2 -2
  425. package/dist/auth/types.d.ts.map +1 -1
  426. package/dist/cli/args.d.ts +1 -1
  427. package/dist/cli/args.d.ts.map +1 -1
  428. package/dist/cli/args.js +70 -68
  429. package/dist/cli/args.js.map +1 -1
  430. package/dist/cli.d.ts +1 -1
  431. package/dist/cli.d.ts.map +1 -1
  432. package/dist/cli.js +44 -34
  433. package/dist/cli.js.map +1 -1
  434. package/dist/constants/ServerInstructions.d.ts +2 -2
  435. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  436. package/dist/constants/ServerInstructions.js +228 -36
  437. package/dist/constants/ServerInstructions.js.map +1 -1
  438. package/dist/filtering/ToolConstants.d.ts +6 -6
  439. package/dist/filtering/ToolConstants.d.ts.map +1 -1
  440. package/dist/filtering/ToolConstants.js +229 -208
  441. package/dist/filtering/ToolConstants.js.map +1 -1
  442. package/dist/filtering/ToolFilter.d.ts +2 -2
  443. package/dist/filtering/ToolFilter.d.ts.map +1 -1
  444. package/dist/filtering/ToolFilter.js +35 -36
  445. package/dist/filtering/ToolFilter.js.map +1 -1
  446. package/dist/index.d.ts +9 -9
  447. package/dist/index.d.ts.map +1 -1
  448. package/dist/index.js +7 -7
  449. package/dist/index.js.map +1 -1
  450. package/dist/logging/McpLogging.d.ts +2 -2
  451. package/dist/logging/McpLogging.d.ts.map +1 -1
  452. package/dist/logging/McpLogging.js +16 -13
  453. package/dist/logging/McpLogging.js.map +1 -1
  454. package/dist/logging/index.d.ts +1 -1
  455. package/dist/logging/index.js +1 -1
  456. package/dist/pool/ConnectionPool.d.ts +3 -3
  457. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  458. package/dist/pool/ConnectionPool.js +30 -26
  459. package/dist/pool/ConnectionPool.js.map +1 -1
  460. package/dist/progress/ProgressReporter.d.ts +1 -1
  461. package/dist/progress/ProgressReporter.d.ts.map +1 -1
  462. package/dist/progress/ProgressReporter.js +5 -5
  463. package/dist/progress/ProgressReporter.js.map +1 -1
  464. package/dist/progress/index.d.ts +1 -1
  465. package/dist/progress/index.d.ts.map +1 -1
  466. package/dist/progress/index.js +1 -1
  467. package/dist/progress/index.js.map +1 -1
  468. package/dist/server/McpServer.d.ts +3 -3
  469. package/dist/server/McpServer.d.ts.map +1 -1
  470. package/dist/server/McpServer.js +58 -53
  471. package/dist/server/McpServer.js.map +1 -1
  472. package/dist/transports/http.d.ts +3 -3
  473. package/dist/transports/http.d.ts.map +1 -1
  474. package/dist/transports/http.js +36 -33
  475. package/dist/transports/http.js.map +1 -1
  476. package/dist/transports/index.d.ts +1 -1
  477. package/dist/transports/index.d.ts.map +1 -1
  478. package/dist/transports/index.js +1 -1
  479. package/dist/transports/index.js.map +1 -1
  480. package/dist/types/index.d.ts +6 -6
  481. package/dist/types/index.d.ts.map +1 -1
  482. package/dist/types/index.js +1 -1
  483. package/dist/types/index.js.map +1 -1
  484. package/dist/types/modules/database.d.ts +1 -1
  485. package/dist/types/modules/database.d.ts.map +1 -1
  486. package/dist/types/modules/errors.d.ts.map +1 -1
  487. package/dist/types/modules/errors.js +15 -15
  488. package/dist/types/modules/errors.js.map +1 -1
  489. package/dist/types/modules/oauth.d.ts +1 -1
  490. package/dist/types/modules/oauth.d.ts.map +1 -1
  491. package/dist/types/modules/query.d.ts +8 -8
  492. package/dist/types/modules/query.d.ts.map +1 -1
  493. package/dist/types/modules/server.d.ts +3 -3
  494. package/dist/types/modules/server.d.ts.map +1 -1
  495. package/dist/types/modules/tools.d.ts +6 -6
  496. package/dist/types/modules/tools.d.ts.map +1 -1
  497. package/dist/utils/logger.d.ts +2 -2
  498. package/dist/utils/logger.d.ts.map +1 -1
  499. package/dist/utils/logger.js +58 -55
  500. package/dist/utils/logger.js.map +1 -1
  501. package/dist/utils/promptGenerator.d.ts +1 -1
  502. package/dist/utils/promptGenerator.d.ts.map +1 -1
  503. package/dist/utils/promptGenerator.js +24 -16
  504. package/dist/utils/promptGenerator.js.map +1 -1
  505. package/dist/utils/validators.d.ts +21 -2
  506. package/dist/utils/validators.d.ts.map +1 -1
  507. package/dist/utils/validators.js +101 -13
  508. package/dist/utils/validators.js.map +1 -1
  509. package/eslint.config.js +117 -81
  510. package/package.json +61 -64
  511. package/releases/release-notes.md +32 -26
  512. package/releases/v2.0.0-release-notes.md +99 -51
  513. package/releases/v2.1.0-release-notes.md +14 -5
  514. package/releases/v2.2.0-release-notes.md +239 -0
  515. package/server.json +1 -1
  516. package/src/__tests__/cli.test.ts +302 -247
  517. package/src/__tests__/index.test.ts +21 -21
  518. package/src/__tests__/mocks/adapter.ts +204 -163
  519. package/src/__tests__/mocks/index.ts +30 -23
  520. package/src/__tests__/mocks/mysql.ts +94 -84
  521. package/src/__tests__/perf.test.ts +207 -203
  522. package/src/__tests__/performance.test.ts +173 -164
  523. package/src/__tests__/setup.ts +26 -21
  524. package/src/adapters/DatabaseAdapter.ts +386 -340
  525. package/src/adapters/__tests__/DatabaseAdapter.test.ts +455 -377
  526. package/src/adapters/mysql/MySQLAdapter.ts +550 -486
  527. package/src/adapters/mysql/SchemaManager.ts +251 -208
  528. package/src/adapters/mysql/__tests__/MySQLAdapter.integration.test.ts +150 -147
  529. package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +590 -477
  530. package/src/adapters/mysql/__tests__/SchemaManager.test.ts +196 -154
  531. package/src/adapters/mysql/index.ts +2 -2
  532. package/src/adapters/mysql/prompts/__tests__/indexTuning.test.ts +33 -26
  533. package/src/adapters/mysql/prompts/__tests__/prompts.test.ts +277 -239
  534. package/src/adapters/mysql/prompts/backupStrategy.ts +29 -17
  535. package/src/adapters/mysql/prompts/clusterSetup.ts +11 -10
  536. package/src/adapters/mysql/prompts/docstoreSetup.ts +10 -10
  537. package/src/adapters/mysql/prompts/eventScheduler.ts +10 -10
  538. package/src/adapters/mysql/prompts/healthCheck.ts +20 -15
  539. package/src/adapters/mysql/prompts/index.ts +194 -144
  540. package/src/adapters/mysql/prompts/indexTuning.ts +22 -17
  541. package/src/adapters/mysql/prompts/mysqlshSetup.ts +11 -11
  542. package/src/adapters/mysql/prompts/proxysqlSetup.ts +10 -10
  543. package/src/adapters/mysql/prompts/replicationSetup.ts +24 -16
  544. package/src/adapters/mysql/prompts/routerSetup.ts +10 -10
  545. package/src/adapters/mysql/prompts/spatialSetup.ts +10 -10
  546. package/src/adapters/mysql/prompts/sysSchema.ts +11 -10
  547. package/src/adapters/mysql/resources/__tests__/capabilities.test.ts +69 -47
  548. package/src/adapters/mysql/resources/__tests__/cluster.test.ts +163 -104
  549. package/src/adapters/mysql/resources/__tests__/docstore.test.ts +88 -81
  550. package/src/adapters/mysql/resources/__tests__/events.test.ts +94 -83
  551. package/src/adapters/mysql/resources/__tests__/health.test.ts +131 -91
  552. package/src/adapters/mysql/resources/__tests__/indexes.test.ts +125 -102
  553. package/src/adapters/mysql/resources/__tests__/innodb.test.ts +86 -62
  554. package/src/adapters/mysql/resources/__tests__/locks.test.ts +142 -104
  555. package/src/adapters/mysql/resources/__tests__/performance.test.ts +81 -58
  556. package/src/adapters/mysql/resources/__tests__/pool.test.ts +45 -40
  557. package/src/adapters/mysql/resources/__tests__/processlist.test.ts +39 -23
  558. package/src/adapters/mysql/resources/__tests__/replication.test.ts +265 -211
  559. package/src/adapters/mysql/resources/__tests__/resources.test.ts +121 -109
  560. package/src/adapters/mysql/resources/__tests__/schema.test.ts +29 -23
  561. package/src/adapters/mysql/resources/__tests__/spatial.test.ts +58 -45
  562. package/src/adapters/mysql/resources/__tests__/status.test.ts +62 -45
  563. package/src/adapters/mysql/resources/__tests__/sysschema.test.ts +99 -60
  564. package/src/adapters/mysql/resources/__tests__/tables.test.ts +41 -32
  565. package/src/adapters/mysql/resources/__tests__/variables.test.ts +77 -49
  566. package/src/adapters/mysql/resources/capabilities.ts +59 -42
  567. package/src/adapters/mysql/resources/cluster.ts +58 -49
  568. package/src/adapters/mysql/resources/docstore.ts +46 -41
  569. package/src/adapters/mysql/resources/events.ts +37 -31
  570. package/src/adapters/mysql/resources/health.ts +98 -74
  571. package/src/adapters/mysql/resources/index.ts +46 -46
  572. package/src/adapters/mysql/resources/indexes.ts +66 -51
  573. package/src/adapters/mysql/resources/innodb.ts +98 -81
  574. package/src/adapters/mysql/resources/locks.ts +43 -40
  575. package/src/adapters/mysql/resources/performance.ts +80 -67
  576. package/src/adapters/mysql/resources/pool.ts +23 -20
  577. package/src/adapters/mysql/resources/processlist.ts +23 -18
  578. package/src/adapters/mysql/resources/replication.ts +124 -105
  579. package/src/adapters/mysql/resources/schema.ts +23 -18
  580. package/src/adapters/mysql/resources/spatial.ts +31 -26
  581. package/src/adapters/mysql/resources/status.ts +27 -22
  582. package/src/adapters/mysql/resources/sysschema.ts +41 -36
  583. package/src/adapters/mysql/resources/tables.ts +23 -18
  584. package/src/adapters/mysql/resources/variables.ts +27 -22
  585. package/src/adapters/mysql/tools/__tests__/cluster.test.ts +419 -311
  586. package/src/adapters/mysql/tools/__tests__/core.test.ts +633 -382
  587. package/src/adapters/mysql/tools/__tests__/docstore.test.ts +782 -413
  588. package/src/adapters/mysql/tools/__tests__/events.test.ts +752 -486
  589. package/src/adapters/mysql/tools/__tests__/json_core.test.ts +326 -259
  590. package/src/adapters/mysql/tools/__tests__/json_enhanced.test.ts +452 -352
  591. package/src/adapters/mysql/tools/__tests__/json_helpers.test.ts +169 -136
  592. package/src/adapters/mysql/tools/__tests__/proxysql.test.ts +576 -340
  593. package/src/adapters/mysql/tools/__tests__/replication.test.ts +697 -393
  594. package/src/adapters/mysql/tools/__tests__/roles.test.ts +423 -166
  595. package/src/adapters/mysql/tools/__tests__/router.test.ts +644 -540
  596. package/src/adapters/mysql/tools/__tests__/security.test.ts +708 -422
  597. package/src/adapters/mysql/tools/__tests__/security_injection.test.ts +246 -173
  598. package/src/adapters/mysql/tools/__tests__/security_integration.test.ts +244 -205
  599. package/src/adapters/mysql/tools/__tests__/spatial.test.ts +413 -300
  600. package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +503 -150
  601. package/src/adapters/mysql/tools/__tests__/stats.test.ts +861 -553
  602. package/src/adapters/mysql/tools/__tests__/transactions.test.ts +454 -263
  603. package/src/adapters/mysql/tools/admin/__tests__/backup.test.ts +612 -372
  604. package/src/adapters/mysql/tools/admin/__tests__/maintenance.test.ts +550 -257
  605. package/src/adapters/mysql/tools/admin/__tests__/monitoring.test.ts +549 -352
  606. package/src/adapters/mysql/tools/admin/backup.ts +334 -215
  607. package/src/adapters/mysql/tools/admin/index.ts +46 -46
  608. package/src/adapters/mysql/tools/admin/maintenance.ts +176 -130
  609. package/src/adapters/mysql/tools/admin/monitoring.ts +373 -199
  610. package/src/adapters/mysql/tools/cluster/__tests__/group-replication.test.ts +200 -186
  611. package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +364 -95
  612. package/src/adapters/mysql/tools/cluster/group-replication.ts +218 -183
  613. package/src/adapters/mysql/tools/cluster/index.ts +27 -27
  614. package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +392 -251
  615. package/src/adapters/mysql/tools/core.ts +408 -285
  616. package/src/adapters/mysql/tools/docstore.ts +478 -276
  617. package/src/adapters/mysql/tools/events.ts +425 -285
  618. package/src/adapters/mysql/tools/index.ts +31 -20
  619. package/src/adapters/mysql/tools/json/__tests__/core.test.ts +456 -199
  620. package/src/adapters/mysql/tools/json/__tests__/enhanced.test.ts +554 -298
  621. package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +150 -74
  622. package/src/adapters/mysql/tools/json/__tests__/validation.test.ts +106 -72
  623. package/src/adapters/mysql/tools/json/core.ts +364 -263
  624. package/src/adapters/mysql/tools/json/enhanced.ts +368 -229
  625. package/src/adapters/mysql/tools/json/helpers.ts +195 -113
  626. package/src/adapters/mysql/tools/json/index.ts +46 -46
  627. package/src/adapters/mysql/tools/partitioning.ts +242 -140
  628. package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +439 -247
  629. package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +401 -179
  630. package/src/adapters/mysql/tools/performance/analysis.ts +263 -213
  631. package/src/adapters/mysql/tools/performance/index.ts +33 -33
  632. package/src/adapters/mysql/tools/performance/optimization.ts +407 -190
  633. package/src/adapters/mysql/tools/proxysql.ts +462 -320
  634. package/src/adapters/mysql/tools/replication.ts +233 -180
  635. package/src/adapters/mysql/tools/roles.ts +429 -171
  636. package/src/adapters/mysql/tools/router.ts +410 -292
  637. package/src/adapters/mysql/tools/schema/__tests__/constraints.test.ts +157 -82
  638. package/src/adapters/mysql/tools/schema/__tests__/management.test.ts +226 -101
  639. package/src/adapters/mysql/tools/schema/__tests__/routines.test.ts +80 -35
  640. package/src/adapters/mysql/tools/schema/__tests__/scheduled_events.test.ts +59 -40
  641. package/src/adapters/mysql/tools/schema/__tests__/triggers.test.ts +65 -40
  642. package/src/adapters/mysql/tools/schema/__tests__/views.test.ts +146 -77
  643. package/src/adapters/mysql/tools/schema/constraints.ts +61 -42
  644. package/src/adapters/mysql/tools/schema/index.ts +26 -35
  645. package/src/adapters/mysql/tools/schema/management.ts +167 -94
  646. package/src/adapters/mysql/tools/schema/routines.ts +79 -48
  647. package/src/adapters/mysql/tools/schema/scheduled_events.ts +53 -32
  648. package/src/adapters/mysql/tools/schema/triggers.ts +51 -33
  649. package/src/adapters/mysql/tools/schema/views.ts +96 -53
  650. package/src/adapters/mysql/tools/security/__tests__/audit.test.ts +216 -158
  651. package/src/adapters/mysql/tools/security/__tests__/data-protection.test.ts +154 -98
  652. package/src/adapters/mysql/tools/security/__tests__/encryption.test.ts +174 -138
  653. package/src/adapters/mysql/tools/security/audit.ts +213 -193
  654. package/src/adapters/mysql/tools/security/data-protection.ts +336 -198
  655. package/src/adapters/mysql/tools/security/encryption.ts +233 -193
  656. package/src/adapters/mysql/tools/security/index.ts +26 -26
  657. package/src/adapters/mysql/tools/shell/__tests__/backup.test.ts +443 -283
  658. package/src/adapters/mysql/tools/shell/__tests__/common.test.ts +138 -131
  659. package/src/adapters/mysql/tools/shell/__tests__/data-transfer.test.ts +516 -353
  660. package/src/adapters/mysql/tools/shell/__tests__/info.test.ts +65 -63
  661. package/src/adapters/mysql/tools/shell/__tests__/restore.test.ts +233 -174
  662. package/src/adapters/mysql/tools/shell/__tests__/utilities.test.ts +161 -143
  663. package/src/adapters/mysql/tools/shell/backup.ts +280 -188
  664. package/src/adapters/mysql/tools/shell/common.ts +173 -155
  665. package/src/adapters/mysql/tools/shell/data-transfer.ts +286 -200
  666. package/src/adapters/mysql/tools/shell/index.ts +29 -29
  667. package/src/adapters/mysql/tools/shell/info.ts +35 -31
  668. package/src/adapters/mysql/tools/shell/restore.ts +176 -124
  669. package/src/adapters/mysql/tools/shell/utilities.ts +86 -45
  670. package/src/adapters/mysql/tools/spatial/__tests__/geometry.test.ts +129 -89
  671. package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +255 -148
  672. package/src/adapters/mysql/tools/spatial/__tests__/queries.test.ts +340 -245
  673. package/src/adapters/mysql/tools/spatial/geometry.ts +120 -74
  674. package/src/adapters/mysql/tools/spatial/index.ts +33 -33
  675. package/src/adapters/mysql/tools/spatial/operations.ts +243 -171
  676. package/src/adapters/mysql/tools/spatial/queries.ts +221 -165
  677. package/src/adapters/mysql/tools/spatial/setup.ts +157 -73
  678. package/src/adapters/mysql/tools/stats/__tests__/comparative.test.ts +188 -130
  679. package/src/adapters/mysql/tools/stats/comparative.ts +261 -187
  680. package/src/adapters/mysql/tools/stats/descriptive.ts +414 -322
  681. package/src/adapters/mysql/tools/stats/index.ts +23 -23
  682. package/src/adapters/mysql/tools/sysschema/__tests__/activity.test.ts +99 -71
  683. package/src/adapters/mysql/tools/sysschema/__tests__/io_summary_fix.test.ts +21 -18
  684. package/src/adapters/mysql/tools/sysschema/__tests__/performance.test.ts +149 -108
  685. package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +222 -104
  686. package/src/adapters/mysql/tools/sysschema/activity.ts +72 -64
  687. package/src/adapters/mysql/tools/sysschema/index.ts +24 -24
  688. package/src/adapters/mysql/tools/sysschema/performance.ts +140 -115
  689. package/src/adapters/mysql/tools/sysschema/resources.ts +135 -99
  690. package/src/adapters/mysql/tools/text/__tests__/fulltext.test.ts +526 -145
  691. package/src/adapters/mysql/tools/text/__tests__/processing.test.ts +452 -193
  692. package/src/adapters/mysql/tools/text/fulltext.ts +319 -123
  693. package/src/adapters/mysql/tools/text/index.ts +32 -30
  694. package/src/adapters/mysql/tools/text/processing.ts +310 -212
  695. package/src/adapters/mysql/tools/transactions.ts +284 -197
  696. package/src/adapters/mysql/types/__tests__/shell-types.test.ts +204 -202
  697. package/src/adapters/mysql/types/proxysql-types.ts +142 -109
  698. package/src/adapters/mysql/types/router-types.ts +36 -36
  699. package/src/adapters/mysql/types/shell-types.ts +280 -94
  700. package/src/adapters/mysql/types.ts +288 -131
  701. package/src/auth/AuthorizationServerDiscovery.ts +127 -113
  702. package/src/auth/OAuthResourceServer.ts +67 -62
  703. package/src/auth/TokenValidator.ts +136 -119
  704. package/src/auth/__tests__/AuthorizationServerDiscovery.test.ts +295 -274
  705. package/src/auth/__tests__/OAuthResourceServer.test.ts +180 -169
  706. package/src/auth/__tests__/TokenValidator.test.ts +297 -285
  707. package/src/auth/__tests__/errors.test.ts +180 -175
  708. package/src/auth/__tests__/middleware.test.ts +281 -247
  709. package/src/auth/__tests__/scopes.test.ts +136 -134
  710. package/src/auth/errors.ts +56 -56
  711. package/src/auth/index.ts +23 -17
  712. package/src/auth/middleware.ts +161 -139
  713. package/src/auth/scopes.ts +133 -107
  714. package/src/auth/types.ts +155 -155
  715. package/src/cli/__tests__/args.test.ts +241 -216
  716. package/src/cli/__tests__/main.test.ts +191 -158
  717. package/src/cli/args.ts +271 -258
  718. package/src/cli.ts +150 -127
  719. package/src/constants/ServerInstructions.ts +271 -70
  720. package/src/filtering/ToolConstants.ts +287 -266
  721. package/src/filtering/ToolFilter.ts +239 -220
  722. package/src/filtering/__tests__/ToolFilter.test.ts +442 -396
  723. package/src/index.ts +62 -57
  724. package/src/logging/McpLogging.ts +128 -119
  725. package/src/logging/__tests__/McpLogging.test.ts +223 -223
  726. package/src/logging/index.ts +2 -2
  727. package/src/pool/ConnectionPool.ts +260 -246
  728. package/src/pool/__tests__/ConnectionPool.test.ts +452 -418
  729. package/src/progress/ProgressReporter.ts +123 -123
  730. package/src/progress/__tests__/ProgressReporter.test.ts +235 -229
  731. package/src/progress/index.ts +6 -2
  732. package/src/server/McpServer.ts +305 -285
  733. package/src/server/__tests__/McpServer.test.ts +333 -291
  734. package/src/transports/__tests__/http.test.ts +658 -527
  735. package/src/transports/http.ts +237 -203
  736. package/src/transports/index.ts +6 -2
  737. package/src/types/__tests__/types.test.ts +197 -193
  738. package/src/types/index.ts +49 -37
  739. package/src/types/modules/database.ts +65 -63
  740. package/src/types/modules/errors.ts +41 -37
  741. package/src/types/modules/oauth.ts +46 -46
  742. package/src/types/modules/query.ts +75 -75
  743. package/src/types/modules/server.ts +18 -18
  744. package/src/types/modules/tools.ts +181 -178
  745. package/src/utils/__tests__/logger.test.ts +424 -414
  746. package/src/utils/__tests__/validators.test.ts +250 -165
  747. package/src/utils/logger.ts +343 -330
  748. package/src/utils/promptGenerator.ts +58 -47
  749. package/src/utils/validators.ts +217 -91
  750. package/tsconfig.json +41 -50
  751. package/vitest.config.ts +23 -23
@@ -1,466 +1,752 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { createMockMySQLAdapter, createMockQueryResult, createMockRequestContext } from '../../../../__tests__/mocks/index.js';
3
- import { getSecurityTools } from '../security/index.js';
4
-
5
- describe('Security Tools', () => {
6
- let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
7
- let mockContext: ReturnType<typeof createMockRequestContext>;
8
- let tools: ReturnType<typeof getSecurityTools>;
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import {
3
+ createMockMySQLAdapter,
4
+ createMockQueryResult,
5
+ createMockRequestContext,
6
+ } from "../../../../__tests__/mocks/index.js";
7
+ import { getSecurityTools } from "../security/index.js";
8
+
9
+ describe("Security Tools", () => {
10
+ let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
11
+ let mockContext: ReturnType<typeof createMockRequestContext>;
12
+ let tools: ReturnType<typeof getSecurityTools>;
13
+
14
+ beforeEach(() => {
15
+ vi.clearAllMocks();
16
+ mockAdapter = createMockMySQLAdapter();
17
+ mockContext = createMockRequestContext();
18
+ tools = getSecurityTools(mockAdapter as any);
19
+ });
20
+
21
+ describe("mysql_security_audit", () => {
22
+ it("should first check for audit log table", async () => {
23
+ // Check table exists (fail)
24
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
25
+
26
+ // Check performance schema fallback
27
+ mockAdapter.executeQuery.mockResolvedValueOnce(
28
+ createMockQueryResult([
29
+ { event: "SELECT", user: "root", startTime: 123456 },
30
+ ]),
31
+ );
32
+
33
+ const tool = tools.find((t) => t.name === "mysql_security_audit");
34
+ const result = (await tool?.handler({ limit: 10 }, mockContext)) as any;
35
+
36
+ expect(result.source).toBe("performance_schema");
37
+ expect(result.events).toHaveLength(1);
38
+ });
9
39
 
10
- beforeEach(() => {
11
- vi.clearAllMocks();
12
- mockAdapter = createMockMySQLAdapter();
13
- mockContext = createMockRequestContext();
14
- tools = getSecurityTools(mockAdapter as any);
40
+ it("should query mysql.audit_log if exists", async () => {
41
+ // Check table exists (success)
42
+ mockAdapter.executeQuery.mockResolvedValueOnce(
43
+ createMockQueryResult([{ TABLE_NAME: "audit_log" }]),
44
+ );
45
+
46
+ // Query audit log
47
+ mockAdapter.executeQuery.mockResolvedValueOnce(
48
+ createMockQueryResult([{ event_type: "CONNECT", user: "root" }]),
49
+ );
50
+
51
+ const tool = tools.find((t) => t.name === "mysql_security_audit");
52
+ const result = (await tool?.handler(
53
+ { limit: 10, user: "root" },
54
+ mockContext,
55
+ )) as any;
56
+
57
+ expect(result.source).toBe("mysql.audit_log");
58
+ expect(result.events).toHaveLength(1);
59
+ const queryArgs = mockAdapter.executeQuery.mock.calls[1][1] as any[];
60
+ expect(queryArgs).toContain("%root%");
15
61
  });
16
62
 
17
- describe('mysql_security_audit', () => {
18
- it('should first check for audit log table', async () => {
19
- // Check table exists (fail)
20
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
63
+ it("should filter by start time", async () => {
64
+ mockAdapter.executeQuery.mockResolvedValueOnce(
65
+ createMockQueryResult([{ TABLE_NAME: "audit_log" }]),
66
+ );
67
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
21
68
 
22
- // Check performance schema fallback
23
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
24
- { event: 'SELECT', user: 'root', startTime: 123456 }
25
- ]));
69
+ const tool = tools.find((t) => t.name === "mysql_security_audit");
70
+ await tool?.handler({ startTime: "2023-01-01" }, mockContext);
26
71
 
27
- const tool = tools.find(t => t.name === 'mysql_security_audit');
28
- const result = await tool?.handler({ limit: 10 }, mockContext) as any;
72
+ const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
73
+ expect(call).toContain("timestamp >= ?");
74
+ });
29
75
 
30
- expect(result.source).toBe('performance_schema');
31
- expect(result.events).toHaveLength(1);
32
- });
76
+ it("should filter by event type and start time in main audit log", async () => {
77
+ mockAdapter.executeQuery.mockResolvedValueOnce(
78
+ createMockQueryResult([{ TABLE_NAME: "audit_log" }]),
79
+ );
80
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
81
+
82
+ const tool = tools.find((t) => t.name === "mysql_security_audit");
83
+ await tool?.handler(
84
+ { eventType: "CONNECT", startTime: "2023-01-01" },
85
+ mockContext,
86
+ );
87
+
88
+ const callArgs = mockAdapter.executeQuery.mock.calls[1];
89
+ const query = callArgs[0] as string;
90
+ const params = callArgs[1] as any[];
91
+
92
+ expect(query).toContain("event_type = ?");
93
+ expect(query).toContain("timestamp >= ?");
94
+ expect(params).toContain("CONNECT");
95
+ expect(params).toContain("2023-01-01");
96
+ });
33
97
 
34
- it('should query mysql.audit_log if exists', async () => {
35
- // Check table exists (success)
36
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ TABLE_NAME: 'audit_log' }]));
98
+ it("should handle audit log unavailable", async () => {
99
+ mockAdapter.executeQuery.mockRejectedValue(new Error("Connect error"));
37
100
 
38
- // Query audit log
39
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
40
- { event_type: 'CONNECT', user: 'root' }
41
- ]));
101
+ const tool = tools.find((t) => t.name === "mysql_security_audit");
102
+ const result = (await tool?.handler({}, mockContext)) as any;
42
103
 
43
- const tool = tools.find(t => t.name === 'mysql_security_audit');
44
- const result = await tool?.handler({ limit: 10, user: 'root' }, mockContext) as any;
104
+ expect(result.available).toBe(false);
105
+ expect(result.message).toContain("Audit logging is not enabled");
106
+ });
107
+ });
108
+
109
+ describe("mysql_security_firewall_rules", () => {
110
+ it("should list firewall rules", async () => {
111
+ mockAdapter.executeQuery.mockResolvedValueOnce(
112
+ createMockQueryResult([
113
+ { USERHOST: "root@localhost", MODE: "RECORDING" },
114
+ ]),
115
+ );
116
+ mockAdapter.executeQuery.mockResolvedValueOnce(
117
+ createMockQueryResult([
118
+ { USERHOST: "root@localhost", RULE: "SELECT * FROM users" },
119
+ ]),
120
+ );
121
+
122
+ const tool = tools.find(
123
+ (t) => t.name === "mysql_security_firewall_rules",
124
+ );
125
+ const result = (await tool?.handler(
126
+ { user: "root" },
127
+ mockContext,
128
+ )) as any;
129
+
130
+ expect(result.userCount).toBe(1);
131
+ expect(result.ruleCount).toBe(1);
132
+ expect(result.rules[0].RULE).toBe("SELECT * FROM users");
133
+ });
45
134
 
46
- expect(result.source).toBe('mysql.audit_log');
47
- expect(result.events).toHaveLength(1);
48
- const queryArgs = mockAdapter.executeQuery.mock.calls[1][1] as any[];
49
- expect(queryArgs).toContain('%root%');
50
- });
135
+ it("should filter by mode", async () => {
136
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
137
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
51
138
 
52
- it('should filter by start time', async () => {
53
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ TABLE_NAME: 'audit_log' }]));
54
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
139
+ const tool = tools.find(
140
+ (t) => t.name === "mysql_security_firewall_rules",
141
+ );
142
+ await tool?.handler({ mode: "PROTECTING" }, mockContext);
55
143
 
56
- const tool = tools.find(t => t.name === 'mysql_security_audit');
57
- await tool?.handler({ startTime: '2023-01-01' }, mockContext);
144
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
145
+ expect(call).toContain("MODE = ?");
146
+ });
58
147
 
59
- const call = mockAdapter.executeQuery.mock.calls[1][0] as string;
60
- expect(call).toContain('timestamp >= ?');
61
- });
148
+ it("should handle firewall tables access error", async () => {
149
+ mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
62
150
 
151
+ const tool = tools.find(
152
+ (t) => t.name === "mysql_security_firewall_rules",
153
+ );
154
+ const result = (await tool?.handler({}, mockContext)) as any;
63
155
 
156
+ expect(result.available).toBe(false);
157
+ });
158
+ });
159
+
160
+ describe("mysql_security_firewall_status", () => {
161
+ it("should return installed status if plugin found", async () => {
162
+ mockAdapter.executeQuery.mockResolvedValueOnce(
163
+ createMockQueryResult([
164
+ { PLUGIN_NAME: "mysql_firewall", PLUGIN_STATUS: "ACTIVE" },
165
+ ]),
166
+ );
167
+
168
+ mockAdapter.executeQuery.mockResolvedValueOnce(
169
+ createMockQueryResult([
170
+ { Variable_name: "mysql_firewall_mode", Value: "ON" },
171
+ ]),
172
+ );
173
+
174
+ const tool = tools.find(
175
+ (t) => t.name === "mysql_security_firewall_status",
176
+ );
177
+ const result = (await tool?.handler({}, mockContext)) as any;
178
+
179
+ expect(result.installed).toBe(true);
180
+ expect(result.configuration).toHaveProperty("mysql_firewall_mode", "ON");
181
+ });
64
182
 
65
- it('should filter by event type and start time in main audit log', async () => {
66
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ TABLE_NAME: 'audit_log' }]));
67
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
183
+ it("should return not installed if plugin missing", async () => {
184
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
68
185
 
69
- const tool = tools.find(t => t.name === 'mysql_security_audit');
70
- await tool?.handler({ eventType: 'CONNECT', startTime: '2023-01-01' }, mockContext);
186
+ const tool = tools.find(
187
+ (t) => t.name === "mysql_security_firewall_status",
188
+ );
189
+ const result = (await tool?.handler({}, mockContext)) as any;
71
190
 
72
- const callArgs = mockAdapter.executeQuery.mock.calls[1];
73
- const query = callArgs[0] as string;
74
- const params = callArgs[1] as any[];
191
+ expect(result.installed).toBe(false);
192
+ expect(result.message).toContain("not installed");
193
+ });
75
194
 
76
- expect(query).toContain('event_type = ?');
77
- expect(query).toContain('timestamp >= ?');
78
- expect(params).toContain('CONNECT');
79
- expect(params).toContain('2023-01-01');
80
- });
195
+ it("should handle plugin check failure", async () => {
196
+ mockAdapter.executeQuery.mockRejectedValue(new Error("DB Error"));
81
197
 
82
- it('should handle audit log unavailable', async () => {
83
- mockAdapter.executeQuery.mockRejectedValue(new Error('Connect error'));
198
+ const tool = tools.find(
199
+ (t) => t.name === "mysql_security_firewall_status",
200
+ );
201
+ const result = (await tool?.handler({}, mockContext)) as any;
84
202
 
85
- const tool = tools.find(t => t.name === 'mysql_security_audit');
86
- const result = await tool?.handler({}, mockContext) as any;
203
+ expect(result.installed).toBe(false);
204
+ expect(result.message).toBe("Firewall plugin check failed");
205
+ });
206
+ });
207
+
208
+ describe("mysql_security_mask_data", () => {
209
+ it("should masking email", async () => {
210
+ const tool = tools.find((t) => t.name === "mysql_security_mask_data");
211
+ const result = (await tool?.handler(
212
+ {
213
+ value: "john.doe@example.com",
214
+ type: "email",
215
+ },
216
+ mockContext,
217
+ )) as any;
218
+
219
+ expect(result.masked).toBe("j******e@example.com");
220
+ });
87
221
 
88
- expect(result.available).toBe(false);
89
- expect(result.message).toContain('Audit logging is not enabled');
90
- });
222
+ it("should mask different types correctly", async () => {
223
+ const tool = tools.find((t) => t.name === "mysql_security_mask_data");
224
+
225
+ // Email without @
226
+ const resNoAt = (await tool?.handler(
227
+ { value: "invalid-email", type: "email" },
228
+ mockContext,
229
+ )) as any;
230
+ expect(resNoAt.masked).toBe("*************");
231
+
232
+ // Phone
233
+ const resPhone = (await tool?.handler(
234
+ { value: "1234567890", type: "phone" },
235
+ mockContext,
236
+ )) as any;
237
+ expect(resPhone.masked).toBe("******7890");
238
+
239
+ // SSN
240
+ const resSSN = (await tool?.handler(
241
+ { value: "123456789", type: "ssn" },
242
+ mockContext,
243
+ )) as any;
244
+ expect(resSSN.masked).toBe("***-**-6789");
245
+
246
+ // Credit Card
247
+ const resCC = (await tool?.handler(
248
+ { value: "1234567812345678", type: "credit_card" },
249
+ mockContext,
250
+ )) as any;
251
+ expect(resCC.masked).toBe("1234********5678");
252
+
253
+ // Partial
254
+ const resPartial = (await tool?.handler(
255
+ { value: "abcdef", type: "partial", keepFirst: 2, keepLast: 2 },
256
+ mockContext,
257
+ )) as any;
258
+ expect(resPartial.masked).toBe("ab**ef");
259
+
260
+ // Default fallback
261
+ // We need to force a type that falls through or just check specific logic
262
+ // Since we can't pass invalid enum via Zod, we trust the switch default handles odd input if it could bypass Zod
263
+ // But Zod prevents it. However, the switch has a default case.
264
+ // Let's assume typescript-eslint doesn't complain about unreachable code if we force it
91
265
  });
92
266
 
93
- describe('mysql_security_firewall_rules', () => {
94
- it('should list firewall rules', async () => {
95
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
96
- { USERHOST: 'root@localhost', MODE: 'RECORDING' }
97
- ]));
98
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
99
- { USERHOST: 'root@localhost', RULE: 'SELECT * FROM users' }
100
- ]));
267
+ it("should mask credit card", async () => {
268
+ const tool = tools.find((t) => t.name === "mysql_security_mask_data");
269
+ const result = (await tool?.handler(
270
+ {
271
+ value: "1234-5678-9012-3456",
272
+ type: "credit_card",
273
+ },
274
+ mockContext,
275
+ )) as any;
276
+
277
+ expect(result.masked).toBe("1234********3456");
278
+ });
101
279
 
102
- const tool = tools.find(t => t.name === 'mysql_security_firewall_rules');
103
- const result = await tool?.handler({ user: 'root' }, mockContext) as any;
280
+ it("should fully mask short credit card values with warning", async () => {
281
+ const tool = tools.find((t) => t.name === "mysql_security_mask_data");
282
+ const result = (await tool?.handler(
283
+ { value: "123", type: "credit_card" },
284
+ mockContext,
285
+ )) as any;
286
+
287
+ expect(result.original).toBe("123");
288
+ expect(result.masked).toBe("***");
289
+ expect(result.type).toBe("credit_card");
290
+ expect(result.warning).toContain("too short");
291
+ });
292
+ });
293
+
294
+ describe("mysql_security_password_validate", () => {
295
+ it("should return password strength", async () => {
296
+ // Variables (checked first to detect component)
297
+ mockAdapter.executeQuery.mockResolvedValueOnce(
298
+ createMockQueryResult([
299
+ { Variable_name: "validate_password.policy", Value: "STRONG" },
300
+ ]),
301
+ );
302
+ // VALIDATE_PASSWORD_STRENGTH
303
+ mockAdapter.executeQuery.mockResolvedValueOnce(
304
+ createMockQueryResult([{ strength: 100 }]),
305
+ );
306
+
307
+ const tool = tools.find(
308
+ (t) => t.name === "mysql_security_password_validate",
309
+ );
310
+ const result = (await tool?.handler(
311
+ { password: "StrongPassword123!" },
312
+ mockContext,
313
+ )) as any;
314
+
315
+ expect(result.strength).toBe(100);
316
+ expect(result.interpretation).toBe("Very Strong");
317
+ expect(result.policy).toHaveProperty(
318
+ "validate_password.policy",
319
+ "STRONG",
320
+ );
321
+ });
104
322
 
105
- expect(result.userCount).toBe(1);
106
- expect(result.ruleCount).toBe(1);
107
- expect(result.rules[0].RULE).toBe('SELECT * FROM users');
108
- });
323
+ it("should handle different password strengths", async () => {
324
+ const tool = tools.find(
325
+ (t) => t.name === "mysql_security_password_validate",
326
+ );
327
+
328
+ // Strong
329
+ mockAdapter.executeQuery.mockResolvedValueOnce(
330
+ createMockQueryResult([
331
+ { Variable_name: "validate_password.policy", Value: "MEDIUM" },
332
+ ]),
333
+ );
334
+ mockAdapter.executeQuery.mockResolvedValueOnce(
335
+ createMockQueryResult([{ strength: 75 }]),
336
+ );
337
+ const resultStrong = (await tool?.handler(
338
+ { password: "Strong1" },
339
+ mockContext,
340
+ )) as any;
341
+ expect(resultStrong.interpretation).toBe("Strong");
342
+
343
+ // Medium
344
+ mockAdapter.executeQuery.mockResolvedValueOnce(
345
+ createMockQueryResult([
346
+ { Variable_name: "validate_password.policy", Value: "MEDIUM" },
347
+ ]),
348
+ );
349
+ mockAdapter.executeQuery.mockResolvedValueOnce(
350
+ createMockQueryResult([{ strength: 50 }]),
351
+ );
352
+ const resultMedium = (await tool?.handler(
353
+ { password: "Medium1" },
354
+ mockContext,
355
+ )) as any;
356
+ expect(resultMedium.interpretation).toBe("Medium");
357
+
358
+ // Weak
359
+ mockAdapter.executeQuery.mockResolvedValueOnce(
360
+ createMockQueryResult([
361
+ { Variable_name: "validate_password.policy", Value: "MEDIUM" },
362
+ ]),
363
+ );
364
+ mockAdapter.executeQuery.mockResolvedValueOnce(
365
+ createMockQueryResult([{ strength: 25 }]),
366
+ );
367
+ const resultWeak = (await tool?.handler(
368
+ { password: "Weak1" },
369
+ mockContext,
370
+ )) as any;
371
+ expect(resultWeak.interpretation).toBe("Weak");
372
+
373
+ // Very Weak
374
+ mockAdapter.executeQuery.mockResolvedValueOnce(
375
+ createMockQueryResult([
376
+ { Variable_name: "validate_password.policy", Value: "MEDIUM" },
377
+ ]),
378
+ );
379
+ mockAdapter.executeQuery.mockResolvedValueOnce(
380
+ createMockQueryResult([{ strength: 0 }]),
381
+ );
382
+ const resultVeryWeak = (await tool?.handler(
383
+ { password: "VeryWeak" },
384
+ mockContext,
385
+ )) as any;
386
+ expect(resultVeryWeak.interpretation).toBe("Very Weak");
387
+ });
109
388
 
110
- it('should filter by mode', async () => {
111
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
112
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
389
+ it("should detect component not installed when no policy variables exist", async () => {
390
+ // Empty policy variables = component not installed
391
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
113
392
 
114
- const tool = tools.find(t => t.name === 'mysql_security_firewall_rules');
115
- await tool?.handler({ mode: 'PROTECTING' }, mockContext);
393
+ const tool = tools.find(
394
+ (t) => t.name === "mysql_security_password_validate",
395
+ );
396
+ const result = (await tool?.handler(
397
+ { password: "test" },
398
+ mockContext,
399
+ )) as any;
116
400
 
117
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
118
- expect(call).toContain('MODE = ?');
119
- });
401
+ expect(result.available).toBe(false);
402
+ expect(result.message).toContain("not installed");
403
+ });
404
+
405
+ it("should handle validation function error", async () => {
406
+ // Policy check passes (component installed)
407
+ mockAdapter.executeQuery.mockResolvedValueOnce(
408
+ createMockQueryResult([
409
+ { Variable_name: "validate_password.policy", Value: "MEDIUM" },
410
+ ]),
411
+ );
412
+ // But function call fails
413
+ mockAdapter.executeQuery.mockRejectedValue(new Error("Function error"));
414
+
415
+ const tool = tools.find(
416
+ (t) => t.name === "mysql_security_password_validate",
417
+ );
418
+ const result = (await tool?.handler(
419
+ { password: "test" },
420
+ mockContext,
421
+ )) as any;
422
+
423
+ expect(result.available).toBe(false);
424
+ expect(result.message).toContain("failed");
425
+ });
426
+ });
427
+
428
+ describe("mysql_security_ssl_status", () => {
429
+ it("should return ssl status", async () => {
430
+ // Status
431
+ mockAdapter.executeQuery.mockResolvedValueOnce(
432
+ createMockQueryResult([
433
+ { Variable_name: "Ssl_cipher", Value: "AES256-SHA" },
434
+ { Variable_name: "Ssl_version", Value: "TLSv1.3" },
435
+ ]),
436
+ );
437
+ // Variables
438
+ mockAdapter.executeQuery.mockResolvedValueOnce(
439
+ createMockQueryResult([{ Variable_name: "ssl_ca", Value: "ca.pem" }]),
440
+ );
441
+ // Connection
442
+ mockAdapter.executeQuery.mockResolvedValueOnce(
443
+ createMockQueryResult([{ cipher: "AES256-SHA", verifyCert: 1 }]),
444
+ );
445
+
446
+ const tool = tools.find((t) => t.name === "mysql_security_ssl_status");
447
+ const result = (await tool?.handler({}, mockContext)) as any;
448
+
449
+ expect(result.sslEnabled).toBe(true);
450
+ expect(result.currentCipher).toBe("AES256-SHA");
451
+ expect(result.configuration.sslCa).toBe("ca.pem");
452
+ });
120
453
 
121
- it('should handle firewall tables access error', async () => {
122
- mockAdapter.executeQuery.mockRejectedValue(new Error('Access denied'));
454
+ it("should handle undefined values gracefully", async () => {
455
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
456
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
457
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
123
458
 
124
- const tool = tools.find(t => t.name === 'mysql_security_firewall_rules');
125
- const result = await tool?.handler({}, mockContext) as any;
459
+ const tool = tools.find((t) => t.name === "mysql_security_ssl_status");
460
+ const result = (await tool?.handler({}, mockContext)) as any;
126
461
 
127
- expect(result.available).toBe(false);
128
- });
462
+ expect(result.sslEnabled).toBe(false);
463
+ expect(result.currentCipher).toBe("None");
464
+ });
465
+ });
466
+
467
+ describe("mysql_security_user_privileges", () => {
468
+ it("should return comprehensive user report", async () => {
469
+ // mysql.user
470
+ mockAdapter.executeQuery.mockResolvedValueOnce(
471
+ createMockQueryResult([
472
+ {
473
+ User: "root",
474
+ Host: "localhost",
475
+ plugin: "caching_sha2_password",
476
+ account_locked: "N",
477
+ },
478
+ ]),
479
+ );
480
+ // SHOW GRANTS
481
+ mockAdapter.executeQuery.mockResolvedValueOnce(
482
+ createMockQueryResult([
483
+ {
484
+ "Grants for root@localhost":
485
+ "GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost`",
486
+ },
487
+ ]),
488
+ );
489
+ // Role edges
490
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
491
+
492
+ const tool = tools.find(
493
+ (t) => t.name === "mysql_security_user_privileges",
494
+ );
495
+ const result = (await tool?.handler({}, mockContext)) as any;
496
+
497
+ expect(result.count).toBe(1);
498
+ expect(result.users[0].user).toBe("root");
499
+ expect(result.users[0].grants).toHaveLength(1);
129
500
  });
130
501
 
131
- describe('mysql_security_firewall_status', () => {
132
- it('should return installed status if plugin found', async () => {
133
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
134
- { PLUGIN_NAME: 'mysql_firewall', PLUGIN_STATUS: 'ACTIVE' }
135
- ]));
502
+ it("should include roles if requested", async () => {
503
+ // P154: User existence pre-check
504
+ mockAdapter.executeQuery.mockResolvedValueOnce(
505
+ createMockQueryResult([{ User: "root" }]),
506
+ );
507
+ mockAdapter.executeQuery.mockResolvedValueOnce(
508
+ createMockQueryResult([{ User: "root", Host: "localhost" }]),
509
+ );
510
+ mockAdapter.executeQuery.mockResolvedValueOnce(
511
+ createMockQueryResult([{ Grants: "GRANT..." }]),
512
+ );
513
+ mockAdapter.executeQuery.mockResolvedValueOnce(
514
+ createMockQueryResult([{ FROM_USER: "app_role", FROM_HOST: "%" }]),
515
+ );
516
+
517
+ const tool = tools.find(
518
+ (t) => t.name === "mysql_security_user_privileges",
519
+ );
520
+ const result = (await tool?.handler(
521
+ { user: "root", includeRoles: true },
522
+ mockContext,
523
+ )) as any;
524
+
525
+ expect(result.users[0].roles).toContain("app_role@%");
526
+ });
136
527
 
137
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
138
- { Variable_name: 'mysql_firewall_mode', Value: 'ON' }
139
- ]));
528
+ it("should filter by specific host", async () => {
529
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
140
530
 
141
- const tool = tools.find(t => t.name === 'mysql_security_firewall_status');
142
- const result = await tool?.handler({}, mockContext) as any;
531
+ const tool = tools.find(
532
+ (t) => t.name === "mysql_security_user_privileges",
533
+ );
534
+ await tool?.handler({ host: "127.0.0.1" }, mockContext);
143
535
 
144
- expect(result.installed).toBe(true);
145
- expect(result.configuration).toHaveProperty('mysql_firewall_mode', 'ON');
146
- });
536
+ const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
537
+ expect(call).toContain("Host = ?");
538
+ });
147
539
 
148
- it('should return not installed if plugin missing', async () => {
149
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
540
+ it("should return condensed summary when summary=true", async () => {
541
+ mockAdapter.executeQuery.mockResolvedValueOnce(
542
+ createMockQueryResult([
543
+ {
544
+ User: "root",
545
+ Host: "localhost",
546
+ plugin: "caching_sha2_password",
547
+ account_locked: "N",
548
+ },
549
+ ]),
550
+ );
551
+ mockAdapter.executeQuery.mockResolvedValueOnce(
552
+ createMockQueryResult([
553
+ {
554
+ "Grants for root@localhost":
555
+ "GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION",
556
+ },
557
+ ]),
558
+ );
559
+ mockAdapter.executeQuery.mockResolvedValueOnce(
560
+ createMockQueryResult([{ FROM_USER: "dba_role", FROM_HOST: "%" }]),
561
+ );
562
+
563
+ const tool = tools.find(
564
+ (t) => t.name === "mysql_security_user_privileges",
565
+ );
566
+ const result = (await tool?.handler(
567
+ { summary: true },
568
+ mockContext,
569
+ )) as any;
570
+
571
+ expect(result.summary).toBe(true);
572
+ expect(result.users[0].grantCount).toBe(1);
573
+ expect(result.users[0].roleCount).toBe(1);
574
+ expect(result.users[0].hasAllPrivileges).toBe(true);
575
+ expect(result.users[0].hasWithGrantOption).toBe(true);
576
+ expect(result.users[0].grants).toBeUndefined();
577
+ expect(result.users[0].roles).toBeUndefined();
578
+ });
150
579
 
151
- const tool = tools.find(t => t.name === 'mysql_security_firewall_status');
152
- const result = await tool?.handler({}, mockContext) as any;
580
+ it("should return exists:false for nonexistent user (P154)", async () => {
581
+ // P154 pre-check returns empty
582
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
583
+
584
+ const tool = tools.find(
585
+ (t) => t.name === "mysql_security_user_privileges",
586
+ );
587
+ const result = (await tool?.handler(
588
+ { user: "nonexistent_user" },
589
+ mockContext,
590
+ )) as any;
591
+
592
+ expect(result.exists).toBe(false);
593
+ expect(result.user).toBe("nonexistent_user");
594
+ expect(result.users).toBeUndefined();
595
+ });
596
+ });
597
+
598
+ describe("mysql_security_sensitive_tables", () => {
599
+ it("should find sensitive columns based on patterns", async () => {
600
+ // P154: Schema existence pre-check
601
+ mockAdapter.executeQuery.mockResolvedValueOnce(
602
+ createMockQueryResult([{ SCHEMA_NAME: "test" }]),
603
+ );
604
+ // COLUMNS query
605
+ mockAdapter.executeQuery.mockResolvedValueOnce(
606
+ createMockQueryResult([
607
+ {
608
+ tableName: "users",
609
+ columnName: "password_hash",
610
+ dataType: "varchar",
611
+ },
612
+ { tableName: "users", columnName: "email", dataType: "varchar" },
613
+ ]),
614
+ );
615
+
616
+ const tool = tools.find(
617
+ (t) => t.name === "mysql_security_sensitive_tables",
618
+ );
619
+ const result = (await tool?.handler(
620
+ { schema: "test" },
621
+ mockContext,
622
+ )) as any;
623
+
624
+ expect(result.tableCount).toBe(1);
625
+ expect(result.sensitiveTables[0].table).toBe("users");
626
+ expect(result.sensitiveTables[0].sensitiveColumns).toHaveLength(2);
627
+ });
153
628
 
154
- expect(result.installed).toBe(false);
155
- expect(result.message).toContain('not installed');
156
- });
629
+ it("should return exists:false for nonexistent schema (P154)", async () => {
630
+ // P154 pre-check returns empty
631
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
632
+
633
+ const tool = tools.find(
634
+ (t) => t.name === "mysql_security_sensitive_tables",
635
+ );
636
+ const result = (await tool?.handler(
637
+ { schema: "nonexistent_schema" },
638
+ mockContext,
639
+ )) as any;
640
+
641
+ expect(result.exists).toBe(false);
642
+ expect(result.schema).toBe("nonexistent_schema");
643
+ expect(result.sensitiveTables).toBeUndefined();
644
+ });
645
+ });
646
+
647
+ describe("mysql_security_encryption_status", () => {
648
+ it("should return encryption status", async () => {
649
+ // Keyring
650
+ mockAdapter.executeQuery.mockResolvedValueOnce(
651
+ createMockQueryResult([
652
+ { PLUGIN_NAME: "keyring_file", PLUGIN_STATUS: "ACTIVE" },
653
+ ]),
654
+ );
655
+ // Tablespaces
656
+ mockAdapter.executeQuery.mockResolvedValueOnce(
657
+ createMockQueryResult([{ NAME: "mysql", ENCRYPTION: "Y" }]),
658
+ );
659
+ // Variables
660
+ mockAdapter.executeQuery.mockResolvedValueOnce(
661
+ createMockQueryResult([
662
+ { Variable_name: "innodb_encryption_threads", Value: "4" },
663
+ ]),
664
+ );
665
+ // InnoDB Vars
666
+ mockAdapter.executeQuery.mockResolvedValueOnce(
667
+ createMockQueryResult([
668
+ { Variable_name: "innodb_redo_log_encrypt", Value: "ON" },
669
+ ]),
670
+ );
671
+
672
+ const tool = tools.find(
673
+ (t) => t.name === "mysql_security_encryption_status",
674
+ );
675
+ const result = (await tool?.handler({}, mockContext)) as any;
676
+
677
+ expect(result.keyringInstalled).toBe(true);
678
+ expect(result.encryptedTablespaceCount).toBe(1);
679
+ expect(result.encryptionSettings.innodb_redo_log_encrypt).toBe("ON");
680
+ });
157
681
 
158
- it('should handle plugin check failure', async () => {
159
- mockAdapter.executeQuery.mockRejectedValue(new Error('DB Error'));
682
+ it("should handle missing keyring", async () => {
683
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
684
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
685
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
686
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
160
687
 
161
- const tool = tools.find(t => t.name === 'mysql_security_firewall_status');
162
- const result = await tool?.handler({}, mockContext) as any;
163
-
164
- expect(result.installed).toBe(false);
165
- expect(result.message).toBe('Firewall plugin check failed');
166
- });
167
- });
168
-
169
- describe('mysql_security_mask_data', () => {
170
- it('should masking email', async () => {
171
- const tool = tools.find(t => t.name === 'mysql_security_mask_data');
172
- const result = await tool?.handler({
173
- value: 'john.doe@example.com',
174
- type: 'email'
175
- }, mockContext) as any;
176
-
177
- expect(result.masked).toBe('j******e@example.com');
178
- });
179
-
180
- it('should mask different types correctly', async () => {
181
- const tool = tools.find(t => t.name === 'mysql_security_mask_data');
182
-
183
- // Email without @
184
- const resNoAt = await tool?.handler({ value: 'invalid-email', type: 'email' }, mockContext) as any;
185
- expect(resNoAt.masked).toBe('*************');
186
-
187
- // Phone
188
- const resPhone = await tool?.handler({ value: '1234567890', type: 'phone' }, mockContext) as any;
189
- expect(resPhone.masked).toBe('******7890');
190
-
191
- // SSN
192
- const resSSN = await tool?.handler({ value: '123456789', type: 'ssn' }, mockContext) as any;
193
- expect(resSSN.masked).toBe('***-**-6789');
194
-
195
- // Credit Card
196
- const resCC = await tool?.handler({ value: '1234567812345678', type: 'credit_card' }, mockContext) as any;
197
- expect(resCC.masked).toBe('1234********5678');
198
-
199
- // Partial
200
- const resPartial = await tool?.handler({ value: 'abcdef', type: 'partial', keepFirst: 2, keepLast: 2 }, mockContext) as any;
201
- expect(resPartial.masked).toBe('ab**ef');
202
-
203
- // Default fallback
204
- // We need to force a type that falls through or just check specific logic
205
- // Since we can't pass invalid enum via Zod, we trust the switch default handles odd input if it could bypass Zod
206
- // But Zod prevents it. However, the switch has a default case.
207
- // Let's assume typescript-eslint doesn't complain about unreachable code if we force it
208
- });
209
-
210
- it('should mask credit card', async () => {
211
- const tool = tools.find(t => t.name === 'mysql_security_mask_data');
212
- const result = await tool?.handler({
213
- value: '1234-5678-9012-3456',
214
- type: 'credit_card'
215
- }, mockContext) as any;
216
-
217
- expect(result.masked).toBe('1234********3456');
218
- });
219
- });
220
-
221
- describe('mysql_security_password_validate', () => {
222
- it('should return password strength', async () => {
223
- // VALIDATE_PASSWORD_STRENGTH
224
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
225
- { strength: 100 }
226
- ]));
227
- // Variables
228
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
229
- { Variable_name: 'policy', Value: 'STRONG' }
230
- ]));
231
-
232
- const tool = tools.find(t => t.name === 'mysql_security_password_validate');
233
- const result = await tool?.handler({ password: 'StrongPassword123!' }, mockContext) as any;
234
-
235
- expect(result.strength).toBe(100);
236
- expect(result.interpretation).toBe('Very Strong');
237
- expect(result.policy).toHaveProperty('policy', 'STRONG');
238
- });
239
-
240
- it('should handle different password strengths', async () => {
241
- // Strong
242
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ strength: 75 }]));
243
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
244
- const tool = tools.find(t => t.name === 'mysql_security_password_validate');
245
- const resultStrong = await tool?.handler({ password: 'Strong1' }, mockContext) as any;
246
- expect(resultStrong.interpretation).toBe('Strong');
247
-
248
- // Medium
249
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ strength: 50 }]));
250
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
251
- const resultMedium = await tool?.handler({ password: 'Medium1' }, mockContext) as any;
252
- expect(resultMedium.interpretation).toBe('Medium');
253
-
254
- // Weak
255
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ strength: 25 }]));
256
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
257
- const resultWeak = await tool?.handler({ password: 'Weak1' }, mockContext) as any;
258
- expect(resultWeak.interpretation).toBe('Weak');
259
-
260
- // Very Weak
261
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([{ strength: 0 }]));
262
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
263
- const resultVeryWeak = await tool?.handler({ password: 'VeryWeak' }, mockContext) as any;
264
- expect(resultVeryWeak.interpretation).toBe('Very Weak');
265
- });
266
-
267
- it('should handle validation component missing', async () => {
268
- mockAdapter.executeQuery.mockRejectedValue(new Error('Function not found'));
269
-
270
- const tool = tools.find(t => t.name === 'mysql_security_password_validate');
271
- const result = await tool?.handler({ password: 'test' }, mockContext) as any;
272
-
273
- expect(result.available).toBe(false);
274
- expect(result.message).toContain('not installed');
275
- });
276
- });
277
-
278
- describe('mysql_security_ssl_status', () => {
279
- it('should return ssl status', async () => {
280
- // Status
281
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
282
- { Variable_name: 'Ssl_cipher', Value: 'AES256-SHA' },
283
- { Variable_name: 'Ssl_version', Value: 'TLSv1.3' }
284
- ]));
285
- // Variables
286
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
287
- { Variable_name: 'ssl_ca', Value: 'ca.pem' }
288
- ]));
289
- // Connection
290
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
291
- { cipher: 'AES256-SHA', verifyCert: 1 }
292
- ]));
293
-
294
- const tool = tools.find(t => t.name === 'mysql_security_ssl_status');
295
- const result = await tool?.handler({}, mockContext) as any;
296
-
297
- expect(result.sslEnabled).toBe(true);
298
- expect(result.currentCipher).toBe('AES256-SHA');
299
- expect(result.configuration.sslCa).toBe('ca.pem');
300
- });
301
-
302
- it('should handle undefined values gracefully', async () => {
303
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
304
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
305
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
306
-
307
- const tool = tools.find(t => t.name === 'mysql_security_ssl_status');
308
- const result = await tool?.handler({}, mockContext) as any;
309
-
310
- expect(result.sslEnabled).toBe(false);
311
- expect(result.currentCipher).toBe('None');
312
- });
313
- });
314
-
315
- describe('mysql_security_user_privileges', () => {
316
- it('should return comprehensive user report', async () => {
317
- // mysql.user
318
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
319
- { User: 'root', Host: 'localhost', plugin: 'caching_sha2_password', account_locked: 'N' }
320
- ]));
321
- // SHOW GRANTS
322
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
323
- { 'Grants for root@localhost': 'GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost`' }
324
- ]));
325
- // Role edges
326
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
327
-
328
- const tool = tools.find(t => t.name === 'mysql_security_user_privileges');
329
- const result = await tool?.handler({}, mockContext) as any;
330
-
331
- expect(result.count).toBe(1);
332
- expect(result.users[0].user).toBe('root');
333
- expect(result.users[0].grants).toHaveLength(1);
334
- });
335
-
336
- it('should include roles if requested', async () => {
337
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
338
- { User: 'root', Host: 'localhost' }
339
- ]));
340
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
341
- { 'Grants': 'GRANT...' }
342
- ]));
343
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
344
- { FROM_USER: 'app_role', FROM_HOST: '%' }
345
- ]));
346
-
347
- const tool = tools.find(t => t.name === 'mysql_security_user_privileges');
348
- const result = await tool?.handler({ user: 'root', includeRoles: true }, mockContext) as any;
349
-
350
- expect(result.users[0].roles).toContain('app_role@%');
351
- });
352
-
353
- it('should filter by specific host', async () => {
354
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
355
-
356
- const tool = tools.find(t => t.name === 'mysql_security_user_privileges');
357
- await tool?.handler({ host: '127.0.0.1' }, mockContext);
358
-
359
- const call = mockAdapter.executeQuery.mock.calls[0][0] as string;
360
- expect(call).toContain('Host = ?');
361
- });
362
- });
363
-
364
- describe('mysql_security_sensitive_tables', () => {
365
- it('should find sensitive columns based on patterns', async () => {
366
- // COLUMNS query
367
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
368
- { tableName: 'users', columnName: 'password_hash', dataType: 'varchar' },
369
- { tableName: 'users', columnName: 'email', dataType: 'varchar' }
370
- ]));
371
-
372
- const tool = tools.find(t => t.name === 'mysql_security_sensitive_tables');
373
- const result = await tool?.handler({ schema: 'test' }, mockContext) as any;
374
-
375
- expect(result.tableCount).toBe(1);
376
- expect(result.sensitiveTables[0].table).toBe('users');
377
- expect(result.sensitiveTables[0].sensitiveColumns).toHaveLength(2);
378
- });
379
- });
380
-
381
- describe('mysql_security_encryption_status', () => {
382
- it('should return encryption status', async () => {
383
- // Keyring
384
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
385
- { PLUGIN_NAME: 'keyring_file', PLUGIN_STATUS: 'ACTIVE' }
386
- ]));
387
- // Tablespaces
388
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
389
- { NAME: 'mysql', ENCRYPTION: 'Y' }
390
- ]));
391
- // Variables
392
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
393
- { Variable_name: 'innodb_encryption_threads', Value: '4' }
394
- ]));
395
- // InnoDB Vars
396
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
397
- { Variable_name: 'innodb_redo_log_encrypt', Value: 'ON' }
398
- ]));
399
-
400
- const tool = tools.find(t => t.name === 'mysql_security_encryption_status');
401
- const result = await tool?.handler({}, mockContext) as any;
402
-
403
- expect(result.keyringInstalled).toBe(true);
404
- expect(result.encryptedTablespaceCount).toBe(1);
405
- expect(result.encryptionSettings.innodb_redo_log_encrypt).toBe('ON');
406
- });
407
-
408
- it('should handle missing keyring', async () => {
409
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
410
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
411
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
412
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
413
-
414
- const tool = tools.find(t => t.name === 'mysql_security_encryption_status');
415
- const result = await tool?.handler({}, mockContext) as any;
416
-
417
- expect(result.keyringInstalled).toBe(false);
418
- expect(result.tdeAvailable).toBe(false);
419
- });
420
- });
421
-
422
- describe('mysql_security_ssl_status (Edge Cases)', () => {
423
- it('should handle partial data in ssl status', async () => {
424
- // Status with some missing/malformed rows
425
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
426
- { Variable_name: 'Ssl_cipher', Value: 'AES256-SHA' },
427
- { Variable_name: 123, Value: 'invalid' } // Invalid variable name
428
- ]));
429
- // Variables (undefined rows)
430
- mockAdapter.executeQuery.mockResolvedValueOnce({ rows: undefined } as any);
431
- // Connection
432
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
433
-
434
- const tool = tools.find(t => t.name === 'mysql_security_ssl_status');
435
- const result = await tool?.handler({}, mockContext) as any;
436
-
437
- expect(result.sslEnabled).toBe(true);
438
- expect(result.configuration.sslCa).toBe('');
439
- expect(result.serverCertVerification).toBe(false);
440
- });
441
- });
442
-
443
- describe('mysql_security_encryption_status (Edge Cases)', () => {
444
- it('should handle partial data in encryption status', async () => {
445
- // Keyring
446
- mockAdapter.executeQuery.mockResolvedValueOnce({ rows: undefined } as any);
447
- // Tablespaces
448
- mockAdapter.executeQuery.mockResolvedValueOnce({ rows: undefined } as any);
449
- // Variables with invalid names
450
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
451
- { Variable_name: 123, Value: 'invalid' }
452
- ]));
453
- // InnoDB Vars with invalid names
454
- mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([
455
- { Variable_name: 123, Value: 'invalid' }
456
- ]));
457
-
458
- const tool = tools.find(t => t.name === 'mysql_security_encryption_status');
459
- const result = await tool?.handler({}, mockContext) as any;
460
-
461
- expect(result.keyringInstalled).toBe(false);
462
- expect(result.encryptedTablespaceCount).toBe(0);
463
- expect(result.encryptionSettings).toEqual({ '': 'invalid' });
464
- });
688
+ const tool = tools.find(
689
+ (t) => t.name === "mysql_security_encryption_status",
690
+ );
691
+ const result = (await tool?.handler({}, mockContext)) as any;
692
+
693
+ expect(result.keyringInstalled).toBe(false);
694
+ expect(result.tdeAvailable).toBe(false);
695
+ });
696
+ });
697
+
698
+ describe("mysql_security_ssl_status (Edge Cases)", () => {
699
+ it("should handle partial data in ssl status", async () => {
700
+ // Status with some missing/malformed rows
701
+ mockAdapter.executeQuery.mockResolvedValueOnce(
702
+ createMockQueryResult([
703
+ { Variable_name: "Ssl_cipher", Value: "AES256-SHA" },
704
+ { Variable_name: 123, Value: "invalid" }, // Invalid variable name
705
+ ]),
706
+ );
707
+ // Variables (undefined rows)
708
+ mockAdapter.executeQuery.mockResolvedValueOnce({
709
+ rows: undefined,
710
+ } as any);
711
+ // Connection
712
+ mockAdapter.executeQuery.mockResolvedValueOnce(createMockQueryResult([]));
713
+
714
+ const tool = tools.find((t) => t.name === "mysql_security_ssl_status");
715
+ const result = (await tool?.handler({}, mockContext)) as any;
716
+
717
+ expect(result.sslEnabled).toBe(true);
718
+ expect(result.configuration.sslCa).toBe("");
719
+ expect(result.serverCertVerification).toBe(false);
720
+ });
721
+ });
722
+
723
+ describe("mysql_security_encryption_status (Edge Cases)", () => {
724
+ it("should handle partial data in encryption status", async () => {
725
+ // Keyring
726
+ mockAdapter.executeQuery.mockResolvedValueOnce({
727
+ rows: undefined,
728
+ } as any);
729
+ // Tablespaces
730
+ mockAdapter.executeQuery.mockResolvedValueOnce({
731
+ rows: undefined,
732
+ } as any);
733
+ // Variables with invalid names
734
+ mockAdapter.executeQuery.mockResolvedValueOnce(
735
+ createMockQueryResult([{ Variable_name: 123, Value: "invalid" }]),
736
+ );
737
+ // InnoDB Vars with invalid names
738
+ mockAdapter.executeQuery.mockResolvedValueOnce(
739
+ createMockQueryResult([{ Variable_name: 123, Value: "invalid" }]),
740
+ );
741
+
742
+ const tool = tools.find(
743
+ (t) => t.name === "mysql_security_encryption_status",
744
+ );
745
+ const result = (await tool?.handler({}, mockContext)) as any;
746
+
747
+ expect(result.keyringInstalled).toBe(false);
748
+ expect(result.encryptedTablespaceCount).toBe(0);
749
+ expect(result.encryptionSettings).toEqual({ "": "invalid" });
465
750
  });
751
+ });
466
752
  });