@berthojoris/mcp-mysql-server 1.0.2 → 1.1.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/README.md CHANGED
@@ -925,48 +925,7 @@ curl http://localhost:3000/health
925
925
 
926
926
  ---
927
927
 
928
- ## 🚀 Publishing to npm
929
-
930
- To make your MCP server available to the world:
931
-
932
- ### 1. Update package.json
933
-
934
- ```json
935
- {
936
- "name": "@your-username/mcp-mysql",
937
- "author": "Your Name <your.email@example.com>",
938
- "repository": {
939
- "type": "git",
940
- "url": "https://github.com/berthojoris/mysql-mcp.git"
941
- }
942
- }
943
- ```
944
-
945
- ### 2. Build
946
-
947
- ```bash
948
- npm run build
949
- ```
950
-
951
- ### 3. Publish
952
-
953
- ```bash
954
- # Login to npm
955
- npm login
956
-
957
- # Publish (for scoped packages)
958
- npm publish --access public
959
- ```
960
-
961
- ### 4. Users Can Install
962
-
963
- ```bash
964
- npx @your-username/mcp-mysql mysql://user:pass@localhost:3306/db "list,read,utility"
965
- ```
966
-
967
- ---
968
-
969
- ## 🐛 Troubleshooting
928
+ ## Troubleshooting
970
929
 
971
930
  ### MCP Server Not Connecting
972
931
 
@@ -3,7 +3,8 @@ export declare class DatabaseTools {
3
3
  private db;
4
4
  constructor();
5
5
  /**
6
- * List all available databases
6
+ * List only the connected database (security restriction)
7
+ * This prevents access to other databases on the MySQL server
7
8
  */
8
9
  listDatabases(): Promise<{
9
10
  status: string;
@@ -6,20 +6,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DatabaseTools = void 0;
7
7
  const connection_1 = __importDefault(require("../db/connection"));
8
8
  const schemas_1 = require("../validation/schemas");
9
+ const config_1 = require("../config/config");
9
10
  class DatabaseTools {
10
11
  constructor() {
11
12
  this.db = connection_1.default.getInstance();
12
13
  }
13
14
  /**
14
- * List all available databases
15
+ * List only the connected database (security restriction)
16
+ * This prevents access to other databases on the MySQL server
15
17
  */
16
18
  async listDatabases() {
17
19
  try {
18
- const results = await this.db.query('SHOW DATABASES');
19
- const databases = results.map(row => row.Database);
20
+ // Only return the database specified in the connection string
21
+ // This is a security measure to prevent access to other databases
22
+ if (!config_1.dbConfig.database) {
23
+ return {
24
+ status: 'error',
25
+ error: 'No database specified in connection string. Please specify a database name in your MySQL connection URL.'
26
+ };
27
+ }
28
+ // Verify the database exists and is accessible
29
+ const results = await this.db.query('SELECT DATABASE() as current_database');
30
+ const currentDatabase = results[0]?.current_database;
31
+ if (!currentDatabase) {
32
+ return {
33
+ status: 'error',
34
+ error: 'No database selected. Please ensure your connection string includes a valid database name.'
35
+ };
36
+ }
20
37
  return {
21
38
  status: 'success',
22
- data: databases
39
+ data: [currentDatabase]
23
40
  };
24
41
  }
25
42
  catch (error) {
@@ -41,8 +58,23 @@ class DatabaseTools {
41
58
  };
42
59
  }
43
60
  try {
61
+ // Security validation: if database is specified, ensure it matches the connected database
62
+ if (params.database) {
63
+ if (!config_1.dbConfig.database) {
64
+ return {
65
+ status: 'error',
66
+ error: 'No database specified in connection string. Cannot access other databases.'
67
+ };
68
+ }
69
+ if (params.database !== config_1.dbConfig.database) {
70
+ return {
71
+ status: 'error',
72
+ error: `Access denied. You can only access the connected database '${config_1.dbConfig.database}'. Requested database '${params.database}' is not allowed.`
73
+ };
74
+ }
75
+ }
44
76
  let query = 'SHOW TABLES';
45
- // If database is specified, use it
77
+ // If database is specified and validated, use it
46
78
  if (params.database) {
47
79
  query = `SHOW TABLES FROM \`${params.database}\``;
48
80
  }
@@ -3,6 +3,10 @@ export declare class StoredProcedureTools {
3
3
  private db;
4
4
  private security;
5
5
  constructor(security: SecurityLayer);
6
+ /**
7
+ * Validate database access - ensures only the connected database can be accessed
8
+ */
9
+ private validateDatabaseAccess;
6
10
  /**
7
11
  * List all stored procedures in the current database
8
12
  */
@@ -12,6 +12,38 @@ class StoredProcedureTools {
12
12
  this.db = connection_1.default.getInstance();
13
13
  this.security = security;
14
14
  }
15
+ /**
16
+ * Validate database access - ensures only the connected database can be accessed
17
+ */
18
+ validateDatabaseAccess(requestedDatabase) {
19
+ const connectedDatabase = config_1.dbConfig.database;
20
+ if (!connectedDatabase) {
21
+ return {
22
+ valid: false,
23
+ database: '',
24
+ error: 'No database specified in connection string. Cannot access any database.'
25
+ };
26
+ }
27
+ // If no database is requested, use the connected database
28
+ if (!requestedDatabase) {
29
+ return {
30
+ valid: true,
31
+ database: connectedDatabase
32
+ };
33
+ }
34
+ // If a specific database is requested, ensure it matches the connected database
35
+ if (requestedDatabase !== connectedDatabase) {
36
+ return {
37
+ valid: false,
38
+ database: '',
39
+ error: `Access denied. You can only access the connected database '${connectedDatabase}'. Requested database '${requestedDatabase}' is not allowed.`
40
+ };
41
+ }
42
+ return {
43
+ valid: true,
44
+ database: connectedDatabase
45
+ };
46
+ }
15
47
  /**
16
48
  * List all stored procedures in the current database
17
49
  */
@@ -24,13 +56,15 @@ class StoredProcedureTools {
24
56
  error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateListStoredProcedures.errors)
25
57
  };
26
58
  }
27
- const database = params.database || config_1.dbConfig.database;
28
- if (!database) {
59
+ // Validate database access
60
+ const dbValidation = this.validateDatabaseAccess(params.database);
61
+ if (!dbValidation.valid) {
29
62
  return {
30
63
  status: 'error',
31
- error: 'No database specified and no current database selected'
64
+ error: dbValidation.error
32
65
  };
33
66
  }
67
+ const database = dbValidation.database;
34
68
  const query = `
35
69
  SELECT
36
70
  ROUTINE_NAME as name,
@@ -72,14 +106,16 @@ class StoredProcedureTools {
72
106
  error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateGetStoredProcedureInfo.errors)
73
107
  };
74
108
  }
75
- const { procedure_name } = params;
76
- const database = params.database || config_1.dbConfig.database;
77
- if (!database) {
109
+ // Validate database access
110
+ const dbValidation = this.validateDatabaseAccess(params.database);
111
+ if (!dbValidation.valid) {
78
112
  return {
79
113
  status: 'error',
80
- error: 'No database specified and no current database selected'
114
+ error: dbValidation.error
81
115
  };
82
116
  }
117
+ const { procedure_name } = params;
118
+ const database = dbValidation.database;
83
119
  // Get procedure information
84
120
  const procedureQuery = `
85
121
  SELECT
@@ -148,14 +184,16 @@ class StoredProcedureTools {
148
184
  };
149
185
  }
150
186
  try {
151
- const { procedure_name, parameters = [] } = params;
152
- const database = params.database || config_1.dbConfig.database;
153
- if (!database) {
187
+ // Validate database access
188
+ const dbValidation = this.validateDatabaseAccess(params.database);
189
+ if (!dbValidation.valid) {
154
190
  return {
155
191
  status: 'error',
156
- error: 'No database specified and no current database selected'
192
+ error: dbValidation.error
157
193
  };
158
194
  }
195
+ const { procedure_name, parameters = [] } = params;
196
+ const database = dbValidation.database;
159
197
  // Validate procedure name
160
198
  const identifierValidation = this.security.validateIdentifier(procedure_name);
161
199
  if (!identifierValidation.valid) {
@@ -260,14 +298,16 @@ class StoredProcedureTools {
260
298
  };
261
299
  }
262
300
  try {
263
- const { procedure_name, parameters = [], body, comment } = params;
264
- const database = params.database || config_1.dbConfig.database;
265
- if (!database) {
301
+ // Validate database access
302
+ const dbValidation = this.validateDatabaseAccess(params.database);
303
+ if (!dbValidation.valid) {
266
304
  return {
267
305
  status: 'error',
268
- error: 'No database specified and no current database selected'
306
+ error: dbValidation.error
269
307
  };
270
308
  }
309
+ const { procedure_name, parameters = [], body, comment } = params;
310
+ const database = dbValidation.database;
271
311
  // Validate procedure name
272
312
  const identifierValidation = this.security.validateIdentifier(procedure_name);
273
313
  if (!identifierValidation.valid) {
@@ -327,14 +367,16 @@ class StoredProcedureTools {
327
367
  error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateDropStoredProcedure.errors)
328
368
  };
329
369
  }
330
- const { procedure_name, if_exists = false } = params;
331
- const database = params.database || config_1.dbConfig.database;
332
- if (!database) {
370
+ // Validate database access
371
+ const dbValidation = this.validateDatabaseAccess(params.database);
372
+ if (!dbValidation.valid) {
333
373
  return {
334
374
  status: 'error',
335
- error: 'No database specified and no current database selected'
375
+ error: dbValidation.error
336
376
  };
337
377
  }
378
+ const { procedure_name, if_exists = false } = params;
379
+ const database = dbValidation.database;
338
380
  // Validate procedure name
339
381
  const identifierValidation = this.security.validateIdentifier(procedure_name);
340
382
  if (!identifierValidation.valid) {
@@ -371,14 +413,16 @@ class StoredProcedureTools {
371
413
  error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateShowCreateProcedure.errors)
372
414
  };
373
415
  }
374
- const { procedure_name } = params;
375
- const database = params.database || config_1.dbConfig.database;
376
- if (!database) {
416
+ // Validate database access
417
+ const dbValidation = this.validateDatabaseAccess(params.database);
418
+ if (!dbValidation.valid) {
377
419
  return {
378
420
  status: 'error',
379
- error: 'No database specified and no current database selected'
421
+ error: dbValidation.error
380
422
  };
381
423
  }
424
+ const { procedure_name } = params;
425
+ const database = dbValidation.database;
382
426
  // Validate procedure name
383
427
  const identifierValidation = this.security.validateIdentifier(procedure_name);
384
428
  if (!identifierValidation.valid) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@berthojoris/mcp-mysql-server",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",