@berthojoris/mcp-mysql-server 1.40.0 → 1.40.1
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 +9 -0
- package/DOCUMENTATIONS.md +5 -5
- package/README.md +3 -3
- package/bin/mcp-mysql.js +3 -6
- package/dist/mcp-server.js +5 -60
- package/dist/tools/toolArgumentValidation.d.ts +4 -0
- package/dist/tools/toolArgumentValidation.js +62 -0
- package/dist/tools/toolRegistry.d.ts +4 -0
- package/dist/tools/toolRegistry.js +11 -0
- package/manifest.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ 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.1] - 2026-03-06
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Synchronized version metadata across `package.json`, `src/mcp-server.ts`, and `manifest.json` to `1.40.1`
|
|
12
|
+
- Updated CLI category examples in `bin/mcp-mysql.js` to match active category set
|
|
13
|
+
- Updated category examples in `README.md` and `DOCUMENTATIONS.md` to remove removed categories
|
|
14
|
+
- Refactored tool registry filtering into `src/tools/toolRegistry.ts`
|
|
15
|
+
- Refactored tool argument validation registry into `src/tools/toolArgumentValidation.ts`
|
|
16
|
+
|
|
8
17
|
## [1.40.0] - 2026-03-06
|
|
9
18
|
|
|
10
19
|
### Removed
|
package/DOCUMENTATIONS.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# MySQL MCP Server - Documentation
|
|
2
2
|
|
|
3
|
-
**Last Updated:** 2026-03-06
|
|
4
|
-
**Version:** 1.40.
|
|
3
|
+
**Last Updated:** 2026-03-06 17:30:00
|
|
4
|
+
**Version:** 1.40.1
|
|
5
5
|
**Total Tools:** 73
|
|
6
6
|
|
|
7
7
|
Comprehensive documentation for the MySQL MCP Server. For quick start, see [README.md](README.md).
|
|
@@ -37,7 +37,7 @@ Configure MySQL MCP with two access-control layers:
|
|
|
37
37
|
"@berthojoris/mcp-mysql-server",
|
|
38
38
|
"mysql://user:password@localhost:3306/database",
|
|
39
39
|
"list,read,utility",
|
|
40
|
-
"database_discovery,
|
|
40
|
+
"database_discovery,custom_queries,analysis"
|
|
41
41
|
]
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -58,7 +58,7 @@ Configure MySQL MCP with two access-control layers:
|
|
|
58
58
|
"DB_PASSWORD": "your_password",
|
|
59
59
|
"DB_NAME": "your_database",
|
|
60
60
|
"MCP_PERMISSIONS": "list,read,utility",
|
|
61
|
-
"MCP_CATEGORIES": "database_discovery,
|
|
61
|
+
"MCP_CATEGORIES": "database_discovery,custom_queries,analysis"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
```
|
|
@@ -391,4 +391,4 @@ The system provides detailed error messages indicating:
|
|
|
391
391
|
|
|
392
392
|
---
|
|
393
393
|
|
|
394
|
-
*For detailed examples and advanced usage patterns, see the project README.md.*
|
|
394
|
+
*For detailed examples and advanced usage patterns, see the project README.md.*
|
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-03-06
|
|
7
|
+
**Last Updated:** 2026-03-06 17:30:00
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@berthojoris/mcp-mysql-server)
|
|
10
10
|
[](https://www.npmjs.com/package/@berthojoris/mcp-mysql-server)
|
|
@@ -200,7 +200,7 @@ Alternative approach using environment variables instead of connection string:
|
|
|
200
200
|
"DB_PASSWORD": "your_password",
|
|
201
201
|
"DB_NAME": "your_database",
|
|
202
202
|
"MCP_PERMISSIONS": "list,read,utility,create,update,delete",
|
|
203
|
-
"MCP_CATEGORIES": "database_discovery,
|
|
203
|
+
"MCP_CATEGORIES": "database_discovery,custom_queries,analysis"
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
}
|
|
@@ -245,7 +245,7 @@ Use documentation categories to fine-tune which tools are exposed (Layer 2):
|
|
|
245
245
|
|
|
246
246
|
| Category List | Use Case | List Tools |
|
|
247
247
|
|---------------|----------|-----------|
|
|
248
|
-
| `database_discovery` | Explore databases, tables, and schema structure | `get_all_tables_relationships,
|
|
248
|
+
| `database_discovery` | Explore databases, tables, and schema structure | `get_all_tables_relationships, list_databases, list_tables, read_table_schema` |
|
|
249
249
|
| `crud_operations` | Create, read, update, delete operations on data | `create_record, delete_record, read_records, update_record` |
|
|
250
250
|
| `bulk_operations` | High-performance batch processing operations | `bulk_delete, bulk_insert, bulk_update` |
|
|
251
251
|
| `custom_queries` | Execute custom SQL queries and advanced operations | `execute_write_query, run_select_query` |
|
package/bin/mcp-mysql.js
CHANGED
|
@@ -50,7 +50,7 @@ if (!mysqlUrl) {
|
|
|
50
50
|
" # Dual-layer: Permissions + Categories (fine-grained control)",
|
|
51
51
|
);
|
|
52
52
|
console.error(
|
|
53
|
-
' mcp-mysql mysql://root:pass@localhost:3306/mydb "list,read,utility" "database_discovery,
|
|
53
|
+
' mcp-mysql mysql://root:pass@localhost:3306/mydb "list,read,utility" "database_discovery,custom_queries,analysis"',
|
|
54
54
|
);
|
|
55
55
|
console.error("");
|
|
56
56
|
console.error("Permissions (Layer 1 - Broad Control):");
|
|
@@ -69,13 +69,10 @@ if (!mysqlUrl) {
|
|
|
69
69
|
" views_management, triggers_management, functions_management, index_management,",
|
|
70
70
|
);
|
|
71
71
|
console.error(
|
|
72
|
-
" constraint_management, table_maintenance,
|
|
72
|
+
" constraint_management, table_maintenance, query_optimization,",
|
|
73
73
|
);
|
|
74
74
|
console.error(
|
|
75
|
-
"
|
|
76
|
-
);
|
|
77
|
-
console.error(
|
|
78
|
-
" backup_restore, import_export, data_migration, schema_migrations",
|
|
75
|
+
" backup_restore, analysis",
|
|
79
76
|
);
|
|
80
77
|
console.error("");
|
|
81
78
|
console.error("Filtering Logic:");
|
package/dist/mcp-server.js
CHANGED
|
@@ -5,7 +5,8 @@ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
|
5
5
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
6
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
7
|
const index_js_2 = require("./index.js");
|
|
8
|
-
const
|
|
8
|
+
const toolRegistry_js_1 = require("./tools/toolRegistry.js");
|
|
9
|
+
const toolArgumentValidation_js_1 = require("./tools/toolArgumentValidation.js");
|
|
9
10
|
// Get permissions and categories from environment variables (set by bin/mcp-mysql.js)
|
|
10
11
|
// Layer 1 (Permissions): MCP_PERMISSIONS or MCP_CONFIG (backward compatible)
|
|
11
12
|
// Layer 2 (Categories): MCP_CATEGORIES (optional, for fine-grained control)
|
|
@@ -2104,7 +2105,7 @@ const TOOLS = [
|
|
|
2104
2105
|
// Create the MCP server
|
|
2105
2106
|
const server = new index_js_1.Server({
|
|
2106
2107
|
name: "mysql-mcp-server",
|
|
2107
|
-
version: "1.
|
|
2108
|
+
version: "1.40.1",
|
|
2108
2109
|
}, {
|
|
2109
2110
|
capabilities: {
|
|
2110
2111
|
tools: {},
|
|
@@ -2112,17 +2113,7 @@ const server = new index_js_1.Server({
|
|
|
2112
2113
|
});
|
|
2113
2114
|
// Handle list tools request - filter tools based on permissions and categories
|
|
2114
2115
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
2115
|
-
|
|
2116
|
-
const enabledTools = TOOLS.filter((tool) => {
|
|
2117
|
-
// Convert tool name from snake_case to camelCase for checking
|
|
2118
|
-
// e.g., "list_databases" -> "listDatabases"
|
|
2119
|
-
const toolNameCamelCase = tool.name.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
2120
|
-
// Check if tool is enabled based on permissions and categories
|
|
2121
|
-
// Most tools are keyed in featureConfig using camelCase, but a few legacy/meta tools
|
|
2122
|
-
// are keyed using their snake_case MCP names (e.g., read_changelog, list_all_tools).
|
|
2123
|
-
return (mysqlMCP.isToolEnabled(toolNameCamelCase) ||
|
|
2124
|
-
mysqlMCP.isToolEnabled(tool.name));
|
|
2125
|
-
});
|
|
2116
|
+
const enabledTools = (0, toolRegistry_js_1.getEnabledTools)(mysqlMCP, TOOLS);
|
|
2126
2117
|
// Log the filtering results
|
|
2127
2118
|
console.error(`Tools available: ${enabledTools.length} of ${TOOLS.length} total tools`);
|
|
2128
2119
|
return {
|
|
@@ -2133,7 +2124,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
|
2133
2124
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
2134
2125
|
const { name, arguments: args } = request.params;
|
|
2135
2126
|
// Validate tool arguments before execution
|
|
2136
|
-
const validation = validateToolArguments(name, args);
|
|
2127
|
+
const validation = (0, toolArgumentValidation_js_1.validateToolArguments)(name, args);
|
|
2137
2128
|
if (!validation.valid) {
|
|
2138
2129
|
return {
|
|
2139
2130
|
content: [
|
|
@@ -2488,52 +2479,6 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2488
2479
|
};
|
|
2489
2480
|
}
|
|
2490
2481
|
});
|
|
2491
|
-
// Validation function to validate tool arguments before execution
|
|
2492
|
-
function validateToolArguments(name, args) {
|
|
2493
|
-
if (!args)
|
|
2494
|
-
return { valid: true }; // Some tools don't require arguments
|
|
2495
|
-
try {
|
|
2496
|
-
switch (name) {
|
|
2497
|
-
case "create_record":
|
|
2498
|
-
return (0, inputValidation_js_1.validateCreateRecord)(args);
|
|
2499
|
-
case "read_records":
|
|
2500
|
-
return (0, inputValidation_js_1.validateReadRecords)(args);
|
|
2501
|
-
case "update_record":
|
|
2502
|
-
return (0, inputValidation_js_1.validateUpdateRecord)(args);
|
|
2503
|
-
case "delete_record":
|
|
2504
|
-
return (0, inputValidation_js_1.validateDeleteRecord)(args);
|
|
2505
|
-
case "run_select_query":
|
|
2506
|
-
case "execute_write_query":
|
|
2507
|
-
case "execute_ddl":
|
|
2508
|
-
return (0, inputValidation_js_1.validateQuery)({ query: args?.query || "" });
|
|
2509
|
-
case "bulk_insert":
|
|
2510
|
-
return (0, inputValidation_js_1.validateBulkInsert)(args);
|
|
2511
|
-
case "list_tables":
|
|
2512
|
-
case "get_schema_erd":
|
|
2513
|
-
case "get_schema_rag_context":
|
|
2514
|
-
case "get_database_summary":
|
|
2515
|
-
if (args.database !== undefined) {
|
|
2516
|
-
const validation = (0, inputValidation_js_1.validateValue)(args.database);
|
|
2517
|
-
if (!validation.valid)
|
|
2518
|
-
return { valid: false, errors: [validation.error || 'Invalid database name'] };
|
|
2519
|
-
}
|
|
2520
|
-
return { valid: true };
|
|
2521
|
-
case "get_column_statistics":
|
|
2522
|
-
case "read_table_schema":
|
|
2523
|
-
if (args.table_name) {
|
|
2524
|
-
const validation = (0, inputValidation_js_1.validateTableName)(args.table_name);
|
|
2525
|
-
if (!validation.valid)
|
|
2526
|
-
return { valid: false, errors: [validation.error || 'Invalid table name'] };
|
|
2527
|
-
}
|
|
2528
|
-
return { valid: true };
|
|
2529
|
-
default:
|
|
2530
|
-
return { valid: true }; // For tools without specific validation
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
catch (error) {
|
|
2534
|
-
return { valid: false, errors: [`Validation error: ${error instanceof Error ? error.message : 'Unknown validation error'}`] };
|
|
2535
|
-
}
|
|
2536
|
-
}
|
|
2537
2482
|
// Start the server
|
|
2538
2483
|
async function main() {
|
|
2539
2484
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateToolArguments = validateToolArguments;
|
|
4
|
+
const inputValidation_js_1 = require("../validation/inputValidation.js");
|
|
5
|
+
function validateToolArguments(name, args) {
|
|
6
|
+
if (!args)
|
|
7
|
+
return { valid: true };
|
|
8
|
+
try {
|
|
9
|
+
switch (name) {
|
|
10
|
+
case "create_record":
|
|
11
|
+
return (0, inputValidation_js_1.validateCreateRecord)(args);
|
|
12
|
+
case "read_records":
|
|
13
|
+
return (0, inputValidation_js_1.validateReadRecords)(args);
|
|
14
|
+
case "update_record":
|
|
15
|
+
return (0, inputValidation_js_1.validateUpdateRecord)(args);
|
|
16
|
+
case "delete_record":
|
|
17
|
+
return (0, inputValidation_js_1.validateDeleteRecord)(args);
|
|
18
|
+
case "run_select_query":
|
|
19
|
+
case "execute_write_query":
|
|
20
|
+
case "execute_ddl":
|
|
21
|
+
return (0, inputValidation_js_1.validateQuery)({ query: args?.query || "" });
|
|
22
|
+
case "bulk_insert":
|
|
23
|
+
return (0, inputValidation_js_1.validateBulkInsert)(args);
|
|
24
|
+
case "list_tables":
|
|
25
|
+
case "get_schema_erd":
|
|
26
|
+
case "get_schema_rag_context":
|
|
27
|
+
case "get_database_summary":
|
|
28
|
+
if (args.database !== undefined) {
|
|
29
|
+
const validation = (0, inputValidation_js_1.validateValue)(args.database);
|
|
30
|
+
if (!validation.valid) {
|
|
31
|
+
return {
|
|
32
|
+
valid: false,
|
|
33
|
+
errors: [validation.error || "Invalid database name"],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { valid: true };
|
|
38
|
+
case "get_column_statistics":
|
|
39
|
+
case "read_table_schema":
|
|
40
|
+
if (args.table_name) {
|
|
41
|
+
const validation = (0, inputValidation_js_1.validateTableName)(args.table_name);
|
|
42
|
+
if (!validation.valid) {
|
|
43
|
+
return {
|
|
44
|
+
valid: false,
|
|
45
|
+
errors: [validation.error || "Invalid table name"],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { valid: true };
|
|
50
|
+
default:
|
|
51
|
+
return { valid: true };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return {
|
|
56
|
+
valid: false,
|
|
57
|
+
errors: [
|
|
58
|
+
`Validation error: ${error instanceof Error ? error.message : "Unknown validation error"}`,
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getEnabledTools = exports.isToolEnabled = void 0;
|
|
4
|
+
const toCamelCase = (value) => value.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
5
|
+
const isToolEnabled = (mysqlMCP, tool) => {
|
|
6
|
+
const camelCaseName = toCamelCase(tool.name);
|
|
7
|
+
return mysqlMCP.isToolEnabled(camelCaseName) || mysqlMCP.isToolEnabled(tool.name);
|
|
8
|
+
};
|
|
9
|
+
exports.isToolEnabled = isToolEnabled;
|
|
10
|
+
const getEnabledTools = (mysqlMCP, tools) => tools.filter((tool) => (0, exports.isToolEnabled)(mysqlMCP, tool));
|
|
11
|
+
exports.getEnabledTools = getEnabledTools;
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@berthojoris/mcp-mysql-server",
|
|
3
|
-
"version": "1.40.
|
|
3
|
+
"version": "1.40.1",
|
|
4
4
|
"description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions, backup/restore capabilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -77,4 +77,4 @@
|
|
|
77
77
|
"ts-node": "^10.9.1",
|
|
78
78
|
"typescript": "^5.2.2"
|
|
79
79
|
}
|
|
80
|
-
}
|
|
80
|
+
}
|