@berthojoris/mcp-mysql-server 1.2.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +290 -1
- package/dist/config/featureConfig.d.ts +5 -0
- package/dist/config/featureConfig.js +59 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +18 -1
- package/dist/mcp-server.js +95 -1
- package/dist/tools/dataExportTools.d.ts +33 -0
- package/dist/tools/dataExportTools.js +240 -0
- package/dist/validation/schemas.d.ts +87 -0
- package/dist/validation/schemas.js +62 -2
- package/manifest.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -157,12 +157,14 @@ The MCP server provides **30 powerful tools**:
|
|
|
157
157
|
| `drop_table` | Delete tables | `ddl` permission |
|
|
158
158
|
| `execute_ddl` | Execute raw DDL SQL (CREATE, ALTER, DROP, TRUNCATE, RENAME) | `ddl` permission |
|
|
159
159
|
|
|
160
|
-
### Utilities (
|
|
160
|
+
### Utilities (4 tools)
|
|
161
161
|
|
|
162
162
|
| Tool | Description |
|
|
163
163
|
|------|-------------|
|
|
164
164
|
| `test_connection` | Test database connectivity and measure latency |
|
|
165
165
|
| `describe_connection` | Get current connection information |
|
|
166
|
+
| `export_table_to_csv` | Export table data to CSV format with optional filtering, pagination, and sorting |
|
|
167
|
+
| `export_query_to_csv` | Export the results of a SELECT query to CSV format |
|
|
166
168
|
|
|
167
169
|
### Transaction Management (5 tools)
|
|
168
170
|
|
|
@@ -281,6 +283,120 @@ You can have different databases with different permissions in the same AI agent
|
|
|
281
283
|
|
|
282
284
|
---
|
|
283
285
|
|
|
286
|
+
## 🚫 Permission Error Handling
|
|
287
|
+
|
|
288
|
+
The MySQL MCP Server provides clear, user-friendly error messages when operations are attempted without proper permissions. This helps users understand exactly what permissions are needed and how to enable them.
|
|
289
|
+
|
|
290
|
+
### Error Message Format
|
|
291
|
+
|
|
292
|
+
When a tool is called without the required permission, you'll receive a detailed error message like:
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
❌ Permission denied: Cannot use tool 'create_table'. This tool requires 'ddl' permission.
|
|
296
|
+
|
|
297
|
+
Current permissions: list,read,utility
|
|
298
|
+
To enable this tool, add 'ddl' to your permissions configuration.
|
|
299
|
+
|
|
300
|
+
Example configuration:
|
|
301
|
+
"args": ["mysql://user:pass@host:3306/db", "list,read,utility,ddl"]
|
|
302
|
+
|
|
303
|
+
Tool description: Create new tables with columns and indexes
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Common Permission Error Examples
|
|
307
|
+
|
|
308
|
+
#### Creating Tables Without DDL Permission
|
|
309
|
+
|
|
310
|
+
**User prompt:** *"Create a new table called 'products'"*
|
|
311
|
+
|
|
312
|
+
**Error response when DDL not enabled:**
|
|
313
|
+
```
|
|
314
|
+
❌ Permission denied: Cannot use tool 'create_table'. This tool requires 'ddl' permission.
|
|
315
|
+
|
|
316
|
+
Current permissions: list,read,utility
|
|
317
|
+
To enable this tool, add 'ddl' to your permissions configuration.
|
|
318
|
+
|
|
319
|
+
Example configuration:
|
|
320
|
+
"args": ["mysql://user:pass@host:3306/db", "list,read,utility,ddl"]
|
|
321
|
+
|
|
322
|
+
Tool description: Create new tables with columns and indexes
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### Inserting Data Without Create Permission
|
|
326
|
+
|
|
327
|
+
**User prompt:** *"Add a new user to the users table"*
|
|
328
|
+
|
|
329
|
+
**Error response when CREATE not enabled:**
|
|
330
|
+
```
|
|
331
|
+
❌ Permission denied: Cannot use tool 'create_record'. This tool requires 'create' permission.
|
|
332
|
+
|
|
333
|
+
Current permissions: list,read,utility
|
|
334
|
+
To enable this tool, add 'create' to your permissions configuration.
|
|
335
|
+
|
|
336
|
+
Example configuration:
|
|
337
|
+
"args": ["mysql://user:pass@host:3306/db", "list,read,utility,create"]
|
|
338
|
+
|
|
339
|
+
Tool description: Insert new records with automatic SQL generation
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Updating Data Without Update Permission
|
|
343
|
+
|
|
344
|
+
**User prompt:** *"Update the email for user ID 123"*
|
|
345
|
+
|
|
346
|
+
**Error response when UPDATE not enabled:**
|
|
347
|
+
```
|
|
348
|
+
❌ Permission denied: Cannot use tool 'update_record'. This tool requires 'update' permission.
|
|
349
|
+
|
|
350
|
+
Current permissions: list,read,utility
|
|
351
|
+
To enable this tool, add 'update' to your permissions configuration.
|
|
352
|
+
|
|
353
|
+
Example configuration:
|
|
354
|
+
"args": ["mysql://user:pass@host:3306/db", "list,read,utility,update"]
|
|
355
|
+
|
|
356
|
+
Tool description: Update existing records based on conditions
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Permission Error Benefits
|
|
360
|
+
|
|
361
|
+
1. **🎯 Clear Guidance** - Exact permission needed and how to add it
|
|
362
|
+
2. **📋 Current State** - Shows what permissions are currently active
|
|
363
|
+
3. **💡 Example Configuration** - Ready-to-use configuration example
|
|
364
|
+
4. **📖 Tool Context** - Explains what the tool does
|
|
365
|
+
5. **🔒 Security** - Prevents unauthorized operations while being helpful
|
|
366
|
+
|
|
367
|
+
### Troubleshooting Permission Errors
|
|
368
|
+
|
|
369
|
+
If you encounter permission errors:
|
|
370
|
+
|
|
371
|
+
1. **Check your configuration** - Verify the permissions string in your MCP configuration
|
|
372
|
+
2. **Add required permission** - Add the missing permission to your configuration
|
|
373
|
+
3. **Restart your AI agent** - Changes require a restart to take effect
|
|
374
|
+
4. **Test with a simple operation** - Verify the permission is working
|
|
375
|
+
|
|
376
|
+
**Example fix for DDL operations:**
|
|
377
|
+
|
|
378
|
+
Before (DDL disabled):
|
|
379
|
+
```json
|
|
380
|
+
{
|
|
381
|
+
"args": [
|
|
382
|
+
"mysql://user:pass@localhost:3306/db",
|
|
383
|
+
"list,read,utility"
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
After (DDL enabled):
|
|
389
|
+
```json
|
|
390
|
+
{
|
|
391
|
+
"args": [
|
|
392
|
+
"mysql://user:pass@localhost:3306/db",
|
|
393
|
+
"list,read,utility,ddl"
|
|
394
|
+
]
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
284
400
|
## 🏗️ DDL Operations
|
|
285
401
|
|
|
286
402
|
DDL (Data Definition Language) operations allow AI to create, modify, and delete tables.
|
|
@@ -366,6 +482,140 @@ DDL operations are **disabled by default** for safety. Add `ddl` to permissions
|
|
|
366
482
|
|
|
367
483
|
---
|
|
368
484
|
|
|
485
|
+
## 📤 Data Export Tools
|
|
486
|
+
|
|
487
|
+
The MySQL MCP Server provides powerful data export capabilities, allowing AI agents to export database content in CSV format for analysis, reporting, and data sharing.
|
|
488
|
+
|
|
489
|
+
### Data Export Tools Overview
|
|
490
|
+
|
|
491
|
+
- **`export_table_to_csv`** - Export all or filtered data from a table to CSV format
|
|
492
|
+
- **`export_query_to_csv`** - Export the results of a custom SELECT query to CSV format
|
|
493
|
+
|
|
494
|
+
Both tools support:
|
|
495
|
+
- Filtering data with conditions
|
|
496
|
+
- Pagination for large datasets
|
|
497
|
+
- Sorting results
|
|
498
|
+
- Optional column headers
|
|
499
|
+
- Proper CSV escaping for special characters
|
|
500
|
+
|
|
501
|
+
### Data Export Tool Examples
|
|
502
|
+
|
|
503
|
+
#### Export Table to CSV
|
|
504
|
+
|
|
505
|
+
**User prompt:** *"Export the first 100 users ordered by registration date to CSV"*
|
|
506
|
+
|
|
507
|
+
**AI will execute:**
|
|
508
|
+
```json
|
|
509
|
+
{
|
|
510
|
+
"tool": "export_table_to_csv",
|
|
511
|
+
"arguments": {
|
|
512
|
+
"table_name": "users",
|
|
513
|
+
"sorting": {
|
|
514
|
+
"field": "registration_date",
|
|
515
|
+
"direction": "desc"
|
|
516
|
+
},
|
|
517
|
+
"pagination": {
|
|
518
|
+
"page": 1,
|
|
519
|
+
"limit": 100
|
|
520
|
+
},
|
|
521
|
+
"include_headers": true
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
#### Export Filtered Data to CSV
|
|
527
|
+
|
|
528
|
+
**User prompt:** *"Export all users from the marketing department to CSV"*
|
|
529
|
+
|
|
530
|
+
**AI will execute:**
|
|
531
|
+
```json
|
|
532
|
+
{
|
|
533
|
+
"tool": "export_table_to_csv",
|
|
534
|
+
"arguments": {
|
|
535
|
+
"table_name": "users",
|
|
536
|
+
"filters": [
|
|
537
|
+
{
|
|
538
|
+
"field": "department",
|
|
539
|
+
"operator": "eq",
|
|
540
|
+
"value": "marketing"
|
|
541
|
+
}
|
|
542
|
+
],
|
|
543
|
+
"include_headers": true
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
#### Export Query Results to CSV
|
|
549
|
+
|
|
550
|
+
**User prompt:** *"Export a report of total sales by product category to CSV"*
|
|
551
|
+
|
|
552
|
+
**AI will execute:**
|
|
553
|
+
```json
|
|
554
|
+
{
|
|
555
|
+
"tool": "export_query_to_csv",
|
|
556
|
+
"arguments": {
|
|
557
|
+
"query": "SELECT category, SUM(sales_amount) as total_sales FROM sales GROUP BY category ORDER BY total_sales DESC",
|
|
558
|
+
"include_headers": true
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Data Export Best Practices
|
|
564
|
+
|
|
565
|
+
1. ✅ **Use filtering** - Export only the data you need to reduce file size
|
|
566
|
+
2. ✅ **Implement pagination** - For large datasets, use pagination to avoid memory issues
|
|
567
|
+
3. ✅ **Include headers** - Make CSV files more understandable with column headers
|
|
568
|
+
4. ✅ **Test with small datasets first** - Verify export format before processing large amounts of data
|
|
569
|
+
5. ✅ **Use proper permissions** - Data export tools require `utility` permission
|
|
570
|
+
|
|
571
|
+
### Common Data Export Patterns
|
|
572
|
+
|
|
573
|
+
**Pattern 1: Simple Table Export**
|
|
574
|
+
```json
|
|
575
|
+
{
|
|
576
|
+
"tool": "export_table_to_csv",
|
|
577
|
+
"arguments": {
|
|
578
|
+
"table_name": "products",
|
|
579
|
+
"include_headers": true
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**Pattern 2: Filtered and Sorted Export**
|
|
585
|
+
```json
|
|
586
|
+
{
|
|
587
|
+
"tool": "export_table_to_csv",
|
|
588
|
+
"arguments": {
|
|
589
|
+
"table_name": "orders",
|
|
590
|
+
"filters": [
|
|
591
|
+
{
|
|
592
|
+
"field": "order_date",
|
|
593
|
+
"operator": "gte",
|
|
594
|
+
"value": "2023-01-01"
|
|
595
|
+
}
|
|
596
|
+
],
|
|
597
|
+
"sorting": {
|
|
598
|
+
"field": "order_date",
|
|
599
|
+
"direction": "desc"
|
|
600
|
+
},
|
|
601
|
+
"include_headers": true
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**Pattern 3: Complex Query Export**
|
|
607
|
+
```json
|
|
608
|
+
{
|
|
609
|
+
"tool": "export_query_to_csv",
|
|
610
|
+
"arguments": {
|
|
611
|
+
"query": "SELECT u.name, u.email, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id HAVING order_count > 5",
|
|
612
|
+
"include_headers": true
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
369
619
|
## 💰 Transaction Management
|
|
370
620
|
|
|
371
621
|
The MySQL MCP Server provides full ACID transaction support, allowing you to group multiple database operations into atomic units.
|
|
@@ -1148,6 +1398,45 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
1148
1398
|
- [ ] Oracle Database adapter
|
|
1149
1399
|
- [ ] SQL Server adapter
|
|
1150
1400
|
|
|
1401
|
+
### Recommended Implementation Order
|
|
1402
|
+
|
|
1403
|
+
#### **Phase 1: Performance & Monitoring** 🚀
|
|
1404
|
+
- [ ] **Query result caching** - Dramatically improve response times for repeated queries
|
|
1405
|
+
- [ ] **Performance metrics** - Track query execution times and database performance
|
|
1406
|
+
- [ ] **Connection pool monitoring** - Monitor database connection health and usage
|
|
1407
|
+
- [ ] **Database health checks** - Comprehensive system health monitoring
|
|
1408
|
+
|
|
1409
|
+
#### **Phase 2: Data Management** 📊
|
|
1410
|
+
- [ ] **Database backup and restore tools** - Essential for production data safety
|
|
1411
|
+
- [ ] **Data migration utilities** - Move data between databases and environments
|
|
1412
|
+
- [ ] **Enhanced export/import** - Support for JSON, XML, Excel formats
|
|
1413
|
+
- [ ] **Query history & analytics** - Track and analyze database usage patterns
|
|
1414
|
+
|
|
1415
|
+
#### **Phase 3: Enterprise Features** 🏢
|
|
1416
|
+
- [ ] **Audit logging and compliance** - Track all database operations for security
|
|
1417
|
+
- [ ] **Schema versioning and migrations** - Version control for database schema changes
|
|
1418
|
+
- [ ] **Query optimization** - Automatic query analysis and optimization suggestions
|
|
1419
|
+
- [ ] **Advanced security features** - Enhanced access control and monitoring
|
|
1420
|
+
|
|
1421
|
+
#### **Phase 4: Multi-Database Support** 🌐
|
|
1422
|
+
- [ ] **PostgreSQL adapter** - Extend support to PostgreSQL databases
|
|
1423
|
+
- [ ] **MongoDB adapter** - Add NoSQL document database support
|
|
1424
|
+
- [ ] **SQLite adapter** - Support for lightweight embedded databases
|
|
1425
|
+
- [ ] **Database-agnostic operations** - Unified API across different database types
|
|
1426
|
+
|
|
1427
|
+
#### **Implementation Priority Matrix**
|
|
1428
|
+
|
|
1429
|
+
| Feature | Impact | Effort | Priority |
|
|
1430
|
+
|---------|--------|--------|----------|
|
|
1431
|
+
| Query Result Caching | High | Medium | 1 |
|
|
1432
|
+
| Database Backup/Restore | High | High | 2 |
|
|
1433
|
+
| Performance Monitoring | High | Medium | 3 |
|
|
1434
|
+
| Data Migration | High | High | 4 |
|
|
1435
|
+
| Query Optimization | Medium | Medium | 5 |
|
|
1436
|
+
| PostgreSQL Adapter | High | High | 6 |
|
|
1437
|
+
| Audit Logging | Medium | Low | 7 |
|
|
1438
|
+
| Schema Versioning | Medium | Medium | 8 |
|
|
1439
|
+
|
|
1151
1440
|
---
|
|
1152
1441
|
|
|
1153
1442
|
**Made with ❤️ for the AI community**
|
|
@@ -22,6 +22,7 @@ export declare const toolCategoryMap: Record<string, ToolCategory>;
|
|
|
22
22
|
*/
|
|
23
23
|
export declare class FeatureConfig {
|
|
24
24
|
private enabledCategories;
|
|
25
|
+
private originalConfigString;
|
|
25
26
|
constructor(configStr?: string);
|
|
26
27
|
/**
|
|
27
28
|
* Parse MCP_CONFIG from provided string or environment variables
|
|
@@ -35,6 +36,10 @@ export declare class FeatureConfig {
|
|
|
35
36
|
* Check if a specific tool is enabled
|
|
36
37
|
*/
|
|
37
38
|
isToolEnabled(toolName: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Get detailed permission error message for a specific tool
|
|
41
|
+
*/
|
|
42
|
+
getPermissionError(toolName: string): string;
|
|
38
43
|
/**
|
|
39
44
|
* Check if a category is enabled
|
|
40
45
|
*/
|
|
@@ -36,6 +36,10 @@ exports.toolCategoryMap = {
|
|
|
36
36
|
'readRecords': ToolCategory.READ,
|
|
37
37
|
'updateRecord': ToolCategory.UPDATE,
|
|
38
38
|
'deleteRecord': ToolCategory.DELETE,
|
|
39
|
+
// Bulk operations
|
|
40
|
+
'bulkInsert': ToolCategory.CREATE,
|
|
41
|
+
'bulkUpdate': ToolCategory.UPDATE,
|
|
42
|
+
'bulkDelete': ToolCategory.DELETE,
|
|
39
43
|
// Query tools
|
|
40
44
|
'runQuery': ToolCategory.READ,
|
|
41
45
|
'executeSql': ToolCategory.EXECUTE,
|
|
@@ -48,6 +52,8 @@ exports.toolCategoryMap = {
|
|
|
48
52
|
'describeConnection': ToolCategory.UTILITY,
|
|
49
53
|
'testConnection': ToolCategory.UTILITY,
|
|
50
54
|
'getTableRelationships': ToolCategory.UTILITY,
|
|
55
|
+
'exportTableToCSV': ToolCategory.UTILITY,
|
|
56
|
+
'exportQueryToCSV': ToolCategory.UTILITY,
|
|
51
57
|
// Transaction tools
|
|
52
58
|
'beginTransaction': ToolCategory.TRANSACTION,
|
|
53
59
|
'commitTransaction': ToolCategory.TRANSACTION,
|
|
@@ -67,6 +73,7 @@ exports.toolCategoryMap = {
|
|
|
67
73
|
*/
|
|
68
74
|
class FeatureConfig {
|
|
69
75
|
constructor(configStr) {
|
|
76
|
+
this.originalConfigString = configStr || process.env.MCP_CONFIG || '';
|
|
70
77
|
this.enabledCategories = this.parseConfig(configStr);
|
|
71
78
|
}
|
|
72
79
|
/**
|
|
@@ -88,6 +95,7 @@ class FeatureConfig {
|
|
|
88
95
|
* Update configuration at runtime
|
|
89
96
|
*/
|
|
90
97
|
setConfig(configStr) {
|
|
98
|
+
this.originalConfigString = configStr;
|
|
91
99
|
this.enabledCategories = this.parseConfig(configStr);
|
|
92
100
|
}
|
|
93
101
|
/**
|
|
@@ -102,6 +110,57 @@ class FeatureConfig {
|
|
|
102
110
|
}
|
|
103
111
|
return this.enabledCategories.has(category);
|
|
104
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Get detailed permission error message for a specific tool
|
|
115
|
+
*/
|
|
116
|
+
getPermissionError(toolName) {
|
|
117
|
+
const category = exports.toolCategoryMap[toolName];
|
|
118
|
+
if (!category) {
|
|
119
|
+
return `Unknown tool '${toolName}'. This tool is not recognized by the MCP server.`;
|
|
120
|
+
}
|
|
121
|
+
const isAllPermissions = !this.originalConfigString.trim();
|
|
122
|
+
const currentPermissions = isAllPermissions ? 'all' : this.originalConfigString;
|
|
123
|
+
const actionDescriptions = {
|
|
124
|
+
[ToolCategory.LIST]: 'list databases and tables',
|
|
125
|
+
[ToolCategory.READ]: 'read data from tables',
|
|
126
|
+
[ToolCategory.CREATE]: 'create new records',
|
|
127
|
+
[ToolCategory.UPDATE]: 'update existing records',
|
|
128
|
+
[ToolCategory.DELETE]: 'delete records',
|
|
129
|
+
[ToolCategory.EXECUTE]: 'execute custom SQL queries',
|
|
130
|
+
[ToolCategory.DDL]: 'create, alter, or drop tables (schema changes)',
|
|
131
|
+
[ToolCategory.UTILITY]: 'use utility functions',
|
|
132
|
+
[ToolCategory.TRANSACTION]: 'manage database transactions',
|
|
133
|
+
[ToolCategory.PROCEDURE]: 'manage stored procedures'
|
|
134
|
+
};
|
|
135
|
+
const toolDescriptions = {
|
|
136
|
+
'createTable': 'create new tables',
|
|
137
|
+
'alterTable': 'modify table structure',
|
|
138
|
+
'dropTable': 'delete tables',
|
|
139
|
+
'executeDdl': 'execute DDL statements',
|
|
140
|
+
'createRecord': 'insert new records',
|
|
141
|
+
'updateRecord': 'update existing records',
|
|
142
|
+
'deleteRecord': 'delete records',
|
|
143
|
+
'bulkInsert': 'insert multiple records in batches',
|
|
144
|
+
'bulkUpdate': 'update multiple records in batches',
|
|
145
|
+
'bulkDelete': 'delete multiple records in batches',
|
|
146
|
+
'executeSql': 'execute custom SQL statements',
|
|
147
|
+
'runQuery': 'run SELECT queries',
|
|
148
|
+
'beginTransaction': 'start database transactions',
|
|
149
|
+
'commitTransaction': 'commit database transactions',
|
|
150
|
+
'rollbackTransaction': 'rollback database transactions',
|
|
151
|
+
'executeInTransaction': 'execute queries within transactions',
|
|
152
|
+
'createStoredProcedure': 'create stored procedures',
|
|
153
|
+
'dropStoredProcedure': 'delete stored procedures',
|
|
154
|
+
'executeStoredProcedure': 'execute stored procedures',
|
|
155
|
+
'exportTableToCSV': 'export table data to CSV',
|
|
156
|
+
'exportQueryToCSV': 'export query results to CSV'
|
|
157
|
+
};
|
|
158
|
+
const toolDescription = toolDescriptions[toolName] || actionDescriptions[category];
|
|
159
|
+
const requiredPermission = category;
|
|
160
|
+
return `Permission denied: Cannot ${toolDescription}. ` +
|
|
161
|
+
`This action requires '${requiredPermission}' permission, but your current MCP configuration only allows: ${currentPermissions}. ` +
|
|
162
|
+
`To enable this feature, update your MCP server configuration to include '${requiredPermission}' in the permissions list.`;
|
|
163
|
+
}
|
|
105
164
|
/**
|
|
106
165
|
* Check if a category is enabled
|
|
107
166
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare class MySQLMCP {
|
|
|
10
10
|
private ddlTools;
|
|
11
11
|
private transactionTools;
|
|
12
12
|
private storedProcedureTools;
|
|
13
|
+
private dataExportTools;
|
|
13
14
|
private security;
|
|
14
15
|
private featureConfig;
|
|
15
16
|
constructor(permissionsConfig?: string);
|
|
@@ -224,6 +225,32 @@ export declare class MySQLMCP {
|
|
|
224
225
|
data?: any;
|
|
225
226
|
error?: string;
|
|
226
227
|
}>;
|
|
228
|
+
exportTableToCSV(params: {
|
|
229
|
+
table_name: string;
|
|
230
|
+
filters?: any[];
|
|
231
|
+
pagination?: {
|
|
232
|
+
page: number;
|
|
233
|
+
limit: number;
|
|
234
|
+
};
|
|
235
|
+
sorting?: {
|
|
236
|
+
field: string;
|
|
237
|
+
direction: 'asc' | 'desc';
|
|
238
|
+
};
|
|
239
|
+
include_headers?: boolean;
|
|
240
|
+
}): Promise<{
|
|
241
|
+
status: string;
|
|
242
|
+
data?: any;
|
|
243
|
+
error?: string;
|
|
244
|
+
}>;
|
|
245
|
+
exportQueryToCSV(params: {
|
|
246
|
+
query: string;
|
|
247
|
+
params?: any[];
|
|
248
|
+
include_headers?: boolean;
|
|
249
|
+
}): Promise<{
|
|
250
|
+
status: string;
|
|
251
|
+
data?: any;
|
|
252
|
+
error?: string;
|
|
253
|
+
}>;
|
|
227
254
|
getFeatureStatus(): {
|
|
228
255
|
status: string;
|
|
229
256
|
data: {
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const utilityTools_1 = require("./tools/utilityTools");
|
|
|
11
11
|
const ddlTools_1 = require("./tools/ddlTools");
|
|
12
12
|
const transactionTools_1 = require("./tools/transactionTools");
|
|
13
13
|
const storedProcedureTools_1 = require("./tools/storedProcedureTools");
|
|
14
|
+
const dataExportTools_1 = require("./tools/dataExportTools");
|
|
14
15
|
const securityLayer_1 = __importDefault(require("./security/securityLayer"));
|
|
15
16
|
const connection_1 = __importDefault(require("./db/connection"));
|
|
16
17
|
const featureConfig_1 = require("./config/featureConfig");
|
|
@@ -29,13 +30,14 @@ class MySQLMCP {
|
|
|
29
30
|
this.ddlTools = new ddlTools_1.DdlTools();
|
|
30
31
|
this.transactionTools = new transactionTools_1.TransactionTools();
|
|
31
32
|
this.storedProcedureTools = new storedProcedureTools_1.StoredProcedureTools(this.security);
|
|
33
|
+
this.dataExportTools = new dataExportTools_1.DataExportTools(this.security);
|
|
32
34
|
}
|
|
33
35
|
// Helper method to check if tool is enabled
|
|
34
36
|
checkToolEnabled(toolName) {
|
|
35
37
|
if (!this.featureConfig.isToolEnabled(toolName)) {
|
|
36
38
|
return {
|
|
37
39
|
enabled: false,
|
|
38
|
-
error:
|
|
40
|
+
error: this.featureConfig.getPermissionError(toolName)
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
return { enabled: true };
|
|
@@ -253,6 +255,21 @@ class MySQLMCP {
|
|
|
253
255
|
}
|
|
254
256
|
return await this.storedProcedureTools.showCreateProcedure(params);
|
|
255
257
|
}
|
|
258
|
+
// Data Export Tools
|
|
259
|
+
async exportTableToCSV(params) {
|
|
260
|
+
const check = this.checkToolEnabled('exportTableToCSV');
|
|
261
|
+
if (!check.enabled) {
|
|
262
|
+
return { status: 'error', error: check.error };
|
|
263
|
+
}
|
|
264
|
+
return await this.dataExportTools.exportTableToCSV(params);
|
|
265
|
+
}
|
|
266
|
+
async exportQueryToCSV(params) {
|
|
267
|
+
const check = this.checkToolEnabled('exportQueryToCSV');
|
|
268
|
+
if (!check.enabled) {
|
|
269
|
+
return { status: 'error', error: check.error };
|
|
270
|
+
}
|
|
271
|
+
return await this.dataExportTools.exportQueryToCSV(params);
|
|
272
|
+
}
|
|
256
273
|
// Get feature configuration status
|
|
257
274
|
getFeatureStatus() {
|
|
258
275
|
return {
|
package/dist/mcp-server.js
CHANGED
|
@@ -692,11 +692,85 @@ const TOOLS = [
|
|
|
692
692
|
required: ['procedure_name'],
|
|
693
693
|
},
|
|
694
694
|
},
|
|
695
|
+
// Data Export Tools
|
|
696
|
+
{
|
|
697
|
+
name: 'export_table_to_csv',
|
|
698
|
+
description: 'Export table data to CSV format with optional filtering, pagination, and sorting.',
|
|
699
|
+
inputSchema: {
|
|
700
|
+
type: 'object',
|
|
701
|
+
properties: {
|
|
702
|
+
table_name: {
|
|
703
|
+
type: 'string',
|
|
704
|
+
description: 'Name of the table to export',
|
|
705
|
+
},
|
|
706
|
+
filters: {
|
|
707
|
+
type: 'array',
|
|
708
|
+
description: 'Array of filter conditions',
|
|
709
|
+
items: {
|
|
710
|
+
type: 'object',
|
|
711
|
+
properties: {
|
|
712
|
+
field: { type: 'string' },
|
|
713
|
+
operator: {
|
|
714
|
+
type: 'string',
|
|
715
|
+
enum: ['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'like', 'in']
|
|
716
|
+
},
|
|
717
|
+
value: {
|
|
718
|
+
description: 'Value to compare against (can be string, number, boolean, or array for "in" operator)'
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
required: ['field', 'operator', 'value'],
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
pagination: {
|
|
725
|
+
type: 'object',
|
|
726
|
+
properties: {
|
|
727
|
+
page: { type: 'number', description: 'Page number (starting from 1)' },
|
|
728
|
+
limit: { type: 'number', description: 'Number of records per page' },
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
sorting: {
|
|
732
|
+
type: 'object',
|
|
733
|
+
properties: {
|
|
734
|
+
field: { type: 'string', description: 'Field name to sort by' },
|
|
735
|
+
direction: { type: 'string', enum: ['asc', 'desc'] },
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
include_headers: {
|
|
739
|
+
type: 'boolean',
|
|
740
|
+
description: 'Whether to include column headers in the CSV output',
|
|
741
|
+
},
|
|
742
|
+
},
|
|
743
|
+
required: ['table_name'],
|
|
744
|
+
},
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
name: 'export_query_to_csv',
|
|
748
|
+
description: 'Export the results of a SELECT query to CSV format.',
|
|
749
|
+
inputSchema: {
|
|
750
|
+
type: 'object',
|
|
751
|
+
properties: {
|
|
752
|
+
query: {
|
|
753
|
+
type: 'string',
|
|
754
|
+
description: 'SQL SELECT query to execute and export',
|
|
755
|
+
},
|
|
756
|
+
params: {
|
|
757
|
+
type: 'array',
|
|
758
|
+
description: 'Optional array of parameters for parameterized queries',
|
|
759
|
+
items: {},
|
|
760
|
+
},
|
|
761
|
+
include_headers: {
|
|
762
|
+
type: 'boolean',
|
|
763
|
+
description: 'Whether to include column headers in the CSV output',
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
required: ['query'],
|
|
767
|
+
},
|
|
768
|
+
},
|
|
695
769
|
];
|
|
696
770
|
// Create the MCP server
|
|
697
771
|
const server = new index_js_1.Server({
|
|
698
772
|
name: 'mysql-mcp-server',
|
|
699
|
-
version: '1.
|
|
773
|
+
version: '1.3.0',
|
|
700
774
|
}, {
|
|
701
775
|
capabilities: {
|
|
702
776
|
tools: {},
|
|
@@ -806,6 +880,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
806
880
|
case 'show_create_procedure':
|
|
807
881
|
result = await mysqlMCP.showCreateProcedure(args);
|
|
808
882
|
break;
|
|
883
|
+
// Data Export Tools
|
|
884
|
+
case 'export_table_to_csv':
|
|
885
|
+
result = await mysqlMCP.exportTableToCSV(args);
|
|
886
|
+
break;
|
|
887
|
+
case 'export_query_to_csv':
|
|
888
|
+
result = await mysqlMCP.exportQueryToCSV(args);
|
|
889
|
+
break;
|
|
809
890
|
default:
|
|
810
891
|
throw new Error(`Unknown tool: ${name}`);
|
|
811
892
|
}
|
|
@@ -857,6 +938,19 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
857
938
|
};
|
|
858
939
|
}
|
|
859
940
|
catch (error) {
|
|
941
|
+
// Check if this is a permission error
|
|
942
|
+
if (error.message && error.message.includes('Permission denied')) {
|
|
943
|
+
return {
|
|
944
|
+
content: [
|
|
945
|
+
{
|
|
946
|
+
type: 'text',
|
|
947
|
+
text: `❌ ${error.message}`,
|
|
948
|
+
},
|
|
949
|
+
],
|
|
950
|
+
isError: true,
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
// Handle other errors with generic message
|
|
860
954
|
return {
|
|
861
955
|
content: [
|
|
862
956
|
{
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { FilterCondition, Pagination, Sorting } from '../validation/schemas';
|
|
2
|
+
import SecurityLayer from '../security/securityLayer';
|
|
3
|
+
export declare class DataExportTools {
|
|
4
|
+
private db;
|
|
5
|
+
private security;
|
|
6
|
+
constructor(security: SecurityLayer);
|
|
7
|
+
/**
|
|
8
|
+
* Export table data to CSV format
|
|
9
|
+
*/
|
|
10
|
+
exportTableToCSV(params: {
|
|
11
|
+
table_name: string;
|
|
12
|
+
filters?: FilterCondition[];
|
|
13
|
+
pagination?: Pagination;
|
|
14
|
+
sorting?: Sorting;
|
|
15
|
+
include_headers?: boolean;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
status: string;
|
|
18
|
+
data?: any;
|
|
19
|
+
error?: string;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Export query results to CSV format
|
|
23
|
+
*/
|
|
24
|
+
exportQueryToCSV(params: {
|
|
25
|
+
query: string;
|
|
26
|
+
params?: any[];
|
|
27
|
+
include_headers?: boolean;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
status: string;
|
|
30
|
+
data?: any;
|
|
31
|
+
error?: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DataExportTools = void 0;
|
|
7
|
+
const connection_1 = __importDefault(require("../db/connection"));
|
|
8
|
+
class DataExportTools {
|
|
9
|
+
constructor(security) {
|
|
10
|
+
this.db = connection_1.default.getInstance();
|
|
11
|
+
this.security = security;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Export table data to CSV format
|
|
15
|
+
*/
|
|
16
|
+
async exportTableToCSV(params) {
|
|
17
|
+
try {
|
|
18
|
+
const { table_name, filters = [], pagination, sorting, include_headers = true } = params;
|
|
19
|
+
// Validate table name
|
|
20
|
+
const tableValidation = this.security.validateIdentifier(table_name);
|
|
21
|
+
if (!tableValidation.valid) {
|
|
22
|
+
return {
|
|
23
|
+
status: 'error',
|
|
24
|
+
error: tableValidation.error
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Build WHERE clause
|
|
28
|
+
let whereClause = '';
|
|
29
|
+
const whereParams = [];
|
|
30
|
+
if (filters && filters.length > 0) {
|
|
31
|
+
const whereConditions = [];
|
|
32
|
+
for (const filter of filters) {
|
|
33
|
+
// Validate field name
|
|
34
|
+
const fieldValidation = this.security.validateIdentifier(filter.field);
|
|
35
|
+
if (!fieldValidation.valid) {
|
|
36
|
+
return {
|
|
37
|
+
status: 'error',
|
|
38
|
+
error: `Invalid field name: ${filter.field}`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const fieldName = this.security.escapeIdentifier(filter.field);
|
|
42
|
+
switch (filter.operator) {
|
|
43
|
+
case 'eq':
|
|
44
|
+
whereConditions.push(`${fieldName} = ?`);
|
|
45
|
+
whereParams.push(filter.value);
|
|
46
|
+
break;
|
|
47
|
+
case 'neq':
|
|
48
|
+
whereConditions.push(`${fieldName} != ?`);
|
|
49
|
+
whereParams.push(filter.value);
|
|
50
|
+
break;
|
|
51
|
+
case 'gt':
|
|
52
|
+
whereConditions.push(`${fieldName} > ?`);
|
|
53
|
+
whereParams.push(filter.value);
|
|
54
|
+
break;
|
|
55
|
+
case 'gte':
|
|
56
|
+
whereConditions.push(`${fieldName} >= ?`);
|
|
57
|
+
whereParams.push(filter.value);
|
|
58
|
+
break;
|
|
59
|
+
case 'lt':
|
|
60
|
+
whereConditions.push(`${fieldName} < ?`);
|
|
61
|
+
whereParams.push(filter.value);
|
|
62
|
+
break;
|
|
63
|
+
case 'lte':
|
|
64
|
+
whereConditions.push(`${fieldName} <= ?`);
|
|
65
|
+
whereParams.push(filter.value);
|
|
66
|
+
break;
|
|
67
|
+
case 'like':
|
|
68
|
+
whereConditions.push(`${fieldName} LIKE ?`);
|
|
69
|
+
whereParams.push(filter.value);
|
|
70
|
+
break;
|
|
71
|
+
case 'in':
|
|
72
|
+
if (Array.isArray(filter.value)) {
|
|
73
|
+
const placeholders = filter.value.map(() => '?').join(', ');
|
|
74
|
+
whereConditions.push(`${fieldName} IN (${placeholders})`);
|
|
75
|
+
whereParams.push(...filter.value);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return {
|
|
79
|
+
status: 'error',
|
|
80
|
+
error: 'IN operator requires an array of values'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
default:
|
|
85
|
+
return {
|
|
86
|
+
status: 'error',
|
|
87
|
+
error: `Unsupported operator: ${filter.operator}`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (whereConditions.length > 0) {
|
|
92
|
+
whereClause = 'WHERE ' + whereConditions.join(' AND ');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Build ORDER BY clause
|
|
96
|
+
let orderByClause = '';
|
|
97
|
+
if (sorting) {
|
|
98
|
+
const fieldValidation = this.security.validateIdentifier(sorting.field);
|
|
99
|
+
if (!fieldValidation.valid) {
|
|
100
|
+
return {
|
|
101
|
+
status: 'error',
|
|
102
|
+
error: `Invalid sort field name: ${sorting.field}`
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const fieldName = this.security.escapeIdentifier(sorting.field);
|
|
106
|
+
const direction = sorting.direction.toUpperCase() === 'DESC' ? 'DESC' : 'ASC';
|
|
107
|
+
orderByClause = `ORDER BY ${fieldName} ${direction}`;
|
|
108
|
+
}
|
|
109
|
+
// Build LIMIT clause
|
|
110
|
+
let limitClause = '';
|
|
111
|
+
if (pagination) {
|
|
112
|
+
const offset = (pagination.page - 1) * pagination.limit;
|
|
113
|
+
limitClause = `LIMIT ${offset}, ${pagination.limit}`;
|
|
114
|
+
}
|
|
115
|
+
// Construct the query
|
|
116
|
+
const escapedTableName = this.security.escapeIdentifier(table_name);
|
|
117
|
+
const query = `SELECT * FROM ${escapedTableName} ${whereClause} ${orderByClause} ${limitClause}`;
|
|
118
|
+
// Execute query
|
|
119
|
+
const results = await this.db.query(query, whereParams);
|
|
120
|
+
// If no results, return empty CSV
|
|
121
|
+
if (results.length === 0) {
|
|
122
|
+
return {
|
|
123
|
+
status: 'success',
|
|
124
|
+
data: {
|
|
125
|
+
csv: include_headers ? '' : '',
|
|
126
|
+
row_count: 0
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// Generate CSV
|
|
131
|
+
let csv = '';
|
|
132
|
+
// Add headers if requested
|
|
133
|
+
if (include_headers) {
|
|
134
|
+
const headers = Object.keys(results[0]).join(',');
|
|
135
|
+
csv += headers + '\n';
|
|
136
|
+
}
|
|
137
|
+
// Add data rows
|
|
138
|
+
for (const row of results) {
|
|
139
|
+
const values = Object.values(row).map(value => {
|
|
140
|
+
if (value === null)
|
|
141
|
+
return '';
|
|
142
|
+
if (typeof value === 'string') {
|
|
143
|
+
// Escape quotes and wrap in quotes if contains comma or newline
|
|
144
|
+
if (value.includes(',') || value.includes('\n') || value.includes('"')) {
|
|
145
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
return String(value);
|
|
150
|
+
}).join(',');
|
|
151
|
+
csv += values + '\n';
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
status: 'success',
|
|
155
|
+
data: {
|
|
156
|
+
csv: csv,
|
|
157
|
+
row_count: results.length
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
return {
|
|
163
|
+
status: 'error',
|
|
164
|
+
error: error.message
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Export query results to CSV format
|
|
170
|
+
*/
|
|
171
|
+
async exportQueryToCSV(params) {
|
|
172
|
+
try {
|
|
173
|
+
const { query, params: queryParams = [], include_headers = true } = params;
|
|
174
|
+
// Validate query is a SELECT statement
|
|
175
|
+
if (!this.security.isReadOnlyQuery(query)) {
|
|
176
|
+
return {
|
|
177
|
+
status: 'error',
|
|
178
|
+
error: 'Only SELECT queries can be exported to CSV'
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// Validate parameters
|
|
182
|
+
const paramValidation = this.security.validateParameters(queryParams);
|
|
183
|
+
if (!paramValidation.valid) {
|
|
184
|
+
return {
|
|
185
|
+
status: 'error',
|
|
186
|
+
error: paramValidation.error
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// Execute query
|
|
190
|
+
const results = await this.db.query(query, queryParams);
|
|
191
|
+
// If no results, return empty CSV
|
|
192
|
+
if (results.length === 0) {
|
|
193
|
+
return {
|
|
194
|
+
status: 'success',
|
|
195
|
+
data: {
|
|
196
|
+
csv: include_headers ? '' : '',
|
|
197
|
+
row_count: 0
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// Generate CSV
|
|
202
|
+
let csv = '';
|
|
203
|
+
// Add headers if requested
|
|
204
|
+
if (include_headers) {
|
|
205
|
+
const headers = Object.keys(results[0]).join(',');
|
|
206
|
+
csv += headers + '\n';
|
|
207
|
+
}
|
|
208
|
+
// Add data rows
|
|
209
|
+
for (const row of results) {
|
|
210
|
+
const values = Object.values(row).map(value => {
|
|
211
|
+
if (value === null)
|
|
212
|
+
return '';
|
|
213
|
+
if (typeof value === 'string') {
|
|
214
|
+
// Escape quotes and wrap in quotes if contains comma or newline
|
|
215
|
+
if (value.includes(',') || value.includes('\n') || value.includes('"')) {
|
|
216
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
217
|
+
}
|
|
218
|
+
return value;
|
|
219
|
+
}
|
|
220
|
+
return String(value);
|
|
221
|
+
}).join(',');
|
|
222
|
+
csv += values + '\n';
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
status: 'success',
|
|
226
|
+
data: {
|
|
227
|
+
csv: csv,
|
|
228
|
+
row_count: results.length
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
return {
|
|
234
|
+
status: 'error',
|
|
235
|
+
error: error.message
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
exports.DataExportTools = DataExportTools;
|
|
@@ -512,6 +512,87 @@ export declare const showCreateProcedureSchema: {
|
|
|
512
512
|
};
|
|
513
513
|
additionalProperties: boolean;
|
|
514
514
|
};
|
|
515
|
+
export declare const exportTableToCsvSchema: {
|
|
516
|
+
type: string;
|
|
517
|
+
required: string[];
|
|
518
|
+
properties: {
|
|
519
|
+
table_name: {
|
|
520
|
+
type: string;
|
|
521
|
+
};
|
|
522
|
+
filters: {
|
|
523
|
+
type: string;
|
|
524
|
+
items: {
|
|
525
|
+
type: string;
|
|
526
|
+
required: string[];
|
|
527
|
+
properties: {
|
|
528
|
+
field: {
|
|
529
|
+
type: string;
|
|
530
|
+
};
|
|
531
|
+
operator: {
|
|
532
|
+
type: string;
|
|
533
|
+
enum: string[];
|
|
534
|
+
};
|
|
535
|
+
value: {};
|
|
536
|
+
};
|
|
537
|
+
};
|
|
538
|
+
nullable: boolean;
|
|
539
|
+
};
|
|
540
|
+
pagination: {
|
|
541
|
+
type: string;
|
|
542
|
+
properties: {
|
|
543
|
+
page: {
|
|
544
|
+
type: string;
|
|
545
|
+
minimum: number;
|
|
546
|
+
};
|
|
547
|
+
limit: {
|
|
548
|
+
type: string;
|
|
549
|
+
minimum: number;
|
|
550
|
+
maximum: number;
|
|
551
|
+
};
|
|
552
|
+
};
|
|
553
|
+
required: string[];
|
|
554
|
+
nullable: boolean;
|
|
555
|
+
};
|
|
556
|
+
sorting: {
|
|
557
|
+
type: string;
|
|
558
|
+
properties: {
|
|
559
|
+
field: {
|
|
560
|
+
type: string;
|
|
561
|
+
};
|
|
562
|
+
direction: {
|
|
563
|
+
type: string;
|
|
564
|
+
enum: string[];
|
|
565
|
+
};
|
|
566
|
+
};
|
|
567
|
+
required: string[];
|
|
568
|
+
nullable: boolean;
|
|
569
|
+
};
|
|
570
|
+
include_headers: {
|
|
571
|
+
type: string;
|
|
572
|
+
nullable: boolean;
|
|
573
|
+
};
|
|
574
|
+
};
|
|
575
|
+
additionalProperties: boolean;
|
|
576
|
+
};
|
|
577
|
+
export declare const exportQueryToCsvSchema: {
|
|
578
|
+
type: string;
|
|
579
|
+
required: string[];
|
|
580
|
+
properties: {
|
|
581
|
+
query: {
|
|
582
|
+
type: string;
|
|
583
|
+
};
|
|
584
|
+
params: {
|
|
585
|
+
type: string;
|
|
586
|
+
items: {};
|
|
587
|
+
nullable: boolean;
|
|
588
|
+
};
|
|
589
|
+
include_headers: {
|
|
590
|
+
type: string;
|
|
591
|
+
nullable: boolean;
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
additionalProperties: boolean;
|
|
595
|
+
};
|
|
515
596
|
export declare const validateListTables: import("ajv").ValidateFunction<{
|
|
516
597
|
database: unknown;
|
|
517
598
|
} & {}>;
|
|
@@ -596,3 +677,9 @@ export declare const validateStoredProcedureCreation: import("ajv").ValidateFunc
|
|
|
596
677
|
export declare const validateGetTableRelationships: import("ajv").ValidateFunction<{
|
|
597
678
|
[x: string]: {};
|
|
598
679
|
}>;
|
|
680
|
+
export declare const validateExportTableToCsv: import("ajv").ValidateFunction<{
|
|
681
|
+
[x: string]: {};
|
|
682
|
+
}>;
|
|
683
|
+
export declare const validateExportQueryToCsv: import("ajv").ValidateFunction<{
|
|
684
|
+
[x: string]: {};
|
|
685
|
+
}>;
|
|
@@ -3,8 +3,8 @@ 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.
|
|
7
|
-
exports.validateGetTableRelationships = exports.validateStoredProcedureCreation = void 0;
|
|
6
|
+
exports.validateDropStoredProcedure = exports.validateCreateStoredProcedure = exports.validateExecuteStoredProcedure = exports.validateGetStoredProcedureInfo = exports.validateListStoredProcedures = exports.validateExecuteInTransaction = exports.validateRollbackTransaction = exports.validateCommitTransaction = exports.validateBeginTransaction = exports.validateExecuteDdl = exports.validateDropTable = exports.validateAlterTable = exports.validateCreateTable = exports.validateExecuteSql = exports.validateRunQuery = exports.validateBulkDelete = exports.validateBulkUpdate = exports.validateBulkInsert = exports.validateDeleteRecord = exports.validateUpdateRecord = exports.validateReadRecords = exports.validateCreateRecord = exports.validateReadTableSchema = exports.validateListTables = exports.exportQueryToCsvSchema = exports.exportTableToCsvSchema = exports.showCreateProcedureSchema = exports.dropStoredProcedureSchema = exports.createStoredProcedureSchema = exports.executeStoredProcedureSchema = exports.getStoredProcedureInfoSchema = exports.listStoredProceduresSchema = exports.executeInTransactionSchema = exports.getTransactionStatusSchema = exports.rollbackTransactionSchema = exports.commitTransactionSchema = exports.beginTransactionSchema = exports.getTableRelationshipsSchema = exports.executeDdlSchema = exports.dropTableSchema = exports.alterTableSchema = exports.createTableSchema = exports.executeSqlSchema = exports.runQuerySchema = exports.deleteRecordSchema = exports.updateRecordSchema = exports.readRecordsSchema = exports.createRecordSchema = exports.readTableSchemaSchema = exports.listTablesSchema = void 0;
|
|
7
|
+
exports.validateExportQueryToCsv = exports.validateExportTableToCsv = exports.validateGetTableRelationships = exports.validateStoredProcedureCreation = exports.validateStoredProcedureExecution = exports.validateShowCreateProcedure = void 0;
|
|
8
8
|
const ajv_1 = __importDefault(require("ajv"));
|
|
9
9
|
const ajv = new ajv_1.default();
|
|
10
10
|
// Schema definitions
|
|
@@ -442,6 +442,64 @@ const bulkDeleteSchema = {
|
|
|
442
442
|
required: ['table_name', 'condition_sets'],
|
|
443
443
|
additionalProperties: false
|
|
444
444
|
};
|
|
445
|
+
// Data Export schemas
|
|
446
|
+
exports.exportTableToCsvSchema = {
|
|
447
|
+
type: 'object',
|
|
448
|
+
required: ['table_name'],
|
|
449
|
+
properties: {
|
|
450
|
+
table_name: { type: 'string' },
|
|
451
|
+
filters: {
|
|
452
|
+
type: 'array',
|
|
453
|
+
items: {
|
|
454
|
+
type: 'object',
|
|
455
|
+
required: ['field', 'operator', 'value'],
|
|
456
|
+
properties: {
|
|
457
|
+
field: { type: 'string' },
|
|
458
|
+
operator: {
|
|
459
|
+
type: 'string',
|
|
460
|
+
enum: ['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'like', 'in']
|
|
461
|
+
},
|
|
462
|
+
value: {}
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
nullable: true
|
|
466
|
+
},
|
|
467
|
+
pagination: {
|
|
468
|
+
type: 'object',
|
|
469
|
+
properties: {
|
|
470
|
+
page: { type: 'integer', minimum: 1 },
|
|
471
|
+
limit: { type: 'integer', minimum: 1, maximum: 10000 }
|
|
472
|
+
},
|
|
473
|
+
required: ['page', 'limit'],
|
|
474
|
+
nullable: true
|
|
475
|
+
},
|
|
476
|
+
sorting: {
|
|
477
|
+
type: 'object',
|
|
478
|
+
properties: {
|
|
479
|
+
field: { type: 'string' },
|
|
480
|
+
direction: { type: 'string', enum: ['asc', 'desc'] }
|
|
481
|
+
},
|
|
482
|
+
required: ['field', 'direction'],
|
|
483
|
+
nullable: true
|
|
484
|
+
},
|
|
485
|
+
include_headers: { type: 'boolean', nullable: true }
|
|
486
|
+
},
|
|
487
|
+
additionalProperties: false
|
|
488
|
+
};
|
|
489
|
+
exports.exportQueryToCsvSchema = {
|
|
490
|
+
type: 'object',
|
|
491
|
+
required: ['query'],
|
|
492
|
+
properties: {
|
|
493
|
+
query: { type: 'string' },
|
|
494
|
+
params: {
|
|
495
|
+
type: 'array',
|
|
496
|
+
items: {},
|
|
497
|
+
nullable: true
|
|
498
|
+
},
|
|
499
|
+
include_headers: { type: 'boolean', nullable: true }
|
|
500
|
+
},
|
|
501
|
+
additionalProperties: false
|
|
502
|
+
};
|
|
445
503
|
// Compile validators
|
|
446
504
|
exports.validateListTables = ajv.compile(exports.listTablesSchema);
|
|
447
505
|
exports.validateReadTableSchema = ajv.compile(exports.readTableSchemaSchema);
|
|
@@ -471,3 +529,5 @@ exports.validateShowCreateProcedure = ajv.compile(exports.showCreateProcedureSch
|
|
|
471
529
|
exports.validateStoredProcedureExecution = ajv.compile(exports.executeStoredProcedureSchema);
|
|
472
530
|
exports.validateStoredProcedureCreation = ajv.compile(exports.createStoredProcedureSchema);
|
|
473
531
|
exports.validateGetTableRelationships = ajv.compile(exports.getTableRelationshipsSchema);
|
|
532
|
+
exports.validateExportTableToCsv = ajv.compile(exports.exportTableToCsvSchema);
|
|
533
|
+
exports.validateExportQueryToCsv = ajv.compile(exports.exportQueryToCsvSchema);
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@berthojoris/mcp-mysql-server",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions and data export capabilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|