@berthojoris/mcp-mysql-server 1.40.5 → 1.40.7
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/CHANGELOG.md +23 -0
- package/DOCUMENTATIONS.md +55 -15
- package/README.md +37 -3
- package/dist/config/featureConfig.js +7 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +11 -4
- package/dist/mcp-server.js +129 -3
- package/dist/security/securityLayer.d.ts +1 -1
- package/dist/security/securityLayer.js +2 -2
- package/dist/tools/dataExportTools.d.ts +11 -0
- package/dist/tools/dataExportTools.js +68 -27
- package/dist/tools/ddlTools.d.ts +2 -0
- package/dist/tools/ddlTools.js +125 -20
- package/dist/tools/toolArgumentValidation.js +5 -0
- package/dist/tools/utilityTools.d.ts +16 -1
- package/dist/tools/utilityTools.js +73 -18
- package/manifest.json +2538 -732
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ All notable changes to the MySQL MCP Server will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.40.7] - 2026-05-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Implemented `export_query_to_csv` end-to-end for SELECT query CSV exports.
|
|
12
|
+
- Enhanced `list_all_tools` with a live runtime tool catalog, enabled/disabled status, access profile, and AI-agent workflow guidance.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Fixed `export_query_to_csv` being advertised but failing with `Unknown tool`.
|
|
16
|
+
- Fixed `list_all_tools` returning stale manifest data instead of the active MCP tool catalog.
|
|
17
|
+
- Fixed `execute_in_transaction` permission checks to match its advertised transaction permission.
|
|
18
|
+
- Hardened DDL tools by validating raw DDL statements and checking structured table, column, and index inputs before building SQL.
|
|
19
|
+
- Added argument validation for Cursor bridge dispatches.
|
|
20
|
+
|
|
21
|
+
## [1.40.6] - 2026-05-04
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- Added `cursor_execute_request`, a no-argument compatibility bridge for Cursor MCP wrappers that cannot send tool `arguments`.
|
|
25
|
+
- The bridge reads `.cursor/mysql-mcp-request.json` or `MYSQL_MCP_CURSOR_REQUEST_FILE` and dispatches to existing MCP tools or auto-routes SQL to SELECT, write, or DDL execution.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- Updated tool totals in documentation to include the Cursor bridge.
|
|
29
|
+
- Synchronized version metadata to `1.40.6`.
|
|
30
|
+
|
|
8
31
|
## [1.40.5] - 2026-04-08
|
|
9
32
|
|
|
10
33
|
### Fixed
|
package/DOCUMENTATIONS.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# MySQL MCP Server - Documentation
|
|
2
2
|
|
|
3
|
-
**Last Updated:** 2026-
|
|
4
|
-
**Version:** 1.40.
|
|
5
|
-
**Total Tools:**
|
|
3
|
+
**Last Updated:** 2026-05-06 22:38:42
|
|
4
|
+
**Version:** 1.40.7
|
|
5
|
+
**Total Tools:** 79
|
|
6
6
|
|
|
7
7
|
Comprehensive documentation for the MySQL MCP Server. For quick start, see [README.md](README.md).
|
|
8
8
|
|
|
@@ -65,6 +65,42 @@ Configure MySQL MCP with two access-control layers:
|
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
+
### Cursor Compatibility Bridge
|
|
69
|
+
|
|
70
|
+
Some Cursor MCP wrappers can call a tool by name but cannot pass `arguments`. For that flow, write a request file at `.cursor/mysql-mcp-request.json` and call the no-argument `cursor_execute_request` tool.
|
|
71
|
+
|
|
72
|
+
Execute any existing MCP tool:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"tool": "execute_ddl",
|
|
77
|
+
"arguments": {
|
|
78
|
+
"query": "DROP TABLE IF EXISTS spark_processes;"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Or execute SQL directly with automatic routing:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"query": "DROP TABLE IF EXISTS spark_processes;",
|
|
88
|
+
"mode": "auto"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Supported `mode` values are `auto`, `select`, `write`, and `ddl`. Set `MYSQL_MCP_CURSOR_REQUEST_FILE` to override the request file path.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### AI Agent Tool Discovery
|
|
97
|
+
|
|
98
|
+
Use `list_all_tools` first when connecting from Codex, Claude Code CLI, Cursor, Droid CLI, or other MCP agents. It returns the live runtime catalog from the server, enabled/disabled status for each tool, the active permission/category profile, and recommended workflows for common agent tasks.
|
|
99
|
+
|
|
100
|
+
For CSV exports, use `export_table_to_csv` for table-based exports and `export_query_to_csv` for SELECT query exports.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
68
104
|
## Permission System
|
|
69
105
|
|
|
70
106
|
### Available Permissions
|
|
@@ -92,12 +128,11 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
92
128
|
|
|
93
129
|
## Tool Categories
|
|
94
130
|
|
|
95
|
-
### 1. Database Discovery (
|
|
131
|
+
### 1. Database Discovery (4 tools)
|
|
96
132
|
- `list_databases` - List all databases
|
|
97
133
|
- `list_tables` - List tables in database
|
|
98
134
|
- `read_table_schema` - Get table structure
|
|
99
135
|
- `get_all_tables_relationships` - Get all FK relationships
|
|
100
|
-
- `list_all_tools` - List available MCP tools
|
|
101
136
|
|
|
102
137
|
### 2. Analysis (4 tools)
|
|
103
138
|
- `get_database_summary` - Database overview with statistics
|
|
@@ -125,7 +160,11 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
125
160
|
- `drop_table` - Delete tables
|
|
126
161
|
- `execute_ddl` - Execute raw DDL
|
|
127
162
|
|
|
128
|
-
### 6.
|
|
163
|
+
### 6. Data Export (2 tools)
|
|
164
|
+
- `export_table_to_csv` - Export table data to CSV
|
|
165
|
+
- `export_query_to_csv` - Export SELECT query results to CSV
|
|
166
|
+
|
|
167
|
+
### 7. Index Management (10 tools)
|
|
129
168
|
- `list_indexes` - List table indexes
|
|
130
169
|
- `get_index_info` - Get index details
|
|
131
170
|
- `create_index` - Create indexes
|
|
@@ -137,7 +176,7 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
137
176
|
- `get_fulltext_stats` - Get FULLTEXT index statistics
|
|
138
177
|
- `optimize_fulltext` - Optimize FULLTEXT indexes
|
|
139
178
|
|
|
140
|
-
###
|
|
179
|
+
### 8. Constraint Management (7 tools)
|
|
141
180
|
- `list_foreign_keys` - List foreign keys
|
|
142
181
|
- `list_constraints` - List all constraints
|
|
143
182
|
- `add_foreign_key` - Add foreign key
|
|
@@ -146,7 +185,7 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
146
185
|
- `drop_constraint` - Remove constraint
|
|
147
186
|
- `add_check_constraint` - Add check constraint
|
|
148
187
|
|
|
149
|
-
###
|
|
188
|
+
### 9. Stored Procedures (6 tools)
|
|
150
189
|
- `list_stored_procedures` - List procedures
|
|
151
190
|
- `get_stored_procedure_info` - Get procedure details
|
|
152
191
|
- `execute_stored_procedure` - Execute procedures
|
|
@@ -154,7 +193,7 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
154
193
|
- `drop_stored_procedure` - Remove procedures
|
|
155
194
|
- `show_create_procedure` - Show CREATE statement
|
|
156
195
|
|
|
157
|
-
###
|
|
196
|
+
### 10. Views Management (6 tools)
|
|
158
197
|
- `list_views` - List views
|
|
159
198
|
- `get_view_info` - Get view details
|
|
160
199
|
- `create_view` - Create views
|
|
@@ -162,14 +201,14 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
162
201
|
- `drop_view` - Remove views
|
|
163
202
|
- `show_create_view` - Show CREATE statement
|
|
164
203
|
|
|
165
|
-
###
|
|
204
|
+
### 11. Triggers Management (5 tools)
|
|
166
205
|
- `list_triggers` - List triggers
|
|
167
206
|
- `get_trigger_info` - Get trigger details
|
|
168
207
|
- `create_trigger` - Create triggers
|
|
169
208
|
- `drop_trigger` - Remove triggers
|
|
170
209
|
- `show_create_trigger` - Show CREATE statement
|
|
171
210
|
|
|
172
|
-
###
|
|
211
|
+
### 12. Table Maintenance (8 tools)
|
|
173
212
|
- `analyze_table` - Update statistics
|
|
174
213
|
- `optimize_table` - Reclaim space
|
|
175
214
|
- `check_table` - Check for errors
|
|
@@ -179,23 +218,24 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
|
|
|
179
218
|
- `flush_table` - Close/reopen table
|
|
180
219
|
- `get_table_size` - Get size information
|
|
181
220
|
|
|
182
|
-
###
|
|
221
|
+
### 13. Transaction Management (5 tools)
|
|
183
222
|
- `begin_transaction` - Start transaction
|
|
184
223
|
- `commit_transaction` - Commit transaction
|
|
185
224
|
- `rollback_transaction` - Rollback transaction
|
|
186
225
|
- `get_transaction_status` - Check transaction state
|
|
187
226
|
- `execute_in_transaction` - Execute within transaction
|
|
188
227
|
|
|
189
|
-
###
|
|
228
|
+
### 14. Query Optimization (3 tools)
|
|
190
229
|
- `analyze_query` - Analyze query performance
|
|
191
230
|
- `get_optimization_hints` - Get optimizer hints
|
|
192
231
|
- `repair_query` - Repair broken SQL queries
|
|
193
232
|
|
|
194
|
-
###
|
|
233
|
+
### 15. Utilities (5 tools)
|
|
195
234
|
- `test_connection` - Test connectivity
|
|
196
235
|
- `describe_connection` - Connection info
|
|
197
236
|
- `read_changelog` - Read changelog
|
|
198
|
-
- `
|
|
237
|
+
- `cursor_execute_request` - Execute a file-backed request for clients that cannot send MCP arguments
|
|
238
|
+
- `list_all_tools` - Runtime tool catalog with agent guidance
|
|
199
239
|
|
|
200
240
|
---
|
|
201
241
|
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**A production-ready Model Context Protocol (MCP) server for MySQL database integration with AI agents**
|
|
6
6
|
|
|
7
|
-
**Last Updated:** 2026-
|
|
7
|
+
**Last Updated:** 2026-05-06 22:38:42
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@berthojoris/mcp-mysql-server)
|
|
10
10
|
[](https://www.npmjs.com/package/@berthojoris/mcp-mysql-server)
|
|
@@ -211,6 +211,40 @@ For more client-specific config snippets, see **[DOCUMENTATIONS.md → Setup & C
|
|
|
211
211
|
|
|
212
212
|
---
|
|
213
213
|
|
|
214
|
+
### Cursor Compatibility Bridge
|
|
215
|
+
|
|
216
|
+
If a Cursor MCP wrapper can call tools but cannot send `arguments`, use the no-argument `cursor_execute_request` bridge. Create `.cursor/mysql-mcp-request.json` in the workspace, then call `cursor_execute_request`:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"tool": "execute_ddl",
|
|
221
|
+
"arguments": {
|
|
222
|
+
"query": "DROP TABLE IF EXISTS spark_processes;"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
For direct SQL, the bridge can infer the right SQL tool:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"query": "DROP TABLE IF EXISTS spark_processes;",
|
|
232
|
+
"mode": "auto"
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Set `MYSQL_MCP_CURSOR_REQUEST_FILE` to override the request file path.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### AI Agent Tool Discovery
|
|
241
|
+
|
|
242
|
+
For Codex, Claude Code CLI, Cursor, Droid CLI, and other MCP agents, call `list_all_tools` first. It returns the live runtime catalog, enabled/disabled status, active permission/category profile, and recommended workflows for schema exploration, safe SELECT queries, CSV exports, transactions, and data changes.
|
|
243
|
+
|
|
244
|
+
Use `export_table_to_csv` for table-based exports and `export_query_to_csv` for SELECT query exports.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
214
248
|
## Permission System
|
|
215
249
|
|
|
216
250
|
Control database access with a **dual-layer filtering system** that provides both broad and fine-grained control:
|
|
@@ -250,7 +284,7 @@ Use documentation categories to fine-tune which tools are exposed (Layer 2):
|
|
|
250
284
|
| `bulk_operations` | High-performance batch processing operations | `bulk_delete, bulk_insert, bulk_update` |
|
|
251
285
|
| `custom_queries` | Execute custom SQL queries and advanced operations | `execute_write_query, run_select_query` |
|
|
252
286
|
| `schema_management` | Manage database schema, tables, and structure | `alter_table, create_table, drop_table, execute_ddl` |
|
|
253
|
-
| `utilities` | Database utilities, diagnostics, and helper functions | `describe_connection, export_query_to_csv, export_table_to_csv, list_all_tools, read_changelog, test_connection` |
|
|
287
|
+
| `utilities` | Database utilities, diagnostics, and helper functions | `cursor_execute_request, describe_connection, export_query_to_csv, export_table_to_csv, list_all_tools, read_changelog, test_connection` |
|
|
254
288
|
| `transaction_management` | Handle ACID transactions and rollback operations | `begin_transaction, commit_transaction, execute_in_transaction, get_transaction_status, rollback_transaction` |
|
|
255
289
|
| `stored_procedures` | Create, execute, and manage stored procedures | `create_stored_procedure, drop_stored_procedure, execute_stored_procedure, get_stored_procedure_info, list_stored_procedures, show_create_procedure` |
|
|
256
290
|
| `views_management` | Create and manage database views | `alter_view, create_view, drop_view, get_view_info, list_views, show_create_view` |
|
|
@@ -276,7 +310,7 @@ Full category → tool mapping (and examples) lives in **[DOCUMENTATIONS.md →
|
|
|
276
310
|
|
|
277
311
|
## Available Tools
|
|
278
312
|
|
|
279
|
-
The server exposes **
|
|
313
|
+
The server exposes **79 tools** organized into categories (CRUD, schema, and utilities).
|
|
280
314
|
|
|
281
315
|
- Complete list of tools: **[DOCUMENTATIONS.md → Complete Tools Reference](DOCUMENTATIONS.md#🔧-complete-tools-reference)**
|
|
282
316
|
|
|
@@ -53,7 +53,8 @@ exports.toolCategoryMap = {
|
|
|
53
53
|
listDatabases: ToolCategory.LIST,
|
|
54
54
|
listTables: ToolCategory.LIST,
|
|
55
55
|
readTableSchema: ToolCategory.LIST,
|
|
56
|
-
|
|
56
|
+
listAllTools: ToolCategory.UTILITY,
|
|
57
|
+
list_all_tools: ToolCategory.UTILITY,
|
|
57
58
|
// Analysis tools (added here to group with database tools)
|
|
58
59
|
getDatabaseSummary: ToolCategory.LIST,
|
|
59
60
|
getSchemaERD: ToolCategory.LIST,
|
|
@@ -81,6 +82,8 @@ exports.toolCategoryMap = {
|
|
|
81
82
|
executeDdl: ToolCategory.DDL,
|
|
82
83
|
// Utility tools
|
|
83
84
|
describeConnection: ToolCategory.UTILITY,
|
|
85
|
+
cursorExecuteRequest: ToolCategory.UTILITY,
|
|
86
|
+
cursor_execute_request: ToolCategory.UTILITY,
|
|
84
87
|
testConnection: ToolCategory.UTILITY,
|
|
85
88
|
getAllTablesRelationships: ToolCategory.UTILITY,
|
|
86
89
|
exportTableToCSV: ToolCategory.UTILITY,
|
|
@@ -183,6 +186,8 @@ exports.toolDocCategoryMap = {
|
|
|
183
186
|
// Utilities
|
|
184
187
|
testConnection: DocCategory.UTILITIES,
|
|
185
188
|
describeConnection: DocCategory.UTILITIES,
|
|
189
|
+
cursorExecuteRequest: DocCategory.UTILITIES,
|
|
190
|
+
cursor_execute_request: DocCategory.UTILITIES,
|
|
186
191
|
exportTableToCSV: DocCategory.UTILITIES,
|
|
187
192
|
exportTableToCsv: DocCategory.UTILITIES,
|
|
188
193
|
export_table_to_csv: DocCategory.UTILITIES,
|
|
@@ -190,6 +195,7 @@ exports.toolDocCategoryMap = {
|
|
|
190
195
|
exportQueryToCsv: DocCategory.UTILITIES,
|
|
191
196
|
export_query_to_csv: DocCategory.UTILITIES,
|
|
192
197
|
read_changelog: DocCategory.UTILITIES,
|
|
198
|
+
listAllTools: DocCategory.UTILITIES,
|
|
193
199
|
list_all_tools: DocCategory.UTILITIES,
|
|
194
200
|
// Transaction Management
|
|
195
201
|
beginTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
package/dist/index.d.ts
CHANGED
|
@@ -203,7 +203,19 @@ export declare class MySQLMCP {
|
|
|
203
203
|
data?: any;
|
|
204
204
|
error?: string;
|
|
205
205
|
}>;
|
|
206
|
-
listAllTools(
|
|
206
|
+
listAllTools(params?: {
|
|
207
|
+
tools?: Array<{
|
|
208
|
+
name: string;
|
|
209
|
+
description?: string;
|
|
210
|
+
inputSchema?: any;
|
|
211
|
+
input_schema?: any;
|
|
212
|
+
output_schema?: any;
|
|
213
|
+
}>;
|
|
214
|
+
enabledToolNames?: string[];
|
|
215
|
+
accessProfile?: any;
|
|
216
|
+
serverName?: string;
|
|
217
|
+
serverVersion?: string;
|
|
218
|
+
}): Promise<{
|
|
207
219
|
status: string;
|
|
208
220
|
data?: any;
|
|
209
221
|
error?: string;
|
|
@@ -315,6 +327,15 @@ export declare class MySQLMCP {
|
|
|
315
327
|
data?: any;
|
|
316
328
|
error?: string;
|
|
317
329
|
}>;
|
|
330
|
+
exportQueryToCSV(params: {
|
|
331
|
+
query: string;
|
|
332
|
+
params?: any[];
|
|
333
|
+
include_headers?: boolean;
|
|
334
|
+
}): Promise<{
|
|
335
|
+
status: string;
|
|
336
|
+
data?: any;
|
|
337
|
+
error?: string;
|
|
338
|
+
}>;
|
|
318
339
|
repairQuery(params: {
|
|
319
340
|
query: string;
|
|
320
341
|
error_message?: string;
|
package/dist/index.js
CHANGED
|
@@ -134,7 +134,7 @@ class MySQLMCP {
|
|
|
134
134
|
return { status: "error", error: check.error };
|
|
135
135
|
}
|
|
136
136
|
// Additional security check
|
|
137
|
-
if (!this.security.isReadOnlyQuery(params.query)) {
|
|
137
|
+
if (!this.security.isReadOnlyQuery(params.query, this.security.hasExecutePermission())) {
|
|
138
138
|
return {
|
|
139
139
|
status: "error",
|
|
140
140
|
error: "Only SELECT queries are allowed with run_select_query. Use execute_write_query for other operations.",
|
|
@@ -239,12 +239,12 @@ class MySQLMCP {
|
|
|
239
239
|
}
|
|
240
240
|
return await this.utilityTools.readChangelog(params);
|
|
241
241
|
}
|
|
242
|
-
async listAllTools() {
|
|
242
|
+
async listAllTools(params) {
|
|
243
243
|
const check = this.checkToolEnabled("list_all_tools");
|
|
244
244
|
if (!check.enabled) {
|
|
245
245
|
return { status: "error", error: check.error };
|
|
246
246
|
}
|
|
247
|
-
return await this.utilityTools.listAllTools();
|
|
247
|
+
return await this.utilityTools.listAllTools(params);
|
|
248
248
|
}
|
|
249
249
|
// Transaction Tools
|
|
250
250
|
async beginTransaction(params) {
|
|
@@ -276,7 +276,7 @@ class MySQLMCP {
|
|
|
276
276
|
return await this.transactionTools.getTransactionStatus();
|
|
277
277
|
}
|
|
278
278
|
async executeInTransaction(params) {
|
|
279
|
-
const check = this.checkToolEnabled("
|
|
279
|
+
const check = this.checkToolEnabled("executeInTransaction");
|
|
280
280
|
if (!check.enabled) {
|
|
281
281
|
return { status: "error", error: check.error };
|
|
282
282
|
}
|
|
@@ -333,6 +333,13 @@ class MySQLMCP {
|
|
|
333
333
|
}
|
|
334
334
|
return await this.dataExportTools.exportTableToCSV(params);
|
|
335
335
|
}
|
|
336
|
+
async exportQueryToCSV(params) {
|
|
337
|
+
const check = this.checkToolEnabled("exportQueryToCSV");
|
|
338
|
+
if (!check.enabled) {
|
|
339
|
+
return { status: "error", error: check.error };
|
|
340
|
+
}
|
|
341
|
+
return await this.dataExportTools.exportQueryToCSV(params);
|
|
342
|
+
}
|
|
336
343
|
// AI Productivity Tools
|
|
337
344
|
async repairQuery(params) {
|
|
338
345
|
const check = this.checkToolEnabled("repairQuery");
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
3
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
4
9
|
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
10
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
11
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
@@ -12,6 +17,8 @@ const toolArgumentValidation_js_1 = require("./tools/toolArgumentValidation.js")
|
|
|
12
17
|
// Layer 2 (Categories): MCP_CATEGORIES (optional, for fine-grained control)
|
|
13
18
|
const permissions = process.env.MCP_PERMISSIONS || process.env.MCP_CONFIG || "";
|
|
14
19
|
const categories = process.env.MCP_CATEGORIES || "";
|
|
20
|
+
const SERVER_NAME = "mysql-mcp-server";
|
|
21
|
+
const SERVER_VERSION = "1.40.7";
|
|
15
22
|
// Declare the MySQL MCP instance (will be initialized in main())
|
|
16
23
|
let mysqlMCP;
|
|
17
24
|
// Define all available tools with their schemas
|
|
@@ -641,6 +648,14 @@ const TOOLS = [
|
|
|
641
648
|
properties: {},
|
|
642
649
|
},
|
|
643
650
|
},
|
|
651
|
+
{
|
|
652
|
+
name: "cursor_execute_request",
|
|
653
|
+
description: "Cursor compatibility bridge for clients that can call MCP tools but cannot send arguments. Reads .cursor/mysql-mcp-request.json (or MYSQL_MCP_CURSOR_REQUEST_FILE) and dispatches to the requested MySQL MCP tool. The request file supports {\"tool\":\"execute_ddl\",\"arguments\":{\"query\":\"DROP TABLE IF EXISTS t;\"}} or direct SQL with {\"query\":\"...\",\"mode\":\"auto\"}.",
|
|
654
|
+
inputSchema: {
|
|
655
|
+
type: "object",
|
|
656
|
+
properties: {},
|
|
657
|
+
},
|
|
658
|
+
},
|
|
644
659
|
{
|
|
645
660
|
name: "read_changelog",
|
|
646
661
|
description: "Reads the MySQL MCP Server changelog to see version history, new features, bug fixes, and breaking changes. Useful for understanding tool capabilities and recent updates.",
|
|
@@ -1849,8 +1864,8 @@ const TOOLS = [
|
|
|
1849
1864
|
];
|
|
1850
1865
|
// Create the MCP server
|
|
1851
1866
|
const server = new index_js_1.Server({
|
|
1852
|
-
name:
|
|
1853
|
-
version:
|
|
1867
|
+
name: SERVER_NAME,
|
|
1868
|
+
version: SERVER_VERSION,
|
|
1854
1869
|
}, {
|
|
1855
1870
|
capabilities: {
|
|
1856
1871
|
tools: {},
|
|
@@ -1865,6 +1880,111 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
|
1865
1880
|
tools: enabledTools,
|
|
1866
1881
|
};
|
|
1867
1882
|
});
|
|
1883
|
+
const TOOL_METHOD_OVERRIDES = {
|
|
1884
|
+
get_schema_erd: "getSchemaERD",
|
|
1885
|
+
export_table_to_csv: "exportTableToCSV",
|
|
1886
|
+
export_query_to_csv: "exportQueryToCSV",
|
|
1887
|
+
};
|
|
1888
|
+
const toCamelCase = (value) => value.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
1889
|
+
const getRuntimeToolCatalog = () => {
|
|
1890
|
+
const enabledTools = (0, toolRegistry_js_1.getEnabledTools)(mysqlMCP, TOOLS);
|
|
1891
|
+
return {
|
|
1892
|
+
tools: TOOLS.map((tool) => ({
|
|
1893
|
+
name: tool.name,
|
|
1894
|
+
description: tool.description,
|
|
1895
|
+
inputSchema: tool.inputSchema,
|
|
1896
|
+
})),
|
|
1897
|
+
enabledToolNames: enabledTools.map((tool) => tool.name),
|
|
1898
|
+
accessProfile: mysqlMCP.getAccessProfile(),
|
|
1899
|
+
serverName: SERVER_NAME,
|
|
1900
|
+
serverVersion: SERVER_VERSION,
|
|
1901
|
+
};
|
|
1902
|
+
};
|
|
1903
|
+
const getCursorRequestFilePath = () => {
|
|
1904
|
+
const configuredPath = process.env.MYSQL_MCP_CURSOR_REQUEST_FILE ||
|
|
1905
|
+
process.env.MCP_MYSQL_REQUEST_FILE ||
|
|
1906
|
+
".cursor/mysql-mcp-request.json";
|
|
1907
|
+
return path_1.default.isAbsolute(configuredPath)
|
|
1908
|
+
? configuredPath
|
|
1909
|
+
: path_1.default.resolve(process.cwd(), configuredPath);
|
|
1910
|
+
};
|
|
1911
|
+
const inferSqlToolName = (query, mode = "auto") => {
|
|
1912
|
+
const upperQuery = query.trim().toUpperCase();
|
|
1913
|
+
if (mode === "select")
|
|
1914
|
+
return "run_select_query";
|
|
1915
|
+
if (mode === "write")
|
|
1916
|
+
return "execute_write_query";
|
|
1917
|
+
if (mode === "ddl")
|
|
1918
|
+
return "execute_ddl";
|
|
1919
|
+
if (/^(CREATE|ALTER|DROP|TRUNCATE|RENAME)\b/.test(upperQuery)) {
|
|
1920
|
+
return "execute_ddl";
|
|
1921
|
+
}
|
|
1922
|
+
if (/^(INSERT|UPDATE|DELETE|REPLACE)\b/.test(upperQuery)) {
|
|
1923
|
+
return "execute_write_query";
|
|
1924
|
+
}
|
|
1925
|
+
if (/^(SELECT|WITH)\b/.test(upperQuery)) {
|
|
1926
|
+
return "run_select_query";
|
|
1927
|
+
}
|
|
1928
|
+
throw new Error("Unable to infer SQL tool. Set mode to one of: select, write, ddl.");
|
|
1929
|
+
};
|
|
1930
|
+
const executeToolByName = async (toolName, args = {}) => {
|
|
1931
|
+
const knownToolNames = new Set(TOOLS.map((tool) => tool.name));
|
|
1932
|
+
if (!knownToolNames.has(toolName)) {
|
|
1933
|
+
throw new Error(`Unknown tool for Cursor bridge: ${toolName}`);
|
|
1934
|
+
}
|
|
1935
|
+
if (toolName === "cursor_execute_request") {
|
|
1936
|
+
throw new Error("cursor_execute_request cannot dispatch to itself");
|
|
1937
|
+
}
|
|
1938
|
+
const validation = (0, toolArgumentValidation_js_1.validateToolArguments)(toolName, args);
|
|
1939
|
+
if (!validation.valid) {
|
|
1940
|
+
throw new Error(`Validation Error: ${validation.errors?.join(", ") || "Invalid arguments"}`);
|
|
1941
|
+
}
|
|
1942
|
+
if (toolName === "list_all_tools") {
|
|
1943
|
+
return await mysqlMCP.listAllTools(getRuntimeToolCatalog());
|
|
1944
|
+
}
|
|
1945
|
+
const methodName = TOOL_METHOD_OVERRIDES[toolName] || toCamelCase(toolName);
|
|
1946
|
+
const method = mysqlMCP[methodName];
|
|
1947
|
+
if (typeof method !== "function") {
|
|
1948
|
+
throw new Error(`No handler method found for Cursor bridge tool: ${toolName}`);
|
|
1949
|
+
}
|
|
1950
|
+
return await method.call(mysqlMCP, args);
|
|
1951
|
+
};
|
|
1952
|
+
const executeCursorRequest = async () => {
|
|
1953
|
+
const requestFilePath = getCursorRequestFilePath();
|
|
1954
|
+
if (!fs_1.default.existsSync(requestFilePath)) {
|
|
1955
|
+
return {
|
|
1956
|
+
status: "error",
|
|
1957
|
+
error: `Cursor request file not found: ${requestFilePath}. ` +
|
|
1958
|
+
'Create it with JSON like {"tool":"execute_ddl","arguments":{"query":"DROP TABLE IF EXISTS spark_processes;"}}',
|
|
1959
|
+
};
|
|
1960
|
+
}
|
|
1961
|
+
let request;
|
|
1962
|
+
try {
|
|
1963
|
+
request = JSON.parse(fs_1.default.readFileSync(requestFilePath, "utf8"));
|
|
1964
|
+
}
|
|
1965
|
+
catch (error) {
|
|
1966
|
+
return {
|
|
1967
|
+
status: "error",
|
|
1968
|
+
error: `Failed to read Cursor request file: ${error.message}`,
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
const requestedTool = request.tool || request.toolName || request.name;
|
|
1972
|
+
if (requestedTool) {
|
|
1973
|
+
return await executeToolByName(requestedTool, request.arguments || request.args || {});
|
|
1974
|
+
}
|
|
1975
|
+
if (request.query) {
|
|
1976
|
+
const inferredTool = inferSqlToolName(request.query, request.mode || "auto");
|
|
1977
|
+
return await executeToolByName(inferredTool, {
|
|
1978
|
+
query: request.query,
|
|
1979
|
+
params: request.params,
|
|
1980
|
+
dry_run: request.dry_run,
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
return {
|
|
1984
|
+
status: "error",
|
|
1985
|
+
error: "Cursor request must contain either tool/toolName/name with arguments, or query with optional mode.",
|
|
1986
|
+
};
|
|
1987
|
+
};
|
|
1868
1988
|
// Handle tool call requests
|
|
1869
1989
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
1870
1990
|
const { name, arguments: args } = request.params;
|
|
@@ -1951,11 +2071,14 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1951
2071
|
case "describe_connection":
|
|
1952
2072
|
result = await mysqlMCP.describeConnection();
|
|
1953
2073
|
break;
|
|
2074
|
+
case "cursor_execute_request":
|
|
2075
|
+
result = await executeCursorRequest();
|
|
2076
|
+
break;
|
|
1954
2077
|
case "test_connection":
|
|
1955
2078
|
result = await mysqlMCP.testConnection();
|
|
1956
2079
|
break;
|
|
1957
2080
|
case "list_all_tools":
|
|
1958
|
-
result = await mysqlMCP.listAllTools();
|
|
2081
|
+
result = await mysqlMCP.listAllTools(getRuntimeToolCatalog());
|
|
1959
2082
|
break;
|
|
1960
2083
|
case "read_changelog":
|
|
1961
2084
|
result = await mysqlMCP.readChangelog((args || {}));
|
|
@@ -2002,6 +2125,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2002
2125
|
case "export_table_to_csv":
|
|
2003
2126
|
result = await mysqlMCP.exportTableToCSV((args || {}));
|
|
2004
2127
|
break;
|
|
2128
|
+
case "export_query_to_csv":
|
|
2129
|
+
result = await mysqlMCP.exportQueryToCSV((args || {}));
|
|
2130
|
+
break;
|
|
2005
2131
|
// Query Optimization Tools
|
|
2006
2132
|
case "analyze_query":
|
|
2007
2133
|
result = mysqlMCP.analyzeQuery((args || {}));
|
|
@@ -71,7 +71,7 @@ export declare class SecurityLayer {
|
|
|
71
71
|
/**
|
|
72
72
|
* Check if a query is a read-only SELECT query or information query (SHOW, DESCRIBE, etc.)
|
|
73
73
|
*/
|
|
74
|
-
isReadOnlyQuery(query: string): boolean;
|
|
74
|
+
isReadOnlyQuery(query: string, bypassDangerousCheck?: boolean): boolean;
|
|
75
75
|
/**
|
|
76
76
|
* Check if a query contains dangerous operations
|
|
77
77
|
*/
|
|
@@ -404,13 +404,13 @@ class SecurityLayer {
|
|
|
404
404
|
/**
|
|
405
405
|
* Check if a query is a read-only SELECT query or information query (SHOW, DESCRIBE, etc.)
|
|
406
406
|
*/
|
|
407
|
-
isReadOnlyQuery(query) {
|
|
407
|
+
isReadOnlyQuery(query, bypassDangerousCheck = false) {
|
|
408
408
|
// Check if it's an information query first (SHOW, DESCRIBE, EXPLAIN, etc.)
|
|
409
409
|
if (this.isInformationQuery(query)) {
|
|
410
410
|
return true;
|
|
411
411
|
}
|
|
412
412
|
// Check if it's a SELECT query
|
|
413
|
-
const validation = this.validateQuery(query);
|
|
413
|
+
const validation = this.validateQuery(query, bypassDangerousCheck);
|
|
414
414
|
return validation.valid && validation.queryType === "SELECT";
|
|
415
415
|
}
|
|
416
416
|
/**
|
|
@@ -12,6 +12,8 @@ export declare class DataExportTools {
|
|
|
12
12
|
* Escape string value for SQL INSERT statements
|
|
13
13
|
*/
|
|
14
14
|
private escapeValue;
|
|
15
|
+
private escapeCsvValue;
|
|
16
|
+
private rowsToCSV;
|
|
15
17
|
/**
|
|
16
18
|
* Export table data to CSV format
|
|
17
19
|
*/
|
|
@@ -26,4 +28,13 @@ export declare class DataExportTools {
|
|
|
26
28
|
data?: any;
|
|
27
29
|
error?: string;
|
|
28
30
|
}>;
|
|
31
|
+
exportQueryToCSV(queryParams: {
|
|
32
|
+
query: string;
|
|
33
|
+
params?: any[];
|
|
34
|
+
include_headers?: boolean;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
status: string;
|
|
37
|
+
data?: any;
|
|
38
|
+
error?: string;
|
|
39
|
+
}>;
|
|
29
40
|
}
|