@berthojoris/mcp-mysql-server 1.40.3 → 1.40.5

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,57 +5,84 @@ 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.40.3] - 2026-03-07
9
-
10
- ### Fixed
11
- - Added missing tool-category mappings for snake_case and camelCase variants in `src/config/featureConfig.ts`
12
- - Resolved unmapped tools: `get_schema_erd`, `repair_query`, `export_table_to_csv`, `export_query_to_csv`, `analyze_query`, `get_optimization_hints`
13
- - Ensured dual-layer filtering recognizes all registered MCP tools from `src/mcp-server.ts`
14
-
15
- ### Changed
16
- - Synchronized versions to `1.40.3` in `package.json`, `src/mcp-server.ts`, and `manifest.json`
17
- - Updated `README.md` and `DOCUMENTATIONS.md` Last Updated metadata
18
-
19
- ## [1.40.2] - 2026-03-07
20
-
21
- ### Removed
22
- - **Functions Management Category**: Removed category `functions_management` and all 6 tools
23
- - `list_functions` - List user-defined functions
24
- - `get_function_info` - Get function details
25
- - `create_function` - Create function
26
- - `drop_function` - Drop function
27
- - `show_create_function` - Show CREATE FUNCTION statement
28
- - `execute_function` - Execute function
29
- - **Backup & Restore Category**: Removed category `backup_restore` and all 5 tools
30
- - `backup_table` - Backup a single table
31
- - `backup_database` - Backup entire database
32
- - `restore_from_sql` - Restore from SQL dump
33
- - `get_create_table_statement` - Get CREATE TABLE statement
34
- - `get_database_schema` - Get complete schema snapshot
35
- - Removed tool modules `src/tools/functionTools.ts` and `src/tools/backupRestoreTools.ts`
36
-
37
- ### Changed
38
- - Updated tool count: 73 62 tools (-11 tools)
39
- - Updated category count: 15 13 categories (removed `functions_management`, `backup_restore`)
40
- - Updated `src/mcp-server.ts` to remove tool schemas and call routing for all 11 tools
41
- - Updated `src/index.ts` to remove MySQLMCP imports, fields, initialization, and methods for removed tool sets
42
- - Updated `src/config/featureConfig.ts` to remove enum values and category mappings for both categories
43
- - Updated CLI category help in `bin/mcp-mysql.js`
44
- - Updated `README.md` and `DOCUMENTATIONS.md` to reflect new category list and tool totals
45
- - Synchronized versions to `1.40.2` in `package.json`, `src/mcp-server.ts`, and `manifest.json`
46
-
47
- ### Fixed
48
- - Updated procedure permission example in docs to reference `execute_stored_procedure` instead of removed function execution tool
49
-
50
- ## [1.40.1] - 2026-03-06
51
-
52
- ### Changed
53
- - Synchronized version metadata across `package.json`, `src/mcp-server.ts`, and `manifest.json` to `1.40.1`
54
- - Updated CLI category examples in `bin/mcp-mysql.js` to match active category set
55
- - Updated category examples in `README.md` and `DOCUMENTATIONS.md` to remove removed categories
56
- - Refactored tool registry filtering into `src/tools/toolRegistry.ts`
57
- - Refactored tool argument validation registry into `src/tools/toolArgumentValidation.ts`
58
-
8
+ ## [1.40.5] - 2026-04-08
9
+
10
+ ### Fixed
11
+ - **Critical Bug in `read_table_schema`**: Fixed query that returned mixed data from multiple schemas
12
+ - Query was missing `TABLE_SCHEMA` filter, causing columns from tables with same name in different databases to be returned
13
+ - Added `TABLE_SCHEMA = ?` filter to ensure only columns from the connected database are returned
14
+ - This fixes the issue where AI agents received incorrect schema information when multiple databases had tables with identical names
15
+
16
+ ### Changed
17
+ - Synchronized version to `1.40.5` in `package.json`, `src/mcp-server.ts`
18
+
19
+ ## [1.40.4] - 2026-03-07
20
+
21
+ ### Removed
22
+ - **Unused Dependencies**: Removed `winston` and `@types/winston` packages (26 packages total)
23
+ - `winston` logging library was not used - project uses custom in-memory `QueryLogger` instead
24
+ - **Dead Code**: Removed unused tool modules left from previous refactoring
25
+ - `src/tools/processTools.ts` - Remnant from removed `server_management` category
26
+ - `src/tools/performanceTools.ts` - Remnant from removed `performance_monitoring` category
27
+ - `src/auth/` folder - Empty unused directory
28
+ - `dist/server.js` and `dist/server.d.ts` - Obsolete build artifacts
29
+
30
+ ### Changed
31
+ - Updated dependencies: 6 5 production dependencies (removed winston)
32
+ - Updated devDependencies: 10 9 (removed @types/winston)
33
+ - Synchronized version to `1.40.4` in `package.json`
34
+
35
+ ## [1.40.3] - 2026-03-07
36
+
37
+ ### Fixed
38
+ - Added missing tool-category mappings for snake_case and camelCase variants in `src/config/featureConfig.ts`
39
+ - Resolved unmapped tools: `get_schema_erd`, `repair_query`, `export_table_to_csv`, `export_query_to_csv`, `analyze_query`, `get_optimization_hints`
40
+ - Ensured dual-layer filtering recognizes all registered MCP tools from `src/mcp-server.ts`
41
+
42
+ ### Changed
43
+ - Synchronized versions to `1.40.3` in `package.json`, `src/mcp-server.ts`, and `manifest.json`
44
+ - Updated `README.md` and `DOCUMENTATIONS.md` Last Updated metadata
45
+
46
+ ## [1.40.2] - 2026-03-07
47
+
48
+ ### Removed
49
+ - **Functions Management Category**: Removed category `functions_management` and all 6 tools
50
+ - `list_functions` - List user-defined functions
51
+ - `get_function_info` - Get function details
52
+ - `create_function` - Create function
53
+ - `drop_function` - Drop function
54
+ - `show_create_function` - Show CREATE FUNCTION statement
55
+ - `execute_function` - Execute function
56
+ - **Backup & Restore Category**: Removed category `backup_restore` and all 5 tools
57
+ - `backup_table` - Backup a single table
58
+ - `backup_database` - Backup entire database
59
+ - `restore_from_sql` - Restore from SQL dump
60
+ - `get_create_table_statement` - Get CREATE TABLE statement
61
+ - `get_database_schema` - Get complete schema snapshot
62
+ - Removed tool modules `src/tools/functionTools.ts` and `src/tools/backupRestoreTools.ts`
63
+
64
+ ### Changed
65
+ - Updated tool count: 73 → 62 tools (-11 tools)
66
+ - Updated category count: 15 → 13 categories (removed `functions_management`, `backup_restore`)
67
+ - Updated `src/mcp-server.ts` to remove tool schemas and call routing for all 11 tools
68
+ - Updated `src/index.ts` to remove MySQLMCP imports, fields, initialization, and methods for removed tool sets
69
+ - Updated `src/config/featureConfig.ts` to remove enum values and category mappings for both categories
70
+ - Updated CLI category help in `bin/mcp-mysql.js`
71
+ - Updated `README.md` and `DOCUMENTATIONS.md` to reflect new category list and tool totals
72
+ - Synchronized versions to `1.40.2` in `package.json`, `src/mcp-server.ts`, and `manifest.json`
73
+
74
+ ### Fixed
75
+ - Updated procedure permission example in docs to reference `execute_stored_procedure` instead of removed function execution tool
76
+
77
+ ## [1.40.1] - 2026-03-06
78
+
79
+ ### Changed
80
+ - Synchronized version metadata across `package.json`, `src/mcp-server.ts`, and `manifest.json` to `1.40.1`
81
+ - Updated CLI category examples in `bin/mcp-mysql.js` to match active category set
82
+ - Updated category examples in `README.md` and `DOCUMENTATIONS.md` to remove removed categories
83
+ - Refactored tool registry filtering into `src/tools/toolRegistry.ts`
84
+ - Refactored tool argument validation registry into `src/tools/toolArgumentValidation.ts`
85
+
59
86
  ## [1.40.0] - 2026-03-06
60
87
 
61
88
  ### Removed
package/DOCUMENTATIONS.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # MySQL MCP Server - Documentation
2
2
 
3
- **Last Updated:** 2026-03-07 11:05:00
4
- **Version:** 1.40.3
5
- **Total Tools:** 62
3
+ **Last Updated:** 2026-04-08 14:30:00
4
+ **Version:** 1.40.5
5
+ **Total Tools:** 62
6
6
 
7
7
  Comprehensive documentation for the MySQL MCP Server. For quick start, see [README.md](README.md).
8
8
 
@@ -37,7 +37,7 @@ Configure MySQL MCP with two access-control layers:
37
37
  "@berthojoris/mcp-mysql-server",
38
38
  "mysql://user:password@localhost:3306/database",
39
39
  "list,read,utility",
40
- "database_discovery,custom_queries,analysis"
40
+ "database_discovery,custom_queries,analysis"
41
41
  ]
42
42
  }
43
43
  }
@@ -58,7 +58,7 @@ Configure MySQL MCP with two access-control layers:
58
58
  "DB_PASSWORD": "your_password",
59
59
  "DB_NAME": "your_database",
60
60
  "MCP_PERMISSIONS": "list,read,utility",
61
- "MCP_CATEGORIES": "database_discovery,custom_queries,analysis"
61
+ "MCP_CATEGORIES": "database_discovery,custom_queries,analysis"
62
62
  }
63
63
  }
64
64
  ```
@@ -80,7 +80,7 @@ Configure MySQL MCP with two access-control layers:
80
80
  | `ddl` | Schema changes | `create_table`, `alter_table` |
81
81
  | `utility` | Utility operations | `test_connection`, `analyze_table` |
82
82
  | `transaction` | Transaction management | `begin_transaction`, `commit_transaction` |
83
- | `procedure` | Stored procedures | `create_stored_procedure`, `execute_stored_procedure` |
83
+ | `procedure` | Stored procedures | `create_stored_procedure`, `execute_stored_procedure` |
84
84
 
85
85
  ### Filtering Logic
86
86
 
@@ -169,7 +169,7 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
169
169
  - `drop_trigger` - Remove triggers
170
170
  - `show_create_trigger` - Show CREATE statement
171
171
 
172
- ### 11. Table Maintenance (8 tools)
172
+ ### 11. Table Maintenance (8 tools)
173
173
  - `analyze_table` - Update statistics
174
174
  - `optimize_table` - Reclaim space
175
175
  - `check_table` - Check for errors
@@ -179,19 +179,19 @@ Tool enabled = (Has Permission) AND (Has Category OR No categories specified)
179
179
  - `flush_table` - Close/reopen table
180
180
  - `get_table_size` - Get size information
181
181
 
182
- ### 12. Transaction Management (5 tools)
182
+ ### 12. Transaction Management (5 tools)
183
183
  - `begin_transaction` - Start transaction
184
184
  - `commit_transaction` - Commit transaction
185
185
  - `rollback_transaction` - Rollback transaction
186
186
  - `get_transaction_status` - Check transaction state
187
187
  - `execute_in_transaction` - Execute within transaction
188
188
 
189
- ### 13. Query Optimization (3 tools)
189
+ ### 13. Query Optimization (3 tools)
190
190
  - `analyze_query` - Analyze query performance
191
191
  - `get_optimization_hints` - Get optimizer hints
192
192
  - `repair_query` - Repair broken SQL queries
193
193
 
194
- ### 14. Utilities (4 tools)
194
+ ### 14. Utilities (4 tools)
195
195
  - `test_connection` - Test connectivity
196
196
  - `describe_connection` - Connection info
197
197
  - `read_changelog` - Read changelog
@@ -383,4 +383,4 @@ The system provides detailed error messages indicating:
383
383
 
384
384
  ---
385
385
 
386
- *For detailed examples and advanced usage patterns, see the project README.md.*
386
+ *For detailed examples and advanced usage patterns, see the project README.md.*
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-07 11:05:00
7
+ **Last Updated:** 2026-04-08 14:30: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)
@@ -200,7 +200,7 @@ Alternative approach using environment variables instead of connection string:
200
200
  "DB_PASSWORD": "your_password",
201
201
  "DB_NAME": "your_database",
202
202
  "MCP_PERMISSIONS": "list,read,utility,create,update,delete",
203
- "MCP_CATEGORIES": "database_discovery,custom_queries,analysis"
203
+ "MCP_CATEGORIES": "database_discovery,custom_queries,analysis"
204
204
  }
205
205
  }
206
206
  }
@@ -245,7 +245,7 @@ Use documentation categories to fine-tune which tools are exposed (Layer 2):
245
245
 
246
246
  | Category List | Use Case | List Tools |
247
247
  |---------------|----------|-----------|
248
- | `database_discovery` | Explore databases, tables, and schema structure | `get_all_tables_relationships, list_databases, list_tables, read_table_schema` |
248
+ | `database_discovery` | Explore databases, tables, and schema structure | `get_all_tables_relationships, list_databases, list_tables, read_table_schema` |
249
249
  | `crud_operations` | Create, read, update, delete operations on data | `create_record, delete_record, read_records, update_record` |
250
250
  | `bulk_operations` | High-performance batch processing operations | `bulk_delete, bulk_insert, bulk_update` |
251
251
  | `custom_queries` | Execute custom SQL queries and advanced operations | `execute_write_query, run_select_query` |
@@ -265,7 +265,7 @@ Use documentation categories to fine-tune which tools are exposed (Layer 2):
265
265
  <summary>Copy/paste list (comma-separated, no spaces)</summary>
266
266
 
267
267
  ```text
268
- database_discovery,crud_operations,bulk_operations,custom_queries,schema_management,utilities,transaction_management,stored_procedures,views_management,triggers_management,index_management,constraint_management,table_maintenance,query_optimization,analysis
268
+ database_discovery,crud_operations,bulk_operations,custom_queries,schema_management,utilities,transaction_management,stored_procedures,views_management,triggers_management,index_management,constraint_management,table_maintenance,query_optimization,analysis
269
269
  ```
270
270
 
271
271
  </details>
@@ -276,7 +276,7 @@ Full category → tool mapping (and examples) lives in **[DOCUMENTATIONS.md →
276
276
 
277
277
  ## Available Tools
278
278
 
279
- The server exposes **62 tools** organized into categories (CRUD, schema, and utilities).
279
+ The server exposes **62 tools** organized into categories (CRUD, schema, and utilities).
280
280
 
281
281
  - Complete list of tools: **[DOCUMENTATIONS.md → Complete Tools Reference](DOCUMENTATIONS.md#🔧-complete-tools-reference)**
282
282
 
@@ -1850,7 +1850,7 @@ const TOOLS = [
1850
1850
  // Create the MCP server
1851
1851
  const server = new index_js_1.Server({
1852
1852
  name: "mysql-mcp-server",
1853
- version: "1.40.3",
1853
+ version: "1.40.5",
1854
1854
  }, {
1855
1855
  capabilities: {
1856
1856
  tools: {},
@@ -120,11 +120,13 @@ class DatabaseTools {
120
120
  FROM
121
121
  INFORMATION_SCHEMA.COLUMNS
122
122
  WHERE
123
+ TABLE_SCHEMA = ? AND
123
124
  TABLE_NAME = ?
124
125
  ORDER BY
125
126
  ORDINAL_POSITION
126
127
  `;
127
128
  const results = await this.db.query(query, [
129
+ config_1.dbConfig.database,
128
130
  params.table_name,
129
131
  ]);
130
132
  return {
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mysql-mcp",
3
3
  "description": "A Model Context Protocol for MySQL database interaction",
4
- "version": "1.40.3",
4
+ "version": "1.40.4",
5
5
  "tools": [
6
6
  {
7
7
  "name": "list_databases",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@berthojoris/mcp-mysql-server",
3
- "version": "1.40.3",
4
- "description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions",
3
+ "version": "1.40.5",
4
+ "description": "Model Context Protocol server for MySQL database integration with dynamic per-project permissions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "commonjs",
@@ -62,13 +62,11 @@
62
62
  "ajv": "^8.12.0",
63
63
  "ajv-formats": "^3.0.1",
64
64
  "dotenv": "^16.3.1",
65
- "mysql2": "^3.6.1",
66
- "winston": "^3.11.0"
65
+ "mysql2": "^3.6.1"
67
66
  },
68
67
  "devDependencies": {
69
68
  "@types/jest": "^29.5.4",
70
69
  "@types/node": "^20.6.0",
71
- "@types/winston": "^2.4.4",
72
70
  "@typescript-eslint/eslint-plugin": "^8.50.1",
73
71
  "@typescript-eslint/parser": "^8.50.1",
74
72
  "eslint": "^9.39.2",
@@ -77,4 +75,4 @@
77
75
  "ts-node": "^10.9.1",
78
76
  "typescript": "^5.2.2"
79
77
  }
80
- }
78
+ }
package/dist/server.d.ts DELETED
@@ -1,2 +0,0 @@
1
- declare const app: import("express-serve-static-core").Express;
2
- export default app;
package/dist/server.js DELETED
@@ -1,345 +0,0 @@
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
- const express_1 = __importDefault(require("express"));
7
- const cors_1 = __importDefault(require("cors"));
8
- const helmet_1 = __importDefault(require("helmet"));
9
- const morgan_1 = __importDefault(require("morgan"));
10
- const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
11
- const index_1 = require("./index");
12
- const winston_1 = require("winston");
13
- const inputValidation_1 = require("./validation/inputValidation");
14
- // Initialize the MCP instance
15
- const mcp = new index_1.MySQLMCP();
16
- // Create Winston logger
17
- const logger = (0, winston_1.createLogger)({
18
- level: 'info',
19
- format: winston_1.format.combine(winston_1.format.timestamp(), winston_1.format.json()),
20
- transports: [
21
- new winston_1.transports.Console(),
22
- new winston_1.transports.File({ filename: 'logs/error.log', level: 'error' }),
23
- new winston_1.transports.File({ filename: 'logs/combined.log' })
24
- ]
25
- });
26
- // Initialize Express app
27
- const app = (0, express_1.default)();
28
- const PORT = process.env.PORT || 3000;
29
- // Middleware
30
- app.use((0, helmet_1.default)()); // Security headers
31
- app.use((0, cors_1.default)()); // Enable CORS
32
- app.use(express_1.default.json()); // Parse JSON bodies
33
- app.use((0, morgan_1.default)('combined')); // HTTP request logging
34
- // Rate limiting
35
- const apiLimiter = (0, express_rate_limit_1.default)({
36
- windowMs: 15 * 60 * 1000, // 15 minutes
37
- max: 100, // Limit each IP to 100 requests per windowMs
38
- standardHeaders: true,
39
- legacyHeaders: false,
40
- });
41
- app.use(apiLimiter);
42
- // No authentication middleware needed for MCP server
43
- // Input validation middleware
44
- const validateInput = (validator) => {
45
- return (req, res, next) => {
46
- const validation = validator(req.body);
47
- if (!validation.valid) {
48
- return res.status(400).json({
49
- error: {
50
- code: 'VALIDATION_ERROR',
51
- message: 'Input validation failed',
52
- details: validation.errors
53
- }
54
- });
55
- }
56
- next();
57
- };
58
- };
59
- // Parameter sanitization middleware
60
- const sanitizeParams = (req, res, next) => {
61
- // Sanitize route parameters
62
- if (req.params.tableName) {
63
- req.params.tableName = (0, inputValidation_1.sanitizeTableName)(req.params.tableName);
64
- }
65
- if (req.params.id) {
66
- req.params.id = (0, inputValidation_1.sanitizeFieldName)(req.params.id);
67
- }
68
- // Sanitize query parameters
69
- if (req.query.id_field) {
70
- req.query.id_field = (0, inputValidation_1.sanitizeFieldName)(req.query.id_field);
71
- }
72
- if (req.query.sort_by) {
73
- req.query.sort_by = (0, inputValidation_1.sanitizeFieldName)(req.query.sort_by);
74
- }
75
- // Sanitize request body
76
- if (req.body.query) {
77
- req.body.query = (0, inputValidation_1.sanitizeQuery)(req.body.query);
78
- }
79
- next();
80
- };
81
- // Request size limiting middleware
82
- const requestSizeLimit = (maxSize) => {
83
- return (req, res, next) => {
84
- const contentLength = parseInt(req.headers['content-length'] || '0');
85
- if (contentLength > maxSize) {
86
- return res.status(413).json({
87
- error: {
88
- code: 'REQUEST_TOO_LARGE',
89
- message: `Request body too large. Maximum size is ${maxSize} bytes`
90
- }
91
- });
92
- }
93
- next();
94
- };
95
- };
96
- // Error handling middleware
97
- const errorHandler = (err, req, res, next) => {
98
- logger.error(`${err.name}: ${err.message}`, {
99
- path: req.path,
100
- method: req.method,
101
- body: req.body,
102
- stack: err.stack
103
- });
104
- res.status(500).json({
105
- error: {
106
- code: 'SERVER_ERROR',
107
- message: 'An unexpected error occurred',
108
- details: process.env.NODE_ENV === 'production' ? 'See server logs for details' : err.message
109
- }
110
- });
111
- };
112
- // Health check endpoint (no auth required)
113
- app.get('/health', (req, res) => {
114
- res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() });
115
- });
116
- // Feature configuration status endpoint
117
- app.get('/features', (req, res) => {
118
- try {
119
- const featureStatus = mcp.getFeatureStatus();
120
- res.status(200).json(featureStatus);
121
- }
122
- catch (error) {
123
- logger.error('Error getting feature status', { error });
124
- res.status(500).json({
125
- status: 'error',
126
- error: 'Failed to retrieve feature configuration status'
127
- });
128
- }
129
- });
130
- // API routes - no authentication required for MCP server
131
- const apiRouter = express_1.default.Router();
132
- app.use('/api', sanitizeParams, apiRouter);
133
- // Database Tools Routes
134
- apiRouter.get('/databases', async (req, res, next) => {
135
- try {
136
- const result = await mcp.listDatabases();
137
- res.json(result);
138
- }
139
- catch (error) {
140
- next(error);
141
- }
142
- });
143
- apiRouter.get('/tables', async (req, res, next) => {
144
- try {
145
- const result = await mcp.listTables({ database: undefined });
146
- res.json(result);
147
- }
148
- catch (error) {
149
- next(error);
150
- }
151
- });
152
- apiRouter.get('/tables/:tableName/schema', async (req, res, next) => {
153
- try {
154
- const { tableName } = req.params;
155
- const result = await mcp.readTableSchema({ table_name: tableName });
156
- res.json(result);
157
- }
158
- catch (error) {
159
- next(error);
160
- }
161
- });
162
- // CRUD Operations Routes
163
- apiRouter.post('/tables/:tableName/records', requestSizeLimit(inputValidation_1.INPUT_LIMITS.MAX_QUERY_LENGTH), validateInput((req) => (0, inputValidation_1.validateCreateRecord)({ table_name: req.params.tableName, data: req.body.data })), async (req, res, next) => {
164
- try {
165
- const { tableName } = req.params;
166
- const { data } = req.body;
167
- const result = await mcp.createRecord({
168
- table_name: tableName,
169
- data
170
- });
171
- res.status(201).json(result);
172
- }
173
- catch (error) {
174
- next(error);
175
- }
176
- });
177
- apiRouter.get('/tables/:tableName/records', async (req, res, next) => {
178
- try {
179
- const { tableName } = req.params;
180
- const { filters, limit, offset, sort_by, sort_direction } = req.query;
181
- // Validate and parse filters
182
- let parsedFilters;
183
- if (filters) {
184
- try {
185
- parsedFilters = JSON.parse(filters);
186
- }
187
- catch (e) {
188
- return res.status(400).json({
189
- error: {
190
- code: 'INVALID_FILTERS',
191
- message: 'Invalid JSON in filters parameter'
192
- }
193
- });
194
- }
195
- }
196
- // Validate the complete request
197
- const validation = (0, inputValidation_1.validateReadRecords)({
198
- table_name: tableName,
199
- filters: parsedFilters,
200
- pagination: {
201
- page: offset ? Math.floor(parseInt(offset) / (limit ? parseInt(limit) : 10)) + 1 : 1,
202
- limit: limit ? parseInt(limit) : 10
203
- },
204
- sorting: sort_by ? {
205
- field: sort_by,
206
- direction: sort_direction?.toLowerCase() === 'desc' ? 'desc' : 'asc'
207
- } : undefined
208
- });
209
- if (!validation.valid) {
210
- return res.status(400).json({
211
- error: {
212
- code: 'VALIDATION_ERROR',
213
- message: 'Input validation failed',
214
- details: validation.errors
215
- }
216
- });
217
- }
218
- const result = await mcp.readRecords({
219
- table_name: tableName,
220
- filters: parsedFilters,
221
- pagination: {
222
- page: offset ? Math.floor(parseInt(offset) / (limit ? parseInt(limit) : 10)) + 1 : 1,
223
- limit: limit ? parseInt(limit) : 10
224
- },
225
- sorting: sort_by ? {
226
- field: sort_by,
227
- direction: sort_direction?.toLowerCase() === 'desc' ? 'desc' : 'asc'
228
- } : undefined
229
- });
230
- res.json(result);
231
- }
232
- catch (error) {
233
- next(error);
234
- }
235
- });
236
- apiRouter.put('/tables/:tableName/records/:id', requestSizeLimit(inputValidation_1.INPUT_LIMITS.MAX_QUERY_LENGTH), validateInput((req) => (0, inputValidation_1.validateUpdateRecord)({
237
- table_name: req.params.tableName,
238
- data: req.body.data,
239
- conditions: [{ field: req.body.id_field || 'id', operator: '=', value: req.params.id }]
240
- })), async (req, res, next) => {
241
- try {
242
- const { tableName, id } = req.params;
243
- const { data, id_field } = req.body;
244
- const result = await mcp.updateRecord({
245
- table_name: tableName,
246
- data,
247
- conditions: [{ field: id_field || 'id', operator: '=', value: id }]
248
- });
249
- res.json(result);
250
- }
251
- catch (error) {
252
- next(error);
253
- }
254
- });
255
- apiRouter.delete('/tables/:tableName/records/:id', validateInput((req) => (0, inputValidation_1.validateDeleteRecord)({
256
- table_name: req.params.tableName,
257
- conditions: [{ field: req.query.id_field || 'id', operator: '=', value: req.params.id }]
258
- })), async (req, res, next) => {
259
- try {
260
- const { tableName, id } = req.params;
261
- const { id_field } = req.query;
262
- const result = await mcp.deleteRecord({
263
- table_name: tableName,
264
- conditions: [{ field: id_field || 'id', operator: '=', value: id }]
265
- });
266
- res.json(result);
267
- }
268
- catch (error) {
269
- next(error);
270
- }
271
- });
272
- // Query Tools Routes
273
- apiRouter.post('/query', requestSizeLimit(inputValidation_1.INPUT_LIMITS.MAX_QUERY_LENGTH), validateInput(inputValidation_1.validateQuery), async (req, res, next) => {
274
- try {
275
- const { query, params } = req.body;
276
- const result = await mcp.runSelectQuery({
277
- query,
278
- params: params || []
279
- });
280
- res.json(result);
281
- }
282
- catch (error) {
283
- next(error);
284
- }
285
- });
286
- apiRouter.post('/execute', requestSizeLimit(inputValidation_1.INPUT_LIMITS.MAX_QUERY_LENGTH), validateInput(inputValidation_1.validateQuery), async (req, res, next) => {
287
- try {
288
- const { query, params } = req.body;
289
- const result = await mcp.executeWriteQuery({
290
- query,
291
- params: params || []
292
- });
293
- res.json(result);
294
- }
295
- catch (error) {
296
- next(error);
297
- }
298
- });
299
- // Utility Tools Routes
300
- apiRouter.get('/connection', async (req, res, next) => {
301
- try {
302
- const result = await mcp.describeConnection();
303
- res.json(result);
304
- }
305
- catch (error) {
306
- next(error);
307
- }
308
- });
309
- apiRouter.get('/connection/test', async (req, res, next) => {
310
- try {
311
- const result = await mcp.testConnection();
312
- res.json(result);
313
- }
314
- catch (error) {
315
- next(error);
316
- }
317
- });
318
- apiRouter.get('/tables/:tableName/relationships', async (req, res, next) => {
319
- try {
320
- const { tableName } = req.params;
321
- const result = await mcp.getTableRelationships({ table_name: tableName });
322
- res.json(result);
323
- }
324
- catch (error) {
325
- next(error);
326
- }
327
- });
328
- // Apply error handler
329
- app.use(errorHandler);
330
- // Start the server
331
- const server = app.listen(PORT, () => {
332
- logger.info(`MCP MySQL Server running on port ${PORT}`);
333
- console.log(`MCP MySQL Server running on port ${PORT}`);
334
- });
335
- // Graceful shutdown
336
- process.on('SIGTERM', () => {
337
- logger.info('SIGTERM signal received: closing HTTP server');
338
- server.close(async () => {
339
- logger.info('HTTP server closed');
340
- await mcp.close();
341
- logger.info('Database connections closed');
342
- process.exit(0);
343
- });
344
- });
345
- exports.default = app;