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