@berthojoris/mcp-mysql-server 1.36.0 → 1.37.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/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ 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.37.0] - 2026-03-06
9
+
10
+ ### Removed
11
+ - **Documentation Categories**: Removed `import_export` and `data_migration` categories from documentation to reduce bundle size
12
+ - **Import/Export Category** (6 tools): `export_query_to_json`, `export_table_to_json`, `export_table_to_sql`, `import_from_csv`, `import_from_json`, `safe_export_table`
13
+ - **Data Migration Category** (5 tools): `clone_table`, `compare_table_structure`, `copy_table_data`, `move_table_data`, `sync_table_data`
14
+
15
+ ### Changed
16
+ - Updated DOCUMENTATIONS.md to remove Data Export and Data Import sections (117 → 106 tools, 21 → 19 categories)
17
+ - Updated README.md with new tool count (106 tools) and removed categories from Documentation Categories table
18
+ - Updated package description to remove "data import/export" reference
19
+ - Bumped package version to `1.37.0`
20
+
8
21
  ## [1.36.0] - 2026-03-05
9
22
 
10
23
  ### Removed
package/DOCUMENTATIONS.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # MySQL MCP Server - Documentation
2
2
 
3
- **Last Updated:** 2026-03-05 00:00:00
4
- **Version:** 1.36.0
5
- **Total Tools:** 117
3
+ **Last Updated:** 2026-03-06 00:00:00
4
+ **Version:** 1.37.0
5
+ **Total Tools:** 106
6
6
 
7
7
  Comprehensive documentation for the MySQL MCP Server. For quick start, see [README.md](README.md).
8
8
 
@@ -221,21 +221,13 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
221
221
  - `configure_cache` - Configure cache settings
222
222
  - `clear_cache` - Clear cached results
223
223
 
224
- ### 18. Data Export (4 tools)
225
- - `export_table_to_csv` - Export table to CSV
226
- - `export_table_to_json` - Export table to JSON
227
- - `safe_export_table` - Export with PII masking
228
-
229
- ### 19. Utilities (4 tools)
224
+ ### 18. Utilities (4 tools)
230
225
  - `test_connection` - Test connectivity
231
226
  - `describe_connection` - Connection info
232
227
  - `read_changelog` - Read changelog
233
228
  - `invalidate_table_cache` - Clear table cache
234
229
 
235
- ### 20. Data Import (1 tool)
236
- - `import_from_json` - Import data from JSON file
237
-
238
- ### 21. Schema Migrations (9 tools)
230
+ ### 19. Schema Migrations (9 tools)
239
231
  - `init_migrations_table` - Initialize migrations tracking table
240
232
  - `create_migration` - Create a new migration
241
233
  - `apply_migrations` - Apply pending migrations
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-05 00:00:00
7
+ **Last Updated:** 2026-03-06 00:00:00
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/@berthojoris/mcp-mysql-server)](https://www.npmjs.com/package/@berthojoris/mcp-mysql-server)
10
10
  [![npm downloads](https://img.shields.io/npm/dm/@berthojoris/mcp-mysql-server)](https://www.npmjs.com/package/@berthojoris/mcp-mysql-server)
@@ -264,8 +264,6 @@ Use documentation categories to fine-tune which tools are exposed (Layer 2):
264
264
  | `cache_management` | Manage query cache and optimization | `clear_cache, configure_cache_settings, get_cache_config, get_cache_stats, invalidate_cache_for_table` |
265
265
  | `query_optimization` | Analyze and optimize SQL queries | `analyze_query, get_optimization_hints` |
266
266
  | `backup_restore` | Create backups and restore databases | `backup_database, backup_table, get_create_table_statement, get_database_schema, restore_from_sql` |
267
- | `import_export` | Import and export data in various formats | `export_query_to_json, export_table_to_json, export_table_to_sql, import_from_csv, import_from_json, safe_export_table` |
268
- | `data_migration` | Migrate data between databases or systems | `clone_table, compare_table_structure, copy_table_data, move_table_data, sync_table_data` |
269
267
  | `schema_migrations` | Version control for database schema changes | `apply_migrations, create_migration, generate_migration_from_diff, get_migration_status, get_schema_version, init_migrations_table, reset_failed_migration, rollback_migration, validate_migrations` |
270
268
  | `analysis` | Data analysis and reporting tools | `get_column_statistics, get_database_summary, get_schema_erd, get_schema_rag_context` |
271
269
 
@@ -273,7 +271,7 @@ Use documentation categories to fine-tune which tools are exposed (Layer 2):
273
271
  <summary>Copy/paste list (comma-separated, no spaces)</summary>
274
272
 
275
273
  ```text
276
- database_discovery,crud_operations,bulk_operations,custom_queries,schema_management,utilities,transaction_management,stored_procedures,views_management,triggers_management,functions_management,index_management,constraint_management,table_maintenance,server_management,performance_monitoring,cache_management,query_optimization,backup_restore,import_export,data_migration,schema_migrations,analysis
274
+ database_discovery,crud_operations,bulk_operations,custom_queries,schema_management,utilities,transaction_management,stored_procedures,views_management,triggers_management,functions_management,index_management,constraint_management,table_maintenance,server_management,performance_monitoring,cache_management,query_optimization,backup_restore,schema_migrations,analysis
277
275
  ```
278
276
 
279
277
  </details>
@@ -284,7 +282,7 @@ Full category → tool mapping (and examples) lives in **[DOCUMENTATIONS.md →
284
282
 
285
283
  ## Available Tools
286
284
 
287
- The server exposes **117 tools** organized into categories (CRUD, schema, migrations, and perf/monitoring).
285
+ The server exposes **106 tools** organized into categories (CRUD, schema, migrations, and perf/monitoring).
288
286
 
289
287
  - Complete list of tools: **[DOCUMENTATIONS.md → Complete Tools Reference](DOCUMENTATIONS.md#🔧-complete-tools-reference)**
290
288
 
@@ -14,7 +14,7 @@ export declare enum ToolCategory {
14
14
  PROCEDURE = "procedure"
15
15
  }
16
16
  /**
17
- * Documentation categories from README (21 categories)
17
+ * Documentation categories from README (19 categories)
18
18
  * More intuitive and matches user mental model
19
19
  */
20
20
  export declare enum DocCategory {
@@ -37,8 +37,6 @@ export declare enum DocCategory {
37
37
  CACHE_MANAGEMENT = "cache_management",
38
38
  QUERY_OPTIMIZATION = "query_optimization",
39
39
  BACKUP_RESTORE = "backup_restore",
40
- IMPORT_EXPORT = "import_export",
41
- DATA_MIGRATION = "data_migration",
42
40
  SCHEMA_MIGRATIONS = "schema_migrations",
43
41
  ANALYSIS = "analysis"
44
42
  }
@@ -24,7 +24,7 @@ var ToolCategory;
24
24
  ToolCategory["PROCEDURE"] = "procedure";
25
25
  })(ToolCategory || (exports.ToolCategory = ToolCategory = {}));
26
26
  /**
27
- * Documentation categories from README (21 categories)
27
+ * Documentation categories from README (19 categories)
28
28
  * More intuitive and matches user mental model
29
29
  */
30
30
  var DocCategory;
@@ -48,8 +48,6 @@ var DocCategory;
48
48
  DocCategory["CACHE_MANAGEMENT"] = "cache_management";
49
49
  DocCategory["QUERY_OPTIMIZATION"] = "query_optimization";
50
50
  DocCategory["BACKUP_RESTORE"] = "backup_restore";
51
- DocCategory["IMPORT_EXPORT"] = "import_export";
52
- DocCategory["DATA_MIGRATION"] = "data_migration";
53
51
  DocCategory["SCHEMA_MIGRATIONS"] = "schema_migrations";
54
52
  DocCategory["ANALYSIS"] = "analysis";
55
53
  })(DocCategory || (exports.DocCategory = DocCategory = {}));
@@ -331,19 +329,6 @@ exports.toolDocCategoryMap = {
331
329
  restoreFromSql: DocCategory.BACKUP_RESTORE,
332
330
  getCreateTableStatement: DocCategory.BACKUP_RESTORE,
333
331
  getDatabaseSchema: DocCategory.BACKUP_RESTORE,
334
- // Import/Export
335
- exportTableToJSON: DocCategory.IMPORT_EXPORT,
336
- exportQueryToJSON: DocCategory.IMPORT_EXPORT,
337
- exportTableToSql: DocCategory.IMPORT_EXPORT,
338
- safe_export_table: DocCategory.IMPORT_EXPORT,
339
- importFromCSV: DocCategory.IMPORT_EXPORT,
340
- importFromJSON: DocCategory.IMPORT_EXPORT,
341
- // Data Migration
342
- copyTableData: DocCategory.DATA_MIGRATION,
343
- moveTableData: DocCategory.DATA_MIGRATION,
344
- cloneTable: DocCategory.DATA_MIGRATION,
345
- compareTableStructure: DocCategory.DATA_MIGRATION,
346
- syncTableData: DocCategory.DATA_MIGRATION,
347
332
  // Schema Migrations
348
333
  initMigrationsTable: DocCategory.SCHEMA_MIGRATIONS,
349
334
  createMigration: DocCategory.SCHEMA_MIGRATIONS,
@@ -390,18 +375,14 @@ const legacyToDocCategoryMap = {
390
375
  create: [
391
376
  DocCategory.CRUD_OPERATIONS,
392
377
  DocCategory.BULK_OPERATIONS,
393
- DocCategory.IMPORT_EXPORT,
394
- DocCategory.DATA_MIGRATION,
395
378
  ],
396
379
  update: [
397
380
  DocCategory.CRUD_OPERATIONS,
398
381
  DocCategory.BULK_OPERATIONS,
399
- DocCategory.DATA_MIGRATION,
400
382
  ],
401
383
  delete: [
402
384
  DocCategory.CRUD_OPERATIONS,
403
385
  DocCategory.BULK_OPERATIONS,
404
- DocCategory.DATA_MIGRATION,
405
386
  ],
406
387
  execute: [DocCategory.CUSTOM_QUERIES, DocCategory.SERVER_MANAGEMENT],
407
388
  ddl: [
@@ -412,7 +393,6 @@ const legacyToDocCategoryMap = {
412
393
  DocCategory.CONSTRAINT_MANAGEMENT,
413
394
  DocCategory.TABLE_MAINTENANCE,
414
395
  DocCategory.BACKUP_RESTORE,
415
- DocCategory.DATA_MIGRATION,
416
396
  DocCategory.SCHEMA_MIGRATIONS,
417
397
  ],
418
398
  utility: [
@@ -422,7 +402,6 @@ const legacyToDocCategoryMap = {
422
402
  DocCategory.CACHE_MANAGEMENT,
423
403
  DocCategory.QUERY_OPTIMIZATION,
424
404
  DocCategory.BACKUP_RESTORE,
425
- DocCategory.IMPORT_EXPORT,
426
405
  ],
427
406
  transaction: [DocCategory.TRANSACTION_MANAGEMENT],
428
407
  procedure: [DocCategory.STORED_PROCEDURES, DocCategory.FUNCTIONS_MANAGEMENT],
package/dist/index.d.ts CHANGED
@@ -321,49 +321,6 @@ export declare class MySQLMCP {
321
321
  data?: any;
322
322
  error?: string;
323
323
  }>;
324
- exportTableToJSON(params: {
325
- table_name: string;
326
- filters?: any[];
327
- pagination?: {
328
- page: number;
329
- limit: number;
330
- };
331
- sorting?: {
332
- field: string;
333
- direction: "asc" | "desc";
334
- };
335
- pretty?: boolean;
336
- database?: string;
337
- }): Promise<{
338
- status: string;
339
- data?: any;
340
- error?: string;
341
- }>;
342
- importFromCSV(params: {
343
- table_name: string;
344
- csv_data: string;
345
- has_headers?: boolean;
346
- column_mapping?: Record<string, string>;
347
- skip_errors?: boolean;
348
- batch_size?: number;
349
- database?: string;
350
- }): Promise<{
351
- status: string;
352
- data?: any;
353
- error?: string;
354
- }>;
355
- importFromJSON(params: {
356
- table_name: string;
357
- json_data: string;
358
- column_mapping?: Record<string, string>;
359
- skip_errors?: boolean;
360
- batch_size?: number;
361
- database?: string;
362
- }): Promise<{
363
- status: string;
364
- data?: any;
365
- error?: string;
366
- }>;
367
324
  /**
368
325
  * Initialize the migrations tracking table
369
326
  */
package/dist/index.js CHANGED
@@ -346,29 +346,6 @@ class MySQLMCP {
346
346
  }
347
347
  return await this.dataExportTools.exportTableToCSV(params);
348
348
  }
349
- // Extended Data Export Tools (JSON, SQL)
350
- async exportTableToJSON(params) {
351
- const check = this.checkToolEnabled("exportTableToJSON");
352
- if (!check.enabled) {
353
- return { status: "error", error: check.error };
354
- }
355
- return await this.dataExportTools.exportTableToJSON(params);
356
- }
357
- // Data Import Tools
358
- async importFromCSV(params) {
359
- const check = this.checkToolEnabled("importFromCSV");
360
- if (!check.enabled) {
361
- return { status: "error", error: check.error };
362
- }
363
- return await this.dataExportTools.importFromCSV(params);
364
- }
365
- async importFromJSON(params) {
366
- const check = this.checkToolEnabled("importFromJSON");
367
- if (!check.enabled) {
368
- return { status: "error", error: check.error };
369
- }
370
- return await this.dataExportTools.importFromJSON(params);
371
- }
372
349
  // ==========================================
373
350
  // Schema Versioning and Migrations Tools
374
351
  // ==========================================
@@ -484,33 +484,6 @@ const TOOLS = [
484
484
  required: ["query"],
485
485
  },
486
486
  },
487
- {
488
- name: "safe_export_table",
489
- description: "🔒 SECURITY: Exports table data to CSV with automatic PII/sensitive data masking. Redacts emails, credit cards, passwords, etc. Use this instead of export_table_to_csv when handling sensitive data or sharing exports externally.",
490
- inputSchema: {
491
- type: "object",
492
- properties: {
493
- table_name: {
494
- type: "string",
495
- description: "Name of the table to export",
496
- },
497
- masking_profile: {
498
- type: "string",
499
- enum: ["soft", "partial", "strict"],
500
- description: "Masking profile to apply (default: strict). strict=redact all PII/secrets, partial=partial mask PII, soft=mask secrets only.",
501
- },
502
- limit: {
503
- type: "number",
504
- description: "Maximum number of rows to export (default: 1000, max: 10000)",
505
- },
506
- include_headers: {
507
- type: "boolean",
508
- description: "Whether to include CSV headers (default: true)",
509
- },
510
- },
511
- required: ["table_name"],
512
- },
513
- },
514
487
  {
515
488
  name: "repair_query",
516
489
  description: "🔧 Diagnoses SQL query errors and suggests fixes. Analyzes syntax errors, missing columns/tables, and logic issues. Provide the query and optional error message to get repair recommendations. Use when a query fails or needs debugging.",
@@ -2145,386 +2118,6 @@ const TOOLS = [
2145
2118
  },
2146
2119
  },
2147
2120
  },
2148
- // Extended Data Export Tools (JSON, SQL)
2149
- {
2150
- name: "export_table_to_json",
2151
- description: "Export table data to JSON format with optional filtering, pagination, and sorting.",
2152
- inputSchema: {
2153
- type: "object",
2154
- properties: {
2155
- table_name: {
2156
- type: "string",
2157
- description: "Name of the table to export",
2158
- },
2159
- filters: {
2160
- type: "array",
2161
- description: "Array of filter conditions",
2162
- items: {
2163
- type: "object",
2164
- properties: {
2165
- field: { type: "string" },
2166
- operator: {
2167
- type: "string",
2168
- enum: ["eq", "neq", "gt", "gte", "lt", "lte", "like", "in"],
2169
- },
2170
- value: {},
2171
- },
2172
- required: ["field", "operator", "value"],
2173
- },
2174
- },
2175
- pagination: {
2176
- type: "object",
2177
- properties: {
2178
- page: { type: "number" },
2179
- limit: { type: "number" },
2180
- },
2181
- },
2182
- sorting: {
2183
- type: "object",
2184
- properties: {
2185
- field: { type: "string" },
2186
- direction: { type: "string", enum: ["asc", "desc"] },
2187
- },
2188
- },
2189
- pretty: {
2190
- type: "boolean",
2191
- description: "Pretty print JSON output (default: true)",
2192
- },
2193
- database: {
2194
- type: "string",
2195
- description: "Optional: specific database name",
2196
- },
2197
- },
2198
- required: ["table_name"],
2199
- },
2200
- },
2201
- {
2202
- name: "export_query_to_json",
2203
- description: "Export the results of a SELECT query to JSON format.",
2204
- inputSchema: {
2205
- type: "object",
2206
- properties: {
2207
- query: {
2208
- type: "string",
2209
- description: "SQL SELECT query to execute and export",
2210
- },
2211
- params: {
2212
- type: "array",
2213
- description: "Optional array of parameters for parameterized queries",
2214
- items: {},
2215
- },
2216
- pretty: {
2217
- type: "boolean",
2218
- description: "Pretty print JSON output (default: true)",
2219
- },
2220
- },
2221
- required: ["query"],
2222
- },
2223
- },
2224
- {
2225
- name: "export_table_to_sql",
2226
- description: "Export table data to SQL INSERT statements with optional CREATE TABLE.",
2227
- inputSchema: {
2228
- type: "object",
2229
- properties: {
2230
- table_name: {
2231
- type: "string",
2232
- description: "Name of the table to export",
2233
- },
2234
- filters: {
2235
- type: "array",
2236
- description: "Array of filter conditions",
2237
- items: {
2238
- type: "object",
2239
- properties: {
2240
- field: { type: "string" },
2241
- operator: {
2242
- type: "string",
2243
- enum: ["eq", "neq", "gt", "gte", "lt", "lte", "like", "in"],
2244
- },
2245
- value: {},
2246
- },
2247
- required: ["field", "operator", "value"],
2248
- },
2249
- },
2250
- include_create_table: {
2251
- type: "boolean",
2252
- description: "Include CREATE TABLE statement (default: false)",
2253
- },
2254
- batch_size: {
2255
- type: "number",
2256
- description: "Number of rows per INSERT statement (default: 100)",
2257
- },
2258
- database: {
2259
- type: "string",
2260
- description: "Optional: specific database name",
2261
- },
2262
- },
2263
- required: ["table_name"],
2264
- },
2265
- },
2266
- // Data Import Tools
2267
- {
2268
- name: "import_from_csv",
2269
- description: "Import data from CSV string into a table. Requires 'create' permission.",
2270
- inputSchema: {
2271
- type: "object",
2272
- properties: {
2273
- table_name: {
2274
- type: "string",
2275
- description: "Name of the table to import into",
2276
- },
2277
- csv_data: {
2278
- type: "string",
2279
- description: "CSV data as a string",
2280
- },
2281
- has_headers: {
2282
- type: "boolean",
2283
- description: "CSV has header row (default: true)",
2284
- },
2285
- column_mapping: {
2286
- type: "object",
2287
- description: "Optional: map CSV columns to table columns {csv_col: table_col}",
2288
- additionalProperties: { type: "string" },
2289
- },
2290
- skip_errors: {
2291
- type: "boolean",
2292
- description: "Continue on row errors (default: false)",
2293
- },
2294
- batch_size: {
2295
- type: "number",
2296
- description: "Number of rows per batch insert (default: 100)",
2297
- },
2298
- database: {
2299
- type: "string",
2300
- description: "Optional: specific database name",
2301
- },
2302
- },
2303
- required: ["table_name", "csv_data"],
2304
- },
2305
- },
2306
- {
2307
- name: "import_from_json",
2308
- description: "Import data from JSON array string into a table. Requires 'create' permission.",
2309
- inputSchema: {
2310
- type: "object",
2311
- properties: {
2312
- table_name: {
2313
- type: "string",
2314
- description: "Name of the table to import into",
2315
- },
2316
- json_data: {
2317
- type: "string",
2318
- description: "JSON array of objects as a string",
2319
- },
2320
- column_mapping: {
2321
- type: "object",
2322
- description: "Optional: map JSON keys to table columns {json_key: table_col}",
2323
- additionalProperties: { type: "string" },
2324
- },
2325
- skip_errors: {
2326
- type: "boolean",
2327
- description: "Continue on row errors (default: false)",
2328
- },
2329
- batch_size: {
2330
- type: "number",
2331
- description: "Number of rows per batch insert (default: 100)",
2332
- },
2333
- database: {
2334
- type: "string",
2335
- description: "Optional: specific database name",
2336
- },
2337
- },
2338
- required: ["table_name", "json_data"],
2339
- },
2340
- },
2341
- // Data Migration Tools
2342
- {
2343
- name: "copy_table_data",
2344
- description: "Copy data from one table to another with optional column mapping and filtering. Requires 'create' permission.",
2345
- inputSchema: {
2346
- type: "object",
2347
- properties: {
2348
- source_table: {
2349
- type: "string",
2350
- description: "Name of the source table to copy from",
2351
- },
2352
- target_table: {
2353
- type: "string",
2354
- description: "Name of the target table to copy to",
2355
- },
2356
- column_mapping: {
2357
- type: "object",
2358
- description: "Optional: map source columns to target columns {source_col: target_col}",
2359
- additionalProperties: { type: "string" },
2360
- },
2361
- filters: {
2362
- type: "array",
2363
- description: "Optional: array of filter conditions for source data",
2364
- items: {
2365
- type: "object",
2366
- properties: {
2367
- field: { type: "string" },
2368
- operator: {
2369
- type: "string",
2370
- enum: ["eq", "neq", "gt", "gte", "lt", "lte", "like", "in"],
2371
- },
2372
- value: {},
2373
- },
2374
- required: ["field", "operator", "value"],
2375
- },
2376
- },
2377
- batch_size: {
2378
- type: "number",
2379
- description: "Number of rows per batch insert (default: 1000)",
2380
- },
2381
- database: {
2382
- type: "string",
2383
- description: "Optional: specific database name",
2384
- },
2385
- },
2386
- required: ["source_table", "target_table"],
2387
- },
2388
- },
2389
- {
2390
- name: "move_table_data",
2391
- description: "Move data from one table to another (copy then delete from source). Requires 'create' and 'delete' permissions.",
2392
- inputSchema: {
2393
- type: "object",
2394
- properties: {
2395
- source_table: {
2396
- type: "string",
2397
- description: "Name of the source table to move from",
2398
- },
2399
- target_table: {
2400
- type: "string",
2401
- description: "Name of the target table to move to",
2402
- },
2403
- column_mapping: {
2404
- type: "object",
2405
- description: "Optional: map source columns to target columns {source_col: target_col}",
2406
- additionalProperties: { type: "string" },
2407
- },
2408
- filters: {
2409
- type: "array",
2410
- description: "Optional: array of filter conditions for source data",
2411
- items: {
2412
- type: "object",
2413
- properties: {
2414
- field: { type: "string" },
2415
- operator: {
2416
- type: "string",
2417
- enum: ["eq", "neq", "gt", "gte", "lt", "lte", "like", "in"],
2418
- },
2419
- value: {},
2420
- },
2421
- required: ["field", "operator", "value"],
2422
- },
2423
- },
2424
- batch_size: {
2425
- type: "number",
2426
- description: "Number of rows per batch (default: 1000)",
2427
- },
2428
- database: {
2429
- type: "string",
2430
- description: "Optional: specific database name",
2431
- },
2432
- },
2433
- required: ["source_table", "target_table"],
2434
- },
2435
- },
2436
- {
2437
- name: "clone_table",
2438
- description: "Clone a table structure with optional data. Requires 'ddl' permission.",
2439
- inputSchema: {
2440
- type: "object",
2441
- properties: {
2442
- source_table: {
2443
- type: "string",
2444
- description: "Name of the source table to clone",
2445
- },
2446
- new_table_name: {
2447
- type: "string",
2448
- description: "Name of the new table to create",
2449
- },
2450
- include_data: {
2451
- type: "boolean",
2452
- description: "Include table data in the clone (default: false)",
2453
- },
2454
- include_indexes: {
2455
- type: "boolean",
2456
- description: "Include indexes in the clone (default: true)",
2457
- },
2458
- database: {
2459
- type: "string",
2460
- description: "Optional: specific database name",
2461
- },
2462
- },
2463
- required: ["source_table", "new_table_name"],
2464
- },
2465
- },
2466
- {
2467
- name: "compare_table_structure",
2468
- description: "Compare the structure of two tables and identify differences in columns, types, and indexes.",
2469
- inputSchema: {
2470
- type: "object",
2471
- properties: {
2472
- table1: {
2473
- type: "string",
2474
- description: "Name of the first table",
2475
- },
2476
- table2: {
2477
- type: "string",
2478
- description: "Name of the second table",
2479
- },
2480
- database: {
2481
- type: "string",
2482
- description: "Optional: specific database name",
2483
- },
2484
- },
2485
- required: ["table1", "table2"],
2486
- },
2487
- },
2488
- {
2489
- name: "sync_table_data",
2490
- description: "Synchronize data between two tables based on a key column. Supports insert-only, update-only, or upsert modes.",
2491
- inputSchema: {
2492
- type: "object",
2493
- properties: {
2494
- source_table: {
2495
- type: "string",
2496
- description: "Name of the source table",
2497
- },
2498
- target_table: {
2499
- type: "string",
2500
- description: "Name of the target table",
2501
- },
2502
- key_column: {
2503
- type: "string",
2504
- description: "Primary key or unique column to match records",
2505
- },
2506
- columns_to_sync: {
2507
- type: "array",
2508
- items: { type: "string" },
2509
- description: "Optional: specific columns to sync (default: all columns)",
2510
- },
2511
- sync_mode: {
2512
- type: "string",
2513
- enum: ["insert_only", "update_only", "upsert"],
2514
- description: "Sync mode: insert_only (new records), update_only (existing), upsert (both). Default: upsert",
2515
- },
2516
- batch_size: {
2517
- type: "number",
2518
- description: "Number of rows per batch (default: 1000)",
2519
- },
2520
- database: {
2521
- type: "string",
2522
- description: "Optional: specific database name",
2523
- },
2524
- },
2525
- required: ["source_table", "target_table", "key_column"],
2526
- },
2527
- },
2528
2121
  // Schema Versioning and Migrations Tools
2529
2122
  {
2530
2123
  name: "init_migrations_table",
@@ -3330,17 +2923,6 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
3330
2923
  case "explain_query":
3331
2924
  result = await mysqlMCP.explainQuery((args || {}));
3332
2925
  break;
3333
- // Extended Data Export Tools
3334
- case "export_table_to_json":
3335
- result = await mysqlMCP.exportTableToJSON((args || {}));
3336
- break;
3337
- case "safe_export_table":
3338
- result = await mysqlMCP.safeExportTable((args || {}));
3339
- break;
3340
- // Data Import Tools
3341
- case "import_from_json":
3342
- result = await mysqlMCP.importFromJSON((args || {}));
3343
- break;
3344
2926
  // Schema Versioning and Migrations Tools
3345
2927
  case "init_migrations_table":
3346
2928
  result = await mysqlMCP.initMigrationsTable((args || {}));
@@ -3527,8 +3109,6 @@ function validateToolArguments(name, args) {
3527
3109
  return { valid: false, errors: [validation.error || 'Invalid table name'] };
3528
3110
  }
3529
3111
  return { valid: true };
3530
- case "import_from_json":
3531
- return (0, inputValidation_js_1.validateImportFromJSON)(args);
3532
3112
  default:
3533
3113
  return { valid: true }; // For tools without specific validation
3534
3114
  }
@@ -26,54 +26,4 @@ export declare class DataExportTools {
26
26
  data?: any;
27
27
  error?: string;
28
28
  }>;
29
- /**
30
- * Export table data to JSON format
31
- */
32
- exportTableToJSON(params: {
33
- table_name: string;
34
- filters?: FilterCondition[];
35
- pagination?: Pagination;
36
- sorting?: Sorting;
37
- pretty?: boolean;
38
- database?: string;
39
- }): Promise<{
40
- status: string;
41
- data?: any;
42
- error?: string;
43
- }>;
44
- /**
45
- * Import data from CSV string
46
- */
47
- importFromCSV(params: {
48
- table_name: string;
49
- csv_data: string;
50
- has_headers?: boolean;
51
- column_mapping?: Record<string, string>;
52
- skip_errors?: boolean;
53
- batch_size?: number;
54
- database?: string;
55
- }): Promise<{
56
- status: string;
57
- data?: any;
58
- error?: string;
59
- }>;
60
- /**
61
- * Parse CSV string into array of arrays
62
- */
63
- private parseCSV;
64
- /**
65
- * Import data from JSON string
66
- */
67
- importFromJSON(params: {
68
- table_name: string;
69
- json_data: string;
70
- column_mapping?: Record<string, string>;
71
- skip_errors?: boolean;
72
- batch_size?: number;
73
- database?: string;
74
- }): Promise<{
75
- status: string;
76
- data?: any;
77
- error?: string;
78
- }>;
79
29
  }
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DataExportTools = void 0;
7
7
  const connection_1 = __importDefault(require("../db/connection"));
8
8
  const config_1 = require("../config/config");
9
- const inputValidation_1 = require("../validation/inputValidation");
10
9
  class DataExportTools {
11
10
  constructor(security) {
12
11
  this.db = connection_1.default.getInstance();
@@ -222,428 +221,5 @@ class DataExportTools {
222
221
  };
223
222
  }
224
223
  }
225
- /**
226
- * Export table data to JSON format
227
- */
228
- async exportTableToJSON(params) {
229
- try {
230
- const { table_name, filters = [], pagination, sorting, pretty = true, database, } = params;
231
- // Validate database access
232
- const dbValidation = this.validateDatabaseAccess(database);
233
- if (!dbValidation.valid) {
234
- return { status: "error", error: dbValidation.error };
235
- }
236
- // Validate table name
237
- const tableValidation = this.security.validateIdentifier(table_name);
238
- if (!tableValidation.valid) {
239
- return { status: "error", error: tableValidation.error };
240
- }
241
- // Build WHERE clause
242
- let whereClause = "";
243
- const whereParams = [];
244
- if (filters && filters.length > 0) {
245
- const whereConditions = [];
246
- for (const filter of filters) {
247
- const fieldValidation = this.security.validateIdentifier(filter.field);
248
- if (!fieldValidation.valid) {
249
- return {
250
- status: "error",
251
- error: `Invalid field name: ${filter.field}`,
252
- };
253
- }
254
- const fieldName = this.security.escapeIdentifier(filter.field);
255
- switch (filter.operator) {
256
- case "eq":
257
- whereConditions.push(`${fieldName} = ?`);
258
- whereParams.push(filter.value);
259
- break;
260
- case "neq":
261
- whereConditions.push(`${fieldName} != ?`);
262
- whereParams.push(filter.value);
263
- break;
264
- case "gt":
265
- whereConditions.push(`${fieldName} > ?`);
266
- whereParams.push(filter.value);
267
- break;
268
- case "gte":
269
- whereConditions.push(`${fieldName} >= ?`);
270
- whereParams.push(filter.value);
271
- break;
272
- case "lt":
273
- whereConditions.push(`${fieldName} < ?`);
274
- whereParams.push(filter.value);
275
- break;
276
- case "lte":
277
- whereConditions.push(`${fieldName} <= ?`);
278
- whereParams.push(filter.value);
279
- break;
280
- case "like":
281
- whereConditions.push(`${fieldName} LIKE ?`);
282
- whereParams.push(filter.value);
283
- break;
284
- case "in":
285
- if (Array.isArray(filter.value)) {
286
- const placeholders = filter.value.map(() => "?").join(", ");
287
- whereConditions.push(`${fieldName} IN (${placeholders})`);
288
- whereParams.push(...filter.value);
289
- }
290
- else {
291
- return {
292
- status: "error",
293
- error: "IN operator requires an array of values",
294
- };
295
- }
296
- break;
297
- default:
298
- return {
299
- status: "error",
300
- error: `Unsupported operator: ${filter.operator}`,
301
- };
302
- }
303
- }
304
- if (whereConditions.length > 0) {
305
- whereClause = "WHERE " + whereConditions.join(" AND ");
306
- }
307
- }
308
- // Build ORDER BY clause
309
- let orderByClause = "";
310
- if (sorting) {
311
- const fieldValidation = this.security.validateIdentifier(sorting.field);
312
- if (!fieldValidation.valid) {
313
- return {
314
- status: "error",
315
- error: `Invalid sort field name: ${sorting.field}`,
316
- };
317
- }
318
- const fieldName = this.security.escapeIdentifier(sorting.field);
319
- const direction = sorting.direction.toUpperCase() === "DESC" ? "DESC" : "ASC";
320
- orderByClause = `ORDER BY ${fieldName} ${direction}`;
321
- }
322
- // Build LIMIT clause
323
- let limitClause = "";
324
- if (pagination) {
325
- const offset = (pagination.page - 1) * pagination.limit;
326
- limitClause = `LIMIT ${offset}, ${pagination.limit}`;
327
- }
328
- // Construct and execute query
329
- const escapedTableName = this.security.escapeIdentifier(table_name);
330
- const query = `SELECT * FROM ${escapedTableName} ${whereClause} ${orderByClause} ${limitClause}`;
331
- const results = await this.db.query(query, whereParams);
332
- // Generate JSON
333
- const json = pretty
334
- ? JSON.stringify(results, null, 2)
335
- : JSON.stringify(results);
336
- return {
337
- status: "success",
338
- data: {
339
- json: json,
340
- row_count: results.length,
341
- table_name: table_name,
342
- },
343
- };
344
- }
345
- catch (error) {
346
- return {
347
- status: "error",
348
- error: error.message,
349
- };
350
- }
351
- }
352
- /**
353
- * Import data from CSV string
354
- */
355
- async importFromCSV(params) {
356
- try {
357
- const { table_name, csv_data, has_headers = true, column_mapping, skip_errors = false, batch_size = 100, database, } = params;
358
- // Validate database access
359
- const dbValidation = this.validateDatabaseAccess(database);
360
- if (!dbValidation.valid) {
361
- return { status: "error", error: dbValidation.error };
362
- }
363
- // Validate table name
364
- const tableValidation = this.security.validateIdentifier(table_name);
365
- if (!tableValidation.valid) {
366
- return { status: "error", error: tableValidation.error };
367
- }
368
- // Parse CSV
369
- const rows = this.parseCSV(csv_data);
370
- if (rows.length === 0) {
371
- return { status: "error", error: "CSV data is empty" };
372
- }
373
- let headers;
374
- let dataRows;
375
- if (has_headers) {
376
- headers = rows[0];
377
- dataRows = rows.slice(1);
378
- }
379
- else {
380
- // If no headers, we need column_mapping or use column indexes
381
- if (!column_mapping) {
382
- return {
383
- status: "error",
384
- error: "Column mapping is required when CSV has no headers",
385
- };
386
- }
387
- headers = Object.keys(column_mapping);
388
- dataRows = rows;
389
- }
390
- // Apply column mapping if provided
391
- const finalHeaders = column_mapping
392
- ? headers.map((h) => column_mapping[h] || h)
393
- : headers;
394
- // Validate all column names
395
- for (const col of finalHeaders) {
396
- const colValidation = this.security.validateIdentifier(col);
397
- if (!colValidation.valid) {
398
- return { status: "error", error: `Invalid column name: ${col}` };
399
- }
400
- }
401
- const escapedTableName = this.security.escapeIdentifier(table_name);
402
- const escapedColumns = finalHeaders
403
- .map((c) => this.security.escapeIdentifier(c))
404
- .join(", ");
405
- let successCount = 0;
406
- let errorCount = 0;
407
- const errors = [];
408
- let queryCount = 0;
409
- // Insert in batches
410
- for (let i = 0; i < dataRows.length; i += batch_size) {
411
- const batch = dataRows.slice(i, i + batch_size);
412
- try {
413
- const values = batch
414
- .map((row) => {
415
- const rowValues = row.map((val) => {
416
- if (val === "" || val === null || val === undefined)
417
- return "NULL";
418
- return this.escapeValue(val);
419
- });
420
- return `(${rowValues.join(", ")})`;
421
- })
422
- .join(", ");
423
- const query = `INSERT INTO ${escapedTableName} (${escapedColumns}) VALUES ${values}`;
424
- await this.db.query(query);
425
- queryCount++;
426
- successCount += batch.length;
427
- }
428
- catch (error) {
429
- if (skip_errors) {
430
- // Try inserting rows one by one
431
- for (let j = 0; j < batch.length; j++) {
432
- try {
433
- const rowValues = batch[j].map((val) => {
434
- if (val === "" || val === null || val === undefined)
435
- return "NULL";
436
- return this.escapeValue(val);
437
- });
438
- const query = `INSERT INTO ${escapedTableName} (${escapedColumns}) VALUES (${rowValues.join(", ")})`;
439
- await this.db.query(query);
440
- queryCount++;
441
- successCount++;
442
- }
443
- catch (rowError) {
444
- errorCount++;
445
- errors.push({
446
- row: i + j + (has_headers ? 2 : 1),
447
- error: rowError.message,
448
- });
449
- }
450
- }
451
- }
452
- else {
453
- return {
454
- status: "error",
455
- error: `Import failed at row ${i + 1}: ${error.message}`,
456
- data: { rows_imported: successCount },
457
- };
458
- }
459
- }
460
- }
461
- return {
462
- status: errorCount > 0 ? "partial" : "success",
463
- data: {
464
- message: errorCount > 0
465
- ? `Import completed with ${errorCount} errors`
466
- : "Import completed successfully",
467
- rows_imported: successCount,
468
- rows_failed: errorCount,
469
- errors: errors.length > 0 ? errors.slice(0, 10) : undefined,
470
- },
471
- };
472
- }
473
- catch (error) {
474
- return {
475
- status: "error",
476
- error: error.message,
477
- };
478
- }
479
- }
480
- /**
481
- * Parse CSV string into array of arrays
482
- */
483
- parseCSV(csv) {
484
- const rows = [];
485
- const lines = csv.split(/\r?\n/);
486
- for (const line of lines) {
487
- if (!line.trim())
488
- continue;
489
- const row = [];
490
- let current = "";
491
- let inQuotes = false;
492
- for (let i = 0; i < line.length; i++) {
493
- const char = line[i];
494
- const nextChar = line[i + 1];
495
- if (inQuotes) {
496
- if (char === '"' && nextChar === '"') {
497
- current += '"';
498
- i++; // Skip next quote
499
- }
500
- else if (char === '"') {
501
- inQuotes = false;
502
- }
503
- else {
504
- current += char;
505
- }
506
- }
507
- else {
508
- if (char === '"') {
509
- inQuotes = true;
510
- }
511
- else if (char === ",") {
512
- row.push(current);
513
- current = "";
514
- }
515
- else {
516
- current += char;
517
- }
518
- }
519
- }
520
- row.push(current);
521
- rows.push(row);
522
- }
523
- return rows;
524
- }
525
- /**
526
- * Import data from JSON string
527
- */
528
- async importFromJSON(params) {
529
- // Validate input parameters using the new validation function
530
- const validation = (0, inputValidation_1.validateImportFromJSON)(params);
531
- if (!validation.valid) {
532
- return {
533
- status: "error",
534
- error: `Validation failed: ${validation.errors?.join(', ') || 'Invalid parameters'}`
535
- };
536
- }
537
- try {
538
- const { table_name, json_data, column_mapping, skip_errors = false, batch_size = 100, database, } = params;
539
- // Validate database access
540
- const dbValidation = this.validateDatabaseAccess(database);
541
- if (!dbValidation.valid) {
542
- return { status: "error", error: dbValidation.error };
543
- }
544
- // Validate table name using security layer
545
- const tableValidation = this.security.validateIdentifier(table_name);
546
- if (!tableValidation.valid) {
547
- return { status: "error", error: tableValidation.error };
548
- }
549
- // Parse JSON - this should already be validated by validateImportFromJSON
550
- let data;
551
- try {
552
- data = JSON.parse(json_data);
553
- }
554
- catch (e) {
555
- return { status: "error", error: "Invalid JSON data" };
556
- }
557
- if (!Array.isArray(data)) {
558
- return {
559
- status: "error",
560
- error: "JSON data must be an array of objects",
561
- };
562
- }
563
- if (data.length === 0) {
564
- return { status: "error", error: "JSON data is empty" };
565
- }
566
- // Get columns from first object
567
- let columns = Object.keys(data[0]);
568
- // Apply column mapping if provided
569
- if (column_mapping) {
570
- columns = columns.map((c) => column_mapping[c] || c);
571
- }
572
- // Validate all column names
573
- for (const col of columns) {
574
- const colValidation = this.security.validateIdentifier(col);
575
- if (!colValidation.valid) {
576
- return { status: "error", error: `Invalid column name: ${col}` };
577
- }
578
- }
579
- const escapedTableName = this.security.escapeIdentifier(table_name);
580
- const originalColumns = Object.keys(data[0]);
581
- const escapedColumns = columns
582
- .map((c) => this.security.escapeIdentifier(c))
583
- .join(", ");
584
- let successCount = 0;
585
- let errorCount = 0;
586
- const errors = [];
587
- let queryCount = 0;
588
- // Insert in batches
589
- for (let i = 0; i < data.length; i += batch_size) {
590
- const batch = data.slice(i, i + batch_size);
591
- try {
592
- const values = batch
593
- .map((row) => {
594
- const rowValues = originalColumns.map((col) => this.escapeValue(row[col]));
595
- return `(${rowValues.join(", ")})`;
596
- })
597
- .join(", ");
598
- const query = `INSERT INTO ${escapedTableName} (${escapedColumns}) VALUES ${values}`;
599
- await this.db.query(query);
600
- queryCount++;
601
- successCount += batch.length;
602
- }
603
- catch (error) {
604
- if (skip_errors) {
605
- // Try inserting rows one by one
606
- for (let j = 0; j < batch.length; j++) {
607
- try {
608
- const rowValues = originalColumns.map((col) => this.escapeValue(batch[j][col]));
609
- const query = `INSERT INTO ${escapedTableName} (${escapedColumns}) VALUES (${rowValues.join(", ")})`;
610
- await this.db.query(query);
611
- queryCount++;
612
- successCount++;
613
- }
614
- catch (rowError) {
615
- errorCount++;
616
- errors.push({ row: i + j + 1, error: rowError.message });
617
- }
618
- }
619
- }
620
- else {
621
- return {
622
- status: "error",
623
- error: `Import failed at row ${i + 1}: ${error.message}`,
624
- data: { rows_imported: successCount },
625
- };
626
- }
627
- }
628
- }
629
- return {
630
- status: errorCount > 0 ? "partial" : "success",
631
- data: {
632
- message: errorCount > 0
633
- ? `Import completed with ${errorCount} errors`
634
- : "Import completed successfully",
635
- rows_imported: successCount,
636
- rows_failed: errorCount,
637
- errors: errors.length > 0 ? errors.slice(0, 10) : undefined,
638
- },
639
- };
640
- }
641
- catch (error) {
642
- return {
643
- status: "error",
644
- error: error.message,
645
- };
646
- }
647
- }
648
224
  }
649
225
  exports.DataExportTools = DataExportTools;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@berthojoris/mcp-mysql-server",
3
- "version": "1.36.0",
4
- "description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions, backup/restore, data import/export, and data migration capabilities",
3
+ "version": "1.37.0",
4
+ "description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions, backup/restore, and schema migration capabilities",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "commonjs",