@berthojoris/mcp-mysql-server 1.4.15 → 1.5.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/DOCUMENTATIONS.md +200 -18
- package/dist/cache/queryCache.d.ts +126 -0
- package/dist/cache/queryCache.js +337 -0
- package/dist/config/featureConfig.js +82 -71
- package/dist/db/connection.d.ts +21 -2
- package/dist/db/connection.js +73 -7
- package/dist/db/queryLogger.d.ts +3 -2
- package/dist/db/queryLogger.js +64 -43
- package/dist/index.d.ts +76 -3
- package/dist/index.js +161 -70
- package/dist/mcp-server.js +166 -5
- package/dist/optimization/queryOptimizer.d.ts +125 -0
- package/dist/optimization/queryOptimizer.js +509 -0
- package/dist/tools/queryTools.d.ts +14 -1
- package/dist/tools/queryTools.js +27 -3
- package/package.json +1 -1
package/dist/db/connection.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const promise_1 = __importDefault(require("mysql2/promise"));
|
|
7
7
|
const config_1 = require("../config/config");
|
|
8
8
|
const queryLogger_1 = require("./queryLogger");
|
|
9
|
+
const queryCache_1 = require("../cache/queryCache");
|
|
9
10
|
class DatabaseConnection {
|
|
10
11
|
constructor() {
|
|
11
12
|
this.pool = promise_1.default.createPool({
|
|
@@ -16,9 +17,10 @@ class DatabaseConnection {
|
|
|
16
17
|
database: config_1.dbConfig.database,
|
|
17
18
|
waitForConnections: true,
|
|
18
19
|
connectionLimit: 10,
|
|
19
|
-
queueLimit: 0
|
|
20
|
+
queueLimit: 0,
|
|
20
21
|
});
|
|
21
22
|
this.activeTransactions = new Map();
|
|
23
|
+
this.queryCache = queryCache_1.QueryCache.getInstance();
|
|
22
24
|
}
|
|
23
25
|
static getInstance() {
|
|
24
26
|
if (!DatabaseConnection.instance) {
|
|
@@ -34,20 +36,54 @@ class DatabaseConnection {
|
|
|
34
36
|
throw new Error(`Failed to get database connection: ${error}`);
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
|
-
async query(sql, params) {
|
|
39
|
+
async query(sql, params, useCache = true) {
|
|
40
|
+
const normalizedSql = sql.trim().toUpperCase();
|
|
41
|
+
const isSelectQuery = normalizedSql.startsWith("SELECT");
|
|
42
|
+
// Check cache for SELECT queries
|
|
43
|
+
if (useCache && isSelectQuery) {
|
|
44
|
+
const cachedEntry = this.queryCache.get(sql, params);
|
|
45
|
+
if (cachedEntry) {
|
|
46
|
+
// Log cache hit
|
|
47
|
+
queryLogger_1.QueryLogger.log(sql, params, 0, "success", undefined, true);
|
|
48
|
+
return cachedEntry.data;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
38
51
|
const startTime = Date.now();
|
|
39
52
|
try {
|
|
40
53
|
const [results] = await this.pool.query(sql, params);
|
|
41
54
|
const duration = Date.now() - startTime;
|
|
42
|
-
queryLogger_1.QueryLogger.log(sql, params, duration,
|
|
55
|
+
queryLogger_1.QueryLogger.log(sql, params, duration, "success");
|
|
56
|
+
// Cache SELECT query results
|
|
57
|
+
if (useCache && isSelectQuery) {
|
|
58
|
+
this.queryCache.set(sql, params, results);
|
|
59
|
+
}
|
|
60
|
+
// Invalidate cache for write operations
|
|
61
|
+
if (!isSelectQuery) {
|
|
62
|
+
this.invalidateCacheForWriteOperation(sql);
|
|
63
|
+
}
|
|
43
64
|
return results;
|
|
44
65
|
}
|
|
45
66
|
catch (error) {
|
|
46
67
|
const duration = Date.now() - startTime;
|
|
47
|
-
queryLogger_1.QueryLogger.log(sql, params, duration,
|
|
68
|
+
queryLogger_1.QueryLogger.log(sql, params, duration, "error", error.message);
|
|
48
69
|
throw new Error(`Query execution failed: ${error}`);
|
|
49
70
|
}
|
|
50
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Invalidate cache entries when write operations occur
|
|
74
|
+
*/
|
|
75
|
+
invalidateCacheForWriteOperation(sql) {
|
|
76
|
+
// Extract table name from INSERT, UPDATE, DELETE statements
|
|
77
|
+
const insertMatch = sql.match(/INSERT\s+INTO\s+[\`"']?(\w+)[\`"']?/i);
|
|
78
|
+
const updateMatch = sql.match(/UPDATE\s+[\`"']?(\w+)[\`"']?/i);
|
|
79
|
+
const deleteMatch = sql.match(/DELETE\s+FROM\s+[\`"']?(\w+)[\`"']?/i);
|
|
80
|
+
const truncateMatch = sql.match(/TRUNCATE\s+(?:TABLE\s+)?[\`"']?(\w+)[\`"']?/i);
|
|
81
|
+
const dropMatch = sql.match(/DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?[\`"']?(\w+)[\`"']?/i);
|
|
82
|
+
const match = insertMatch || updateMatch || deleteMatch || truncateMatch || dropMatch;
|
|
83
|
+
if (match && match[1]) {
|
|
84
|
+
this.queryCache.invalidateTable(match[1]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
51
87
|
async testConnection() {
|
|
52
88
|
const startTime = Date.now();
|
|
53
89
|
try {
|
|
@@ -96,7 +132,7 @@ class DatabaseConnection {
|
|
|
96
132
|
connection.release();
|
|
97
133
|
}
|
|
98
134
|
catch (rollbackError) {
|
|
99
|
-
console.error(
|
|
135
|
+
console.error("Failed to rollback after commit error:", rollbackError);
|
|
100
136
|
}
|
|
101
137
|
this.activeTransactions.delete(transactionId);
|
|
102
138
|
throw new Error(`Failed to commit transaction: ${error}`);
|
|
@@ -133,6 +169,36 @@ class DatabaseConnection {
|
|
|
133
169
|
getFormattedQueryLogs(count = 1) {
|
|
134
170
|
return queryLogger_1.QueryLogger.formatLogs(queryLogger_1.QueryLogger.getLastLogs(count));
|
|
135
171
|
}
|
|
172
|
+
// Cache Management Methods
|
|
173
|
+
getCacheStats() {
|
|
174
|
+
return this.queryCache.getStats();
|
|
175
|
+
}
|
|
176
|
+
getCacheConfig() {
|
|
177
|
+
return this.queryCache.getConfig();
|
|
178
|
+
}
|
|
179
|
+
setCacheConfig(config) {
|
|
180
|
+
this.queryCache.setConfig(config);
|
|
181
|
+
}
|
|
182
|
+
clearCache() {
|
|
183
|
+
const previousSize = this.queryCache.getStats().currentSize;
|
|
184
|
+
this.queryCache.clear();
|
|
185
|
+
return previousSize;
|
|
186
|
+
}
|
|
187
|
+
invalidateCache(pattern) {
|
|
188
|
+
return this.queryCache.invalidate(pattern);
|
|
189
|
+
}
|
|
190
|
+
invalidateCacheForTable(tableName) {
|
|
191
|
+
return this.queryCache.invalidateTable(tableName);
|
|
192
|
+
}
|
|
193
|
+
enableCache() {
|
|
194
|
+
this.queryCache.enable();
|
|
195
|
+
}
|
|
196
|
+
disableCache() {
|
|
197
|
+
this.queryCache.disable();
|
|
198
|
+
}
|
|
199
|
+
resetCacheStats() {
|
|
200
|
+
this.queryCache.resetStats();
|
|
201
|
+
}
|
|
136
202
|
async executeInTransaction(transactionId, sql, params) {
|
|
137
203
|
const connection = this.activeTransactions.get(transactionId);
|
|
138
204
|
if (!connection) {
|
|
@@ -142,12 +208,12 @@ class DatabaseConnection {
|
|
|
142
208
|
try {
|
|
143
209
|
const [results] = await connection.query(sql, params);
|
|
144
210
|
const duration = Date.now() - startTime;
|
|
145
|
-
queryLogger_1.QueryLogger.log(sql, params, duration,
|
|
211
|
+
queryLogger_1.QueryLogger.log(sql, params, duration, "success");
|
|
146
212
|
return results;
|
|
147
213
|
}
|
|
148
214
|
catch (error) {
|
|
149
215
|
const duration = Date.now() - startTime;
|
|
150
|
-
queryLogger_1.QueryLogger.log(sql, params, duration,
|
|
216
|
+
queryLogger_1.QueryLogger.log(sql, params, duration, "error", error.message);
|
|
151
217
|
throw new Error(`Query execution in transaction failed: ${error}`);
|
|
152
218
|
}
|
|
153
219
|
}
|
package/dist/db/queryLogger.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ export interface QueryLog {
|
|
|
3
3
|
params?: any[];
|
|
4
4
|
duration: number;
|
|
5
5
|
timestamp: string;
|
|
6
|
-
status:
|
|
6
|
+
status: "success" | "error";
|
|
7
7
|
error?: string;
|
|
8
|
+
cacheHit?: boolean;
|
|
8
9
|
}
|
|
9
10
|
export declare class QueryLogger {
|
|
10
11
|
private static logs;
|
|
@@ -27,7 +28,7 @@ export declare class QueryLogger {
|
|
|
27
28
|
/**
|
|
28
29
|
* Log a query execution
|
|
29
30
|
*/
|
|
30
|
-
static log(sql: string, params: any[] | undefined, duration: number, status:
|
|
31
|
+
static log(sql: string, params: any[] | undefined, duration: number, status: "success" | "error", error?: string, cacheHit?: boolean): void;
|
|
31
32
|
/**
|
|
32
33
|
* Get all logged queries (returns shallow copy of array)
|
|
33
34
|
*/
|
package/dist/db/queryLogger.js
CHANGED
|
@@ -8,34 +8,38 @@ class QueryLogger {
|
|
|
8
8
|
static safeStringify(value, maxLength = 100) {
|
|
9
9
|
try {
|
|
10
10
|
if (value === null)
|
|
11
|
-
return
|
|
11
|
+
return "null";
|
|
12
12
|
if (value === undefined)
|
|
13
|
-
return
|
|
14
|
-
if (typeof value ===
|
|
15
|
-
return value.length > maxLength
|
|
13
|
+
return "undefined";
|
|
14
|
+
if (typeof value === "string") {
|
|
15
|
+
return value.length > maxLength
|
|
16
|
+
? value.substring(0, maxLength) + "..."
|
|
17
|
+
: value;
|
|
16
18
|
}
|
|
17
|
-
if (typeof value ===
|
|
19
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
18
20
|
return String(value);
|
|
19
21
|
}
|
|
20
|
-
if (typeof value ===
|
|
21
|
-
return value.toString() +
|
|
22
|
+
if (typeof value === "bigint") {
|
|
23
|
+
return value.toString() + "n";
|
|
22
24
|
}
|
|
23
25
|
if (Array.isArray(value)) {
|
|
24
26
|
if (value.length === 0)
|
|
25
|
-
return
|
|
26
|
-
const items = value.slice(0, 3).map(v => this.safeStringify(v, 30));
|
|
27
|
+
return "[]";
|
|
28
|
+
const items = value.slice(0, 3).map((v) => this.safeStringify(v, 30));
|
|
27
29
|
return value.length > 3
|
|
28
|
-
? `[${items.join(
|
|
29
|
-
: `[${items.join(
|
|
30
|
+
? `[${items.join(", ")}, ... +${value.length - 3} more]`
|
|
31
|
+
: `[${items.join(", ")}]`;
|
|
30
32
|
}
|
|
31
|
-
if (typeof value ===
|
|
33
|
+
if (typeof value === "object") {
|
|
32
34
|
const str = JSON.stringify(value);
|
|
33
|
-
return str.length > maxLength
|
|
35
|
+
return str.length > maxLength
|
|
36
|
+
? str.substring(0, maxLength) + "...}"
|
|
37
|
+
: str;
|
|
34
38
|
}
|
|
35
39
|
return String(value);
|
|
36
40
|
}
|
|
37
41
|
catch (error) {
|
|
38
|
-
return
|
|
42
|
+
return "[Unstringifiable]";
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
/**
|
|
@@ -44,7 +48,8 @@ class QueryLogger {
|
|
|
44
48
|
static truncateSQL(sql) {
|
|
45
49
|
if (sql.length <= this.MAX_SQL_LENGTH)
|
|
46
50
|
return sql;
|
|
47
|
-
return sql.substring(0, this.MAX_SQL_LENGTH) +
|
|
51
|
+
return (sql.substring(0, this.MAX_SQL_LENGTH) +
|
|
52
|
+
`... [truncated ${sql.length - this.MAX_SQL_LENGTH} chars]`);
|
|
48
53
|
}
|
|
49
54
|
/**
|
|
50
55
|
* Create a memory-safe copy of parameters
|
|
@@ -60,20 +65,25 @@ class QueryLogger {
|
|
|
60
65
|
}
|
|
61
66
|
catch (error) {
|
|
62
67
|
// If JSON serialization fails, create safe string representations
|
|
63
|
-
return limitedParams.map(p => this.safeStringify(p, 50));
|
|
68
|
+
return limitedParams.map((p) => this.safeStringify(p, 50));
|
|
64
69
|
}
|
|
65
70
|
}
|
|
66
71
|
/**
|
|
67
72
|
* Log a query execution
|
|
68
73
|
*/
|
|
69
|
-
static log(sql, params, duration, status, error) {
|
|
74
|
+
static log(sql, params, duration, status, error, cacheHit) {
|
|
70
75
|
const log = {
|
|
71
76
|
sql: this.truncateSQL(sql),
|
|
72
77
|
params: this.sanitizeParams(params),
|
|
73
78
|
duration,
|
|
74
79
|
timestamp: new Date().toISOString(),
|
|
75
80
|
status,
|
|
76
|
-
|
|
81
|
+
cacheHit: cacheHit,
|
|
82
|
+
error: error
|
|
83
|
+
? error.length > 200
|
|
84
|
+
? error.substring(0, 200) + "..."
|
|
85
|
+
: error
|
|
86
|
+
: undefined,
|
|
77
87
|
};
|
|
78
88
|
this.logs.push(log);
|
|
79
89
|
// Keep only the last MAX_LOGS entries
|
|
@@ -113,9 +123,9 @@ class QueryLogger {
|
|
|
113
123
|
static formatSQL(sql) {
|
|
114
124
|
// Add line breaks for better readability
|
|
115
125
|
return sql
|
|
116
|
-
.replace(/\s+/g,
|
|
117
|
-
.replace(/\b(SELECT|FROM|WHERE|JOIN|LEFT JOIN|RIGHT JOIN|INNER JOIN|OUTER JOIN|GROUP BY|ORDER BY|HAVING|LIMIT|UNION|INSERT INTO|UPDATE|DELETE FROM|SET|VALUES|CREATE|ALTER|DROP|TRUNCATE|BEGIN|COMMIT|ROLLBACK|CALL)\b/gi,
|
|
118
|
-
.replace(/,\s*/g,
|
|
126
|
+
.replace(/\s+/g, " ") // Normalize whitespace
|
|
127
|
+
.replace(/\b(SELECT|FROM|WHERE|JOIN|LEFT JOIN|RIGHT JOIN|INNER JOIN|OUTER JOIN|GROUP BY|ORDER BY|HAVING|LIMIT|UNION|INSERT INTO|UPDATE|DELETE FROM|SET|VALUES|CREATE|ALTER|DROP|TRUNCATE|BEGIN|COMMIT|ROLLBACK|CALL)\b/gi, "\n$1")
|
|
128
|
+
.replace(/,\s*/g, ",\n ") // Add line breaks after commas
|
|
119
129
|
.trim();
|
|
120
130
|
}
|
|
121
131
|
/**
|
|
@@ -124,61 +134,72 @@ class QueryLogger {
|
|
|
124
134
|
*/
|
|
125
135
|
static formatLogs(logs) {
|
|
126
136
|
if (logs.length === 0)
|
|
127
|
-
return
|
|
128
|
-
return logs
|
|
137
|
+
return "";
|
|
138
|
+
return logs
|
|
139
|
+
.map((log, index) => {
|
|
129
140
|
// Format the SQL for better readability
|
|
130
141
|
const formattedSQL = this.formatSQL(log.sql);
|
|
131
142
|
// Format parameters
|
|
132
|
-
let paramStr =
|
|
143
|
+
let paramStr = "";
|
|
133
144
|
if (log.params && log.params.length > 0) {
|
|
134
145
|
try {
|
|
135
146
|
const paramsJson = JSON.stringify(log.params, null, 2);
|
|
136
|
-
paramStr =
|
|
137
|
-
|
|
138
|
-
|
|
147
|
+
paramStr =
|
|
148
|
+
paramsJson.length > this.MAX_PARAM_LENGTH
|
|
149
|
+
? `\n📋 Parameters:\n${paramsJson.substring(0, this.MAX_PARAM_LENGTH)}...`
|
|
150
|
+
: `\n📋 Parameters:\n${paramsJson}`;
|
|
139
151
|
}
|
|
140
152
|
catch (error) {
|
|
141
|
-
paramStr =
|
|
153
|
+
paramStr = "\n📋 Parameters: [Error serializing]";
|
|
142
154
|
}
|
|
143
155
|
}
|
|
144
156
|
// Format error if present
|
|
145
|
-
const errorStr = log.error ? `\n❌ Error: ${log.error}` :
|
|
157
|
+
const errorStr = log.error ? `\n❌ Error: ${log.error}` : "";
|
|
146
158
|
// Format status with emoji for better visibility
|
|
147
|
-
const statusEmoji = log.status ===
|
|
148
|
-
const statusText = log.status ===
|
|
159
|
+
const statusEmoji = log.status === "success" ? "✅" : "❌";
|
|
160
|
+
const statusText = log.status === "success" ? "SUCCESS" : "ERROR";
|
|
161
|
+
// Format cache hit indicator
|
|
162
|
+
const cacheStr = log.cacheHit
|
|
163
|
+
? "\n💾 Cache: HIT (served from cache)"
|
|
164
|
+
: "";
|
|
165
|
+
const cacheLabel = log.cacheHit ? " [CACHED]" : "";
|
|
149
166
|
// Build the formatted log entry with clear visual hierarchy
|
|
150
167
|
return `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
151
|
-
${statusEmoji} SQL Query #${index + 1} - ${statusText}
|
|
168
|
+
${statusEmoji} SQL Query #${index + 1} - ${statusText}${cacheLabel}
|
|
152
169
|
⏱️ Execution Time: ${log.duration}ms
|
|
153
|
-
🕐 Timestamp: ${log.timestamp}
|
|
170
|
+
🕐 Timestamp: ${log.timestamp}${cacheStr}
|
|
154
171
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
155
172
|
|
|
156
173
|
📝 SQL Query:
|
|
157
174
|
${formattedSQL}${paramStr}${errorStr}`;
|
|
158
|
-
})
|
|
175
|
+
})
|
|
176
|
+
.join("\n\n");
|
|
159
177
|
}
|
|
160
178
|
/**
|
|
161
179
|
* Get logs as compact formatted string (for backward compatibility)
|
|
162
180
|
*/
|
|
163
181
|
static formatLogsCompact(logs) {
|
|
164
182
|
if (logs.length === 0)
|
|
165
|
-
return
|
|
166
|
-
return logs
|
|
167
|
-
|
|
183
|
+
return "";
|
|
184
|
+
return logs
|
|
185
|
+
.map((log, index) => {
|
|
186
|
+
let paramStr = "";
|
|
168
187
|
if (log.params && log.params.length > 0) {
|
|
169
188
|
try {
|
|
170
189
|
const paramsJson = JSON.stringify(log.params);
|
|
171
|
-
paramStr =
|
|
172
|
-
|
|
173
|
-
|
|
190
|
+
paramStr =
|
|
191
|
+
paramsJson.length > this.MAX_PARAM_LENGTH
|
|
192
|
+
? ` | Params: ${paramsJson.substring(0, this.MAX_PARAM_LENGTH)}...`
|
|
193
|
+
: ` | Params: ${paramsJson}`;
|
|
174
194
|
}
|
|
175
195
|
catch (error) {
|
|
176
|
-
paramStr =
|
|
196
|
+
paramStr = " | Params: [Error serializing]";
|
|
177
197
|
}
|
|
178
198
|
}
|
|
179
|
-
const errorStr = log.error ? ` | Error: ${log.error}` :
|
|
199
|
+
const errorStr = log.error ? ` | Error: ${log.error}` : "";
|
|
180
200
|
return `[${index + 1}] ${log.timestamp} | ${log.sql}${paramStr} | Duration: ${log.duration}ms | Status: ${log.status}${errorStr}`;
|
|
181
|
-
})
|
|
201
|
+
})
|
|
202
|
+
.join("\n");
|
|
182
203
|
}
|
|
183
204
|
}
|
|
184
205
|
exports.QueryLogger = QueryLogger;
|
package/dist/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export declare class MySQLMCP {
|
|
|
55
55
|
};
|
|
56
56
|
sorting?: {
|
|
57
57
|
field: string;
|
|
58
|
-
direction:
|
|
58
|
+
direction: "asc" | "desc";
|
|
59
59
|
};
|
|
60
60
|
}): Promise<{
|
|
61
61
|
status: string;
|
|
@@ -95,6 +95,7 @@ export declare class MySQLMCP {
|
|
|
95
95
|
data?: any[];
|
|
96
96
|
error?: string;
|
|
97
97
|
queryLog?: string;
|
|
98
|
+
optimizedQuery?: string;
|
|
98
99
|
}>;
|
|
99
100
|
executeSql(params: {
|
|
100
101
|
query: string;
|
|
@@ -214,7 +215,7 @@ export declare class MySQLMCP {
|
|
|
214
215
|
procedure_name: string;
|
|
215
216
|
parameters?: Array<{
|
|
216
217
|
name: string;
|
|
217
|
-
mode:
|
|
218
|
+
mode: "IN" | "OUT" | "INOUT";
|
|
218
219
|
data_type: string;
|
|
219
220
|
}>;
|
|
220
221
|
body: string;
|
|
@@ -251,7 +252,7 @@ export declare class MySQLMCP {
|
|
|
251
252
|
};
|
|
252
253
|
sorting?: {
|
|
253
254
|
field: string;
|
|
254
|
-
direction:
|
|
255
|
+
direction: "asc" | "desc";
|
|
255
256
|
};
|
|
256
257
|
include_headers?: boolean;
|
|
257
258
|
}): Promise<{
|
|
@@ -317,5 +318,77 @@ export declare class MySQLMCP {
|
|
|
317
318
|
error?: string;
|
|
318
319
|
}>;
|
|
319
320
|
close(): Promise<void>;
|
|
321
|
+
/**
|
|
322
|
+
* Get cache statistics
|
|
323
|
+
*/
|
|
324
|
+
getCacheStats(): {
|
|
325
|
+
status: string;
|
|
326
|
+
data: import("./cache/queryCache").CacheStats;
|
|
327
|
+
};
|
|
328
|
+
/**
|
|
329
|
+
* Get cache configuration
|
|
330
|
+
*/
|
|
331
|
+
getCacheConfig(): {
|
|
332
|
+
status: string;
|
|
333
|
+
data: import("./cache/queryCache").CacheConfig;
|
|
334
|
+
};
|
|
335
|
+
/**
|
|
336
|
+
* Configure cache settings
|
|
337
|
+
*/
|
|
338
|
+
configureCacheSettings(params: {
|
|
339
|
+
enabled?: boolean;
|
|
340
|
+
ttlMs?: number;
|
|
341
|
+
maxSize?: number;
|
|
342
|
+
maxMemoryMB?: number;
|
|
343
|
+
}): {
|
|
344
|
+
status: string;
|
|
345
|
+
data: {
|
|
346
|
+
message: string;
|
|
347
|
+
config: import("./cache/queryCache").CacheConfig;
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* Clear the query cache
|
|
352
|
+
*/
|
|
353
|
+
clearCache(): {
|
|
354
|
+
status: string;
|
|
355
|
+
data: {
|
|
356
|
+
message: string;
|
|
357
|
+
entriesCleared: number;
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* Invalidate cache for a specific table
|
|
362
|
+
*/
|
|
363
|
+
invalidateCacheForTable(params: {
|
|
364
|
+
table_name: string;
|
|
365
|
+
}): {
|
|
366
|
+
status: string;
|
|
367
|
+
data: {
|
|
368
|
+
message: string;
|
|
369
|
+
entriesInvalidated: number;
|
|
370
|
+
};
|
|
371
|
+
};
|
|
372
|
+
/**
|
|
373
|
+
* Analyze a query and get optimization suggestions
|
|
374
|
+
*/
|
|
375
|
+
analyzeQuery(params: {
|
|
376
|
+
query: string;
|
|
377
|
+
}): {
|
|
378
|
+
status: string;
|
|
379
|
+
data: import("./optimization/queryOptimizer").QueryAnalysis;
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* Get suggested optimizer hints for a specific optimization goal
|
|
383
|
+
*/
|
|
384
|
+
getOptimizationHints(params: {
|
|
385
|
+
goal: "SPEED" | "MEMORY" | "STABILITY";
|
|
386
|
+
}): {
|
|
387
|
+
status: string;
|
|
388
|
+
data: {
|
|
389
|
+
goal: "SPEED" | "MEMORY" | "STABILITY";
|
|
390
|
+
hints: import("./optimization/queryOptimizer").QueryHints;
|
|
391
|
+
};
|
|
392
|
+
};
|
|
320
393
|
}
|
|
321
394
|
export default MySQLMCP;
|