@berthojoris/mcp-mysql-server 1.10.0 → 1.10.2
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/DOCUMENTATIONS.md +4083 -3617
- package/README.md +199 -283
- package/bin/mcp-mysql.js +110 -53
- package/dist/config/featureConfig.d.ts +72 -9
- package/dist/config/featureConfig.js +404 -87
- package/dist/index.d.ts +7 -1
- package/dist/index.js +10 -2
- package/dist/mcp-server.js +25 -7
- package/package.json +1 -1
package/bin/mcp-mysql.js
CHANGED
|
@@ -6,25 +6,70 @@
|
|
|
6
6
|
* It implements the Model Context Protocol using stdio transport
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
const path = require(
|
|
10
|
-
const { spawn } = require(
|
|
11
|
-
require(
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const { spawn } = require("child_process");
|
|
11
|
+
require("dotenv").config();
|
|
12
12
|
|
|
13
|
-
// Get MySQL connection string and optional
|
|
13
|
+
// Get MySQL connection string, permissions, and optional categories from command line arguments
|
|
14
14
|
const mysqlUrl = process.argv[2];
|
|
15
|
-
const permissions = process.argv[3]; // Optional: comma-separated list of permissions
|
|
15
|
+
const permissions = process.argv[3]; // Optional: comma-separated list of permissions (legacy categories)
|
|
16
|
+
const categories = process.argv[4]; // Optional: comma-separated list of documentation categories
|
|
16
17
|
|
|
17
18
|
if (!mysqlUrl) {
|
|
18
|
-
console.error(
|
|
19
|
-
console.error(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.error(
|
|
23
|
-
console.error(
|
|
24
|
-
console.error(
|
|
25
|
-
console.error(
|
|
26
|
-
console.error(
|
|
27
|
-
console.error(
|
|
19
|
+
console.error("Error: MySQL connection URL is required");
|
|
20
|
+
console.error(
|
|
21
|
+
"Usage: mcp-mysql mysql://user:password@host:port/dbname [permissions] [categories]",
|
|
22
|
+
);
|
|
23
|
+
console.error("");
|
|
24
|
+
console.error("Examples:");
|
|
25
|
+
console.error(" # All tools enabled (no filtering)");
|
|
26
|
+
console.error(" mcp-mysql mysql://root:pass@localhost:3306/mydb");
|
|
27
|
+
console.error("");
|
|
28
|
+
console.error(" # Permission-based filtering only (Layer 1)");
|
|
29
|
+
console.error(
|
|
30
|
+
' mcp-mysql mysql://root:pass@localhost:3306/mydb "list,read,utility"',
|
|
31
|
+
);
|
|
32
|
+
console.error("");
|
|
33
|
+
console.error(
|
|
34
|
+
" # Dual-layer: Permissions + Categories (fine-grained control)",
|
|
35
|
+
);
|
|
36
|
+
console.error(
|
|
37
|
+
' mcp-mysql mysql://root:pass@localhost:3306/mydb "list,read,utility" "database_discovery,performance_monitoring"',
|
|
38
|
+
);
|
|
39
|
+
console.error("");
|
|
40
|
+
console.error("Permissions (Layer 1 - Broad Control):");
|
|
41
|
+
console.error(
|
|
42
|
+
" list, read, create, update, delete, execute, ddl, utility, transaction, procedure",
|
|
43
|
+
);
|
|
44
|
+
console.error("");
|
|
45
|
+
console.error("Categories (Layer 2 - Fine-Grained Control, Optional):");
|
|
46
|
+
console.error(
|
|
47
|
+
" database_discovery, crud_operations, bulk_operations, custom_queries,",
|
|
48
|
+
);
|
|
49
|
+
console.error(
|
|
50
|
+
" schema_management, utilities, transaction_management, stored_procedures,",
|
|
51
|
+
);
|
|
52
|
+
console.error(
|
|
53
|
+
" views_management, triggers_management, functions_management, index_management,",
|
|
54
|
+
);
|
|
55
|
+
console.error(
|
|
56
|
+
" constraint_management, table_maintenance, server_management,",
|
|
57
|
+
);
|
|
58
|
+
console.error(
|
|
59
|
+
" performance_monitoring, cache_management, query_optimization,",
|
|
60
|
+
);
|
|
61
|
+
console.error(
|
|
62
|
+
" backup_restore, import_export, data_migration, schema_migrations",
|
|
63
|
+
);
|
|
64
|
+
console.error("");
|
|
65
|
+
console.error("Filtering Logic:");
|
|
66
|
+
console.error(
|
|
67
|
+
" - If only permissions: All tools within those permissions enabled",
|
|
68
|
+
);
|
|
69
|
+
console.error(
|
|
70
|
+
" - If permissions + categories: Only tools matching BOTH layers enabled",
|
|
71
|
+
);
|
|
72
|
+
console.error(" - If nothing specified: All 119 tools enabled");
|
|
28
73
|
process.exit(1);
|
|
29
74
|
}
|
|
30
75
|
|
|
@@ -33,22 +78,23 @@ let connectionConfig;
|
|
|
33
78
|
let database;
|
|
34
79
|
try {
|
|
35
80
|
const url = new URL(mysqlUrl);
|
|
36
|
-
|
|
81
|
+
|
|
37
82
|
// Remove leading slash from pathname and make database optional
|
|
38
|
-
database = url.pathname.replace(/^\//,
|
|
39
|
-
|
|
83
|
+
database = url.pathname.replace(/^\//, "") || null;
|
|
84
|
+
|
|
40
85
|
// Extract username and password from auth
|
|
41
|
-
const auth =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
86
|
+
const auth =
|
|
87
|
+
url.username && url.password
|
|
88
|
+
? { user: url.username, password: url.password }
|
|
89
|
+
: { user: url.username || "root", password: url.password || "" };
|
|
90
|
+
|
|
45
91
|
connectionConfig = {
|
|
46
92
|
host: url.hostname,
|
|
47
93
|
port: url.port || 3306,
|
|
48
94
|
...auth,
|
|
49
|
-
...(database ? { database } : {})
|
|
95
|
+
...(database ? { database } : {}),
|
|
50
96
|
};
|
|
51
|
-
|
|
97
|
+
|
|
52
98
|
// Set environment variables for the server
|
|
53
99
|
process.env.DB_HOST = connectionConfig.host;
|
|
54
100
|
process.env.DB_PORT = connectionConfig.port;
|
|
@@ -57,23 +103,35 @@ try {
|
|
|
57
103
|
if (database) {
|
|
58
104
|
process.env.DB_NAME = database;
|
|
59
105
|
}
|
|
60
|
-
|
|
61
106
|
} catch (error) {
|
|
62
|
-
console.error(
|
|
63
|
-
console.error(
|
|
107
|
+
console.error("Error parsing MySQL URL:", error.message);
|
|
108
|
+
console.error(
|
|
109
|
+
"Usage: npx @berthojoris/mcp-mysql-server mysql://user:password@host:port/dbname",
|
|
110
|
+
);
|
|
64
111
|
process.exit(1);
|
|
65
112
|
}
|
|
66
113
|
|
|
67
|
-
const dbMessage = database
|
|
114
|
+
const dbMessage = database
|
|
68
115
|
? `${connectionConfig.host}:${connectionConfig.port}/${database}`
|
|
69
116
|
: `${connectionConfig.host}:${connectionConfig.port} (no specific database selected)`;
|
|
70
117
|
|
|
71
|
-
// Set permissions as environment
|
|
118
|
+
// Set permissions/categories as environment variables if provided
|
|
72
119
|
if (permissions) {
|
|
73
120
|
process.env.MCP_PERMISSIONS = permissions;
|
|
74
|
-
console.error(`Permissions: ${permissions}`);
|
|
75
|
-
}
|
|
76
|
-
|
|
121
|
+
console.error(`Permissions (Layer 1): ${permissions}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (categories) {
|
|
125
|
+
process.env.MCP_CATEGORIES = categories;
|
|
126
|
+
console.error(`Categories (Layer 2): ${categories}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!permissions && !categories) {
|
|
130
|
+
console.error("Access Control: All tools enabled (no filtering)");
|
|
131
|
+
} else if (permissions && !categories) {
|
|
132
|
+
console.error("Filtering Mode: Permission-based only");
|
|
133
|
+
} else if (permissions && categories) {
|
|
134
|
+
console.error("Filtering Mode: Dual-layer (Permissions + Categories)");
|
|
77
135
|
}
|
|
78
136
|
|
|
79
137
|
// Log to stderr (not stdout, which is used for MCP protocol)
|
|
@@ -82,41 +140,40 @@ console.error(`Starting MySQL MCP server with connection to ${dbMessage}`);
|
|
|
82
140
|
// Run the MCP server
|
|
83
141
|
try {
|
|
84
142
|
// Determine the path to the compiled MCP server file
|
|
85
|
-
const serverPath = path.resolve(__dirname,
|
|
86
|
-
|
|
143
|
+
const serverPath = path.resolve(__dirname, "../dist/mcp-server.js");
|
|
144
|
+
|
|
87
145
|
// Spawn the MCP server process with stdio transport
|
|
88
146
|
// stdin/stdout are used for MCP protocol communication
|
|
89
147
|
// stderr is used for logging
|
|
90
|
-
const server = spawn(
|
|
91
|
-
stdio: [
|
|
92
|
-
env: process.env
|
|
148
|
+
const server = spawn("node", [serverPath], {
|
|
149
|
+
stdio: ["inherit", "inherit", "inherit"],
|
|
150
|
+
env: process.env,
|
|
93
151
|
});
|
|
94
|
-
|
|
152
|
+
|
|
95
153
|
// Handle server process events
|
|
96
|
-
server.on(
|
|
97
|
-
console.error(
|
|
154
|
+
server.on("error", (err) => {
|
|
155
|
+
console.error("Failed to start MCP server:", err);
|
|
98
156
|
process.exit(1);
|
|
99
157
|
});
|
|
100
|
-
|
|
101
|
-
server.on(
|
|
158
|
+
|
|
159
|
+
server.on("exit", (code) => {
|
|
102
160
|
if (code !== 0 && code !== null) {
|
|
103
161
|
console.error(`MCP server exited with code ${code}`);
|
|
104
162
|
process.exit(code);
|
|
105
163
|
}
|
|
106
164
|
});
|
|
107
|
-
|
|
165
|
+
|
|
108
166
|
// Handle termination signals
|
|
109
|
-
process.on(
|
|
110
|
-
console.error(
|
|
111
|
-
server.kill(
|
|
167
|
+
process.on("SIGINT", () => {
|
|
168
|
+
console.error("Shutting down MySQL MCP server...");
|
|
169
|
+
server.kill("SIGINT");
|
|
112
170
|
});
|
|
113
|
-
|
|
114
|
-
process.on(
|
|
115
|
-
console.error(
|
|
116
|
-
server.kill(
|
|
171
|
+
|
|
172
|
+
process.on("SIGTERM", () => {
|
|
173
|
+
console.error("Shutting down MySQL MCP server...");
|
|
174
|
+
server.kill("SIGTERM");
|
|
117
175
|
});
|
|
118
|
-
|
|
119
176
|
} catch (error) {
|
|
120
|
-
console.error(
|
|
177
|
+
console.error("Error starting MCP server:", error.message);
|
|
121
178
|
process.exit(1);
|
|
122
|
-
}
|
|
179
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Available MCP tool categories
|
|
2
|
+
* Available MCP tool categories (Legacy - for backward compatibility)
|
|
3
3
|
*/
|
|
4
4
|
export declare enum ToolCategory {
|
|
5
5
|
LIST = "list",// List databases, tables, etc.
|
|
@@ -14,26 +14,69 @@ export declare enum ToolCategory {
|
|
|
14
14
|
PROCEDURE = "procedure"
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Documentation categories from README (21 categories)
|
|
18
|
+
* More intuitive and matches user mental model
|
|
19
|
+
*/
|
|
20
|
+
export declare enum DocCategory {
|
|
21
|
+
DATABASE_DISCOVERY = "database_discovery",
|
|
22
|
+
CRUD_OPERATIONS = "crud_operations",
|
|
23
|
+
BULK_OPERATIONS = "bulk_operations",
|
|
24
|
+
CUSTOM_QUERIES = "custom_queries",
|
|
25
|
+
SCHEMA_MANAGEMENT = "schema_management",
|
|
26
|
+
UTILITIES = "utilities",
|
|
27
|
+
TRANSACTION_MANAGEMENT = "transaction_management",
|
|
28
|
+
STORED_PROCEDURES = "stored_procedures",
|
|
29
|
+
VIEWS_MANAGEMENT = "views_management",
|
|
30
|
+
TRIGGERS_MANAGEMENT = "triggers_management",
|
|
31
|
+
FUNCTIONS_MANAGEMENT = "functions_management",
|
|
32
|
+
INDEX_MANAGEMENT = "index_management",
|
|
33
|
+
CONSTRAINT_MANAGEMENT = "constraint_management",
|
|
34
|
+
TABLE_MAINTENANCE = "table_maintenance",
|
|
35
|
+
SERVER_MANAGEMENT = "server_management",
|
|
36
|
+
PERFORMANCE_MONITORING = "performance_monitoring",
|
|
37
|
+
CACHE_MANAGEMENT = "cache_management",
|
|
38
|
+
QUERY_OPTIMIZATION = "query_optimization",
|
|
39
|
+
BACKUP_RESTORE = "backup_restore",
|
|
40
|
+
IMPORT_EXPORT = "import_export",
|
|
41
|
+
DATA_MIGRATION = "data_migration",
|
|
42
|
+
SCHEMA_MIGRATIONS = "schema_migrations"
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Map of tool names to their legacy categories
|
|
18
46
|
*/
|
|
19
47
|
export declare const toolCategoryMap: Record<string, ToolCategory>;
|
|
48
|
+
/**
|
|
49
|
+
* Map of tool names to their documentation categories (New Enhanced System)
|
|
50
|
+
*/
|
|
51
|
+
export declare const toolDocCategoryMap: Record<string, DocCategory>;
|
|
20
52
|
/**
|
|
21
53
|
* Class to manage feature configuration based on runtime or environment variables
|
|
54
|
+
* Supports dual-layer filtering:
|
|
55
|
+
* - Layer 1 (Permissions): Legacy categories (broad control)
|
|
56
|
+
* - Layer 2 (Categories): Documentation categories (fine-grained control, optional)
|
|
22
57
|
*/
|
|
23
58
|
export declare class FeatureConfig {
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
|
|
59
|
+
private enabledLegacyCategories;
|
|
60
|
+
private enabledDocCategories;
|
|
61
|
+
private originalPermissionsString;
|
|
62
|
+
private originalCategoriesString;
|
|
63
|
+
private useDualLayer;
|
|
64
|
+
constructor(permissionsStr?: string, categoriesStr?: string);
|
|
27
65
|
/**
|
|
28
|
-
* Parse
|
|
66
|
+
* Parse permissions and categories for dual-layer filtering
|
|
67
|
+
* Layer 1 (permissions): Broad control using legacy categories
|
|
68
|
+
* Layer 2 (categories): Fine-grained control using documentation categories (optional)
|
|
29
69
|
*/
|
|
30
70
|
private parseConfig;
|
|
31
71
|
/**
|
|
32
72
|
* Update configuration at runtime
|
|
33
73
|
*/
|
|
34
|
-
setConfig(
|
|
74
|
+
setConfig(permissionsStr: string, categoriesStr?: string): void;
|
|
35
75
|
/**
|
|
36
76
|
* Check if a specific tool is enabled
|
|
77
|
+
* Dual-layer logic:
|
|
78
|
+
* - Layer 1 (Permission): Tool must be allowed by its legacy category
|
|
79
|
+
* - Layer 2 (Category): If categories specified, tool must also be in allowed doc category
|
|
37
80
|
*/
|
|
38
81
|
isToolEnabled(toolName: string): boolean;
|
|
39
82
|
/**
|
|
@@ -41,16 +84,36 @@ export declare class FeatureConfig {
|
|
|
41
84
|
*/
|
|
42
85
|
getPermissionError(toolName: string): string;
|
|
43
86
|
/**
|
|
44
|
-
* Check if a category is enabled
|
|
87
|
+
* Check if a legacy category is enabled
|
|
45
88
|
*/
|
|
46
89
|
isCategoryEnabled(category: ToolCategory): boolean;
|
|
47
90
|
/**
|
|
48
|
-
*
|
|
91
|
+
* Check if a documentation category is enabled
|
|
92
|
+
*/
|
|
93
|
+
isDocCategoryEnabled(category: DocCategory): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Get all enabled legacy categories
|
|
49
96
|
*/
|
|
50
97
|
getEnabledCategories(): ToolCategory[];
|
|
98
|
+
/**
|
|
99
|
+
* Get all enabled documentation categories
|
|
100
|
+
*/
|
|
101
|
+
getEnabledDocCategories(): DocCategory[];
|
|
51
102
|
/**
|
|
52
103
|
* Get all available categories with their status
|
|
53
104
|
*/
|
|
54
105
|
getCategoryStatus(): Record<ToolCategory, boolean>;
|
|
106
|
+
/**
|
|
107
|
+
* Get all available documentation categories with their status
|
|
108
|
+
*/
|
|
109
|
+
getDocCategoryStatus(): Record<DocCategory, boolean>;
|
|
110
|
+
/**
|
|
111
|
+
* Check if using dual-layer filtering mode
|
|
112
|
+
*/
|
|
113
|
+
isUsingDualLayer(): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Get filtering mode description
|
|
116
|
+
*/
|
|
117
|
+
getFilteringMode(): string;
|
|
55
118
|
}
|
|
56
119
|
export declare const featureConfig: FeatureConfig;
|