@berthojoris/mcp-mysql-server 1.10.5 → 1.13.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.
@@ -39,7 +39,17 @@ export declare enum DocCategory {
39
39
  BACKUP_RESTORE = "backup_restore",
40
40
  IMPORT_EXPORT = "import_export",
41
41
  DATA_MIGRATION = "data_migration",
42
- SCHEMA_MIGRATIONS = "schema_migrations"
42
+ SCHEMA_MIGRATIONS = "schema_migrations",
43
+ ANALYSIS = "analysis"
44
+ }
45
+ /**
46
+ * Permission preset bundles for faster, safer configuration
47
+ */
48
+ export interface PermissionPreset {
49
+ name: string;
50
+ description: string;
51
+ permissions: ToolCategory[];
52
+ categories: DocCategory[];
43
53
  }
44
54
  /**
45
55
  * Map of tool names to their legacy categories
@@ -61,7 +71,17 @@ export declare class FeatureConfig {
61
71
  private originalPermissionsString;
62
72
  private originalCategoriesString;
63
73
  private useDualLayer;
64
- constructor(permissionsStr?: string, categoriesStr?: string);
74
+ private activePreset?;
75
+ private presetName?;
76
+ constructor(permissionsStr?: string, categoriesStr?: string, presetName?: string);
77
+ /**
78
+ * Normalize and merge preset + user-supplied configuration lists
79
+ */
80
+ private mergeConfigStrings;
81
+ /**
82
+ * Resolve a preset name to its configuration
83
+ */
84
+ private resolvePreset;
65
85
  /**
66
86
  * Parse permissions and categories for dual-layer filtering
67
87
  * Layer 1 (permissions): Broad control using legacy categories
@@ -71,7 +91,7 @@ export declare class FeatureConfig {
71
91
  /**
72
92
  * Update configuration at runtime
73
93
  */
74
- setConfig(permissionsStr: string, categoriesStr?: string): void;
94
+ setConfig(permissionsStr: string, categoriesStr?: string, presetName?: string): void;
75
95
  /**
76
96
  * Check if a specific tool is enabled
77
97
  * Dual-layer logic:
@@ -111,6 +131,24 @@ export declare class FeatureConfig {
111
131
  * Check if using dual-layer filtering mode
112
132
  */
113
133
  isUsingDualLayer(): boolean;
134
+ /**
135
+ * Get the active preset (if any)
136
+ */
137
+ getActivePreset(): PermissionPreset | undefined;
138
+ /**
139
+ * Snapshot of the resolved configuration for logging/telemetry
140
+ */
141
+ getConfigSnapshot(): {
142
+ preset?: {
143
+ name: string;
144
+ description: string;
145
+ };
146
+ permissions: string;
147
+ categories: string;
148
+ filteringMode: string;
149
+ enabledLegacy: ToolCategory[];
150
+ enabledDoc: DocCategory[];
151
+ };
114
152
  /**
115
153
  * Get filtering mode description
116
154
  */
@@ -51,7 +51,71 @@ var DocCategory;
51
51
  DocCategory["IMPORT_EXPORT"] = "import_export";
52
52
  DocCategory["DATA_MIGRATION"] = "data_migration";
53
53
  DocCategory["SCHEMA_MIGRATIONS"] = "schema_migrations";
54
+ DocCategory["ANALYSIS"] = "analysis";
54
55
  })(DocCategory || (exports.DocCategory = DocCategory = {}));
56
+ const normalizePresetName = (value) => (value || "").toLowerCase().replace(/[\s_-]/g, "");
57
+ const permissionPresets = {
58
+ readonly: {
59
+ name: "readonly",
60
+ description: "Safe read-only profile with discovery, querying, exports, and diagnostics",
61
+ permissions: [ToolCategory.LIST, ToolCategory.READ, ToolCategory.UTILITY],
62
+ categories: [
63
+ DocCategory.DATABASE_DISCOVERY,
64
+ DocCategory.CRUD_OPERATIONS,
65
+ DocCategory.CUSTOM_QUERIES,
66
+ DocCategory.UTILITIES,
67
+ DocCategory.IMPORT_EXPORT,
68
+ DocCategory.PERFORMANCE_MONITORING,
69
+ DocCategory.ANALYSIS,
70
+ ],
71
+ },
72
+ analyst: {
73
+ name: "analyst",
74
+ description: "Exploratory analytics profile with query insights and safe exports",
75
+ permissions: [ToolCategory.LIST, ToolCategory.READ, ToolCategory.UTILITY],
76
+ categories: [
77
+ DocCategory.DATABASE_DISCOVERY,
78
+ DocCategory.CRUD_OPERATIONS,
79
+ DocCategory.CUSTOM_QUERIES,
80
+ DocCategory.UTILITIES,
81
+ DocCategory.IMPORT_EXPORT,
82
+ DocCategory.PERFORMANCE_MONITORING,
83
+ DocCategory.ANALYSIS,
84
+ DocCategory.QUERY_OPTIMIZATION,
85
+ DocCategory.CACHE_MANAGEMENT,
86
+ DocCategory.SERVER_MANAGEMENT,
87
+ ],
88
+ },
89
+ dbalite: {
90
+ name: "dba-lite",
91
+ description: "Admin-lite profile for schema care, migrations, and maintenance",
92
+ permissions: [
93
+ ToolCategory.LIST,
94
+ ToolCategory.READ,
95
+ ToolCategory.UTILITY,
96
+ ToolCategory.DDL,
97
+ ToolCategory.TRANSACTION,
98
+ ToolCategory.PROCEDURE,
99
+ ],
100
+ categories: [
101
+ DocCategory.DATABASE_DISCOVERY,
102
+ DocCategory.CUSTOM_QUERIES,
103
+ DocCategory.UTILITIES,
104
+ DocCategory.SERVER_MANAGEMENT,
105
+ DocCategory.SCHEMA_MANAGEMENT,
106
+ DocCategory.TABLE_MAINTENANCE,
107
+ DocCategory.INDEX_MANAGEMENT,
108
+ DocCategory.CONSTRAINT_MANAGEMENT,
109
+ DocCategory.BACKUP_RESTORE,
110
+ DocCategory.SCHEMA_MIGRATIONS,
111
+ DocCategory.PERFORMANCE_MONITORING,
112
+ DocCategory.VIEWS_MANAGEMENT,
113
+ DocCategory.TRIGGERS_MANAGEMENT,
114
+ DocCategory.FUNCTIONS_MANAGEMENT,
115
+ DocCategory.STORED_PROCEDURES,
116
+ ],
117
+ },
118
+ };
55
119
  /**
56
120
  * Map of tool names to their legacy categories
57
121
  */
@@ -60,11 +124,17 @@ exports.toolCategoryMap = {
60
124
  listDatabases: ToolCategory.LIST,
61
125
  listTables: ToolCategory.LIST,
62
126
  readTableSchema: ToolCategory.LIST,
127
+ // Analysis tools (added here to group with database tools)
128
+ getDatabaseSummary: ToolCategory.LIST,
129
+ getSchemaERD: ToolCategory.LIST,
130
+ getSchemaRagContext: ToolCategory.LIST,
63
131
  // CRUD tools
64
132
  createRecord: ToolCategory.CREATE,
65
133
  readRecords: ToolCategory.READ,
66
134
  updateRecord: ToolCategory.UPDATE,
67
135
  deleteRecord: ToolCategory.DELETE,
136
+ // Analysis tools (added here to group with read tools)
137
+ getColumnStatistics: ToolCategory.READ,
68
138
  // Bulk operations
69
139
  bulkInsert: ToolCategory.CREATE,
70
140
  bulkUpdate: ToolCategory.UPDATE,
@@ -186,6 +256,8 @@ exports.toolCategoryMap = {
186
256
  validateMigrations: ToolCategory.LIST,
187
257
  resetFailedMigration: ToolCategory.DDL,
188
258
  generateMigrationFromDiff: ToolCategory.DDL,
259
+ // Analysis tools - MOVED here to avoid duplication
260
+ // Note: keys must be unique in the object literal
189
261
  // Performance monitoring tools
190
262
  getPerformanceMetrics: ToolCategory.UTILITY,
191
263
  getTopQueriesByTime: ToolCategory.UTILITY,
@@ -343,6 +415,11 @@ exports.toolDocCategoryMap = {
343
415
  validateMigrations: DocCategory.SCHEMA_MIGRATIONS,
344
416
  resetFailedMigration: DocCategory.SCHEMA_MIGRATIONS,
345
417
  generateMigrationFromDiff: DocCategory.SCHEMA_MIGRATIONS,
418
+ // Analysis
419
+ getDatabaseSummary: DocCategory.ANALYSIS,
420
+ getSchemaERD: DocCategory.ANALYSIS,
421
+ getColumnStatistics: DocCategory.ANALYSIS,
422
+ getSchemaRagContext: DocCategory.ANALYSIS,
346
423
  };
347
424
  /**
348
425
  * Mapping between legacy categories and documentation categories
@@ -360,8 +437,9 @@ const legacyToDocCategoryMap = {
360
437
  DocCategory.TABLE_MAINTENANCE,
361
438
  DocCategory.SERVER_MANAGEMENT,
362
439
  DocCategory.SCHEMA_MIGRATIONS,
440
+ DocCategory.ANALYSIS,
363
441
  ],
364
- read: [DocCategory.CRUD_OPERATIONS, DocCategory.CUSTOM_QUERIES],
442
+ read: [DocCategory.CRUD_OPERATIONS, DocCategory.CUSTOM_QUERIES, DocCategory.ANALYSIS],
365
443
  create: [
366
444
  DocCategory.CRUD_OPERATIONS,
367
445
  DocCategory.BULK_OPERATIONS,
@@ -409,20 +487,66 @@ const legacyToDocCategoryMap = {
409
487
  * - Layer 2 (Categories): Documentation categories (fine-grained control, optional)
410
488
  */
411
489
  class FeatureConfig {
412
- constructor(permissionsStr, categoriesStr) {
490
+ constructor(permissionsStr, categoriesStr, presetName) {
491
+ const presetInput = presetName ||
492
+ process.env.MCP_PERMISSION_PRESET ||
493
+ process.env.MCP_PRESET ||
494
+ "";
495
+ this.activePreset = this.resolvePreset(presetInput);
496
+ this.presetName = this.activePreset?.name;
497
+ const presetRequested = !!presetInput.trim();
413
498
  // Support both old single-parameter and new dual-parameter signatures
414
- const permissions = permissionsStr ||
499
+ const permissionsInput = permissionsStr ||
415
500
  process.env.MCP_PERMISSIONS ||
416
501
  process.env.MCP_CONFIG ||
417
502
  "";
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);
503
+ const categoriesInput = categoriesStr || process.env.MCP_CATEGORIES || "";
504
+ // Use preset values when available, otherwise fall back to user input
505
+ // If an unknown preset is requested without explicit permissions/categories,
506
+ // default to a safe read-only baseline rather than enabling everything.
507
+ const basePermissions = this.activePreset
508
+ ? this.activePreset.permissions.join(",")
509
+ : presetRequested && !permissionsInput
510
+ ? [ToolCategory.LIST, ToolCategory.READ, ToolCategory.UTILITY].join(",")
511
+ : "";
512
+ const baseCategories = this.activePreset
513
+ ? this.activePreset.categories.join(",")
514
+ : presetRequested && !categoriesInput
515
+ ? [
516
+ DocCategory.DATABASE_DISCOVERY,
517
+ DocCategory.CRUD_OPERATIONS,
518
+ DocCategory.CUSTOM_QUERIES,
519
+ DocCategory.UTILITIES,
520
+ ].join(",")
521
+ : "";
522
+ if (presetRequested && !this.activePreset) {
523
+ console.warn(`Preset '${presetInput}' not recognized. Falling back to safe read-only defaults.`);
524
+ }
525
+ const mergedPermissions = this.mergeConfigStrings(basePermissions, permissionsInput);
526
+ const mergedCategories = this.mergeConfigStrings(baseCategories, categoriesInput);
527
+ this.originalPermissionsString = mergedPermissions;
528
+ this.originalCategoriesString = mergedCategories;
529
+ this.useDualLayer = !!mergedCategories.trim();
530
+ const parsed = this.parseConfig(mergedPermissions, mergedCategories);
423
531
  this.enabledLegacyCategories = parsed.legacy;
424
532
  this.enabledDocCategories = parsed.doc;
425
533
  }
534
+ /**
535
+ * Normalize and merge preset + user-supplied configuration lists
536
+ */
537
+ mergeConfigStrings(base, override) {
538
+ const items = [...(base || "").split(","), ...(override || "").split(",")]
539
+ .map((c) => c.trim().toLowerCase())
540
+ .filter(Boolean);
541
+ return Array.from(new Set(items)).join(",");
542
+ }
543
+ /**
544
+ * Resolve a preset name to its configuration
545
+ */
546
+ resolvePreset(name) {
547
+ const normalized = normalizePresetName(name);
548
+ return normalized ? permissionPresets[normalized] : undefined;
549
+ }
426
550
  /**
427
551
  * Parse permissions and categories for dual-layer filtering
428
552
  * Layer 1 (permissions): Broad control using legacy categories
@@ -472,11 +596,37 @@ class FeatureConfig {
472
596
  /**
473
597
  * Update configuration at runtime
474
598
  */
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 || "");
599
+ setConfig(permissionsStr, categoriesStr, presetName) {
600
+ const presetRequested = presetName !== undefined ? !!presetName.trim() : !!this.presetName;
601
+ this.activePreset =
602
+ presetName === ""
603
+ ? undefined
604
+ : this.resolvePreset(presetName || this.presetName);
605
+ this.presetName = this.activePreset?.name;
606
+ const basePermissions = this.activePreset
607
+ ? this.activePreset.permissions.join(",")
608
+ : presetRequested && !permissionsStr
609
+ ? [ToolCategory.LIST, ToolCategory.READ, ToolCategory.UTILITY].join(",")
610
+ : "";
611
+ const baseCategories = this.activePreset
612
+ ? this.activePreset.categories.join(",")
613
+ : presetRequested && !categoriesStr
614
+ ? [
615
+ DocCategory.DATABASE_DISCOVERY,
616
+ DocCategory.CRUD_OPERATIONS,
617
+ DocCategory.CUSTOM_QUERIES,
618
+ DocCategory.UTILITIES,
619
+ ].join(",")
620
+ : "";
621
+ if (presetRequested && !this.activePreset) {
622
+ console.warn(`Preset '${presetName}' not recognized. Falling back to safe read-only defaults.`);
623
+ }
624
+ const mergedPermissions = this.mergeConfigStrings(basePermissions, permissionsStr);
625
+ const mergedCategories = this.mergeConfigStrings(baseCategories, categoriesStr || "");
626
+ this.originalPermissionsString = mergedPermissions;
627
+ this.originalCategoriesString = mergedCategories;
628
+ this.useDualLayer = !!(mergedCategories && mergedCategories.trim());
629
+ const parsed = this.parseConfig(mergedPermissions, mergedCategories || "");
480
630
  this.enabledLegacyCategories = parsed.legacy;
481
631
  this.enabledDocCategories = parsed.doc;
482
632
  }
@@ -602,6 +752,31 @@ class FeatureConfig {
602
752
  isUsingDualLayer() {
603
753
  return this.useDualLayer;
604
754
  }
755
+ /**
756
+ * Get the active preset (if any)
757
+ */
758
+ getActivePreset() {
759
+ return this.activePreset;
760
+ }
761
+ /**
762
+ * Snapshot of the resolved configuration for logging/telemetry
763
+ */
764
+ getConfigSnapshot() {
765
+ return {
766
+ preset: this.activePreset
767
+ ? {
768
+ name: this.activePreset.name,
769
+ description: this.activePreset.description,
770
+ }
771
+ : undefined,
772
+ permissions: this.originalPermissionsString || "all",
773
+ categories: this.originalCategoriesString ||
774
+ (this.useDualLayer ? "" : "derived from permissions"),
775
+ filteringMode: this.getFilteringMode(),
776
+ enabledLegacy: this.getEnabledCategories(),
777
+ enabledDoc: this.getEnabledDocCategories(),
778
+ };
779
+ }
605
780
  /**
606
781
  * Get filtering mode description
607
782
  */
package/dist/index.d.ts CHANGED
@@ -22,9 +22,11 @@ export declare class MySQLMCP {
22
22
  private migrationTools;
23
23
  private schemaVersioningTools;
24
24
  private performanceTools;
25
+ private analysisTools;
26
+ private aiTools;
25
27
  private security;
26
28
  private featureConfig;
27
- constructor(permissionsConfig?: string, categoriesConfig?: string);
29
+ constructor(permissionsConfig?: string, categoriesConfig?: string, presetName?: string);
28
30
  private checkToolEnabled;
29
31
  listDatabases(): Promise<{
30
32
  status: string;
@@ -45,6 +47,20 @@ export declare class MySQLMCP {
45
47
  data?: import("./validation/schemas").ColumnInfo[];
46
48
  error?: string;
47
49
  }>;
50
+ getDatabaseSummary(params: {
51
+ database?: string;
52
+ }): Promise<{
53
+ status: string;
54
+ data?: string;
55
+ error?: string;
56
+ }>;
57
+ getSchemaERD(params: {
58
+ database?: string;
59
+ }): Promise<{
60
+ status: string;
61
+ data?: string;
62
+ error?: string;
63
+ }>;
48
64
  createRecord(params: {
49
65
  table_name: string;
50
66
  data: Record<string, any>;
@@ -94,11 +110,18 @@ export declare class MySQLMCP {
94
110
  runQuery(params: {
95
111
  query: string;
96
112
  params?: any[];
113
+ hints?: any;
114
+ useCache?: boolean;
115
+ dry_run?: boolean;
97
116
  }): Promise<{
98
117
  status: string;
99
118
  data?: any[];
100
119
  error?: string;
101
120
  optimizedQuery?: string;
121
+ dry_run?: boolean;
122
+ execution_plan?: any;
123
+ estimated_cost?: string;
124
+ message?: string;
102
125
  }>;
103
126
  executeSql(params: {
104
127
  query: string;
@@ -108,6 +131,25 @@ export declare class MySQLMCP {
108
131
  data?: any;
109
132
  error?: string;
110
133
  }>;
134
+ getColumnStatistics(params: {
135
+ table_name: string;
136
+ column_name: string;
137
+ database?: string;
138
+ }): Promise<{
139
+ status: string;
140
+ data?: any;
141
+ error?: string;
142
+ }>;
143
+ getSchemaRagContext(params: {
144
+ database?: string;
145
+ max_tables?: number;
146
+ max_columns?: number;
147
+ include_relationships?: boolean;
148
+ }): Promise<{
149
+ status: string;
150
+ data?: any;
151
+ error?: string;
152
+ }>;
111
153
  createTable(params: any): Promise<{
112
154
  status: string;
113
155
  data?: any;
@@ -538,11 +580,35 @@ export declare class MySQLMCP {
538
580
  data?: any;
539
581
  error?: string;
540
582
  }>;
583
+ repairQuery(params: {
584
+ query: string;
585
+ error_message?: string;
586
+ }): Promise<{
587
+ status: string;
588
+ analysis?: any;
589
+ fixed_query?: string;
590
+ suggestions?: string[];
591
+ error?: string;
592
+ }>;
541
593
  getFeatureStatus(): {
542
594
  status: string;
543
595
  data: {
596
+ config: {
597
+ preset?: {
598
+ name: string;
599
+ description: string;
600
+ };
601
+ permissions: string;
602
+ categories: string;
603
+ filteringMode: string;
604
+ enabledLegacy: import("./config/featureConfig").ToolCategory[];
605
+ enabledDoc: import("./config/featureConfig").DocCategory[];
606
+ };
607
+ preset: import("./config/featureConfig").PermissionPreset | undefined;
608
+ filteringMode: string;
544
609
  enabledCategories: import("./config/featureConfig").ToolCategory[];
545
610
  categoryStatus: Record<import("./config/featureConfig").ToolCategory, boolean>;
611
+ docCategoryStatus: Record<import("./config/featureConfig").DocCategory, boolean>;
546
612
  };
547
613
  };
548
614
  /**
@@ -551,6 +617,20 @@ export declare class MySQLMCP {
551
617
  * @returns boolean indicating if the tool is enabled
552
618
  */
553
619
  isToolEnabled(toolName: string): boolean;
620
+ /**
621
+ * Expose resolved access profile (preset + merged permissions/categories)
622
+ */
623
+ getAccessProfile(): {
624
+ preset?: {
625
+ name: string;
626
+ description: string;
627
+ };
628
+ permissions: string;
629
+ categories: string;
630
+ filteringMode: string;
631
+ enabledLegacy: import("./config/featureConfig").ToolCategory[];
632
+ enabledDoc: import("./config/featureConfig").DocCategory[];
633
+ };
554
634
  /**
555
635
  * Bulk insert multiple records into the specified table
556
636
  */
package/dist/index.js CHANGED
@@ -23,6 +23,8 @@ const backupRestoreTools_1 = require("./tools/backupRestoreTools");
23
23
  const migrationTools_1 = require("./tools/migrationTools");
24
24
  const schemaVersioningTools_1 = require("./tools/schemaVersioningTools");
25
25
  const performanceTools_1 = require("./tools/performanceTools");
26
+ const analysisTools_1 = require("./tools/analysisTools");
27
+ const aiTools_1 = require("./tools/aiTools");
26
28
  const securityLayer_1 = __importDefault(require("./security/securityLayer"));
27
29
  const connection_1 = __importDefault(require("./db/connection"));
28
30
  const featureConfig_1 = require("./config/featureConfig");
@@ -31,8 +33,8 @@ const featureConfig_1 = require("./config/featureConfig");
31
33
  * A secure interface for AI models to interact with MySQL databases
32
34
  */
33
35
  class MySQLMCP {
34
- constructor(permissionsConfig, categoriesConfig) {
35
- this.featureConfig = new featureConfig_1.FeatureConfig(permissionsConfig, categoriesConfig);
36
+ constructor(permissionsConfig, categoriesConfig, presetName) {
37
+ this.featureConfig = new featureConfig_1.FeatureConfig(permissionsConfig, categoriesConfig, presetName);
36
38
  this.security = new securityLayer_1.default(this.featureConfig);
37
39
  this.dbTools = new databaseTools_1.DatabaseTools();
38
40
  this.crudTools = new crudTools_1.CrudTools(this.security);
@@ -53,6 +55,8 @@ class MySQLMCP {
53
55
  this.migrationTools = new migrationTools_1.MigrationTools(this.security);
54
56
  this.schemaVersioningTools = new schemaVersioningTools_1.SchemaVersioningTools(this.security);
55
57
  this.performanceTools = new performanceTools_1.PerformanceTools(this.security);
58
+ this.analysisTools = new analysisTools_1.AnalysisTools(this.security);
59
+ this.aiTools = new aiTools_1.AiTools(this.security);
56
60
  }
57
61
  // Helper method to check if tool is enabled
58
62
  checkToolEnabled(toolName) {
@@ -86,6 +90,20 @@ class MySQLMCP {
86
90
  }
87
91
  return await this.dbTools.readTableSchema(params);
88
92
  }
93
+ async getDatabaseSummary(params) {
94
+ const check = this.checkToolEnabled("getDatabaseSummary");
95
+ if (!check.enabled) {
96
+ return { status: "error", error: check.error };
97
+ }
98
+ return await this.dbTools.getDatabaseSummary(params);
99
+ }
100
+ async getSchemaERD(params) {
101
+ const check = this.checkToolEnabled("getSchemaERD");
102
+ if (!check.enabled) {
103
+ return { status: "error", error: check.error };
104
+ }
105
+ return await this.dbTools.getSchemaERD(params);
106
+ }
89
107
  // CRUD Tools
90
108
  async createRecord(params) {
91
109
  const check = this.checkToolEnabled("createRecord");
@@ -147,6 +165,21 @@ class MySQLMCP {
147
165
  }
148
166
  return await this.queryTools.executeSql(params);
149
167
  }
168
+ // Analysis Tools
169
+ async getColumnStatistics(params) {
170
+ const check = this.checkToolEnabled("getColumnStatistics");
171
+ if (!check.enabled) {
172
+ return { status: "error", error: check.error };
173
+ }
174
+ return await this.analysisTools.getColumnStatistics(params);
175
+ }
176
+ async getSchemaRagContext(params) {
177
+ const check = this.checkToolEnabled("getSchemaRagContext");
178
+ if (!check.enabled) {
179
+ return { status: "error", error: check.error };
180
+ }
181
+ return await this.analysisTools.getSchemaRagContext(params);
182
+ }
150
183
  // DDL Tools
151
184
  async createTable(params) {
152
185
  const check = this.checkToolEnabled("createTable");
@@ -494,13 +527,26 @@ class MySQLMCP {
494
527
  }
495
528
  return await this.schemaVersioningTools.generateMigrationFromDiff(params);
496
529
  }
530
+ // AI Productivity Tools
531
+ async repairQuery(params) {
532
+ const check = this.checkToolEnabled("repairQuery");
533
+ if (!check.enabled) {
534
+ return { status: "error", error: check.error };
535
+ }
536
+ return await this.aiTools.repairQuery(params);
537
+ }
497
538
  // Get feature configuration status
498
539
  getFeatureStatus() {
540
+ const snapshot = this.featureConfig.getConfigSnapshot();
499
541
  return {
500
542
  status: "success",
501
543
  data: {
544
+ config: snapshot,
545
+ preset: this.featureConfig.getActivePreset(),
546
+ filteringMode: this.featureConfig.getFilteringMode(),
502
547
  enabledCategories: this.featureConfig.getEnabledCategories(),
503
548
  categoryStatus: this.featureConfig.getCategoryStatus(),
549
+ docCategoryStatus: this.featureConfig.getDocCategoryStatus(),
504
550
  },
505
551
  };
506
552
  }
@@ -512,6 +558,12 @@ class MySQLMCP {
512
558
  isToolEnabled(toolName) {
513
559
  return this.featureConfig.isToolEnabled(toolName);
514
560
  }
561
+ /**
562
+ * Expose resolved access profile (preset + merged permissions/categories)
563
+ */
564
+ getAccessProfile() {
565
+ return this.featureConfig.getConfigSnapshot();
566
+ }
515
567
  /**
516
568
  * Bulk insert multiple records into the specified table
517
569
  */