@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
|
@@ -5,13 +5,22 @@
|
|
|
5
5
|
* 3 tools: schema_stats, innodb_lock_waits, memory_summary.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { z } from "zod";
|
|
8
|
+
import { z, ZodError } from "zod";
|
|
9
9
|
import type { MySQLAdapter } from "../../MySQLAdapter.js";
|
|
10
10
|
import type {
|
|
11
11
|
ToolDefinition,
|
|
12
12
|
RequestContext,
|
|
13
13
|
} from "../../../../types/index.js";
|
|
14
14
|
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Helpers
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
/** Extract human-readable messages from a ZodError instead of raw JSON array */
|
|
20
|
+
function formatZodError(error: ZodError): string {
|
|
21
|
+
return error.issues.map((i) => i.message).join("; ");
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
// =============================================================================
|
|
16
25
|
// Zod Schemas
|
|
17
26
|
// =============================================================================
|
|
@@ -45,35 +54,41 @@ export function createSysSchemaStatsTool(
|
|
|
45
54
|
idempotentHint: true,
|
|
46
55
|
},
|
|
47
56
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
try {
|
|
58
|
+
const { schema, limit } = z
|
|
59
|
+
.object({
|
|
60
|
+
schema: z.string().optional(),
|
|
61
|
+
limit: z.number().default(10),
|
|
62
|
+
})
|
|
63
|
+
.parse(params);
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
// P154: Schema existence check when explicitly provided
|
|
66
|
+
if (schema) {
|
|
67
|
+
const schemaCheck = await adapter.executeQuery(
|
|
68
|
+
"SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ?",
|
|
69
|
+
[schema],
|
|
70
|
+
);
|
|
71
|
+
if (!schemaCheck.rows || schemaCheck.rows.length === 0) {
|
|
72
|
+
return {
|
|
73
|
+
success: false,
|
|
74
|
+
error: `Schema '${schema}' does not exist`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
63
77
|
}
|
|
64
|
-
}
|
|
65
78
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
// Resolve actual database name for response
|
|
80
|
+
let resolvedSchema = schema;
|
|
81
|
+
if (!resolvedSchema) {
|
|
82
|
+
const dbResult = await adapter.executeQuery(
|
|
83
|
+
"SELECT DATABASE() as db",
|
|
84
|
+
);
|
|
85
|
+
const rows = dbResult.rows ?? [];
|
|
86
|
+
const dbRow = rows[0] as Record<string, unknown> | undefined;
|
|
87
|
+
resolvedSchema = (dbRow?.["db"] as string) ?? "unknown";
|
|
88
|
+
}
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
// Get table statistics
|
|
91
|
+
const tableStatsQuery = `
|
|
77
92
|
SELECT
|
|
78
93
|
table_schema,
|
|
79
94
|
table_name,
|
|
@@ -97,8 +112,8 @@ export function createSysSchemaStatsTool(
|
|
|
97
112
|
LIMIT ${String(limit)}
|
|
98
113
|
`;
|
|
99
114
|
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
// Get index statistics
|
|
116
|
+
const indexStatsQuery = `
|
|
102
117
|
SELECT
|
|
103
118
|
table_schema,
|
|
104
119
|
table_name,
|
|
@@ -117,8 +132,8 @@ export function createSysSchemaStatsTool(
|
|
|
117
132
|
LIMIT ${String(limit)}
|
|
118
133
|
`;
|
|
119
134
|
|
|
120
|
-
|
|
121
|
-
|
|
135
|
+
// Get auto-increment status
|
|
136
|
+
const autoIncQuery = `
|
|
122
137
|
SELECT
|
|
123
138
|
table_schema,
|
|
124
139
|
table_name,
|
|
@@ -132,21 +147,28 @@ export function createSysSchemaStatsTool(
|
|
|
132
147
|
LIMIT ${String(limit)}
|
|
133
148
|
`;
|
|
134
149
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
150
|
+
const [tableStats, indexStats, autoIncStats] = await Promise.all([
|
|
151
|
+
adapter.executeQuery(tableStatsQuery, [schema ?? null]),
|
|
152
|
+
adapter.executeQuery(indexStatsQuery, [schema ?? null]),
|
|
153
|
+
adapter.executeQuery(autoIncQuery, [schema ?? null]),
|
|
154
|
+
]);
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
return {
|
|
157
|
+
tableStatistics: tableStats.rows ?? [],
|
|
158
|
+
indexStatistics: indexStats.rows ?? [],
|
|
159
|
+
autoIncrementStatus: autoIncStats.rows ?? [],
|
|
160
|
+
tableStatisticsCount: (tableStats.rows ?? []).length,
|
|
161
|
+
indexStatisticsCount: (indexStats.rows ?? []).length,
|
|
162
|
+
autoIncrementStatusCount: (autoIncStats.rows ?? []).length,
|
|
163
|
+
schemaName: resolvedSchema,
|
|
164
|
+
};
|
|
165
|
+
} catch (error) {
|
|
166
|
+
if (error instanceof ZodError) {
|
|
167
|
+
return { success: false, error: formatZodError(error) };
|
|
168
|
+
}
|
|
169
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
170
|
+
return { success: false, error: message };
|
|
171
|
+
}
|
|
150
172
|
},
|
|
151
173
|
};
|
|
152
174
|
}
|
|
@@ -170,9 +192,10 @@ export function createSysInnoDBLockWaitsTool(
|
|
|
170
192
|
idempotentHint: true,
|
|
171
193
|
},
|
|
172
194
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
173
|
-
|
|
195
|
+
try {
|
|
196
|
+
const { limit } = LimitSchema.parse(params);
|
|
174
197
|
|
|
175
|
-
|
|
198
|
+
const query = `
|
|
176
199
|
SELECT
|
|
177
200
|
wait_started,
|
|
178
201
|
wait_age,
|
|
@@ -198,12 +221,19 @@ export function createSysInnoDBLockWaitsTool(
|
|
|
198
221
|
LIMIT ${String(limit)}
|
|
199
222
|
`;
|
|
200
223
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
224
|
+
const result = await adapter.executeQuery(query);
|
|
225
|
+
return {
|
|
226
|
+
lockWaits: result.rows,
|
|
227
|
+
count: result.rows?.length ?? 0,
|
|
228
|
+
hasContention: (result.rows?.length ?? 0) > 0,
|
|
229
|
+
};
|
|
230
|
+
} catch (error) {
|
|
231
|
+
if (error instanceof ZodError) {
|
|
232
|
+
return { success: false, error: formatZodError(error) };
|
|
233
|
+
}
|
|
234
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
235
|
+
return { success: false, error: message };
|
|
236
|
+
}
|
|
207
237
|
},
|
|
208
238
|
};
|
|
209
239
|
}
|
|
@@ -226,10 +256,11 @@ export function createSysMemorySummaryTool(
|
|
|
226
256
|
idempotentHint: true,
|
|
227
257
|
},
|
|
228
258
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
229
|
-
|
|
259
|
+
try {
|
|
260
|
+
const { limit } = LimitSchema.parse(params);
|
|
230
261
|
|
|
231
|
-
|
|
232
|
-
|
|
262
|
+
// Global memory summary
|
|
263
|
+
const globalQuery = `
|
|
233
264
|
SELECT
|
|
234
265
|
event_name,
|
|
235
266
|
current_count,
|
|
@@ -243,8 +274,8 @@ export function createSysMemorySummaryTool(
|
|
|
243
274
|
LIMIT ${String(limit)}
|
|
244
275
|
`;
|
|
245
276
|
|
|
246
|
-
|
|
247
|
-
|
|
277
|
+
// Memory by user
|
|
278
|
+
const userQuery = `
|
|
248
279
|
SELECT
|
|
249
280
|
user,
|
|
250
281
|
current_count_used,
|
|
@@ -257,17 +288,24 @@ export function createSysMemorySummaryTool(
|
|
|
257
288
|
LIMIT ${String(limit)}
|
|
258
289
|
`;
|
|
259
290
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
291
|
+
const [globalStats, userStats] = await Promise.all([
|
|
292
|
+
adapter.executeQuery(globalQuery),
|
|
293
|
+
adapter.executeQuery(userQuery),
|
|
294
|
+
]);
|
|
264
295
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
296
|
+
return {
|
|
297
|
+
globalMemory: globalStats.rows ?? [],
|
|
298
|
+
memoryByUser: userStats.rows ?? [],
|
|
299
|
+
globalMemoryCount: (globalStats.rows ?? []).length,
|
|
300
|
+
memoryByUserCount: (userStats.rows ?? []).length,
|
|
301
|
+
};
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error instanceof ZodError) {
|
|
304
|
+
return { success: false, error: formatZodError(error) };
|
|
305
|
+
}
|
|
306
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
307
|
+
return { success: false, error: message };
|
|
308
|
+
}
|
|
271
309
|
},
|
|
272
310
|
};
|
|
273
311
|
}
|
|
@@ -93,14 +93,14 @@ describe("Text Fulltext Tools", () => {
|
|
|
93
93
|
indexName: "ft_idx",
|
|
94
94
|
},
|
|
95
95
|
mockContext,
|
|
96
|
-
)) as { success: boolean;
|
|
96
|
+
)) as { success: boolean; error: string };
|
|
97
97
|
|
|
98
98
|
expect(result.success).toBe(false);
|
|
99
|
-
expect(result.
|
|
100
|
-
expect(result.
|
|
99
|
+
expect(result.error).toContain("already exists");
|
|
100
|
+
expect(result.error).toContain("ft_idx");
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
it("should
|
|
103
|
+
it("should return structured error for non-duplicate errors", async () => {
|
|
104
104
|
mockAdapter.executeQuery.mockRejectedValue(
|
|
105
105
|
new Error("Connection refused"),
|
|
106
106
|
);
|
|
@@ -108,12 +108,36 @@ describe("Text Fulltext Tools", () => {
|
|
|
108
108
|
const tool = createFulltextCreateTool(
|
|
109
109
|
mockAdapter as unknown as MySQLAdapter,
|
|
110
110
|
);
|
|
111
|
-
await
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
).
|
|
111
|
+
const result = (await tool.handler(
|
|
112
|
+
{ table: "articles", columns: ["title"], indexName: "ft_idx" },
|
|
113
|
+
mockContext,
|
|
114
|
+
)) as { success: boolean; error: string };
|
|
115
|
+
|
|
116
|
+
expect(result.success).toBe(false);
|
|
117
|
+
expect(result.error).toContain("Connection refused");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("should return structured error for nonexistent column", async () => {
|
|
121
|
+
const colError = new Error(
|
|
122
|
+
"Key column 'nonexistent_col' doesn't exist in table",
|
|
123
|
+
);
|
|
124
|
+
(colError as Error & { errno?: number }).errno = 1072;
|
|
125
|
+
mockAdapter.executeQuery.mockRejectedValue(colError);
|
|
126
|
+
|
|
127
|
+
const tool = createFulltextCreateTool(
|
|
128
|
+
mockAdapter as unknown as MySQLAdapter,
|
|
129
|
+
);
|
|
130
|
+
const result = (await tool.handler(
|
|
131
|
+
{
|
|
132
|
+
table: "articles",
|
|
133
|
+
columns: ["nonexistent_col"],
|
|
134
|
+
indexName: "ft_idx",
|
|
135
|
+
},
|
|
136
|
+
mockContext,
|
|
137
|
+
)) as { success: boolean; error: string };
|
|
138
|
+
|
|
139
|
+
expect(result.success).toBe(false);
|
|
140
|
+
expect(result.error).toContain("Key column");
|
|
117
141
|
});
|
|
118
142
|
|
|
119
143
|
it("should return exists:false for nonexistent table", async () => {
|
|
@@ -170,22 +194,26 @@ describe("Text Fulltext Tools", () => {
|
|
|
170
194
|
const result = (await tool.handler(
|
|
171
195
|
{ table: "articles", indexName: "ft_nonexistent" },
|
|
172
196
|
mockContext,
|
|
173
|
-
)) as { success: boolean;
|
|
197
|
+
)) as { success: boolean; error: string };
|
|
174
198
|
|
|
175
199
|
expect(result.success).toBe(false);
|
|
176
|
-
expect(result.
|
|
177
|
-
expect(result.
|
|
200
|
+
expect(result.error).toContain("does not exist");
|
|
201
|
+
expect(result.error).toContain("ft_nonexistent");
|
|
178
202
|
});
|
|
179
203
|
|
|
180
|
-
it("should
|
|
204
|
+
it("should return structured error for non-drop errors", async () => {
|
|
181
205
|
mockAdapter.executeQuery.mockRejectedValue(new Error("Access denied"));
|
|
182
206
|
|
|
183
207
|
const tool = createFulltextDropTool(
|
|
184
208
|
mockAdapter as unknown as MySQLAdapter,
|
|
185
209
|
);
|
|
186
|
-
await
|
|
187
|
-
|
|
188
|
-
|
|
210
|
+
const result = (await tool.handler(
|
|
211
|
+
{ table: "articles", indexName: "ft_idx" },
|
|
212
|
+
mockContext,
|
|
213
|
+
)) as { success: boolean; error: string };
|
|
214
|
+
|
|
215
|
+
expect(result.success).toBe(false);
|
|
216
|
+
expect(result.error).toContain("Access denied");
|
|
189
217
|
});
|
|
190
218
|
|
|
191
219
|
it("should return exists:false for nonexistent table", async () => {
|
|
@@ -15,6 +15,12 @@ import {
|
|
|
15
15
|
FulltextCreateSchemaBase,
|
|
16
16
|
FulltextSearchSchema,
|
|
17
17
|
FulltextSearchSchemaBase,
|
|
18
|
+
FulltextDropSchema,
|
|
19
|
+
FulltextDropSchemaBase,
|
|
20
|
+
FulltextBooleanSchema,
|
|
21
|
+
FulltextBooleanSchemaBase,
|
|
22
|
+
FulltextExpandSchema,
|
|
23
|
+
FulltextExpandSchemaBase,
|
|
18
24
|
} from "../../types.js";
|
|
19
25
|
import { z } from "zod";
|
|
20
26
|
import {
|
|
@@ -99,33 +105,37 @@ export function createFulltextCreateTool(
|
|
|
99
105
|
if (isDuplicateKeyError(err)) {
|
|
100
106
|
return {
|
|
101
107
|
success: false,
|
|
102
|
-
|
|
108
|
+
error: `Index '${name}' already exists on table '${table}'`,
|
|
103
109
|
};
|
|
104
110
|
}
|
|
105
111
|
const msg = err instanceof Error ? err.message : String(err);
|
|
112
|
+
// Distinguish column-not-found (errno 1072) from table-not-found
|
|
113
|
+
if (
|
|
114
|
+
(err as Error & { errno?: number }).errno === 1072 ||
|
|
115
|
+
msg.includes("Key column") ||
|
|
116
|
+
msg.includes("Column '")
|
|
117
|
+
) {
|
|
118
|
+
return { success: false, error: msg };
|
|
119
|
+
}
|
|
106
120
|
if (msg.includes("doesn't exist")) {
|
|
107
121
|
return { exists: false, table };
|
|
108
122
|
}
|
|
109
|
-
|
|
123
|
+
return { success: false, error: msg };
|
|
110
124
|
}
|
|
111
125
|
|
|
126
|
+
adapter.clearSchemaCache();
|
|
112
127
|
return { success: true, indexName: name, columns };
|
|
113
128
|
},
|
|
114
129
|
};
|
|
115
130
|
}
|
|
116
131
|
|
|
117
|
-
const FulltextDropSchema = z.object({
|
|
118
|
-
table: z.string().describe("Table containing the index"),
|
|
119
|
-
indexName: z.string().describe("Name of the FULLTEXT index to drop"),
|
|
120
|
-
});
|
|
121
|
-
|
|
122
132
|
export function createFulltextDropTool(adapter: MySQLAdapter): ToolDefinition {
|
|
123
133
|
return {
|
|
124
134
|
name: "mysql_fulltext_drop",
|
|
125
135
|
title: "MySQL Drop FULLTEXT Index",
|
|
126
136
|
description: "Drop a FULLTEXT index from a table.",
|
|
127
137
|
group: "fulltext",
|
|
128
|
-
inputSchema:
|
|
138
|
+
inputSchema: FulltextDropSchemaBase,
|
|
129
139
|
requiredScopes: ["write"],
|
|
130
140
|
annotations: {
|
|
131
141
|
readOnlyHint: false,
|
|
@@ -146,16 +156,17 @@ export function createFulltextDropTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
146
156
|
if (isCantDropKeyError(err)) {
|
|
147
157
|
return {
|
|
148
158
|
success: false,
|
|
149
|
-
|
|
159
|
+
error: `Index '${indexName}' does not exist on table '${table}'`,
|
|
150
160
|
};
|
|
151
161
|
}
|
|
152
162
|
const msg = err instanceof Error ? err.message : String(err);
|
|
153
163
|
if (msg.includes("doesn't exist")) {
|
|
154
164
|
return { exists: false, table };
|
|
155
165
|
}
|
|
156
|
-
|
|
166
|
+
return { success: false, error: msg };
|
|
157
167
|
}
|
|
158
168
|
|
|
169
|
+
adapter.clearSchemaCache();
|
|
159
170
|
return { success: true, indexName, table };
|
|
160
171
|
},
|
|
161
172
|
};
|
|
@@ -232,32 +243,21 @@ export function createFulltextSearchTool(
|
|
|
232
243
|
export function createFulltextBooleanTool(
|
|
233
244
|
adapter: MySQLAdapter,
|
|
234
245
|
): ToolDefinition {
|
|
235
|
-
const schema = z.object({
|
|
236
|
-
table: z.string(),
|
|
237
|
-
columns: z.array(z.string()),
|
|
238
|
-
query: z.string().describe("Boolean search query with +, -, *, etc."),
|
|
239
|
-
maxLength: z
|
|
240
|
-
.number()
|
|
241
|
-
.optional()
|
|
242
|
-
.describe(
|
|
243
|
-
"Optional max characters per text column in results. Truncates with '...' if exceeded.",
|
|
244
|
-
),
|
|
245
|
-
});
|
|
246
|
-
|
|
247
246
|
return {
|
|
248
247
|
name: "mysql_fulltext_boolean",
|
|
249
248
|
title: "MySQL FULLTEXT Boolean",
|
|
250
249
|
description:
|
|
251
250
|
"Perform FULLTEXT search in BOOLEAN MODE with operators (+, -, *, etc.).",
|
|
252
251
|
group: "fulltext",
|
|
253
|
-
inputSchema:
|
|
252
|
+
inputSchema: FulltextBooleanSchemaBase,
|
|
254
253
|
requiredScopes: ["read"],
|
|
255
254
|
annotations: {
|
|
256
255
|
readOnlyHint: true,
|
|
257
256
|
idempotentHint: true,
|
|
258
257
|
},
|
|
259
258
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
260
|
-
const { table, columns, query, maxLength } =
|
|
259
|
+
const { table, columns, query, maxLength } =
|
|
260
|
+
FulltextBooleanSchema.parse(params);
|
|
261
261
|
|
|
262
262
|
// Validate inputs
|
|
263
263
|
validateQualifiedIdentifier(table, "table");
|
|
@@ -289,32 +289,21 @@ export function createFulltextBooleanTool(
|
|
|
289
289
|
export function createFulltextExpandTool(
|
|
290
290
|
adapter: MySQLAdapter,
|
|
291
291
|
): ToolDefinition {
|
|
292
|
-
const schema = z.object({
|
|
293
|
-
table: z.string(),
|
|
294
|
-
columns: z.array(z.string()),
|
|
295
|
-
query: z.string().describe("Search query to expand"),
|
|
296
|
-
maxLength: z
|
|
297
|
-
.number()
|
|
298
|
-
.optional()
|
|
299
|
-
.describe(
|
|
300
|
-
"Optional max characters per text column in results. Truncates with '...' if exceeded.",
|
|
301
|
-
),
|
|
302
|
-
});
|
|
303
|
-
|
|
304
292
|
return {
|
|
305
293
|
name: "mysql_fulltext_expand",
|
|
306
294
|
title: "MySQL FULLTEXT Expand",
|
|
307
295
|
description:
|
|
308
296
|
"Perform FULLTEXT search WITH QUERY EXPANSION for finding related terms.",
|
|
309
297
|
group: "fulltext",
|
|
310
|
-
inputSchema:
|
|
298
|
+
inputSchema: FulltextExpandSchemaBase,
|
|
311
299
|
requiredScopes: ["read"],
|
|
312
300
|
annotations: {
|
|
313
301
|
readOnlyHint: true,
|
|
314
302
|
idempotentHint: true,
|
|
315
303
|
},
|
|
316
304
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
317
|
-
const { table, columns, query, maxLength } =
|
|
305
|
+
const { table, columns, query, maxLength } =
|
|
306
|
+
FulltextExpandSchema.parse(params);
|
|
318
307
|
|
|
319
308
|
// Validate inputs
|
|
320
309
|
validateQualifiedIdentifier(table, "table");
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import type { MySQLAdapter } from "../MySQLAdapter.js";
|
|
9
9
|
import type { ToolDefinition, RequestContext } from "../../../types/index.js";
|
|
10
|
+
import { ZodError } from "zod";
|
|
10
11
|
import {
|
|
11
12
|
TransactionBeginSchema,
|
|
13
|
+
TransactionBeginSchemaBase,
|
|
12
14
|
TransactionIdSchema,
|
|
13
15
|
TransactionIdSchemaBase,
|
|
14
16
|
TransactionSavepointSchema,
|
|
@@ -17,6 +19,11 @@ import {
|
|
|
17
19
|
TransactionExecuteSchemaBase,
|
|
18
20
|
} from "../types.js";
|
|
19
21
|
|
|
22
|
+
/** Extract human-readable messages from a ZodError instead of raw JSON array */
|
|
23
|
+
function formatZodError(error: ZodError): string {
|
|
24
|
+
return error.issues.map((i) => i.message).join("; ");
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
/**
|
|
21
28
|
* Get all transaction tools
|
|
22
29
|
*/
|
|
@@ -42,20 +49,28 @@ function createTransactionBeginTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
42
49
|
description:
|
|
43
50
|
"Begin a new transaction with optional isolation level. Returns a transaction ID for subsequent operations.",
|
|
44
51
|
group: "transactions",
|
|
45
|
-
inputSchema:
|
|
52
|
+
inputSchema: TransactionBeginSchemaBase,
|
|
46
53
|
requiredScopes: ["write"],
|
|
47
54
|
annotations: {
|
|
48
55
|
readOnlyHint: false,
|
|
49
56
|
},
|
|
50
57
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
try {
|
|
59
|
+
const { isolationLevel } = TransactionBeginSchema.parse(params);
|
|
60
|
+
const transactionId = await adapter.beginTransaction(isolationLevel);
|
|
61
|
+
return {
|
|
62
|
+
transactionId,
|
|
63
|
+
isolationLevel: isolationLevel ?? "REPEATABLE READ (default)",
|
|
64
|
+
message:
|
|
65
|
+
"Transaction started. Use transactionId for commit/rollback operations.",
|
|
66
|
+
};
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error instanceof ZodError) {
|
|
69
|
+
return { success: false, error: formatZodError(error) };
|
|
70
|
+
}
|
|
71
|
+
const msg = String(error instanceof Error ? error.message : error);
|
|
72
|
+
return { success: false, error: msg };
|
|
73
|
+
}
|
|
59
74
|
},
|
|
60
75
|
};
|
|
61
76
|
}
|
|
@@ -85,7 +100,7 @@ function createTransactionCommitTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
85
100
|
};
|
|
86
101
|
} catch (error) {
|
|
87
102
|
const msg = String(error instanceof Error ? error.message : error);
|
|
88
|
-
return { success: false,
|
|
103
|
+
return { success: false, error: msg };
|
|
89
104
|
}
|
|
90
105
|
},
|
|
91
106
|
};
|
|
@@ -116,7 +131,7 @@ function createTransactionRollbackTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
116
131
|
};
|
|
117
132
|
} catch (error) {
|
|
118
133
|
const msg = String(error instanceof Error ? error.message : error);
|
|
119
|
-
return { success: false,
|
|
134
|
+
return { success: false, error: msg };
|
|
120
135
|
}
|
|
121
136
|
},
|
|
122
137
|
};
|
|
@@ -145,13 +160,13 @@ function createTransactionSavepointTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
145
160
|
if (!connection) {
|
|
146
161
|
return {
|
|
147
162
|
success: false,
|
|
148
|
-
|
|
163
|
+
error: `Transaction not found: ${transactionId}`,
|
|
149
164
|
};
|
|
150
165
|
}
|
|
151
166
|
|
|
152
167
|
// Validate savepoint name
|
|
153
168
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(savepoint)) {
|
|
154
|
-
return { success: false,
|
|
169
|
+
return { success: false, error: "Invalid savepoint name" };
|
|
155
170
|
}
|
|
156
171
|
|
|
157
172
|
try {
|
|
@@ -160,7 +175,7 @@ function createTransactionSavepointTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
160
175
|
return { success: true, transactionId, savepoint };
|
|
161
176
|
} catch (error) {
|
|
162
177
|
const msg = String(error instanceof Error ? error.message : error);
|
|
163
|
-
return { success: false,
|
|
178
|
+
return { success: false, error: msg };
|
|
164
179
|
}
|
|
165
180
|
},
|
|
166
181
|
};
|
|
@@ -188,12 +203,12 @@ function createTransactionReleaseTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
188
203
|
if (!connection) {
|
|
189
204
|
return {
|
|
190
205
|
success: false,
|
|
191
|
-
|
|
206
|
+
error: `Transaction not found: ${transactionId}`,
|
|
192
207
|
};
|
|
193
208
|
}
|
|
194
209
|
|
|
195
210
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(savepoint)) {
|
|
196
|
-
return { success: false,
|
|
211
|
+
return { success: false, error: "Invalid savepoint name" };
|
|
197
212
|
}
|
|
198
213
|
|
|
199
214
|
try {
|
|
@@ -207,7 +222,7 @@ function createTransactionReleaseTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
207
222
|
};
|
|
208
223
|
} catch (error) {
|
|
209
224
|
const msg = String(error instanceof Error ? error.message : error);
|
|
210
|
-
return { success: false,
|
|
225
|
+
return { success: false, error: msg };
|
|
211
226
|
}
|
|
212
227
|
},
|
|
213
228
|
};
|
|
@@ -237,12 +252,12 @@ function createTransactionRollbackToTool(
|
|
|
237
252
|
if (!connection) {
|
|
238
253
|
return {
|
|
239
254
|
success: false,
|
|
240
|
-
|
|
255
|
+
error: `Transaction not found: ${transactionId}`,
|
|
241
256
|
};
|
|
242
257
|
}
|
|
243
258
|
|
|
244
259
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(savepoint)) {
|
|
245
|
-
return { success: false,
|
|
260
|
+
return { success: false, error: "Invalid savepoint name" };
|
|
246
261
|
}
|
|
247
262
|
|
|
248
263
|
try {
|
|
@@ -256,7 +271,7 @@ function createTransactionRollbackToTool(
|
|
|
256
271
|
};
|
|
257
272
|
} catch (error) {
|
|
258
273
|
const msg = String(error instanceof Error ? error.message : error);
|
|
259
|
-
return { success: false,
|
|
274
|
+
return { success: false, error: msg };
|
|
260
275
|
}
|
|
261
276
|
},
|
|
262
277
|
};
|
|
@@ -278,13 +293,23 @@ function createTransactionExecuteTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
278
293
|
readOnlyHint: false,
|
|
279
294
|
},
|
|
280
295
|
handler: async (params: unknown, _context: RequestContext) => {
|
|
281
|
-
|
|
282
|
-
|
|
296
|
+
let parsedParams;
|
|
297
|
+
try {
|
|
298
|
+
parsedParams = TransactionExecuteSchema.parse(params);
|
|
299
|
+
} catch (error) {
|
|
300
|
+
if (error instanceof ZodError) {
|
|
301
|
+
return { success: false, error: formatZodError(error) };
|
|
302
|
+
}
|
|
303
|
+
const msg = String(error instanceof Error ? error.message : error);
|
|
304
|
+
return { success: false, error: msg };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const { statements, isolationLevel } = parsedParams;
|
|
283
308
|
|
|
284
309
|
if (statements.length === 0) {
|
|
285
310
|
return {
|
|
286
311
|
success: false,
|
|
287
|
-
|
|
312
|
+
error:
|
|
288
313
|
"No statements provided. Pass at least one SQL statement in statements (or queries alias).",
|
|
289
314
|
};
|
|
290
315
|
}
|
|
@@ -334,7 +359,7 @@ function createTransactionExecuteTool(adapter: MySQLAdapter): ToolDefinition {
|
|
|
334
359
|
const msg = String(error instanceof Error ? error.message : error);
|
|
335
360
|
return {
|
|
336
361
|
success: false,
|
|
337
|
-
|
|
362
|
+
error: `Transaction failed and was rolled back: ${msg}`,
|
|
338
363
|
rolledBack: true,
|
|
339
364
|
};
|
|
340
365
|
}
|