@berthojoris/mcp-mysql-server 1.10.0 → 1.10.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/DOCUMENTATIONS.md +3847 -3617
- package/README.md +134 -12
- 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
|
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.featureConfig = exports.FeatureConfig = exports.toolCategoryMap = exports.ToolCategory = void 0;
|
|
6
|
+
exports.featureConfig = exports.FeatureConfig = exports.toolDocCategoryMap = exports.toolCategoryMap = exports.DocCategory = exports.ToolCategory = void 0;
|
|
7
7
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
8
8
|
// Load environment variables
|
|
9
9
|
dotenv_1.default.config();
|
|
10
10
|
/**
|
|
11
|
-
* Available MCP tool categories
|
|
11
|
+
* Available MCP tool categories (Legacy - for backward compatibility)
|
|
12
12
|
*/
|
|
13
13
|
var ToolCategory;
|
|
14
14
|
(function (ToolCategory) {
|
|
@@ -24,7 +24,36 @@ var ToolCategory;
|
|
|
24
24
|
ToolCategory["PROCEDURE"] = "procedure";
|
|
25
25
|
})(ToolCategory || (exports.ToolCategory = ToolCategory = {}));
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Documentation categories from README (21 categories)
|
|
28
|
+
* More intuitive and matches user mental model
|
|
29
|
+
*/
|
|
30
|
+
var DocCategory;
|
|
31
|
+
(function (DocCategory) {
|
|
32
|
+
DocCategory["DATABASE_DISCOVERY"] = "database_discovery";
|
|
33
|
+
DocCategory["CRUD_OPERATIONS"] = "crud_operations";
|
|
34
|
+
DocCategory["BULK_OPERATIONS"] = "bulk_operations";
|
|
35
|
+
DocCategory["CUSTOM_QUERIES"] = "custom_queries";
|
|
36
|
+
DocCategory["SCHEMA_MANAGEMENT"] = "schema_management";
|
|
37
|
+
DocCategory["UTILITIES"] = "utilities";
|
|
38
|
+
DocCategory["TRANSACTION_MANAGEMENT"] = "transaction_management";
|
|
39
|
+
DocCategory["STORED_PROCEDURES"] = "stored_procedures";
|
|
40
|
+
DocCategory["VIEWS_MANAGEMENT"] = "views_management";
|
|
41
|
+
DocCategory["TRIGGERS_MANAGEMENT"] = "triggers_management";
|
|
42
|
+
DocCategory["FUNCTIONS_MANAGEMENT"] = "functions_management";
|
|
43
|
+
DocCategory["INDEX_MANAGEMENT"] = "index_management";
|
|
44
|
+
DocCategory["CONSTRAINT_MANAGEMENT"] = "constraint_management";
|
|
45
|
+
DocCategory["TABLE_MAINTENANCE"] = "table_maintenance";
|
|
46
|
+
DocCategory["SERVER_MANAGEMENT"] = "server_management";
|
|
47
|
+
DocCategory["PERFORMANCE_MONITORING"] = "performance_monitoring";
|
|
48
|
+
DocCategory["CACHE_MANAGEMENT"] = "cache_management";
|
|
49
|
+
DocCategory["QUERY_OPTIMIZATION"] = "query_optimization";
|
|
50
|
+
DocCategory["BACKUP_RESTORE"] = "backup_restore";
|
|
51
|
+
DocCategory["IMPORT_EXPORT"] = "import_export";
|
|
52
|
+
DocCategory["DATA_MIGRATION"] = "data_migration";
|
|
53
|
+
DocCategory["SCHEMA_MIGRATIONS"] = "schema_migrations";
|
|
54
|
+
})(DocCategory || (exports.DocCategory = DocCategory = {}));
|
|
55
|
+
/**
|
|
56
|
+
* Map of tool names to their legacy categories
|
|
28
57
|
*/
|
|
29
58
|
exports.toolCategoryMap = {
|
|
30
59
|
// Database tools
|
|
@@ -169,124 +198,383 @@ exports.toolCategoryMap = {
|
|
|
169
198
|
getDatabaseHealthCheck: ToolCategory.UTILITY,
|
|
170
199
|
resetPerformanceStats: ToolCategory.UTILITY,
|
|
171
200
|
};
|
|
201
|
+
/**
|
|
202
|
+
* Map of tool names to their documentation categories (New Enhanced System)
|
|
203
|
+
*/
|
|
204
|
+
exports.toolDocCategoryMap = {
|
|
205
|
+
// Database Discovery
|
|
206
|
+
listDatabases: DocCategory.DATABASE_DISCOVERY,
|
|
207
|
+
listTables: DocCategory.DATABASE_DISCOVERY,
|
|
208
|
+
readTableSchema: DocCategory.DATABASE_DISCOVERY,
|
|
209
|
+
getTableRelationships: DocCategory.DATABASE_DISCOVERY,
|
|
210
|
+
// CRUD Operations
|
|
211
|
+
createRecord: DocCategory.CRUD_OPERATIONS,
|
|
212
|
+
readRecords: DocCategory.CRUD_OPERATIONS,
|
|
213
|
+
updateRecord: DocCategory.CRUD_OPERATIONS,
|
|
214
|
+
deleteRecord: DocCategory.CRUD_OPERATIONS,
|
|
215
|
+
// Bulk Operations
|
|
216
|
+
bulkInsert: DocCategory.BULK_OPERATIONS,
|
|
217
|
+
bulkUpdate: DocCategory.BULK_OPERATIONS,
|
|
218
|
+
bulkDelete: DocCategory.BULK_OPERATIONS,
|
|
219
|
+
// Custom Queries
|
|
220
|
+
runQuery: DocCategory.CUSTOM_QUERIES,
|
|
221
|
+
executeSql: DocCategory.CUSTOM_QUERIES,
|
|
222
|
+
// Schema Management (DDL)
|
|
223
|
+
createTable: DocCategory.SCHEMA_MANAGEMENT,
|
|
224
|
+
alterTable: DocCategory.SCHEMA_MANAGEMENT,
|
|
225
|
+
dropTable: DocCategory.SCHEMA_MANAGEMENT,
|
|
226
|
+
executeDdl: DocCategory.SCHEMA_MANAGEMENT,
|
|
227
|
+
// Utilities
|
|
228
|
+
testConnection: DocCategory.UTILITIES,
|
|
229
|
+
describeConnection: DocCategory.UTILITIES,
|
|
230
|
+
exportTableToCSV: DocCategory.UTILITIES,
|
|
231
|
+
exportQueryToCSV: DocCategory.UTILITIES,
|
|
232
|
+
// Transaction Management
|
|
233
|
+
beginTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
|
234
|
+
commitTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
|
235
|
+
rollbackTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
|
236
|
+
getTransactionStatus: DocCategory.TRANSACTION_MANAGEMENT,
|
|
237
|
+
executeInTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
|
238
|
+
// Stored Procedures
|
|
239
|
+
listStoredProcedures: DocCategory.STORED_PROCEDURES,
|
|
240
|
+
getStoredProcedureInfo: DocCategory.STORED_PROCEDURES,
|
|
241
|
+
executeStoredProcedure: DocCategory.STORED_PROCEDURES,
|
|
242
|
+
createStoredProcedure: DocCategory.STORED_PROCEDURES,
|
|
243
|
+
dropStoredProcedure: DocCategory.STORED_PROCEDURES,
|
|
244
|
+
showCreateProcedure: DocCategory.STORED_PROCEDURES,
|
|
245
|
+
// Views Management
|
|
246
|
+
listViews: DocCategory.VIEWS_MANAGEMENT,
|
|
247
|
+
getViewInfo: DocCategory.VIEWS_MANAGEMENT,
|
|
248
|
+
createView: DocCategory.VIEWS_MANAGEMENT,
|
|
249
|
+
alterView: DocCategory.VIEWS_MANAGEMENT,
|
|
250
|
+
dropView: DocCategory.VIEWS_MANAGEMENT,
|
|
251
|
+
showCreateView: DocCategory.VIEWS_MANAGEMENT,
|
|
252
|
+
// Triggers Management
|
|
253
|
+
listTriggers: DocCategory.TRIGGERS_MANAGEMENT,
|
|
254
|
+
getTriggerInfo: DocCategory.TRIGGERS_MANAGEMENT,
|
|
255
|
+
createTrigger: DocCategory.TRIGGERS_MANAGEMENT,
|
|
256
|
+
dropTrigger: DocCategory.TRIGGERS_MANAGEMENT,
|
|
257
|
+
showCreateTrigger: DocCategory.TRIGGERS_MANAGEMENT,
|
|
258
|
+
// Functions Management
|
|
259
|
+
listFunctions: DocCategory.FUNCTIONS_MANAGEMENT,
|
|
260
|
+
getFunctionInfo: DocCategory.FUNCTIONS_MANAGEMENT,
|
|
261
|
+
createFunction: DocCategory.FUNCTIONS_MANAGEMENT,
|
|
262
|
+
dropFunction: DocCategory.FUNCTIONS_MANAGEMENT,
|
|
263
|
+
showCreateFunction: DocCategory.FUNCTIONS_MANAGEMENT,
|
|
264
|
+
executeFunction: DocCategory.FUNCTIONS_MANAGEMENT,
|
|
265
|
+
// Index Management
|
|
266
|
+
listIndexes: DocCategory.INDEX_MANAGEMENT,
|
|
267
|
+
getIndexInfo: DocCategory.INDEX_MANAGEMENT,
|
|
268
|
+
createIndex: DocCategory.INDEX_MANAGEMENT,
|
|
269
|
+
dropIndex: DocCategory.INDEX_MANAGEMENT,
|
|
270
|
+
analyzeIndex: DocCategory.INDEX_MANAGEMENT,
|
|
271
|
+
// Constraint Management
|
|
272
|
+
listForeignKeys: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
273
|
+
listConstraints: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
274
|
+
addForeignKey: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
275
|
+
dropForeignKey: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
276
|
+
addUniqueConstraint: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
277
|
+
dropConstraint: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
278
|
+
addCheckConstraint: DocCategory.CONSTRAINT_MANAGEMENT,
|
|
279
|
+
// Table Maintenance
|
|
280
|
+
analyzeTable: DocCategory.TABLE_MAINTENANCE,
|
|
281
|
+
optimizeTable: DocCategory.TABLE_MAINTENANCE,
|
|
282
|
+
checkTable: DocCategory.TABLE_MAINTENANCE,
|
|
283
|
+
repairTable: DocCategory.TABLE_MAINTENANCE,
|
|
284
|
+
truncateTable: DocCategory.TABLE_MAINTENANCE,
|
|
285
|
+
getTableStatus: DocCategory.TABLE_MAINTENANCE,
|
|
286
|
+
flushTable: DocCategory.TABLE_MAINTENANCE,
|
|
287
|
+
getTableSize: DocCategory.TABLE_MAINTENANCE,
|
|
288
|
+
// Server Management
|
|
289
|
+
showProcessList: DocCategory.SERVER_MANAGEMENT,
|
|
290
|
+
killProcess: DocCategory.SERVER_MANAGEMENT,
|
|
291
|
+
showStatus: DocCategory.SERVER_MANAGEMENT,
|
|
292
|
+
showVariables: DocCategory.SERVER_MANAGEMENT,
|
|
293
|
+
explainQuery: DocCategory.SERVER_MANAGEMENT,
|
|
294
|
+
showEngineStatus: DocCategory.SERVER_MANAGEMENT,
|
|
295
|
+
getServerInfo: DocCategory.SERVER_MANAGEMENT,
|
|
296
|
+
showBinaryLogs: DocCategory.SERVER_MANAGEMENT,
|
|
297
|
+
showReplicationStatus: DocCategory.SERVER_MANAGEMENT,
|
|
298
|
+
// Performance Monitoring
|
|
299
|
+
getPerformanceMetrics: DocCategory.PERFORMANCE_MONITORING,
|
|
300
|
+
getTopQueriesByTime: DocCategory.PERFORMANCE_MONITORING,
|
|
301
|
+
getTopQueriesByCount: DocCategory.PERFORMANCE_MONITORING,
|
|
302
|
+
getSlowQueries: DocCategory.PERFORMANCE_MONITORING,
|
|
303
|
+
getTableIOStats: DocCategory.PERFORMANCE_MONITORING,
|
|
304
|
+
getIndexUsageStats: DocCategory.PERFORMANCE_MONITORING,
|
|
305
|
+
getUnusedIndexes: DocCategory.PERFORMANCE_MONITORING,
|
|
306
|
+
getConnectionPoolStats: DocCategory.PERFORMANCE_MONITORING,
|
|
307
|
+
getDatabaseHealthCheck: DocCategory.PERFORMANCE_MONITORING,
|
|
308
|
+
resetPerformanceStats: DocCategory.PERFORMANCE_MONITORING,
|
|
309
|
+
// Cache Management
|
|
310
|
+
getCacheStats: DocCategory.CACHE_MANAGEMENT,
|
|
311
|
+
getCacheConfig: DocCategory.CACHE_MANAGEMENT,
|
|
312
|
+
configureCacheSettings: DocCategory.CACHE_MANAGEMENT,
|
|
313
|
+
clearCache: DocCategory.CACHE_MANAGEMENT,
|
|
314
|
+
invalidateCacheForTable: DocCategory.CACHE_MANAGEMENT,
|
|
315
|
+
// Query Optimization
|
|
316
|
+
analyzeQuery: DocCategory.QUERY_OPTIMIZATION,
|
|
317
|
+
getOptimizationHints: DocCategory.QUERY_OPTIMIZATION,
|
|
318
|
+
// Backup & Restore
|
|
319
|
+
backupTable: DocCategory.BACKUP_RESTORE,
|
|
320
|
+
backupDatabase: DocCategory.BACKUP_RESTORE,
|
|
321
|
+
restoreFromSql: DocCategory.BACKUP_RESTORE,
|
|
322
|
+
getCreateTableStatement: DocCategory.BACKUP_RESTORE,
|
|
323
|
+
getDatabaseSchema: DocCategory.BACKUP_RESTORE,
|
|
324
|
+
// Import/Export
|
|
325
|
+
exportTableToJSON: DocCategory.IMPORT_EXPORT,
|
|
326
|
+
exportQueryToJSON: DocCategory.IMPORT_EXPORT,
|
|
327
|
+
exportTableToSql: DocCategory.IMPORT_EXPORT,
|
|
328
|
+
importFromCSV: DocCategory.IMPORT_EXPORT,
|
|
329
|
+
importFromJSON: DocCategory.IMPORT_EXPORT,
|
|
330
|
+
// Data Migration
|
|
331
|
+
copyTableData: DocCategory.DATA_MIGRATION,
|
|
332
|
+
moveTableData: DocCategory.DATA_MIGRATION,
|
|
333
|
+
cloneTable: DocCategory.DATA_MIGRATION,
|
|
334
|
+
compareTableStructure: DocCategory.DATA_MIGRATION,
|
|
335
|
+
syncTableData: DocCategory.DATA_MIGRATION,
|
|
336
|
+
// Schema Migrations
|
|
337
|
+
initMigrationsTable: DocCategory.SCHEMA_MIGRATIONS,
|
|
338
|
+
createMigration: DocCategory.SCHEMA_MIGRATIONS,
|
|
339
|
+
applyMigrations: DocCategory.SCHEMA_MIGRATIONS,
|
|
340
|
+
rollbackMigration: DocCategory.SCHEMA_MIGRATIONS,
|
|
341
|
+
getMigrationStatus: DocCategory.SCHEMA_MIGRATIONS,
|
|
342
|
+
getSchemaVersion: DocCategory.SCHEMA_MIGRATIONS,
|
|
343
|
+
validateMigrations: DocCategory.SCHEMA_MIGRATIONS,
|
|
344
|
+
resetFailedMigration: DocCategory.SCHEMA_MIGRATIONS,
|
|
345
|
+
generateMigrationFromDiff: DocCategory.SCHEMA_MIGRATIONS,
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* Mapping between legacy categories and documentation categories
|
|
349
|
+
* This allows backward compatibility
|
|
350
|
+
*/
|
|
351
|
+
const legacyToDocCategoryMap = {
|
|
352
|
+
list: [
|
|
353
|
+
DocCategory.DATABASE_DISCOVERY,
|
|
354
|
+
DocCategory.STORED_PROCEDURES,
|
|
355
|
+
DocCategory.VIEWS_MANAGEMENT,
|
|
356
|
+
DocCategory.TRIGGERS_MANAGEMENT,
|
|
357
|
+
DocCategory.FUNCTIONS_MANAGEMENT,
|
|
358
|
+
DocCategory.INDEX_MANAGEMENT,
|
|
359
|
+
DocCategory.CONSTRAINT_MANAGEMENT,
|
|
360
|
+
DocCategory.TABLE_MAINTENANCE,
|
|
361
|
+
DocCategory.SERVER_MANAGEMENT,
|
|
362
|
+
DocCategory.SCHEMA_MIGRATIONS,
|
|
363
|
+
],
|
|
364
|
+
read: [DocCategory.CRUD_OPERATIONS, DocCategory.CUSTOM_QUERIES],
|
|
365
|
+
create: [
|
|
366
|
+
DocCategory.CRUD_OPERATIONS,
|
|
367
|
+
DocCategory.BULK_OPERATIONS,
|
|
368
|
+
DocCategory.IMPORT_EXPORT,
|
|
369
|
+
DocCategory.DATA_MIGRATION,
|
|
370
|
+
],
|
|
371
|
+
update: [
|
|
372
|
+
DocCategory.CRUD_OPERATIONS,
|
|
373
|
+
DocCategory.BULK_OPERATIONS,
|
|
374
|
+
DocCategory.DATA_MIGRATION,
|
|
375
|
+
],
|
|
376
|
+
delete: [
|
|
377
|
+
DocCategory.CRUD_OPERATIONS,
|
|
378
|
+
DocCategory.BULK_OPERATIONS,
|
|
379
|
+
DocCategory.DATA_MIGRATION,
|
|
380
|
+
],
|
|
381
|
+
execute: [DocCategory.CUSTOM_QUERIES, DocCategory.SERVER_MANAGEMENT],
|
|
382
|
+
ddl: [
|
|
383
|
+
DocCategory.SCHEMA_MANAGEMENT,
|
|
384
|
+
DocCategory.VIEWS_MANAGEMENT,
|
|
385
|
+
DocCategory.TRIGGERS_MANAGEMENT,
|
|
386
|
+
DocCategory.INDEX_MANAGEMENT,
|
|
387
|
+
DocCategory.CONSTRAINT_MANAGEMENT,
|
|
388
|
+
DocCategory.TABLE_MAINTENANCE,
|
|
389
|
+
DocCategory.BACKUP_RESTORE,
|
|
390
|
+
DocCategory.DATA_MIGRATION,
|
|
391
|
+
DocCategory.SCHEMA_MIGRATIONS,
|
|
392
|
+
],
|
|
393
|
+
utility: [
|
|
394
|
+
DocCategory.UTILITIES,
|
|
395
|
+
DocCategory.TABLE_MAINTENANCE,
|
|
396
|
+
DocCategory.PERFORMANCE_MONITORING,
|
|
397
|
+
DocCategory.CACHE_MANAGEMENT,
|
|
398
|
+
DocCategory.QUERY_OPTIMIZATION,
|
|
399
|
+
DocCategory.BACKUP_RESTORE,
|
|
400
|
+
DocCategory.IMPORT_EXPORT,
|
|
401
|
+
],
|
|
402
|
+
transaction: [DocCategory.TRANSACTION_MANAGEMENT],
|
|
403
|
+
procedure: [DocCategory.STORED_PROCEDURES, DocCategory.FUNCTIONS_MANAGEMENT],
|
|
404
|
+
};
|
|
172
405
|
/**
|
|
173
406
|
* Class to manage feature configuration based on runtime or environment variables
|
|
407
|
+
* Supports dual-layer filtering:
|
|
408
|
+
* - Layer 1 (Permissions): Legacy categories (broad control)
|
|
409
|
+
* - Layer 2 (Categories): Documentation categories (fine-grained control, optional)
|
|
174
410
|
*/
|
|
175
411
|
class FeatureConfig {
|
|
176
|
-
constructor(
|
|
177
|
-
|
|
178
|
-
|
|
412
|
+
constructor(permissionsStr, categoriesStr) {
|
|
413
|
+
// Support both old single-parameter and new dual-parameter signatures
|
|
414
|
+
const permissions = permissionsStr ||
|
|
415
|
+
process.env.MCP_PERMISSIONS ||
|
|
416
|
+
process.env.MCP_CONFIG ||
|
|
417
|
+
"";
|
|
418
|
+
const categories = categoriesStr || process.env.MCP_CATEGORIES || "";
|
|
419
|
+
this.originalPermissionsString = permissions;
|
|
420
|
+
this.originalCategoriesString = categories;
|
|
421
|
+
this.useDualLayer = !!categories.trim();
|
|
422
|
+
const parsed = this.parseConfig(permissions, categories);
|
|
423
|
+
this.enabledLegacyCategories = parsed.legacy;
|
|
424
|
+
this.enabledDocCategories = parsed.doc;
|
|
179
425
|
}
|
|
180
426
|
/**
|
|
181
|
-
* Parse
|
|
427
|
+
* Parse permissions and categories for dual-layer filtering
|
|
428
|
+
* Layer 1 (permissions): Broad control using legacy categories
|
|
429
|
+
* Layer 2 (categories): Fine-grained control using documentation categories (optional)
|
|
182
430
|
*/
|
|
183
|
-
parseConfig(
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
431
|
+
parseConfig(permissionsStr, categoriesStr) {
|
|
432
|
+
// If both are empty, enable all features
|
|
433
|
+
if (!permissionsStr.trim() && !categoriesStr.trim()) {
|
|
434
|
+
return {
|
|
435
|
+
legacy: new Set(Object.values(ToolCategory)),
|
|
436
|
+
doc: new Set(Object.values(DocCategory)),
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
// Parse Layer 1: Permissions (legacy categories)
|
|
440
|
+
let legacySet = new Set();
|
|
441
|
+
if (permissionsStr.trim()) {
|
|
442
|
+
const items = permissionsStr
|
|
443
|
+
.split(",")
|
|
444
|
+
.map((c) => c.trim().toLowerCase());
|
|
445
|
+
const validLegacyCategories = items.filter((c) => Object.values(ToolCategory).includes(c));
|
|
446
|
+
legacySet = new Set(validLegacyCategories);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
// If no permissions specified but categories are, allow all permissions
|
|
450
|
+
legacySet = new Set(Object.values(ToolCategory));
|
|
451
|
+
}
|
|
452
|
+
// Parse Layer 2: Categories (documentation categories)
|
|
453
|
+
let docSet = new Set();
|
|
454
|
+
if (categoriesStr.trim()) {
|
|
455
|
+
// Categories specified - use them for fine-grained filtering
|
|
456
|
+
const items = categoriesStr.split(",").map((c) => c.trim().toLowerCase());
|
|
457
|
+
const validDocCategories = items.filter((c) => Object.values(DocCategory).includes(c));
|
|
458
|
+
docSet = new Set(validDocCategories);
|
|
189
459
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
460
|
+
else {
|
|
461
|
+
// No categories specified - derive from permissions
|
|
462
|
+
legacySet.forEach((legacyCat) => {
|
|
463
|
+
const docCats = legacyToDocCategoryMap[legacyCat] || [];
|
|
464
|
+
docCats.forEach((dc) => docSet.add(dc));
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
legacy: legacySet,
|
|
469
|
+
doc: docSet,
|
|
470
|
+
};
|
|
194
471
|
}
|
|
195
472
|
/**
|
|
196
473
|
* Update configuration at runtime
|
|
197
474
|
*/
|
|
198
|
-
setConfig(
|
|
199
|
-
this.
|
|
200
|
-
this.
|
|
475
|
+
setConfig(permissionsStr, categoriesStr) {
|
|
476
|
+
this.originalPermissionsString = permissionsStr;
|
|
477
|
+
this.originalCategoriesString = categoriesStr || "";
|
|
478
|
+
this.useDualLayer = !!(categoriesStr && categoriesStr.trim());
|
|
479
|
+
const parsed = this.parseConfig(permissionsStr, categoriesStr || "");
|
|
480
|
+
this.enabledLegacyCategories = parsed.legacy;
|
|
481
|
+
this.enabledDocCategories = parsed.doc;
|
|
201
482
|
}
|
|
202
483
|
/**
|
|
203
484
|
* Check if a specific tool is enabled
|
|
485
|
+
* Dual-layer logic:
|
|
486
|
+
* - Layer 1 (Permission): Tool must be allowed by its legacy category
|
|
487
|
+
* - Layer 2 (Category): If categories specified, tool must also be in allowed doc category
|
|
204
488
|
*/
|
|
205
489
|
isToolEnabled(toolName) {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
490
|
+
const docCategory = exports.toolDocCategoryMap[toolName];
|
|
491
|
+
const legacyCategory = exports.toolCategoryMap[toolName];
|
|
492
|
+
// If tool is not in either map, default to disabled
|
|
493
|
+
if (!docCategory && !legacyCategory) {
|
|
209
494
|
console.warn(`Unknown tool: ${toolName}`);
|
|
210
495
|
return false;
|
|
211
496
|
}
|
|
212
|
-
|
|
497
|
+
// Layer 1: Check permission (legacy category)
|
|
498
|
+
const hasPermission = legacyCategory
|
|
499
|
+
? this.enabledLegacyCategories.has(legacyCategory)
|
|
500
|
+
: false;
|
|
501
|
+
if (!hasPermission) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
// Layer 2: Check category (documentation category) if dual-layer mode
|
|
505
|
+
if (this.useDualLayer) {
|
|
506
|
+
const hasCategory = docCategory
|
|
507
|
+
? this.enabledDocCategories.has(docCategory)
|
|
508
|
+
: false;
|
|
509
|
+
return hasCategory;
|
|
510
|
+
}
|
|
511
|
+
// Single-layer mode: permission is sufficient
|
|
512
|
+
return true;
|
|
213
513
|
}
|
|
214
514
|
/**
|
|
215
515
|
* Get detailed permission error message for a specific tool
|
|
216
516
|
*/
|
|
217
517
|
getPermissionError(toolName) {
|
|
218
|
-
const
|
|
219
|
-
|
|
518
|
+
const docCategory = exports.toolDocCategoryMap[toolName];
|
|
519
|
+
const legacyCategory = exports.toolCategoryMap[toolName];
|
|
520
|
+
if (!docCategory && !legacyCategory) {
|
|
220
521
|
return `Unknown tool '${toolName}'. This tool is not recognized by the MCP server.`;
|
|
221
522
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
rollbackTransaction: "rollback database transactions",
|
|
254
|
-
executeInTransaction: "execute queries within transactions",
|
|
255
|
-
createStoredProcedure: "create stored procedures",
|
|
256
|
-
dropStoredProcedure: "delete stored procedures",
|
|
257
|
-
executeStoredProcedure: "execute stored procedures",
|
|
258
|
-
exportTableToCSV: "export table data to CSV",
|
|
259
|
-
exportQueryToCSV: "export query results to CSV",
|
|
260
|
-
// Backup and restore
|
|
261
|
-
backupTable: "backup table to SQL dump",
|
|
262
|
-
backupDatabase: "backup database to SQL dump",
|
|
263
|
-
restoreFromSql: "restore database from SQL dump",
|
|
264
|
-
getCreateTableStatement: "get CREATE TABLE statement",
|
|
265
|
-
getDatabaseSchema: "get database schema overview",
|
|
266
|
-
// Extended export/import
|
|
267
|
-
exportTableToJSON: "export table data to JSON",
|
|
268
|
-
exportQueryToJSON: "export query results to JSON",
|
|
269
|
-
exportTableToSql: "export table data to SQL INSERT statements",
|
|
270
|
-
importFromCSV: "import data from CSV",
|
|
271
|
-
importFromJSON: "import data from JSON",
|
|
272
|
-
};
|
|
273
|
-
const toolDescription = toolDescriptions[toolName] || actionDescriptions[category];
|
|
274
|
-
const requiredPermission = category;
|
|
275
|
-
return (`Permission denied: Cannot ${toolDescription}. ` +
|
|
276
|
-
`This action requires '${requiredPermission}' permission, but your current MCP configuration only allows: ${currentPermissions}. ` +
|
|
277
|
-
`To enable this feature, update your MCP server configuration to include '${requiredPermission}' in the permissions list.`);
|
|
523
|
+
const isAllEnabled = !this.originalPermissionsString.trim() &&
|
|
524
|
+
!this.originalCategoriesString.trim();
|
|
525
|
+
if (isAllEnabled) {
|
|
526
|
+
return `Unknown error: All tools should be enabled but '${toolName}' was blocked.`;
|
|
527
|
+
}
|
|
528
|
+
// Build error message based on dual-layer or single-layer mode
|
|
529
|
+
if (this.useDualLayer) {
|
|
530
|
+
const hasPermission = legacyCategory
|
|
531
|
+
? this.enabledLegacyCategories.has(legacyCategory)
|
|
532
|
+
: false;
|
|
533
|
+
const hasCategory = docCategory
|
|
534
|
+
? this.enabledDocCategories.has(docCategory)
|
|
535
|
+
: false;
|
|
536
|
+
if (!hasPermission) {
|
|
537
|
+
return (`Permission denied: This tool requires '${legacyCategory}' permission (Layer 1). ` +
|
|
538
|
+
`Your current permissions: ${this.originalPermissionsString || "none"}. ` +
|
|
539
|
+
`Add '${legacyCategory}' to the permissions argument.`);
|
|
540
|
+
}
|
|
541
|
+
if (!hasCategory) {
|
|
542
|
+
return (`Permission denied: This tool requires '${docCategory}' category (Layer 2). ` +
|
|
543
|
+
`Your current categories: ${this.originalCategoriesString || "none"}. ` +
|
|
544
|
+
`Add '${docCategory}' to the categories argument.`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
// Single-layer mode
|
|
549
|
+
return (`Permission denied: This tool requires '${legacyCategory}' permission. ` +
|
|
550
|
+
`Your current configuration allows: ${this.originalPermissionsString || "all"}. ` +
|
|
551
|
+
`Add '${legacyCategory}' to enable this tool.`);
|
|
552
|
+
}
|
|
553
|
+
return `Permission denied for tool '${toolName}'.`;
|
|
278
554
|
}
|
|
279
555
|
/**
|
|
280
|
-
* Check if a category is enabled
|
|
556
|
+
* Check if a legacy category is enabled
|
|
281
557
|
*/
|
|
282
558
|
isCategoryEnabled(category) {
|
|
283
|
-
return this.
|
|
559
|
+
return this.enabledLegacyCategories.has(category);
|
|
284
560
|
}
|
|
285
561
|
/**
|
|
286
|
-
*
|
|
562
|
+
* Check if a documentation category is enabled
|
|
563
|
+
*/
|
|
564
|
+
isDocCategoryEnabled(category) {
|
|
565
|
+
return this.enabledDocCategories.has(category);
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Get all enabled legacy categories
|
|
287
569
|
*/
|
|
288
570
|
getEnabledCategories() {
|
|
289
|
-
return Array.from(this.
|
|
571
|
+
return Array.from(this.enabledLegacyCategories);
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Get all enabled documentation categories
|
|
575
|
+
*/
|
|
576
|
+
getEnabledDocCategories() {
|
|
577
|
+
return Array.from(this.enabledDocCategories);
|
|
290
578
|
}
|
|
291
579
|
/**
|
|
292
580
|
* Get all available categories with their status
|
|
@@ -294,10 +582,39 @@ class FeatureConfig {
|
|
|
294
582
|
getCategoryStatus() {
|
|
295
583
|
const result = {};
|
|
296
584
|
for (const category of Object.values(ToolCategory)) {
|
|
297
|
-
result[category] = this.
|
|
585
|
+
result[category] = this.enabledLegacyCategories.has(category);
|
|
586
|
+
}
|
|
587
|
+
return result;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Get all available documentation categories with their status
|
|
591
|
+
*/
|
|
592
|
+
getDocCategoryStatus() {
|
|
593
|
+
const result = {};
|
|
594
|
+
for (const category of Object.values(DocCategory)) {
|
|
595
|
+
result[category] = this.enabledDocCategories.has(category);
|
|
298
596
|
}
|
|
299
597
|
return result;
|
|
300
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* Check if using dual-layer filtering mode
|
|
601
|
+
*/
|
|
602
|
+
isUsingDualLayer() {
|
|
603
|
+
return this.useDualLayer;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Get filtering mode description
|
|
607
|
+
*/
|
|
608
|
+
getFilteringMode() {
|
|
609
|
+
if (!this.originalPermissionsString.trim() &&
|
|
610
|
+
!this.originalCategoriesString.trim()) {
|
|
611
|
+
return "No filtering (all tools enabled)";
|
|
612
|
+
}
|
|
613
|
+
if (this.useDualLayer) {
|
|
614
|
+
return "Dual-layer (Permissions + Categories)";
|
|
615
|
+
}
|
|
616
|
+
return "Single-layer (Permissions only)";
|
|
617
|
+
}
|
|
301
618
|
}
|
|
302
619
|
exports.FeatureConfig = FeatureConfig;
|
|
303
620
|
// Export singleton instance
|
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare class MySQLMCP {
|
|
|
24
24
|
private performanceTools;
|
|
25
25
|
private security;
|
|
26
26
|
private featureConfig;
|
|
27
|
-
constructor(permissionsConfig?: string);
|
|
27
|
+
constructor(permissionsConfig?: string, categoriesConfig?: string);
|
|
28
28
|
private checkToolEnabled;
|
|
29
29
|
listDatabases(): Promise<{
|
|
30
30
|
status: string;
|
|
@@ -588,6 +588,12 @@ export declare class MySQLMCP {
|
|
|
588
588
|
categoryStatus: Record<import("./config/featureConfig").ToolCategory, boolean>;
|
|
589
589
|
};
|
|
590
590
|
};
|
|
591
|
+
/**
|
|
592
|
+
* Check if a specific tool is enabled based on current permissions and categories
|
|
593
|
+
* @param toolName - The tool name in camelCase (e.g., 'listDatabases')
|
|
594
|
+
* @returns boolean indicating if the tool is enabled
|
|
595
|
+
*/
|
|
596
|
+
isToolEnabled(toolName: string): boolean;
|
|
591
597
|
/**
|
|
592
598
|
* Bulk insert multiple records into the specified table
|
|
593
599
|
*/
|
package/dist/index.js
CHANGED
|
@@ -31,8 +31,8 @@ const featureConfig_1 = require("./config/featureConfig");
|
|
|
31
31
|
* A secure interface for AI models to interact with MySQL databases
|
|
32
32
|
*/
|
|
33
33
|
class MySQLMCP {
|
|
34
|
-
constructor(permissionsConfig) {
|
|
35
|
-
this.featureConfig = new featureConfig_1.FeatureConfig(permissionsConfig);
|
|
34
|
+
constructor(permissionsConfig, categoriesConfig) {
|
|
35
|
+
this.featureConfig = new featureConfig_1.FeatureConfig(permissionsConfig, categoriesConfig);
|
|
36
36
|
this.security = new securityLayer_1.default(this.featureConfig);
|
|
37
37
|
this.dbTools = new databaseTools_1.DatabaseTools();
|
|
38
38
|
this.crudTools = new crudTools_1.CrudTools(this.security);
|
|
@@ -504,6 +504,14 @@ class MySQLMCP {
|
|
|
504
504
|
},
|
|
505
505
|
};
|
|
506
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Check if a specific tool is enabled based on current permissions and categories
|
|
509
|
+
* @param toolName - The tool name in camelCase (e.g., 'listDatabases')
|
|
510
|
+
* @returns boolean indicating if the tool is enabled
|
|
511
|
+
*/
|
|
512
|
+
isToolEnabled(toolName) {
|
|
513
|
+
return this.featureConfig.isToolEnabled(toolName);
|
|
514
|
+
}
|
|
507
515
|
/**
|
|
508
516
|
* Bulk insert multiple records into the specified table
|
|
509
517
|
*/
|
package/dist/mcp-server.js
CHANGED
|
@@ -5,9 +5,11 @@ 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
|
-
// Get permissions from environment
|
|
9
|
-
//
|
|
8
|
+
// Get permissions and categories from environment variables (set by bin/mcp-mysql.js)
|
|
9
|
+
// Layer 1 (Permissions): MCP_PERMISSIONS or MCP_CONFIG (backward compatible)
|
|
10
|
+
// Layer 2 (Categories): MCP_CATEGORIES (optional, for fine-grained control)
|
|
10
11
|
const permissions = process.env.MCP_PERMISSIONS || process.env.MCP_CONFIG || "";
|
|
12
|
+
const categories = process.env.MCP_CATEGORIES || "";
|
|
11
13
|
// Declare the MySQL MCP instance (will be initialized in main())
|
|
12
14
|
let mysqlMCP;
|
|
13
15
|
// Define all available tools with their schemas
|
|
@@ -2691,10 +2693,20 @@ const server = new index_js_1.Server({
|
|
|
2691
2693
|
tools: {},
|
|
2692
2694
|
},
|
|
2693
2695
|
});
|
|
2694
|
-
// Handle list tools request
|
|
2696
|
+
// Handle list tools request - filter tools based on permissions and categories
|
|
2695
2697
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
2698
|
+
// Filter tools to only return those that are enabled based on current config
|
|
2699
|
+
const enabledTools = TOOLS.filter((tool) => {
|
|
2700
|
+
// Convert tool name from snake_case to camelCase for checking
|
|
2701
|
+
// e.g., "list_databases" -> "listDatabases"
|
|
2702
|
+
const toolNameCamelCase = tool.name.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
2703
|
+
// Check if tool is enabled based on permissions and categories
|
|
2704
|
+
return mysqlMCP.isToolEnabled(toolNameCamelCase);
|
|
2705
|
+
});
|
|
2706
|
+
// Log the filtering results
|
|
2707
|
+
console.error(`Tools available: ${enabledTools.length} of ${TOOLS.length} total tools`);
|
|
2696
2708
|
return {
|
|
2697
|
-
tools:
|
|
2709
|
+
tools: enabledTools,
|
|
2698
2710
|
};
|
|
2699
2711
|
});
|
|
2700
2712
|
// Handle tool call requests
|
|
@@ -3182,10 +3194,16 @@ async function main() {
|
|
|
3182
3194
|
await server.connect(transport);
|
|
3183
3195
|
// Initialize the MySQL MCP instance AFTER transport is connected
|
|
3184
3196
|
// This ensures the database connection pool is created when the server is ready
|
|
3185
|
-
mysqlMCP = new index_js_2.MySQLMCP(permissions);
|
|
3186
|
-
// Log the effective
|
|
3187
|
-
if (permissions) {
|
|
3197
|
+
mysqlMCP = new index_js_2.MySQLMCP(permissions, categories);
|
|
3198
|
+
// Log the effective filtering configuration to stderr
|
|
3199
|
+
if (permissions && categories) {
|
|
3200
|
+
console.error(`Active permissions (Layer 1): ${permissions}`);
|
|
3201
|
+
console.error(`Active categories (Layer 2): ${categories}`);
|
|
3202
|
+
console.error("Filtering mode: Dual-layer");
|
|
3203
|
+
}
|
|
3204
|
+
else if (permissions) {
|
|
3188
3205
|
console.error(`Active permissions: ${permissions}`);
|
|
3206
|
+
console.error("Filtering mode: Single-layer");
|
|
3189
3207
|
}
|
|
3190
3208
|
else {
|
|
3191
3209
|
console.error("Active permissions: all (default)");
|