@berthojoris/mcp-mysql-server 1.14.0 β 1.15.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 +18 -0
- package/DOCUMENTATIONS.md +115 -16
- package/README.md +10 -18
- package/dist/config/featureConfig.d.ts +4 -0
- package/dist/config/featureConfig.js +74 -13
- package/dist/index.d.ts +19 -0
- package/dist/index.js +18 -0
- package/dist/mcp-server.js +53 -0
- package/dist/tools/macroTools.d.ts +20 -0
- package/dist/tools/macroTools.js +91 -0
- package/dist/tools/utilityTools.d.ts +11 -0
- package/dist/tools/utilityTools.js +71 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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.15.0] - 2025-12-08
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Connection Profiles** - New `dev`, `stage`, and `prod` presets.
|
|
12
|
+
- `dev`: Full access to all tools.
|
|
13
|
+
- `stage`: Allows CRUD but blocks destructive DDL (drop, truncate).
|
|
14
|
+
- `prod`: Strict read-only with explicit denials for modification tools.
|
|
15
|
+
- Implements allowed/denied tools logic for robust security enforcement.
|
|
16
|
+
- **Agent-Facing Changelog Feed** - New `read_changelog` tool.
|
|
17
|
+
- Allows AI agents to read the CHANGELOG.md directly to understand new features and changes.
|
|
18
|
+
|
|
19
|
+
## [1.14.1] - 2025-12-08
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **Workflow Macros** - New `safe_export_table` tool that combines data export with mandatory masking.
|
|
23
|
+
- Allows safe export of sensitive data by enforcing masking before the data leaves the database.
|
|
24
|
+
- Supports configurable masking profiles (strict (default), partial, soft).
|
|
25
|
+
|
|
8
26
|
## [1.14.0] - 2025-12-08
|
|
9
27
|
|
|
10
28
|
### Added
|
package/DOCUMENTATIONS.md
CHANGED
|
@@ -26,19 +26,6 @@ This file contains detailed documentation for all features of the MySQL MCP Serv
|
|
|
26
26
|
18. [Performance Monitoring](#π-performance-monitoring)
|
|
27
27
|
19. [Usage Examples](#π-usage-examples)
|
|
28
28
|
20. [Query Logging & Automatic SQL Display](#π-query-logging--automatic-sql-display)
|
|
29
|
-
21. [Security Features](#π-security-features)
|
|
30
|
-
22. [Query Result Caching](#πΎ-query-result-caching)
|
|
31
|
-
23. [Query Optimization Hints](#π―-query-optimization-hints)
|
|
32
|
-
24. [Guided Query Builder/Fixer](#π€-guided-query-builderfixer)
|
|
33
|
-
25. [Bulk Operations](#π-bulk-operations)
|
|
34
|
-
26. [OpenAI Codex Integration](#π€-openai-codex-integration)
|
|
35
|
-
27. [Troubleshooting](#π οΈ-troubleshooting)
|
|
36
|
-
28. [License](#π-license)
|
|
37
|
-
29. [Roadmap](#πΊοΈ-roadmap)
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Dual-Layer Filtering System
|
|
42
29
|
|
|
43
30
|
Control which database operations are available to AI using a **dual-layer filtering system**:
|
|
44
31
|
|
|
@@ -205,6 +192,16 @@ Preset bundles provide safe starting points and **merge** with any explicit perm
|
|
|
205
192
|
| `readonly` | `list,read,utility` | `database_discovery,crud_operations,custom_queries,utilities,import_export,performance_monitoring,analysis` | Safe read-only access, exports, and diagnostics |
|
|
206
193
|
| `analyst` | `list,read,utility` | `database_discovery,crud_operations,custom_queries,utilities,import_export,performance_monitoring,analysis,query_optimization,cache_management,server_management` | Exploration with EXPLAIN, cache, and performance visibility |
|
|
207
194
|
| `dba-lite` | `list,read,utility,ddl,transaction,procedure` | `database_discovery,custom_queries,utilities,server_management,schema_management,table_maintenance,index_management,constraint_management,backup_restore,schema_migrations,performance_monitoring,views_management,triggers_management,functions_management,stored_procedures` | Admin-lite schema care, maintenance, and migrations |
|
|
195
|
+
| `dev` | ALL | ALL | Full access to all tools (Development environment) |
|
|
196
|
+
| `stage` | `list,read,create,update,delete,utility,transaction` | Most categories (except schema_management) | Data modification allowed, but destructive DDL (drop_table, truncate_table) is **explicitly denied** |
|
|
197
|
+
| `prod` | `list,read,utility` | `database_discovery,crud_operations,custom_queries,utilities,performance_monitoring,analysis` | Strict read-only. Data modification and DDL are **strictly denied** (even if permissions suggest otherwise) |
|
|
198
|
+
|
|
199
|
+
### Connection Profiles (Allow/Deny Lists)
|
|
200
|
+
|
|
201
|
+
The new mechanism introduces "Connection Profiles" which can enforce strict `allow` and `deny` lists for tools, providing security beyond standard permissions.
|
|
202
|
+
|
|
203
|
+
- **Explicit Deny**: Tools in the `deniedTools` list are blocked *regardless* of their permissions. E.g., `prod` profile denies `create_record` even if `create` permission is somehow granted.
|
|
204
|
+
- **Explicit Allow**: Tools in the `allowedTools` list are enabled even if their category is not listed (unless denied).
|
|
208
205
|
|
|
209
206
|
**Usage**
|
|
210
207
|
|
|
@@ -337,6 +334,7 @@ This section provides a comprehensive reference of all 120 available tools organ
|
|
|
337
334
|
|------|-------------|
|
|
338
335
|
| `test_connection` | Test database connectivity and measure latency |
|
|
339
336
|
| `describe_connection` | Get current connection information |
|
|
337
|
+
| `read_changelog` | Read the changelog to see new features/changes |
|
|
340
338
|
| `export_table_to_csv` | Export table data to CSV format |
|
|
341
339
|
| `export_query_to_csv` | Export query results to CSV format |
|
|
342
340
|
|
|
@@ -533,6 +531,11 @@ This section provides a comprehensive reference of all 120 available tools organ
|
|
|
533
531
|
- Safety: respects the connected database onlyβcannot introspect other schemasβand notes when tables/columns are truncated.
|
|
534
532
|
- Output includes per-table PKs, FK targets, nullable flags, and approximate row counts from `INFORMATION_SCHEMA.TABLES` (InnoDB estimates).
|
|
535
533
|
|
|
534
|
+
#### Agent-Facing Changelog Feed
|
|
535
|
+
- **`read_changelog`**: Allows AI agents to read the project's CHANGELOG.md directly.
|
|
536
|
+
- **Purpose**: Enables the agent to understand new features, changes, and deprecations in the version it is running.
|
|
537
|
+
- **Usage**: Call `read_changelog()` to get the latest changes, or `read_changelog(version='1.15.0')` for specific version details.
|
|
538
|
+
|
|
536
539
|
---
|
|
537
540
|
|
|
538
541
|
## ποΈ DDL Operations
|
|
@@ -754,6 +757,47 @@ Both tools support:
|
|
|
754
757
|
|
|
755
758
|
---
|
|
756
759
|
|
|
760
|
+
## π Workflow Macros
|
|
761
|
+
|
|
762
|
+
Workflow Macros are composite tools designed to execute complex, multi-step operations safely and efficiently. They encapsulate best practices and security policies (like data masking) into single, atomic tool calls.
|
|
763
|
+
|
|
764
|
+
### Available Macros
|
|
765
|
+
|
|
766
|
+
| Tool | Description |
|
|
767
|
+
|------|-------------|
|
|
768
|
+
| `safe_export_table` | Exports table data to CSV with mandated data masking (redaction/hashing) |
|
|
769
|
+
|
|
770
|
+
### safe_export_table
|
|
771
|
+
|
|
772
|
+
Exports table data to CSV format *with enforced data masking*. This is safer than standard export tools because it ensures sensitive data is masked before leaving the database layer, regardless of the global masking configuration.
|
|
773
|
+
|
|
774
|
+
**Parameters:**
|
|
775
|
+
- `table_name` (required): Name of the table to export.
|
|
776
|
+
- `masking_profile` (optional): "strict" (default), "partial", or "soft".
|
|
777
|
+
- `limit` (optional): Maximum rows to export (default 1000, max 10000).
|
|
778
|
+
- `include_headers` (optional): Whether to include CSV headers (default true).
|
|
779
|
+
|
|
780
|
+
**Example:**
|
|
781
|
+
*User prompt: "Safely export the users table to a CSV file"*
|
|
782
|
+
|
|
783
|
+
```json
|
|
784
|
+
{
|
|
785
|
+
"tool": "safe_export_table",
|
|
786
|
+
"arguments": {
|
|
787
|
+
"table_name": "users",
|
|
788
|
+
"masking_profile": "strict"
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
**Result:**
|
|
794
|
+
CSV content where:
|
|
795
|
+
- Emails are masked (e.g., `j***@domain.com`)
|
|
796
|
+
- Passwords/secrets are `[REDACTED]`
|
|
797
|
+
- Phone numbers are partially hidden
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
757
801
|
## π₯ Data Import Tools
|
|
758
802
|
|
|
759
803
|
The MySQL MCP Server provides tools to import data from various formats into your database tables.
|
|
@@ -3796,6 +3840,61 @@ Each bulk operation returns performance metrics:
|
|
|
3796
3840
|
|
|
3797
3841
|
---
|
|
3798
3842
|
|
|
3843
|
+
|
|
3844
|
+
---
|
|
3845
|
+
|
|
3846
|
+
## β‘ Workflow Macros
|
|
3847
|
+
|
|
3848
|
+
Workflow macros are high-level tools that combine multiple operations into a single, safe, and efficient workflow. They are designed to simplify complex tasks and ensure best practices (like data masking) are automatically applied.
|
|
3849
|
+
|
|
3850
|
+
### Safe Export Table
|
|
3851
|
+
|
|
3852
|
+
The `safe_export_table` tool allows you to export table data to CSV while strictly enforcing data masking rules. This ensures that sensitive information (PII) is never leaked during exports, even if the agent forgets to apply masking manually.
|
|
3853
|
+
|
|
3854
|
+
#### Features
|
|
3855
|
+
|
|
3856
|
+
- **Forced Masking**: Applies a masking profile (default: `strict`) to all exported data.
|
|
3857
|
+
- **Hard Limit**: Enforces a maximum row limit (10,000) to prevent Out-Of-Memory errors during large exports.
|
|
3858
|
+
- **CSV Formatting**: Automatically handles special characters, quotes, and newlines.
|
|
3859
|
+
- **Header Control**: Option to include or exclude CSV headers.
|
|
3860
|
+
|
|
3861
|
+
#### Usage
|
|
3862
|
+
|
|
3863
|
+
```json
|
|
3864
|
+
{
|
|
3865
|
+
"tool": "safe_export_table",
|
|
3866
|
+
"arguments": {
|
|
3867
|
+
"table_name": "users",
|
|
3868
|
+
"masking_profile": "partial",
|
|
3869
|
+
"limit": 1000
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
```
|
|
3873
|
+
|
|
3874
|
+
#### Parameters
|
|
3875
|
+
|
|
3876
|
+
| Parameter | Type | Required | Description | Default |
|
|
3877
|
+
|-----------|------|----------|-------------|---------|
|
|
3878
|
+
| `table_name` | string | Yes | Name of the table to export | - |
|
|
3879
|
+
| `masking_profile` | string | No | Masking profile to apply (`strict`, `partial`, `soft`) | `strict` |
|
|
3880
|
+
| `limit` | number | No | Number of rows to export (max 10,000) | 1000 |
|
|
3881
|
+
| `include_headers` | boolean | No | Whether to include CSV headers | `true` |
|
|
3882
|
+
|
|
3883
|
+
#### Response
|
|
3884
|
+
|
|
3885
|
+
```json
|
|
3886
|
+
{
|
|
3887
|
+
"status": "success",
|
|
3888
|
+
"data": {
|
|
3889
|
+
"csv": "id,name,email\n1,John Doe,j***@example.com...",
|
|
3890
|
+
"row_count": 50,
|
|
3891
|
+
"applied_profile": "partial"
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
```
|
|
3895
|
+
|
|
3896
|
+
---
|
|
3897
|
+
|
|
3799
3898
|
## π€ OpenAI Codex Integration
|
|
3800
3899
|
|
|
3801
3900
|
OpenAI Codex CLI and VS Code Extension support MCP servers through a shared TOML configuration file. This section provides detailed setup instructions for integrating the MySQL MCP Server with Codex.
|
|
@@ -4182,9 +4281,9 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
4182
4281
|
| Safety Sandbox Mode (runQuery dry-run/EXPLAIN-only) | Medium | Low | 5 | β
Completed |
|
|
4183
4282
|
| Anomaly & Slow-Query Watcher | Medium | Medium | 6 | β
Completed |
|
|
4184
4283
|
| Data Masking Profiles for Responses | Medium | Medium | 7 | β
Completed |
|
|
4185
|
-
| Workflow Macros (e.g., safe_export_table) | Medium | Low | 8 |
|
|
4186
|
-
| Agent-Facing Changelog Feed | Medium | Low | 9 |
|
|
4187
|
-
| Connection Profiles (dev/stage/prod with allow/deny) | High | Low | 10 |
|
|
4284
|
+
| Workflow Macros (e.g., safe_export_table) | Medium | Low | 8 | β
Completed |
|
|
4285
|
+
| Agent-Facing Changelog Feed | Medium | Low | 9 | β
Completed |
|
|
4286
|
+
| Connection Profiles (dev/stage/prod with allow/deny) | High | Low | 10 | β
Completed |
|
|
4188
4287
|
|
|
4189
4288
|
---
|
|
4190
4289
|
|
package/README.md
CHANGED
|
@@ -50,26 +50,12 @@ Add to your AI agent config (`.mcp.json`, `.cursor/mcp.json`, etc.):
|
|
|
50
50
|
- [Environment Variables](#environment-variables-configuration)
|
|
51
51
|
- [Local Development](#local-path-configuration)
|
|
52
52
|
- [Permission System](#-permission-system)
|
|
53
|
-
- [Available Tools (
|
|
53
|
+
- [Available Tools (126 total)](#-available-tools)
|
|
54
54
|
- [Documentation](#-detailed-documentation)
|
|
55
55
|
- [Comparison: MCP vs Manual Access](#-mysql-mcp-vs-manual-database-access)
|
|
56
56
|
- [License](#-license)
|
|
57
57
|
|
|
58
58
|
---
|
|
59
|
-
|
|
60
|
-
## Features
|
|
61
|
-
|
|
62
|
-
| Category | Description |
|
|
63
|
-
|----------|-------------|
|
|
64
|
-
| **Full MCP Support** | Works with Claude Code, Cursor, Windsurf, Zed, Cline, Kilo Code, Roo Code, Gemini CLI, OpenAI Codex, and any MCP-compatible AI agent |
|
|
65
|
-
| **Security First** | Parameterized queries, SQL injection protection, permission-based access control |
|
|
66
|
-
| **124 Powerful Tools** | Complete database operations including CRUD, DDL, transactions, stored procedures, backup/restore, migrations |
|
|
67
|
-
| **Adaptive Presets** | Built-in ReadOnly/Analyst/DBA Lite permission bundles with override merging |
|
|
68
|
-
| **Schema-Aware RAG Pack** | Compact schema snapshots (tables, PK/FK, row estimates) tailored for embeddings-friendly prompts |
|
|
69
|
-
| **Category Filtering** | 22 documentation categories for intuitive, fine-grained access control (backward compatible with 10 legacy categories) |
|
|
70
|
-
| **Transaction Support** | Full ACID transaction management (BEGIN, COMMIT, ROLLBACK) |
|
|
71
|
-
| **Schema Migrations** | Version control for database schema with up/down migrations |
|
|
72
|
-
| **Dual Mode** | Run as MCP server OR as REST API |
|
|
73
59
|
| **Data Masking** | Protect PII/Secrets in responses with configurable profiles (soft/partial/strict) |
|
|
74
60
|
| **TypeScript** | Fully typed with TypeScript definitions |
|
|
75
61
|
|
|
@@ -402,6 +388,12 @@ Alternative approach using environment variables instead of connection string:
|
|
|
402
388
|
|
|
403
389
|
Add `MCP_PRESET` for the base bundle and optionally layer on `MCP_PERMISSIONS` / `MCP_CATEGORIES` for project-specific overrides.
|
|
404
390
|
|
|
391
|
+
#### Connection Profiles (dev/stage/prod)
|
|
392
|
+
New presets are available for environment-specific control:
|
|
393
|
+
- `dev`: Full access to all tools (explicitly allows everything).
|
|
394
|
+
- `stage`: Allows data modification but blocks destructive DDL (drop/truncate).
|
|
395
|
+
- `prod`: Strict read-only mode, explicitly denying keys modification keys.
|
|
396
|
+
|
|
405
397
|
---
|
|
406
398
|
|
|
407
399
|
### Local Path Configuration
|
|
@@ -655,11 +647,11 @@ Use both 2nd argument (permissions) and 3rd argument (categories):
|
|
|
655
647
|
|
|
656
648
|
## Available Tools
|
|
657
649
|
|
|
658
|
-
The MCP server provides **
|
|
650
|
+
The MCP server provides **126 powerful tools** organized into 22 categories:
|
|
659
651
|
|
|
660
652
|
### Quick Reference
|
|
661
653
|
|
|
662
|
-
**
|
|
654
|
+
**126 Tools Available** - Organized into 22 categories
|
|
663
655
|
|
|
664
656
|
| Category | Count | Key Tools |
|
|
665
657
|
|----------|-------|-----------|
|
|
@@ -681,7 +673,7 @@ The MCP server provides **124 powerful tools** organized into categories:
|
|
|
681
673
|
| Cache | 5 | `get_cache_stats`, `clear_cache` |
|
|
682
674
|
| Query Optimization | 3 | `analyze_query`, `get_optimization_hints`, `repair_query` |
|
|
683
675
|
| Backup & Restore | 5 | `backup_database`, `restore_from_sql` |
|
|
684
|
-
| Import/Export |
|
|
676
|
+
| Import/Export | 6 | `safe_export_table`, `export_table_to_json`, `import_from_csv` |
|
|
685
677
|
| Data Migration | 5 | `copy_table_data`, `sync_table_data` |
|
|
686
678
|
| Schema Migrations | 9 | `create_migration`, `apply_migrations` |
|
|
687
679
|
| Utilities | 4 | `test_connection`, `export_table_to_csv` |
|
|
@@ -50,6 +50,8 @@ export interface PermissionPreset {
|
|
|
50
50
|
description: string;
|
|
51
51
|
permissions: ToolCategory[];
|
|
52
52
|
categories: DocCategory[];
|
|
53
|
+
allowedTools?: string[];
|
|
54
|
+
deniedTools?: string[];
|
|
53
55
|
}
|
|
54
56
|
/**
|
|
55
57
|
* Map of tool names to their legacy categories
|
|
@@ -68,6 +70,8 @@ export declare const toolDocCategoryMap: Record<string, DocCategory>;
|
|
|
68
70
|
export declare class FeatureConfig {
|
|
69
71
|
private enabledLegacyCategories;
|
|
70
72
|
private enabledDocCategories;
|
|
73
|
+
private allowedTools;
|
|
74
|
+
private deniedTools;
|
|
71
75
|
private originalPermissionsString;
|
|
72
76
|
private originalCategoriesString;
|
|
73
77
|
private useDualLayer;
|
|
@@ -115,6 +115,58 @@ const permissionPresets = {
|
|
|
115
115
|
DocCategory.STORED_PROCEDURES,
|
|
116
116
|
],
|
|
117
117
|
},
|
|
118
|
+
dev: {
|
|
119
|
+
name: "dev",
|
|
120
|
+
description: "Development profile with full access to all tools",
|
|
121
|
+
permissions: Object.values(ToolCategory),
|
|
122
|
+
categories: Object.values(DocCategory),
|
|
123
|
+
deniedTools: [], // Explicitly allow everything
|
|
124
|
+
},
|
|
125
|
+
stage: {
|
|
126
|
+
name: "stage",
|
|
127
|
+
description: "Staging profile with data modification but no destructive DDL",
|
|
128
|
+
permissions: [
|
|
129
|
+
ToolCategory.LIST,
|
|
130
|
+
ToolCategory.READ,
|
|
131
|
+
ToolCategory.CREATE,
|
|
132
|
+
ToolCategory.UPDATE,
|
|
133
|
+
ToolCategory.DELETE,
|
|
134
|
+
ToolCategory.UTILITY,
|
|
135
|
+
ToolCategory.TRANSACTION,
|
|
136
|
+
],
|
|
137
|
+
categories: [
|
|
138
|
+
DocCategory.DATABASE_DISCOVERY,
|
|
139
|
+
DocCategory.CRUD_OPERATIONS,
|
|
140
|
+
DocCategory.BULK_OPERATIONS,
|
|
141
|
+
DocCategory.CUSTOM_QUERIES,
|
|
142
|
+
DocCategory.UTILITIES,
|
|
143
|
+
DocCategory.TRANSACTION_MANAGEMENT,
|
|
144
|
+
DocCategory.IMPORT_EXPORT,
|
|
145
|
+
DocCategory.DATA_MIGRATION,
|
|
146
|
+
DocCategory.PERFORMANCE_MONITORING,
|
|
147
|
+
DocCategory.ANALYSIS,
|
|
148
|
+
],
|
|
149
|
+
deniedTools: ["drop_table", "truncate_table", "drop_database"],
|
|
150
|
+
},
|
|
151
|
+
prod: {
|
|
152
|
+
name: "prod",
|
|
153
|
+
description: "Production profile with strict read-only access and safety checks",
|
|
154
|
+
permissions: [ToolCategory.LIST, ToolCategory.READ, ToolCategory.UTILITY],
|
|
155
|
+
categories: [
|
|
156
|
+
DocCategory.DATABASE_DISCOVERY,
|
|
157
|
+
DocCategory.CRUD_OPERATIONS, // Read only via permissions
|
|
158
|
+
DocCategory.CUSTOM_QUERIES,
|
|
159
|
+
DocCategory.UTILITIES,
|
|
160
|
+
DocCategory.PERFORMANCE_MONITORING,
|
|
161
|
+
DocCategory.ANALYSIS,
|
|
162
|
+
],
|
|
163
|
+
deniedTools: [
|
|
164
|
+
"create_table", "alter_table", "drop_table", "truncate_table",
|
|
165
|
+
"create_record", "update_record", "delete_record",
|
|
166
|
+
"bulk_insert", "bulk_update", "bulk_delete",
|
|
167
|
+
"execute_sql", "execute_ddl"
|
|
168
|
+
],
|
|
169
|
+
},
|
|
118
170
|
};
|
|
119
171
|
/**
|
|
120
172
|
* Map of tool names to their legacy categories
|
|
@@ -153,6 +205,8 @@ exports.toolCategoryMap = {
|
|
|
153
205
|
getTableRelationships: ToolCategory.UTILITY,
|
|
154
206
|
exportTableToCSV: ToolCategory.UTILITY,
|
|
155
207
|
exportQueryToCSV: ToolCategory.UTILITY,
|
|
208
|
+
safe_export_table: ToolCategory.UTILITY,
|
|
209
|
+
read_changelog: ToolCategory.UTILITY,
|
|
156
210
|
// Transaction tools
|
|
157
211
|
beginTransaction: ToolCategory.TRANSACTION,
|
|
158
212
|
commitTransaction: ToolCategory.TRANSACTION,
|
|
@@ -230,19 +284,6 @@ exports.toolCategoryMap = {
|
|
|
230
284
|
showReplicationStatus: ToolCategory.LIST,
|
|
231
285
|
// Backup and restore tools
|
|
232
286
|
backupTable: ToolCategory.UTILITY,
|
|
233
|
-
backupDatabase: ToolCategory.UTILITY,
|
|
234
|
-
restoreFromSql: ToolCategory.DDL,
|
|
235
|
-
getCreateTableStatement: ToolCategory.LIST,
|
|
236
|
-
getDatabaseSchema: ToolCategory.LIST,
|
|
237
|
-
// Extended data export/import tools
|
|
238
|
-
exportTableToJSON: ToolCategory.UTILITY,
|
|
239
|
-
exportQueryToJSON: ToolCategory.UTILITY,
|
|
240
|
-
exportTableToSql: ToolCategory.UTILITY,
|
|
241
|
-
importFromCSV: ToolCategory.CREATE,
|
|
242
|
-
importFromJSON: ToolCategory.CREATE,
|
|
243
|
-
// Data migration tools
|
|
244
|
-
copyTableData: ToolCategory.CREATE,
|
|
245
|
-
moveTableData: ToolCategory.DELETE,
|
|
246
287
|
cloneTable: ToolCategory.DDL,
|
|
247
288
|
compareTableStructure: ToolCategory.LIST,
|
|
248
289
|
syncTableData: ToolCategory.UPDATE,
|
|
@@ -301,6 +342,7 @@ exports.toolDocCategoryMap = {
|
|
|
301
342
|
describeConnection: DocCategory.UTILITIES,
|
|
302
343
|
exportTableToCSV: DocCategory.UTILITIES,
|
|
303
344
|
exportQueryToCSV: DocCategory.UTILITIES,
|
|
345
|
+
read_changelog: DocCategory.UTILITIES,
|
|
304
346
|
// Transaction Management
|
|
305
347
|
beginTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
|
306
348
|
commitTransaction: DocCategory.TRANSACTION_MANAGEMENT,
|
|
@@ -397,6 +439,7 @@ exports.toolDocCategoryMap = {
|
|
|
397
439
|
exportTableToJSON: DocCategory.IMPORT_EXPORT,
|
|
398
440
|
exportQueryToJSON: DocCategory.IMPORT_EXPORT,
|
|
399
441
|
exportTableToSql: DocCategory.IMPORT_EXPORT,
|
|
442
|
+
safe_export_table: DocCategory.IMPORT_EXPORT,
|
|
400
443
|
importFromCSV: DocCategory.IMPORT_EXPORT,
|
|
401
444
|
importFromJSON: DocCategory.IMPORT_EXPORT,
|
|
402
445
|
// Data Migration
|
|
@@ -530,6 +573,9 @@ class FeatureConfig {
|
|
|
530
573
|
const parsed = this.parseConfig(mergedPermissions, mergedCategories);
|
|
531
574
|
this.enabledLegacyCategories = parsed.legacy;
|
|
532
575
|
this.enabledDocCategories = parsed.doc;
|
|
576
|
+
// Initialize Allow/Deny Lists
|
|
577
|
+
this.allowedTools = new Set(this.activePreset?.allowedTools || []);
|
|
578
|
+
this.deniedTools = new Set(this.activePreset?.deniedTools || []);
|
|
533
579
|
}
|
|
534
580
|
/**
|
|
535
581
|
* Normalize and merge preset + user-supplied configuration lists
|
|
@@ -588,6 +634,9 @@ class FeatureConfig {
|
|
|
588
634
|
docCats.forEach((dc) => docSet.add(dc));
|
|
589
635
|
});
|
|
590
636
|
}
|
|
637
|
+
// Re-initialize Allow/Deny Lists if preset changed
|
|
638
|
+
this.allowedTools = new Set(this.activePreset?.allowedTools || []);
|
|
639
|
+
this.deniedTools = new Set(this.activePreset?.deniedTools || []);
|
|
591
640
|
return {
|
|
592
641
|
legacy: legacySet,
|
|
593
642
|
doc: docSet,
|
|
@@ -644,6 +693,15 @@ class FeatureConfig {
|
|
|
644
693
|
console.warn(`Unknown tool: ${toolName}`);
|
|
645
694
|
return false;
|
|
646
695
|
}
|
|
696
|
+
// Layer 0: Check explicit Deny/Allow lists
|
|
697
|
+
// Deny takes precedence
|
|
698
|
+
if (this.deniedTools.has(toolName)) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
// Allow overrides other checks
|
|
702
|
+
if (this.allowedTools.has(toolName)) {
|
|
703
|
+
return true;
|
|
704
|
+
}
|
|
647
705
|
// Layer 1: Check permission (legacy category)
|
|
648
706
|
const hasPermission = legacyCategory
|
|
649
707
|
? this.enabledLegacyCategories.has(legacyCategory)
|
|
@@ -670,6 +728,9 @@ class FeatureConfig {
|
|
|
670
728
|
if (!docCategory && !legacyCategory) {
|
|
671
729
|
return `Unknown tool '${toolName}'. This tool is not recognized by the MCP server.`;
|
|
672
730
|
}
|
|
731
|
+
if (this.deniedTools.has(toolName)) {
|
|
732
|
+
return `Permission denied: Tool '${toolName}' is explicitly denied by the current profile ('${this.presetName}').`;
|
|
733
|
+
}
|
|
673
734
|
const isAllEnabled = !this.originalPermissionsString.trim() &&
|
|
674
735
|
!this.originalCategoriesString.trim();
|
|
675
736
|
if (isAllEnabled) {
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class MySQLMCP {
|
|
|
24
24
|
private performanceTools;
|
|
25
25
|
private analysisTools;
|
|
26
26
|
private aiTools;
|
|
27
|
+
private macroTools;
|
|
27
28
|
private security;
|
|
28
29
|
private featureConfig;
|
|
29
30
|
constructor(permissionsConfig?: string, categoriesConfig?: string, presetName?: string);
|
|
@@ -189,6 +190,14 @@ export declare class MySQLMCP {
|
|
|
189
190
|
data?: any;
|
|
190
191
|
error?: string;
|
|
191
192
|
}>;
|
|
193
|
+
readChangelog(params?: {
|
|
194
|
+
version?: string;
|
|
195
|
+
limit?: number;
|
|
196
|
+
}): Promise<{
|
|
197
|
+
status: string;
|
|
198
|
+
data?: any;
|
|
199
|
+
error?: string;
|
|
200
|
+
}>;
|
|
192
201
|
beginTransaction(params?: {
|
|
193
202
|
transactionId?: string;
|
|
194
203
|
}): Promise<import("./tools/transactionTools").TransactionResult | {
|
|
@@ -590,6 +599,16 @@ export declare class MySQLMCP {
|
|
|
590
599
|
suggestions?: string[];
|
|
591
600
|
error?: string;
|
|
592
601
|
}>;
|
|
602
|
+
safeExportTable(params: {
|
|
603
|
+
table_name: string;
|
|
604
|
+
masking_profile?: string;
|
|
605
|
+
limit?: number;
|
|
606
|
+
include_headers?: boolean;
|
|
607
|
+
}): Promise<{
|
|
608
|
+
status: string;
|
|
609
|
+
data?: any;
|
|
610
|
+
error?: string;
|
|
611
|
+
}>;
|
|
593
612
|
getFeatureStatus(): {
|
|
594
613
|
status: string;
|
|
595
614
|
data: {
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ const schemaVersioningTools_1 = require("./tools/schemaVersioningTools");
|
|
|
25
25
|
const performanceTools_1 = require("./tools/performanceTools");
|
|
26
26
|
const analysisTools_1 = require("./tools/analysisTools");
|
|
27
27
|
const aiTools_1 = require("./tools/aiTools");
|
|
28
|
+
const macroTools_1 = require("./tools/macroTools");
|
|
28
29
|
const securityLayer_1 = __importDefault(require("./security/securityLayer"));
|
|
29
30
|
const connection_1 = __importDefault(require("./db/connection"));
|
|
30
31
|
const featureConfig_1 = require("./config/featureConfig");
|
|
@@ -56,7 +57,9 @@ class MySQLMCP {
|
|
|
56
57
|
this.schemaVersioningTools = new schemaVersioningTools_1.SchemaVersioningTools(this.security);
|
|
57
58
|
this.performanceTools = new performanceTools_1.PerformanceTools(this.security);
|
|
58
59
|
this.analysisTools = new analysisTools_1.AnalysisTools(this.security);
|
|
60
|
+
this.analysisTools = new analysisTools_1.AnalysisTools(this.security);
|
|
59
61
|
this.aiTools = new aiTools_1.AiTools(this.security);
|
|
62
|
+
this.macroTools = new macroTools_1.MacroTools(this.security);
|
|
60
63
|
}
|
|
61
64
|
// Helper method to check if tool is enabled
|
|
62
65
|
checkToolEnabled(toolName) {
|
|
@@ -231,6 +234,13 @@ class MySQLMCP {
|
|
|
231
234
|
}
|
|
232
235
|
return await this.utilityTools.getTableRelationships(params);
|
|
233
236
|
}
|
|
237
|
+
async readChangelog(params) {
|
|
238
|
+
const check = this.checkToolEnabled("read_changelog");
|
|
239
|
+
if (!check.enabled) {
|
|
240
|
+
return { status: "error", error: check.error };
|
|
241
|
+
}
|
|
242
|
+
return await this.utilityTools.readChangelog(params);
|
|
243
|
+
}
|
|
234
244
|
// Transaction Tools
|
|
235
245
|
async beginTransaction(params) {
|
|
236
246
|
const check = this.checkToolEnabled("beginTransaction");
|
|
@@ -535,6 +545,14 @@ class MySQLMCP {
|
|
|
535
545
|
}
|
|
536
546
|
return await this.aiTools.repairQuery(params);
|
|
537
547
|
}
|
|
548
|
+
// Workflow Macros
|
|
549
|
+
async safeExportTable(params) {
|
|
550
|
+
const check = this.checkToolEnabled("safe_export_table");
|
|
551
|
+
if (!check.enabled) {
|
|
552
|
+
return { status: "error", error: check.error };
|
|
553
|
+
}
|
|
554
|
+
return await this.macroTools.safeExportTable(params);
|
|
555
|
+
}
|
|
538
556
|
// Get feature configuration status
|
|
539
557
|
getFeatureStatus() {
|
|
540
558
|
const snapshot = this.featureConfig.getConfigSnapshot();
|
package/dist/mcp-server.js
CHANGED
|
@@ -476,6 +476,33 @@ const TOOLS = [
|
|
|
476
476
|
required: ["query"],
|
|
477
477
|
},
|
|
478
478
|
},
|
|
479
|
+
{
|
|
480
|
+
name: "safe_export_table",
|
|
481
|
+
description: "Exports table data to CSV with enforced data masking rules to protect sensitive information.",
|
|
482
|
+
inputSchema: {
|
|
483
|
+
type: "object",
|
|
484
|
+
properties: {
|
|
485
|
+
table_name: {
|
|
486
|
+
type: "string",
|
|
487
|
+
description: "Name of the table to export",
|
|
488
|
+
},
|
|
489
|
+
masking_profile: {
|
|
490
|
+
type: "string",
|
|
491
|
+
enum: ["soft", "partial", "strict"],
|
|
492
|
+
description: "Masking profile to apply (default: strict). strict=redact all PII/secrets, partial=partial mask PII, soft=mask secrets only.",
|
|
493
|
+
},
|
|
494
|
+
limit: {
|
|
495
|
+
type: "number",
|
|
496
|
+
description: "Maximum number of rows to export (default: 1000, max: 10000)",
|
|
497
|
+
},
|
|
498
|
+
include_headers: {
|
|
499
|
+
type: "boolean",
|
|
500
|
+
description: "Whether to include CSV headers (default: true)",
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
required: ["table_name"],
|
|
504
|
+
},
|
|
505
|
+
},
|
|
479
506
|
{
|
|
480
507
|
name: "repair_query",
|
|
481
508
|
description: "Analyzes a SQL query (and optional error) to suggest repairs or optimizations using EXPLAIN and heuristics.",
|
|
@@ -632,6 +659,23 @@ const TOOLS = [
|
|
|
632
659
|
properties: {},
|
|
633
660
|
},
|
|
634
661
|
},
|
|
662
|
+
{
|
|
663
|
+
name: "read_changelog",
|
|
664
|
+
description: "Reads the changelog to see what features are new or changed.",
|
|
665
|
+
inputSchema: {
|
|
666
|
+
type: "object",
|
|
667
|
+
properties: {
|
|
668
|
+
version: {
|
|
669
|
+
type: "string",
|
|
670
|
+
description: "Optional: specific version to read (e.g., '1.0.0')",
|
|
671
|
+
},
|
|
672
|
+
limit: {
|
|
673
|
+
type: "number",
|
|
674
|
+
description: "Optional: limit character count (default: 5000)",
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
},
|
|
635
679
|
{
|
|
636
680
|
name: "test_connection",
|
|
637
681
|
description: "Tests the database connection and returns latency information.",
|
|
@@ -2847,6 +2891,9 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
2847
2891
|
case "test_connection":
|
|
2848
2892
|
result = await mysqlMCP.testConnection();
|
|
2849
2893
|
break;
|
|
2894
|
+
case "read_changelog":
|
|
2895
|
+
result = await mysqlMCP.readChangelog((args || {}));
|
|
2896
|
+
break;
|
|
2850
2897
|
case "get_table_relationships":
|
|
2851
2898
|
result = await mysqlMCP.getTableRelationships((args || {}));
|
|
2852
2899
|
break;
|
|
@@ -3083,6 +3130,12 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
3083
3130
|
case "export_query_to_json":
|
|
3084
3131
|
result = await mysqlMCP.exportQueryToJSON((args || {}));
|
|
3085
3132
|
break;
|
|
3133
|
+
case "export_query_to_csv":
|
|
3134
|
+
result = await mysqlMCP.exportQueryToCSV((args || {}));
|
|
3135
|
+
break;
|
|
3136
|
+
case "safe_export_table":
|
|
3137
|
+
result = await mysqlMCP.safeExportTable((args || {}));
|
|
3138
|
+
break;
|
|
3086
3139
|
case "export_table_to_sql":
|
|
3087
3140
|
result = await mysqlMCP.exportTableToSql((args || {}));
|
|
3088
3141
|
break;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import SecurityLayer from "../security/securityLayer";
|
|
2
|
+
export declare class MacroTools {
|
|
3
|
+
private db;
|
|
4
|
+
private security;
|
|
5
|
+
constructor(security: SecurityLayer);
|
|
6
|
+
/**
|
|
7
|
+
* Safe Export Table: Exports table data to CSV with enforced data masking
|
|
8
|
+
* This macro prioritizes data safety by applying masking rules before export.
|
|
9
|
+
*/
|
|
10
|
+
safeExportTable(params: {
|
|
11
|
+
table_name: string;
|
|
12
|
+
masking_profile?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
include_headers?: boolean;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
status: string;
|
|
17
|
+
data?: any;
|
|
18
|
+
error?: string;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
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.MacroTools = void 0;
|
|
7
|
+
const connection_1 = __importDefault(require("../db/connection"));
|
|
8
|
+
const maskingLayer_1 = require("../security/maskingLayer");
|
|
9
|
+
class MacroTools {
|
|
10
|
+
constructor(security) {
|
|
11
|
+
this.db = connection_1.default.getInstance();
|
|
12
|
+
this.security = security;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Safe Export Table: Exports table data to CSV with enforced data masking
|
|
16
|
+
* This macro prioritizes data safety by applying masking rules before export.
|
|
17
|
+
*/
|
|
18
|
+
async safeExportTable(params) {
|
|
19
|
+
try {
|
|
20
|
+
const { table_name, masking_profile = "strict", limit = 1000, include_headers = true, } = params;
|
|
21
|
+
// 1. Validate table name
|
|
22
|
+
const tableValidation = this.security.validateIdentifier(table_name);
|
|
23
|
+
if (!tableValidation.valid) {
|
|
24
|
+
return {
|
|
25
|
+
status: "error",
|
|
26
|
+
error: tableValidation.error,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// 2. Fetch data (with hard limit to prevent OOM on large safe exports)
|
|
30
|
+
const maxLimit = 10000;
|
|
31
|
+
const actualLimit = Math.min(limit, maxLimit);
|
|
32
|
+
const escapedTableName = this.security.escapeIdentifier(table_name);
|
|
33
|
+
const query = `SELECT * FROM ${escapedTableName} LIMIT ?`;
|
|
34
|
+
const results = (await this.db.query(query, [actualLimit]));
|
|
35
|
+
if (results.length === 0) {
|
|
36
|
+
return {
|
|
37
|
+
status: "success",
|
|
38
|
+
data: {
|
|
39
|
+
csv: include_headers ? "" : "",
|
|
40
|
+
row_count: 0,
|
|
41
|
+
applied_profile: masking_profile,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// 3. Apply masking explicitly using a new temporary layer to ensure strictness
|
|
46
|
+
// We don't rely on the global masking profile here; we use the one requested (default strict)
|
|
47
|
+
const tempMaskingLayer = new maskingLayer_1.MaskingLayer(masking_profile);
|
|
48
|
+
const maskedResults = tempMaskingLayer.processResults(results);
|
|
49
|
+
// 4. Convert to CSV
|
|
50
|
+
let csv = "";
|
|
51
|
+
if (include_headers) {
|
|
52
|
+
const headers = Object.keys(maskedResults[0]).join(",");
|
|
53
|
+
csv += headers + "\n";
|
|
54
|
+
}
|
|
55
|
+
for (const row of maskedResults) {
|
|
56
|
+
const values = Object.values(row)
|
|
57
|
+
.map((value) => {
|
|
58
|
+
if (value === null)
|
|
59
|
+
return "";
|
|
60
|
+
if (value === undefined)
|
|
61
|
+
return "";
|
|
62
|
+
let str = String(value);
|
|
63
|
+
// Escape quotes and wrap in quotes if contains comma, newline or quotes
|
|
64
|
+
if (str.includes(",") ||
|
|
65
|
+
str.includes("\n") ||
|
|
66
|
+
str.includes('"')) {
|
|
67
|
+
return `"${str.replace(/"/g, '""')}"`;
|
|
68
|
+
}
|
|
69
|
+
return str;
|
|
70
|
+
})
|
|
71
|
+
.join(",");
|
|
72
|
+
csv += values + "\n";
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
status: "success",
|
|
76
|
+
data: {
|
|
77
|
+
csv: csv,
|
|
78
|
+
row_count: maskedResults.length,
|
|
79
|
+
applied_profile: tempMaskingLayer.getProfile(),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return {
|
|
85
|
+
status: "error",
|
|
86
|
+
error: error.message,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.MacroTools = MacroTools;
|
|
@@ -27,4 +27,15 @@ export declare class UtilityTools {
|
|
|
27
27
|
data?: any;
|
|
28
28
|
error?: string;
|
|
29
29
|
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Reads the CHANGELOG.md file from the project root
|
|
32
|
+
*/
|
|
33
|
+
readChangelog(params?: {
|
|
34
|
+
version?: string;
|
|
35
|
+
limit?: number;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
status: string;
|
|
38
|
+
data?: any;
|
|
39
|
+
error?: string;
|
|
40
|
+
}>;
|
|
30
41
|
}
|
|
@@ -7,6 +7,8 @@ exports.UtilityTools = void 0;
|
|
|
7
7
|
const connection_1 = __importDefault(require("../db/connection"));
|
|
8
8
|
const config_1 = require("../config/config");
|
|
9
9
|
const schemas_1 = require("../validation/schemas");
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
10
12
|
class UtilityTools {
|
|
11
13
|
constructor() {
|
|
12
14
|
this.db = connection_1.default.getInstance();
|
|
@@ -208,5 +210,74 @@ class UtilityTools {
|
|
|
208
210
|
};
|
|
209
211
|
}
|
|
210
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Reads the CHANGELOG.md file from the project root
|
|
215
|
+
*/
|
|
216
|
+
async readChangelog(params) {
|
|
217
|
+
try {
|
|
218
|
+
// Resolve path relative to the built file (dist/tools/utilityTools.js -> ../../CHANGELOG.md)
|
|
219
|
+
// or source file (src/tools/utilityTools.ts -> ../../CHANGELOG.md)
|
|
220
|
+
const changelogPath = path_1.default.resolve(__dirname, "..", "..", "CHANGELOG.md");
|
|
221
|
+
if (!fs_1.default.existsSync(changelogPath)) {
|
|
222
|
+
return {
|
|
223
|
+
status: "error",
|
|
224
|
+
error: "CHANGELOG.md not found in the project root.",
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const content = fs_1.default.readFileSync(changelogPath, "utf-8");
|
|
228
|
+
// If version specified, try to parse and find it
|
|
229
|
+
if (params?.version) {
|
|
230
|
+
// Simple parsing - look for headers like "## [1.2.3]"
|
|
231
|
+
const versionHeader = `## [${params.version}]`;
|
|
232
|
+
const lines = content.split("\n");
|
|
233
|
+
let found = false;
|
|
234
|
+
let versionContent = "";
|
|
235
|
+
for (const line of lines) {
|
|
236
|
+
if (line.startsWith(versionHeader)) {
|
|
237
|
+
found = true;
|
|
238
|
+
versionContent += line + "\n";
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (found) {
|
|
242
|
+
if (line.startsWith("## ["))
|
|
243
|
+
break; // Next version starts
|
|
244
|
+
versionContent += line + "\n";
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (!found) {
|
|
248
|
+
return {
|
|
249
|
+
status: "error",
|
|
250
|
+
error: `Version ${params.version} not found in CHANGELOG.md`,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
status: "success",
|
|
255
|
+
data: {
|
|
256
|
+
version: params.version,
|
|
257
|
+
content: versionContent.trim(),
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
// If no version, return the whole file or top N characters/lines?
|
|
262
|
+
// For now, let's return the most recent versions.
|
|
263
|
+
// Limit default to 3000 chars to avoid overflowing context
|
|
264
|
+
const maxLength = params?.limit || 5000;
|
|
265
|
+
const truncated = content.length > maxLength
|
|
266
|
+
? content.substring(0, maxLength) + "\n... (truncated)"
|
|
267
|
+
: content;
|
|
268
|
+
return {
|
|
269
|
+
status: "success",
|
|
270
|
+
data: {
|
|
271
|
+
content: truncated,
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
return {
|
|
277
|
+
status: "error",
|
|
278
|
+
error: `Failed to read changelog: ${error.message}`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
211
282
|
}
|
|
212
283
|
exports.UtilityTools = UtilityTools;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@berthojoris/mcp-mysql-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions, backup/restore, data import/export, and data migration capabilities",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|