@neverinfamous/mysql-mcp 2.2.0 → 2.3.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/.github/workflows/docker-publish.yml +1 -2
- package/CHANGELOG.md +85 -0
- package/CODE_MODE.md +245 -0
- package/DOCKER_README.md +59 -36
- package/README.md +65 -42
- package/VERSION +1 -1
- package/dist/adapters/mysql/MySQLAdapter.d.ts +4 -0
- package/dist/adapters/mysql/MySQLAdapter.d.ts.map +1 -1
- package/dist/adapters/mysql/MySQLAdapter.js +9 -0
- package/dist/adapters/mysql/MySQLAdapter.js.map +1 -1
- package/dist/adapters/mysql/prompts/index.d.ts +8 -1
- package/dist/adapters/mysql/prompts/index.d.ts.map +1 -1
- package/dist/adapters/mysql/prompts/index.js +8 -1
- package/dist/adapters/mysql/prompts/index.js.map +1 -1
- package/dist/adapters/mysql/prompts/routerSetup.d.ts.map +1 -1
- package/dist/adapters/mysql/prompts/routerSetup.js +5 -0
- package/dist/adapters/mysql/prompts/routerSetup.js.map +1 -1
- package/dist/adapters/mysql/resources/capabilities.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/capabilities.js +6 -5
- package/dist/adapters/mysql/resources/capabilities.js.map +1 -1
- package/dist/adapters/mysql/resources/index.d.ts +9 -1
- package/dist/adapters/mysql/resources/index.d.ts.map +1 -1
- package/dist/adapters/mysql/resources/index.js +9 -1
- package/dist/adapters/mysql/resources/index.js.map +1 -1
- package/dist/adapters/mysql/tools/admin/backup.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/admin/backup.js +3 -3
- package/dist/adapters/mysql/tools/admin/backup.js.map +1 -1
- package/dist/adapters/mysql/tools/admin/maintenance.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/admin/maintenance.js +5 -5
- package/dist/adapters/mysql/tools/admin/maintenance.js.map +1 -1
- package/dist/adapters/mysql/tools/cluster/innodb-cluster.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/cluster/innodb-cluster.js +26 -5
- package/dist/adapters/mysql/tools/cluster/innodb-cluster.js.map +1 -1
- package/dist/adapters/mysql/tools/codemode/index.d.ts +38 -0
- package/dist/adapters/mysql/tools/codemode/index.d.ts.map +1 -0
- package/dist/adapters/mysql/tools/codemode/index.js +203 -0
- package/dist/adapters/mysql/tools/codemode/index.js.map +1 -0
- package/dist/adapters/mysql/tools/core.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/core.js +32 -20
- package/dist/adapters/mysql/tools/core.js.map +1 -1
- package/dist/adapters/mysql/tools/events.js +18 -6
- package/dist/adapters/mysql/tools/events.js.map +1 -1
- package/dist/adapters/mysql/tools/json/core.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/json/core.js +5 -5
- package/dist/adapters/mysql/tools/json/core.js.map +1 -1
- package/dist/adapters/mysql/tools/json/helpers.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/json/helpers.js +9 -3
- package/dist/adapters/mysql/tools/json/helpers.js.map +1 -1
- package/dist/adapters/mysql/tools/partitioning.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/partitioning.js +38 -6
- package/dist/adapters/mysql/tools/partitioning.js.map +1 -1
- package/dist/adapters/mysql/tools/performance/analysis.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/performance/analysis.js +67 -20
- package/dist/adapters/mysql/tools/performance/analysis.js.map +1 -1
- package/dist/adapters/mysql/tools/performance/optimization.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/performance/optimization.js +36 -6
- package/dist/adapters/mysql/tools/performance/optimization.js.map +1 -1
- package/dist/adapters/mysql/tools/security/data-protection.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/security/data-protection.js +9 -4
- package/dist/adapters/mysql/tools/security/data-protection.js.map +1 -1
- package/dist/adapters/mysql/tools/shell/common.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/shell/common.js +28 -2
- package/dist/adapters/mysql/tools/shell/common.js.map +1 -1
- package/dist/adapters/mysql/tools/shell/restore.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/shell/restore.js +54 -4
- package/dist/adapters/mysql/tools/shell/restore.js.map +1 -1
- package/dist/adapters/mysql/tools/spatial/operations.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/spatial/operations.js +10 -2
- package/dist/adapters/mysql/tools/spatial/operations.js.map +1 -1
- package/dist/adapters/mysql/tools/spatial/setup.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/spatial/setup.js +18 -0
- package/dist/adapters/mysql/tools/spatial/setup.js.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/resources.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/sysschema/resources.js +5 -0
- package/dist/adapters/mysql/tools/sysschema/resources.js.map +1 -1
- package/dist/adapters/mysql/tools/text/fulltext.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/text/fulltext.js +6 -4
- package/dist/adapters/mysql/tools/text/fulltext.js.map +1 -1
- package/dist/adapters/mysql/tools/text/processing.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/text/processing.js +10 -45
- package/dist/adapters/mysql/tools/text/processing.js.map +1 -1
- package/dist/adapters/mysql/tools/transactions.d.ts.map +1 -1
- package/dist/adapters/mysql/tools/transactions.js +8 -8
- package/dist/adapters/mysql/tools/transactions.js.map +1 -1
- package/dist/adapters/mysql/types.d.ts +968 -78
- package/dist/adapters/mysql/types.d.ts.map +1 -1
- package/dist/adapters/mysql/types.js +1084 -78
- package/dist/adapters/mysql/types.js.map +1 -1
- package/dist/auth/scopes.d.ts.map +1 -1
- package/dist/auth/scopes.js +1 -0
- package/dist/auth/scopes.js.map +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +12 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/codemode/api.d.ts +69 -0
- package/dist/codemode/api.d.ts.map +1 -0
- package/dist/codemode/api.js +1035 -0
- package/dist/codemode/api.js.map +1 -0
- package/dist/codemode/index.d.ts +13 -0
- package/dist/codemode/index.d.ts.map +1 -0
- package/dist/codemode/index.js +17 -0
- package/dist/codemode/index.js.map +1 -0
- package/dist/codemode/sandbox-factory.d.ts +72 -0
- package/dist/codemode/sandbox-factory.d.ts.map +1 -0
- package/dist/codemode/sandbox-factory.js +88 -0
- package/dist/codemode/sandbox-factory.js.map +1 -0
- package/dist/codemode/sandbox.d.ts +96 -0
- package/dist/codemode/sandbox.d.ts.map +1 -0
- package/dist/codemode/sandbox.js +345 -0
- package/dist/codemode/sandbox.js.map +1 -0
- package/dist/codemode/security.d.ts +44 -0
- package/dist/codemode/security.d.ts.map +1 -0
- package/dist/codemode/security.js +149 -0
- package/dist/codemode/security.js.map +1 -0
- package/dist/codemode/types.d.ts +137 -0
- package/dist/codemode/types.d.ts.map +1 -0
- package/dist/codemode/types.js +46 -0
- package/dist/codemode/types.js.map +1 -0
- package/dist/codemode/worker-sandbox.d.ts +82 -0
- package/dist/codemode/worker-sandbox.d.ts.map +1 -0
- package/dist/codemode/worker-sandbox.js +244 -0
- package/dist/codemode/worker-sandbox.js.map +1 -0
- package/dist/codemode/worker-script.d.ts +8 -0
- package/dist/codemode/worker-script.d.ts.map +1 -0
- package/dist/codemode/worker-script.js +113 -0
- package/dist/codemode/worker-script.js.map +1 -0
- package/dist/constants/ServerInstructions.d.ts +1 -1
- package/dist/constants/ServerInstructions.d.ts.map +1 -1
- package/dist/constants/ServerInstructions.js +33 -9
- package/dist/constants/ServerInstructions.js.map +1 -1
- package/dist/filtering/ToolConstants.d.ts +11 -11
- package/dist/filtering/ToolConstants.d.ts.map +1 -1
- package/dist/filtering/ToolConstants.js +37 -19
- package/dist/filtering/ToolConstants.js.map +1 -1
- package/dist/filtering/ToolFilter.d.ts.map +1 -1
- package/dist/filtering/ToolFilter.js +12 -0
- package/dist/filtering/ToolFilter.js.map +1 -1
- package/dist/server/McpServer.js +1 -1
- package/dist/server/McpServer.js.map +1 -1
- package/dist/types/modules/server.d.ts +2 -0
- package/dist/types/modules/server.d.ts.map +1 -1
- package/dist/types/modules/tools.d.ts +1 -1
- package/dist/types/modules/tools.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/package.json +12 -7
- package/releases/v2.2.0-release-notes.md +18 -18
- package/releases/v2.3.0-release-notes.md +191 -0
- package/src/__tests__/perf.test.ts +12 -12
- package/src/adapters/mysql/MySQLAdapter.ts +10 -0
- package/src/adapters/mysql/__tests__/MySQLAdapter.test.ts +1 -1
- package/src/adapters/mysql/prompts/index.ts +8 -1
- package/src/adapters/mysql/prompts/routerSetup.ts +5 -0
- package/src/adapters/mysql/resources/__tests__/capabilities.test.ts +50 -1
- package/src/adapters/mysql/resources/capabilities.ts +6 -4
- package/src/adapters/mysql/resources/index.ts +9 -1
- package/src/adapters/mysql/tools/__tests__/core.test.ts +68 -0
- package/src/adapters/mysql/tools/__tests__/events.test.ts +56 -2
- package/src/adapters/mysql/tools/__tests__/json_core.test.ts +1 -1
- package/src/adapters/mysql/tools/__tests__/json_helpers.test.ts +46 -4
- package/src/adapters/mysql/tools/__tests__/replication.test.ts +144 -42
- package/src/adapters/mysql/tools/__tests__/security.test.ts +39 -0
- package/src/adapters/mysql/tools/__tests__/spatial.test.ts +39 -7
- package/src/adapters/mysql/tools/__tests__/spatial_handler.test.ts +35 -3
- package/src/adapters/mysql/tools/__tests__/transactions.test.ts +3 -5
- package/src/adapters/mysql/tools/admin/backup.ts +8 -3
- package/src/adapters/mysql/tools/admin/maintenance.ts +8 -4
- package/src/adapters/mysql/tools/cluster/__tests__/innodb-cluster.test.ts +35 -0
- package/src/adapters/mysql/tools/cluster/innodb-cluster.ts +26 -5
- package/src/adapters/mysql/tools/codemode/index.ts +249 -0
- package/src/adapters/mysql/tools/core.ts +44 -27
- package/src/adapters/mysql/tools/events.ts +23 -7
- package/src/adapters/mysql/tools/json/__tests__/helpers.test.ts +59 -14
- package/src/adapters/mysql/tools/json/core.ts +8 -4
- package/src/adapters/mysql/tools/json/helpers.ts +13 -3
- package/src/adapters/mysql/tools/partitioning.ts +53 -6
- package/src/adapters/mysql/tools/performance/__tests__/analysis.test.ts +227 -4
- package/src/adapters/mysql/tools/performance/__tests__/optimization.test.ts +35 -0
- package/src/adapters/mysql/tools/performance/analysis.ts +75 -21
- package/src/adapters/mysql/tools/performance/optimization.ts +44 -6
- package/src/adapters/mysql/tools/security/data-protection.ts +10 -4
- package/src/adapters/mysql/tools/shell/__tests__/common.test.ts +46 -0
- package/src/adapters/mysql/tools/shell/__tests__/restore.test.ts +28 -1
- package/src/adapters/mysql/tools/shell/common.ts +34 -2
- package/src/adapters/mysql/tools/shell/restore.ts +70 -7
- package/src/adapters/mysql/tools/spatial/__tests__/operations.test.ts +29 -0
- package/src/adapters/mysql/tools/spatial/operations.ts +13 -2
- package/src/adapters/mysql/tools/spatial/setup.ts +23 -0
- package/src/adapters/mysql/tools/sysschema/__tests__/resources.test.ts +21 -0
- package/src/adapters/mysql/tools/sysschema/resources.ts +5 -0
- package/src/adapters/mysql/tools/text/fulltext.ts +13 -5
- package/src/adapters/mysql/tools/text/processing.ts +20 -49
- package/src/adapters/mysql/tools/transactions.ts +11 -7
- package/src/adapters/mysql/types.ts +1241 -87
- package/src/auth/scopes.ts +1 -0
- package/src/cli/args.ts +14 -0
- package/src/codemode/api.ts +1224 -0
- package/src/codemode/index.ts +51 -0
- package/src/codemode/sandbox-factory.ts +146 -0
- package/src/codemode/sandbox.ts +450 -0
- package/src/codemode/security.ts +188 -0
- package/src/codemode/types.ts +194 -0
- package/src/codemode/worker-sandbox.ts +326 -0
- package/src/codemode/worker-script.ts +144 -0
- package/src/constants/ServerInstructions.ts +33 -9
- package/src/filtering/ToolConstants.ts +37 -19
- package/src/filtering/ToolFilter.ts +15 -0
- package/src/filtering/__tests__/ToolFilter.test.ts +65 -38
- package/src/server/McpServer.ts +1 -1
- package/src/types/modules/server.ts +3 -0
- package/src/types/modules/tools.ts +2 -1
- package/src/utils/logger.ts +2 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mysql-mcp - Code Mode Worker Script
|
|
3
|
+
*
|
|
4
|
+
* This script runs in a worker thread to execute user code in isolation.
|
|
5
|
+
* It uses Node.js vm module within the worker for additional sandboxing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
9
|
+
import vm from "node:vm";
|
|
10
|
+
|
|
11
|
+
interface WorkerData {
|
|
12
|
+
code: string;
|
|
13
|
+
apiBindings: Record<string, string[]>;
|
|
14
|
+
timeout: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface WorkerResult {
|
|
18
|
+
success: boolean;
|
|
19
|
+
result?: unknown;
|
|
20
|
+
error?: string | undefined;
|
|
21
|
+
stack?: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Execute code in a sandboxed vm context within the worker
|
|
26
|
+
*/
|
|
27
|
+
async function executeCode(): Promise<void> {
|
|
28
|
+
const { code, timeout } = workerData as WorkerData;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Create minimal sandbox context
|
|
32
|
+
const logBuffer: string[] = [];
|
|
33
|
+
const sandbox = {
|
|
34
|
+
console: {
|
|
35
|
+
log: (...args: unknown[]) => {
|
|
36
|
+
logBuffer.push(
|
|
37
|
+
args
|
|
38
|
+
.map((a) =>
|
|
39
|
+
typeof a === "object" && a !== null
|
|
40
|
+
? JSON.stringify(a)
|
|
41
|
+
: String(a),
|
|
42
|
+
)
|
|
43
|
+
.join(" "),
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
warn: (...args: unknown[]) =>
|
|
47
|
+
logBuffer.push("[WARN] " + args.map((a) => String(a)).join(" ")),
|
|
48
|
+
error: (...args: unknown[]) =>
|
|
49
|
+
logBuffer.push("[ERROR] " + args.map((a) => String(a)).join(" ")),
|
|
50
|
+
info: (...args: unknown[]) =>
|
|
51
|
+
logBuffer.push("[INFO] " + args.map((a) => String(a)).join(" ")),
|
|
52
|
+
},
|
|
53
|
+
// Block dangerous globals
|
|
54
|
+
require: undefined,
|
|
55
|
+
process: undefined,
|
|
56
|
+
global: undefined,
|
|
57
|
+
globalThis: undefined,
|
|
58
|
+
__dirname: undefined,
|
|
59
|
+
__filename: undefined,
|
|
60
|
+
module: undefined,
|
|
61
|
+
exports: undefined,
|
|
62
|
+
// Safe built-ins
|
|
63
|
+
JSON,
|
|
64
|
+
Math,
|
|
65
|
+
Date,
|
|
66
|
+
Array,
|
|
67
|
+
Object,
|
|
68
|
+
String,
|
|
69
|
+
Number,
|
|
70
|
+
Boolean,
|
|
71
|
+
Map,
|
|
72
|
+
Set,
|
|
73
|
+
Promise,
|
|
74
|
+
Error,
|
|
75
|
+
TypeError,
|
|
76
|
+
RangeError,
|
|
77
|
+
SyntaxError,
|
|
78
|
+
// Disabled for security
|
|
79
|
+
setTimeout: undefined,
|
|
80
|
+
setInterval: undefined,
|
|
81
|
+
setImmediate: undefined,
|
|
82
|
+
// mysql API placeholder (populated by main thread via message passing)
|
|
83
|
+
mysql: {},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const context = vm.createContext(sandbox);
|
|
87
|
+
|
|
88
|
+
// Wrap code in async IIFE to support await
|
|
89
|
+
const wrappedCode = `
|
|
90
|
+
(async () => {
|
|
91
|
+
${code}
|
|
92
|
+
})();
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
// Compile and run with timeout
|
|
96
|
+
const script = new vm.Script(wrappedCode, {
|
|
97
|
+
filename: "worker-codemode-script.js",
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const result = await (script.runInContext(context, {
|
|
101
|
+
timeout,
|
|
102
|
+
breakOnSigint: true,
|
|
103
|
+
}) as Promise<unknown>);
|
|
104
|
+
|
|
105
|
+
const response: WorkerResult = {
|
|
106
|
+
success: true,
|
|
107
|
+
result,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
parentPort?.postMessage(response);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
113
|
+
const stack = error instanceof Error ? error.stack : undefined;
|
|
114
|
+
|
|
115
|
+
// Check for timeout
|
|
116
|
+
if (errorMessage.includes("Script execution timed out")) {
|
|
117
|
+
const response: WorkerResult = {
|
|
118
|
+
success: false,
|
|
119
|
+
error: `Execution timeout: exceeded ${String(timeout)}ms limit`,
|
|
120
|
+
stack,
|
|
121
|
+
};
|
|
122
|
+
parentPort?.postMessage(response);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const response: WorkerResult = {
|
|
127
|
+
success: false,
|
|
128
|
+
error: errorMessage,
|
|
129
|
+
stack,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
parentPort?.postMessage(response);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Execute immediately
|
|
137
|
+
executeCode().catch((error: unknown) => {
|
|
138
|
+
const response: WorkerResult = {
|
|
139
|
+
success: false,
|
|
140
|
+
error: error instanceof Error ? error.message : String(error),
|
|
141
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
142
|
+
};
|
|
143
|
+
parentPort?.postMessage(response);
|
|
144
|
+
});
|
|
@@ -86,6 +86,7 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
86
86
|
|
|
87
87
|
- **Prepared statements**: \`mysql_read_query\` and \`mysql_write_query\` support parameterized queries via the \`params\` array. Use \`?\` placeholders: \`query: "SELECT * FROM users WHERE id = ?", params: [123]\`.
|
|
88
88
|
- **DDL statements**: DDL (e.g., \`CREATE TABLE\`, \`ALTER TABLE\`) is automatically handled via text protocol fallback in \`mysql_write_query\`.
|
|
89
|
+
- **Query error handling**: \`mysql_read_query\` and \`mysql_write_query\` return \`{ success: false, error }\` for all query errors (nonexistent table, syntax, permissions, etc.), instead of throwing raw errors.
|
|
89
90
|
- **Boolean defaults**: \`mysql_create_table\` auto-converts boolean \`default: true\` to \`1\` and \`default: false\` to \`0\` for MySQL compatibility. Alternatively, use \`TINYINT(1)\` with numeric defaults directly.
|
|
90
91
|
- **Existence checks**: \`mysql_describe_table\` and \`mysql_get_indexes\` return \`{ exists: false, table: "..." }\` gracefully when the table does not exist, avoiding raw SQL errors.
|
|
91
92
|
- **Create/Drop safety**: \`mysql_create_table\` returns \`{ success: false, reason }\` when the table already exists (without \`ifNotExists\`). \`mysql_drop_table\` returns \`{ success: false, reason }\` when the table does not exist (without \`ifExists\`). With \`ifExists: true\`, dropping a nonexistent table returns \`{ success: true, skipped: true, reason: "Table did not exist" }\`.
|
|
@@ -115,8 +116,8 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
115
116
|
- **Cluster status**: \`mysql_cluster_status\` returns cluster metadata. Use \`summary: true\` for condensed output without Router configuration schemas. Returns \`isInnoDBCluster: false\` if not in a cluster.
|
|
116
117
|
- **Instance list**: \`mysql_cluster_instances\` lists all configured instances with their current member state and role.
|
|
117
118
|
- **Topology**: \`mysql_cluster_topology\` returns a structured \`topology\` object (with \`primary\`, \`secondaries\`, \`recovering\`, \`offline\` arrays) and a \`visualization\` string grouping members by role.
|
|
118
|
-
- **Router status**: \`mysql_cluster_router_status\` lists registered routers from cluster metadata. Use \`summary: true\` to return
|
|
119
|
-
- **Switchover analysis**: \`mysql_cluster_switchover\` evaluates replication lag on secondaries and
|
|
119
|
+
- **Router status**: \`mysql_cluster_router_status\` lists registered routers from cluster metadata. Use \`summary: true\` to return routerId, routerName, address, version, lastCheckIn, roPort, rwPort, and localCluster. Each router includes \`isStale\` (true if lastCheckIn is null or >1 hour old). The response includes \`staleCount\` for quick filtering.
|
|
120
|
+
- **Switchover analysis**: \`mysql_cluster_switchover\` evaluates replication lag on secondaries and rates each as GOOD (fully synced), ACCEPTABLE (<100 pending), or NOT_RECOMMENDED (>=100 pending). Returns \`canSwitchover: false\` with a \`warning\` field if no viable candidates exist.
|
|
120
121
|
|
|
121
122
|
## MySQL Router Tools (\`mysql_router_*\`)
|
|
122
123
|
|
|
@@ -124,7 +125,7 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
124
125
|
- **Self-signed certificates**: Set \`MYSQL_ROUTER_INSECURE=true\` to bypass TLS certificate verification for development/testing environments.
|
|
125
126
|
- **Route names**: Use \`mysql_router_routes\` to list available routes (e.g., \`bootstrap_rw\`, \`bootstrap_ro\`).
|
|
126
127
|
- **Metadata cache**: The \`metadataName\` parameter is typically \`bootstrap\` for bootstrapped routers.
|
|
127
|
-
- **Connection pools**:
|
|
128
|
+
- **Connection pools**: \`mysql_router_pool_status\` requires the \`[rest_connection_pool]\` REST plugin AND \`connection_sharing=1\` on routes. Without these, the endpoint returns 404. When enabled, pool name is \`main\`.
|
|
128
129
|
- **Unavailability handling**: When Router REST API is unreachable, tools return \`{ available: false, reason: "..." }\` with descriptive error message instead of throwing.
|
|
129
130
|
|
|
130
131
|
## Partitioning Tools (\`mysql_partition_*\`, \`mysql_add_partition\`, \`mysql_drop_partition\`, \`mysql_reorganize_partition\`)
|
|
@@ -167,7 +168,7 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
167
168
|
|
|
168
169
|
- **EXPLAIN formats**: \`mysql_explain\` supports JSON (default), TREE, and TRADITIONAL formats.
|
|
169
170
|
- **EXPLAIN ANALYZE**: \`mysql_explain_analyze\` shows actual execution times (MySQL 8.0+). Only TREE format is supported; JSON format returns \`{ supported: false, reason }\`.
|
|
170
|
-
- **Performance schema**: \`mysql_slow_queries\`, \`mysql_query_stats\`, and \`mysql_index_usage\` require \`performance_schema\` enabled. \`mysql_slow_queries\` and \`mysql_query_stats\` truncate query digests to 200 characters for payload efficiency.
|
|
171
|
+
- **Performance schema**: \`mysql_slow_queries\`, \`mysql_query_stats\`, and \`mysql_index_usage\` require \`performance_schema\` enabled. \`mysql_slow_queries\` and \`mysql_query_stats\` truncate query digests to 200 characters for payload efficiency. Timer values exceeding 24 hours are clamped to \`-1\` with \`overflow: true\` on the row (indicates a \`performance_schema\` counter overflow artifact, not a real value).
|
|
171
172
|
- **Index usage**: \`mysql_index_usage\` filters to the current database by default. Use \`table\` parameter to filter further. Use \`limit\` (default: 10) to cap results. Returns \`{ exists: false, table }\` when the specified table does not exist.
|
|
172
173
|
- **Table stats**: \`mysql_table_stats\` returns \`{ exists: false, table: "..." }\` gracefully when the table does not exist.
|
|
173
174
|
- **Server-level tools**: \`mysql_slow_queries\`, \`mysql_query_stats\`, \`mysql_buffer_pool_stats\`, and \`mysql_thread_stats\` query server-level \`performance_schema\` metadata. They do not take a table parameter and return empty results when no data is available. No table existence checks apply.
|
|
@@ -234,8 +235,8 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
234
235
|
- **I/O analysis**: \`mysql_sys_io_summary\` supports \`table\` (default), \`file\`, and \`global\` types for I/O breakdown (default \`limit: 20\`).
|
|
235
236
|
- **Wait events**: \`mysql_sys_wait_summary\` supports \`global\` (default), \`by_host\`, \`by_user\`, and \`by_instance\` types for wait analysis. The \`by_instance\` type queries \`performance_schema\` directly (no sys view exists) and returns \`event\`, \`total\`, \`total_latency\`, and \`avg_latency\` columns with formatted latencies.
|
|
236
237
|
- **Lock contention**: \`mysql_sys_innodb_lock_waits\` shows active lock waits. Returns \`hasContention: false\` when none.
|
|
237
|
-
- **Memory usage**: \`mysql_sys_memory_summary\` returns \`globalMemory\` (by event type) and \`memoryByUser\` arrays. The \`limit\` parameter (default 10) applies to both arrays.
|
|
238
|
-
- **Schema stats**: \`mysql_sys_schema_stats\` returns 3 arrays: \`tableStatistics\` (DML and I/O per table), \`indexStatistics\` (per-index usage), and \`autoIncrementStatus\` (usage ratios). Filter by \`schema\` (defaults to current database). Returns \`{ exists: false, schema }\` when the specified schema does not exist. The \`limit\` parameter (default 10) applies per array.
|
|
238
|
+
- **Memory usage**: \`mysql_sys_memory_summary\` returns \`globalMemory\` (by event type) and \`memoryByUser\` arrays with corresponding \`globalMemoryCount\` and \`memoryByUserCount\` fields. The \`limit\` parameter (default 10) applies to both arrays.
|
|
239
|
+
- **Schema stats**: \`mysql_sys_schema_stats\` returns 3 arrays: \`tableStatistics\` (DML and I/O per table), \`indexStatistics\` (per-index usage), and \`autoIncrementStatus\` (usage ratios), each with a corresponding count field (\`tableStatisticsCount\`, \`indexStatisticsCount\`, \`autoIncrementStatusCount\`). Filter by \`schema\` (defaults to current database). Returns \`{ exists: false, schema }\` when the specified schema does not exist. The \`limit\` parameter (default 10) applies per array.
|
|
239
240
|
|
|
240
241
|
## Stats Tools (\`mysql_stats_*\`)
|
|
241
242
|
|
|
@@ -254,7 +255,7 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
254
255
|
- **SSL status**: \`mysql_security_ssl_status\` returns SSL/TLS connection status, cipher, certificate paths, and session statistics.
|
|
255
256
|
- **Encryption status**: \`mysql_security_encryption_status\` checks TDE availability, keyring plugins, encrypted tablespaces, and encryption settings.
|
|
256
257
|
- **Password validation**: \`mysql_security_password_validate\` uses MySQL \`validate_password\` component to check password strength (0-100 scale). Returns \`available: false\` if component not installed.
|
|
257
|
-
- **Data masking**: \`mysql_security_mask_data\` masks sensitive data. Types: \`email\` (preserves domain), \`phone\` (shows last 4), \`ssn\` (shows last 4), \`credit_card\` (shows first/last 4), \`partial\` (uses \`keepFirst\`/\`keepLast\`). Credit card masking requires
|
|
258
|
+
- **Data masking**: \`mysql_security_mask_data\` masks sensitive data. Types: \`email\` (preserves domain), \`phone\` (shows last 4), \`ssn\` (shows last 4), \`credit_card\` (shows first/last 4), \`partial\` (uses \`keepFirst\`/\`keepLast\`). Credit card masking requires more than 8 digits; values with 8 or fewer digits are fully masked with a \`warning\` field.
|
|
258
259
|
- **User privileges**: \`mysql_security_user_privileges\` returns comprehensive user privilege report. Filter with \`user\` parameter to reduce payload. Returns \`{ exists: false, user }\` for nonexistent users (P154). Use \`summary: true\` for condensed output (privilege counts instead of raw GRANT strings). Summary mode caps \`globalPrivileges\` at 10 entries and includes \`totalGlobalPrivileges\` for the full count.
|
|
259
260
|
- **Sensitive tables**: \`mysql_security_sensitive_tables\` identifies columns matching sensitive patterns (password, email, ssn, etc.). Use \`schema\` parameter to limit scope. Returns \`{ exists: false, schema }\` for nonexistent schemas (P154).
|
|
260
261
|
- **Enterprise features**: \`mysql_security_audit\`, \`mysql_security_firewall_status\`, \`mysql_security_firewall_rules\` report availability and suggest installation for MySQL Enterprise Edition.
|
|
@@ -275,15 +276,38 @@ const BASE_INSTRUCTIONS = `# mysql-mcp Usage Instructions
|
|
|
275
276
|
|
|
276
277
|
- **Prerequisites**: MySQL Shell must be installed and accessible via \`MYSQLSH_PATH\` environment variable or system PATH.
|
|
277
278
|
- **Version check**: \`mysqlsh_version\` verifies MySQL Shell availability before running other shell tools.
|
|
278
|
-
- **Upgrade checking**: \`mysqlsh_check_upgrade\` analyzes MySQL server for upgrade compatibility issues. Returns \`errorCount\`, \`warningCount\`, and \`noticeCount\` summary with full JSON report. **Note**: Returns \`{ success: false, error }\` when \`targetVersion\` is lower than the current server version (no downgrade analysis
|
|
279
|
+
- **Upgrade checking**: \`mysqlsh_check_upgrade\` analyzes MySQL server for upgrade compatibility issues. Returns \`errorCount\`, \`warningCount\`, and \`noticeCount\` summary with full JSON report. **Note**: Returns \`{ success: false, error }\` when MySQL Shell's version is lower than the current server version—Shell cannot analyze a server newer than itself. Also fails when \`targetVersion\` is lower than the current server version (no downgrade analysis).
|
|
279
280
|
- **Script execution**: \`mysqlsh_run_script\` supports JavaScript (\`js\`), Python (\`py\`), and SQL (\`sql\`) languages with full access to MySQL Shell APIs. SQL scripts support comments and multi-statement syntax.
|
|
280
281
|
- **Table export**: \`mysqlsh_export_table\` uses \`util.exportTable()\` for CSV or TSV export. Use \`where\` parameter for filtered exports. Returns structured error for privilege issues.
|
|
281
282
|
- **Parallel import**: \`mysqlsh_import_table\` uses \`util.importTable()\` for high-performance parallel import. **Important**: For CSV files, explicitly set \`fieldsTerminatedBy: ","\` as the delimiter is not auto-detected. Requires \`local_infile\` enabled on server (use \`updateServerSettings: true\` to auto-enable). Use \`skipRows: 1\` to skip header row. The \`columns\` parameter maps input fields **by position** to the specified table columns. **Note**: On InnoDB Cluster (Group Replication), target tables must have a PRIMARY KEY.
|
|
282
283
|
- **JSON import**: \`mysqlsh_import_json\` uses \`util.importJson()\` for document import. Supports both NDJSON (one JSON object per line) and multi-line JSON objects. **Does NOT support JSON arrays.** **Requires X Protocol (port 33060)**.
|
|
283
284
|
- **Dump utilities**: \`mysqlsh_dump_instance\`, \`mysqlsh_dump_schemas\`, \`mysqlsh_dump_tables\` create compressed parallel dumps. Use \`dryRun: true\` to preview. All dump tools return structured error messages for privilege issues with actionable guidance.
|
|
284
|
-
- **Load utility**: \`mysqlsh_load_dump\` restores dumps. Requires \`local_infile\` enabled or \`updateServerSettings: true\`. Returns \`{ success: false, error, hint }\` for duplicate object conflicts.
|
|
285
|
+
- **Load utility**: \`mysqlsh_load_dump\` restores dumps. Requires \`local_infile\` enabled or \`updateServerSettings: true\`. Use \`dryRun: true\` to preview what would be loaded without applying changes. Returns \`{ success: false, error, hint }\` for duplicate object conflicts.
|
|
285
286
|
- **Privilege note**: Dump operations may require EVENT, TRIGGER, or ROUTINE privileges. Use \`ddlOnly: true\` (schemas) or \`all: false\` (tables) to skip restricted metadata.
|
|
286
287
|
- **Error handling**: All shell tools return \`{ success: false, error }\` for operational failures instead of throwing raw exceptions. Privilege, local_infile, and X Protocol errors include a \`hint\` field with actionable remediation guidance.
|
|
288
|
+
|
|
289
|
+
## Parameter Aliases
|
|
290
|
+
|
|
291
|
+
Many tools accept **alternative parameter names** (aliases) for commonly used fields. The server normalizes these automatically—use whichever feels most natural:
|
|
292
|
+
|
|
293
|
+
- **Table name**: \`table\`, \`tableName\`, or \`name\` — accepted by Core tools (\`mysql_describe_table\`, \`mysql_get_indexes\`, \`mysql_drop_table\`, \`mysql_create_index\`), Text tools (\`mysql_like_search\`, \`mysql_regexp_match\`, \`mysql_soundex\`, \`mysql_substring\`, \`mysql_concat\`, \`mysql_collation_convert\`), Backup tools (\`mysql_export_table\`, \`mysql_import_data\`), Partitioning tools (\`mysql_partition_info\`, \`mysql_add_partition\`, \`mysql_drop_partition\`, \`mysql_reorganize_partition\`), Performance tools (\`mysql_table_stats\`, \`mysql_index_usage\`), and Admin tools (\`mysql_optimize_table\`, \`mysql_analyze_table\`, \`mysql_check_table\`, \`mysql_flush_tables\`).
|
|
294
|
+
- **Query/SQL**: \`query\` or \`sql\` — accepted by \`mysql_read_query\`, \`mysql_write_query\`, \`mysql_explain\`, \`mysql_explain_analyze\`, \`mysql_query_rewrite\`, and \`mysql_optimizer_trace\`.
|
|
295
|
+
- **WHERE clause**: \`where\` or \`filter\` — accepted by \`mysql_export_table\` and Text tools (\`mysql_like_search\`, \`mysql_regexp_match\`, \`mysql_soundex\`, \`mysql_substring\`, \`mysql_concat\`, \`mysql_collation_convert\`).
|
|
296
|
+
- **Column name**: \`column\` or \`col\` — accepted by Text tools (\`mysql_like_search\`, \`mysql_regexp_match\`, \`mysql_soundex\`, \`mysql_substring\`, \`mysql_collation_convert\`).
|
|
297
|
+
- **Admin tables array**: Admin maintenance tools accept a singular \`table\` (or \`tableName\`/\`name\`) as an alias for the \`tables\` array parameter, automatically wrapping it in an array.
|
|
298
|
+
|
|
299
|
+
## Code Mode (\`mysql_execute_code\`)
|
|
300
|
+
|
|
301
|
+
- **Purpose**: Execute JavaScript/TypeScript code in a sandboxed VM with access to all MySQL tools via the \`mysql.*\` API namespace. Ideal for multi-step workflows, data aggregation, conditional logic, and complex orchestrations that would otherwise require many sequential tool calls.
|
|
302
|
+
- **When to use**: Prefer Code Mode when a task requires 3+ sequential tool calls, conditional branching based on query results, data transformation between steps, or aggregation across multiple tables.
|
|
303
|
+
- **API namespace**: The \`mysql\` object exposes 24 groups matching the tool groups: \`mysql.core\`, \`mysql.json\`, \`mysql.transactions\`, \`mysql.text\`, \`mysql.fulltext\`, \`mysql.performance\`, \`mysql.optimization\`, \`mysql.admin\`, \`mysql.monitoring\`, \`mysql.backup\`, \`mysql.replication\`, \`mysql.partitioning\`, \`mysql.schema\`, \`mysql.shell\`, \`mysql.events\`, \`mysql.sysschema\`, \`mysql.stats\`, \`mysql.spatial\`, \`mysql.security\`, \`mysql.roles\`, \`mysql.docstore\`, \`mysql.cluster\`, \`mysql.proxysql\`, \`mysql.router\`.
|
|
304
|
+
- **Method naming**: Tool names map to methods by stripping the prefix: \`mysql_read_query\` → \`mysql.core.readQuery(sql)\`, \`mysql_json_extract\` → \`mysql.json.extract({...})\`, \`mysqlsh_version\` → \`mysql.shell.version()\`.
|
|
305
|
+
- **Positional shorthand**: Common tools accept positional arguments: \`mysql.core.readQuery("SELECT 1")\` instead of \`mysql.core.readQuery({ query: "SELECT 1" })\`.
|
|
306
|
+
- **Help**: Call \`mysql.help()\` for a full API overview, or \`mysql.<group>.help()\` for group-specific methods and examples.
|
|
307
|
+
- **Return value**: The last expression in the code block is returned as the result. Use \`return\` in async functions or let the final expression evaluate.
|
|
308
|
+
- **Security**: Code runs in an isolated VM sandbox. Blocked patterns include \`require\`, \`import\`, \`process\`, \`eval\`, \`Function\`, filesystem/network access. Rate-limited to prevent abuse.
|
|
309
|
+
- **Transaction cleanup**: Any transactions opened but not committed are automatically rolled back when execution completes.
|
|
310
|
+
- **Scope**: Requires \`admin\` scope.
|
|
287
311
|
`;
|
|
288
312
|
|
|
289
313
|
/**
|
|
@@ -253,6 +253,7 @@ export const TOOL_GROUPS: Record<ToolGroup, string[]> = {
|
|
|
253
253
|
"mysql_doc_create_index",
|
|
254
254
|
"mysql_doc_collection_info",
|
|
255
255
|
],
|
|
256
|
+
codemode: ["mysql_execute_code"],
|
|
256
257
|
};
|
|
257
258
|
|
|
258
259
|
/**
|
|
@@ -262,22 +263,22 @@ export const TOOL_GROUPS: Record<ToolGroup, string[]> = {
|
|
|
262
263
|
* STRICT LIMIT: NO group may exceed 50 tools.
|
|
263
264
|
*
|
|
264
265
|
* Tool counts (verified):
|
|
265
|
-
* starter:
|
|
266
|
-
* essential:
|
|
267
|
-
* dev-power:
|
|
268
|
-
* ai-data:
|
|
269
|
-
* ai-spatial:
|
|
270
|
-
* dba-monitor:
|
|
271
|
-
* dba-manage:
|
|
272
|
-
* dba-secure:
|
|
273
|
-
* base-core:
|
|
274
|
-
* base-advanced:
|
|
275
|
-
* ecosystem:
|
|
266
|
+
* starter: 39 (core:8 + json:17 + transactions:7 + text:6 + codemode:1)
|
|
267
|
+
* essential: 16 (core:8 + transactions:7 + codemode:1)
|
|
268
|
+
* dev-power: 47 (core:8 + schema:10 + performance:8 + stats:8 + fulltext:5 + transactions:7 + codemode:1)
|
|
269
|
+
* ai-data: 46 (core:8 + json:17 + docstore:9 + text:6 + fulltext:5 + codemode:1)
|
|
270
|
+
* ai-spatial: 44 (core:8 + spatial:12 + stats:8 + performance:8 + transactions:7 + codemode:1)
|
|
271
|
+
* dba-monitor: 36 (core:8 + monitoring:7 + performance:8 + sysschema:8 + optimization:4 + codemode:1)
|
|
272
|
+
* dba-manage: 34 (core:8 + admin:6 + backup:4 + replication:5 + partitioning:4 + events:6 + codemode:1)
|
|
273
|
+
* dba-secure: 33 (core:8 + security:9 + roles:8 + transactions:7 + codemode:1)
|
|
274
|
+
* base-core: 49 (core:8 + json:17 + transactions:7 + text:6 + schema:10 + codemode:1)
|
|
275
|
+
* base-advanced: 41 (docstore:9 + spatial:12 + stats:8 + fulltext:5 + events:6 + codemode:1)
|
|
276
|
+
* ecosystem: 42 (router:9 + proxysql:12 + shell:10 + cluster:10 + codemode:1)
|
|
276
277
|
*/
|
|
277
278
|
export const META_GROUPS: Record<MetaGroup, ToolGroup[]> = {
|
|
278
279
|
// 1. General Use
|
|
279
|
-
starter: ["core", "json", "transactions", "text"],
|
|
280
|
-
essential: ["core", "transactions"],
|
|
280
|
+
starter: ["core", "json", "transactions", "text", "codemode"],
|
|
281
|
+
essential: ["core", "transactions", "codemode"],
|
|
281
282
|
"dev-power": [
|
|
282
283
|
"core",
|
|
283
284
|
"schema",
|
|
@@ -285,11 +286,19 @@ export const META_GROUPS: Record<MetaGroup, ToolGroup[]> = {
|
|
|
285
286
|
"stats",
|
|
286
287
|
"fulltext",
|
|
287
288
|
"transactions",
|
|
289
|
+
"codemode",
|
|
288
290
|
],
|
|
289
291
|
|
|
290
292
|
// 2. AI Workloads
|
|
291
|
-
"ai-data": ["core", "json", "docstore", "text", "fulltext"],
|
|
292
|
-
"ai-spatial": [
|
|
293
|
+
"ai-data": ["core", "json", "docstore", "text", "fulltext", "codemode"],
|
|
294
|
+
"ai-spatial": [
|
|
295
|
+
"core",
|
|
296
|
+
"spatial",
|
|
297
|
+
"stats",
|
|
298
|
+
"performance",
|
|
299
|
+
"transactions",
|
|
300
|
+
"codemode",
|
|
301
|
+
],
|
|
293
302
|
|
|
294
303
|
// 3. DBA Workloads
|
|
295
304
|
"dba-monitor": [
|
|
@@ -298,6 +307,7 @@ export const META_GROUPS: Record<MetaGroup, ToolGroup[]> = {
|
|
|
298
307
|
"performance",
|
|
299
308
|
"sysschema",
|
|
300
309
|
"optimization",
|
|
310
|
+
"codemode",
|
|
301
311
|
],
|
|
302
312
|
"dba-manage": [
|
|
303
313
|
"core",
|
|
@@ -306,13 +316,21 @@ export const META_GROUPS: Record<MetaGroup, ToolGroup[]> = {
|
|
|
306
316
|
"replication",
|
|
307
317
|
"partitioning",
|
|
308
318
|
"events",
|
|
319
|
+
"codemode",
|
|
309
320
|
],
|
|
310
|
-
"dba-secure": ["core", "security", "roles", "transactions"],
|
|
321
|
+
"dba-secure": ["core", "security", "roles", "transactions", "codemode"],
|
|
311
322
|
|
|
312
323
|
// 4. Base Blocks (Building Blocks)
|
|
313
|
-
"base-core": ["core", "json", "transactions", "text", "schema"],
|
|
314
|
-
"base-advanced": [
|
|
324
|
+
"base-core": ["core", "json", "transactions", "text", "schema", "codemode"],
|
|
325
|
+
"base-advanced": [
|
|
326
|
+
"docstore",
|
|
327
|
+
"spatial",
|
|
328
|
+
"stats",
|
|
329
|
+
"fulltext",
|
|
330
|
+
"events",
|
|
331
|
+
"codemode",
|
|
332
|
+
],
|
|
315
333
|
|
|
316
334
|
// 5. Ecosystem
|
|
317
|
-
ecosystem: ["router", "proxysql", "shell", "cluster"],
|
|
335
|
+
ecosystem: ["router", "proxysql", "shell", "cluster", "codemode"],
|
|
318
336
|
};
|
|
@@ -230,6 +230,21 @@ export function parseToolFilter(
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
// Auto-inject codemode tools (mysql_execute_code) in whitelist mode only.
|
|
234
|
+
// In blacklist mode (starts with -), codemode is already in the initial set
|
|
235
|
+
// and user exclusions are respected. In whitelist mode, raw group filters
|
|
236
|
+
// (e.g., "core") would otherwise miss codemode — every meta-group includes it.
|
|
237
|
+
if (!startsWithExclude && enabledTools.size > 0) {
|
|
238
|
+
const codemodeExplicitlyExcluded = parts.some(
|
|
239
|
+
(p) => p === "-codemode" || p === "-mysql_execute_code",
|
|
240
|
+
);
|
|
241
|
+
if (!codemodeExplicitlyExcluded) {
|
|
242
|
+
for (const tool of TOOL_GROUPS.codemode) {
|
|
243
|
+
enabledTools.add(tool);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
233
248
|
return {
|
|
234
249
|
raw: filterString,
|
|
235
250
|
rules,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
import type { ToolDefinition } from "../../types/index.js";
|
|
24
24
|
|
|
25
25
|
describe("TOOL_GROUPS", () => {
|
|
26
|
-
it("should contain all
|
|
26
|
+
it("should contain all 25 tool groups", () => {
|
|
27
27
|
const expectedGroups = [
|
|
28
28
|
"core",
|
|
29
29
|
"json",
|
|
@@ -49,9 +49,10 @@ describe("TOOL_GROUPS", () => {
|
|
|
49
49
|
"cluster",
|
|
50
50
|
"roles",
|
|
51
51
|
"docstore",
|
|
52
|
+
"codemode",
|
|
52
53
|
];
|
|
53
54
|
|
|
54
|
-
expect(Object.keys(TOOL_GROUPS)).toHaveLength(
|
|
55
|
+
expect(Object.keys(TOOL_GROUPS)).toHaveLength(25);
|
|
55
56
|
for (const group of expectedGroups) {
|
|
56
57
|
expect(TOOL_GROUPS).toHaveProperty(group);
|
|
57
58
|
}
|
|
@@ -82,11 +83,12 @@ describe("TOOL_GROUPS", () => {
|
|
|
82
83
|
expect(TOOL_GROUPS.cluster).toHaveLength(10);
|
|
83
84
|
expect(TOOL_GROUPS.roles).toHaveLength(8);
|
|
84
85
|
expect(TOOL_GROUPS.docstore).toHaveLength(9);
|
|
86
|
+
expect(TOOL_GROUPS.codemode).toHaveLength(1);
|
|
85
87
|
});
|
|
86
88
|
|
|
87
|
-
it("should total
|
|
89
|
+
it("should total 193 tools across all groups", () => {
|
|
88
90
|
const totalTools = Object.values(TOOL_GROUPS).flat().length;
|
|
89
|
-
expect(totalTools).toBe(
|
|
91
|
+
expect(totalTools).toBe(193);
|
|
90
92
|
});
|
|
91
93
|
});
|
|
92
94
|
|
|
@@ -128,9 +130,9 @@ describe("META_GROUPS", () => {
|
|
|
128
130
|
});
|
|
129
131
|
|
|
130
132
|
describe("getAllToolNames", () => {
|
|
131
|
-
it("should return all
|
|
133
|
+
it("should return all 193 tool names", () => {
|
|
132
134
|
const tools = getAllToolNames();
|
|
133
|
-
expect(tools).toHaveLength(
|
|
135
|
+
expect(tools).toHaveLength(193);
|
|
134
136
|
});
|
|
135
137
|
|
|
136
138
|
it("should return unique tool names", () => {
|
|
@@ -168,81 +170,81 @@ describe("getToolGroup", () => {
|
|
|
168
170
|
describe("getMetaGroupTools", () => {
|
|
169
171
|
it("should return all tools for starter meta-group", () => {
|
|
170
172
|
const tools = getMetaGroupTools("starter");
|
|
171
|
-
// starter = core(8) + json(17) + transactions(7) + text(6) =
|
|
172
|
-
expect(tools).toHaveLength(
|
|
173
|
+
// starter = core(8) + json(17) + transactions(7) + text(6) + codemode(1) = 39
|
|
174
|
+
expect(tools).toHaveLength(39);
|
|
173
175
|
});
|
|
174
176
|
|
|
175
177
|
it("should return all tools for essential meta-group", () => {
|
|
176
178
|
const tools = getMetaGroupTools("essential");
|
|
177
|
-
// essential = core(8) + transactions(7) =
|
|
178
|
-
expect(tools).toHaveLength(
|
|
179
|
+
// essential = core(8) + transactions(7) + codemode(1) = 16
|
|
180
|
+
expect(tools).toHaveLength(16);
|
|
179
181
|
});
|
|
180
182
|
|
|
181
183
|
it("should return all tools for ecosystem meta-group", () => {
|
|
182
184
|
const tools = getMetaGroupTools("ecosystem");
|
|
183
|
-
// ecosystem = router(9) + proxysql(12) + shell(10) + cluster(10) =
|
|
184
|
-
expect(tools).toHaveLength(
|
|
185
|
+
// ecosystem = router(9) + proxysql(12) + shell(10) + cluster(10) + codemode(1) = 42
|
|
186
|
+
expect(tools).toHaveLength(42);
|
|
185
187
|
});
|
|
186
188
|
|
|
187
189
|
it("should return correct tools for base-core meta-group", () => {
|
|
188
190
|
const tools = getMetaGroupTools("base-core");
|
|
189
|
-
// base-core = core(8) + json(17) + transactions(7) + text(6) + schema(10) =
|
|
190
|
-
expect(tools).toHaveLength(
|
|
191
|
+
// base-core = core(8) + json(17) + transactions(7) + text(6) + schema(10) + codemode(1) = 49
|
|
192
|
+
expect(tools).toHaveLength(49);
|
|
191
193
|
});
|
|
192
194
|
|
|
193
195
|
it("should return correct tools for base-advanced meta-group", () => {
|
|
194
196
|
const tools = getMetaGroupTools("base-advanced");
|
|
195
|
-
// base-advanced = docstore(9) + spatial(12) + stats(8) + fulltext(5) + events(6) =
|
|
196
|
-
expect(tools).toHaveLength(
|
|
197
|
+
// base-advanced = docstore(9) + spatial(12) + stats(8) + fulltext(5) + events(6) + codemode(1) = 41
|
|
198
|
+
expect(tools).toHaveLength(41);
|
|
197
199
|
});
|
|
198
200
|
|
|
199
201
|
it("should return correct tools for dba-monitor meta-group", () => {
|
|
200
202
|
const tools = getMetaGroupTools("dba-monitor");
|
|
201
|
-
expect(tools).toHaveLength(
|
|
203
|
+
expect(tools).toHaveLength(36);
|
|
202
204
|
});
|
|
203
205
|
|
|
204
206
|
it("should return correct tools for dba-manage meta-group", () => {
|
|
205
207
|
const tools = getMetaGroupTools("dba-manage");
|
|
206
|
-
expect(tools).toHaveLength(
|
|
208
|
+
expect(tools).toHaveLength(34);
|
|
207
209
|
});
|
|
208
210
|
|
|
209
211
|
it("should return correct tools for dba-secure meta-group", () => {
|
|
210
212
|
const tools = getMetaGroupTools("dba-secure");
|
|
211
|
-
expect(tools).toHaveLength(
|
|
213
|
+
expect(tools).toHaveLength(33);
|
|
212
214
|
});
|
|
213
215
|
});
|
|
214
216
|
|
|
215
217
|
describe("parseToolFilter", () => {
|
|
216
|
-
it("should return starter tools (
|
|
218
|
+
it("should return starter tools (39) enabled for empty filter", () => {
|
|
217
219
|
const config = parseToolFilter("");
|
|
218
|
-
expect(config.enabledTools.size).toBe(
|
|
220
|
+
expect(config.enabledTools.size).toBe(39);
|
|
219
221
|
expect(config.rules).toHaveLength(0);
|
|
220
222
|
expect(config.enabledTools.has("mysql_read_query")).toBe(true);
|
|
221
223
|
});
|
|
222
224
|
|
|
223
|
-
it("should return starter tools (
|
|
225
|
+
it("should return starter tools (39) enabled for undefined filter", () => {
|
|
224
226
|
const config = parseToolFilter(undefined);
|
|
225
|
-
expect(config.enabledTools.size).toBe(
|
|
227
|
+
expect(config.enabledTools.size).toBe(39);
|
|
226
228
|
expect(config.rules).toHaveLength(0);
|
|
227
229
|
});
|
|
228
230
|
|
|
229
231
|
it("should disable a single tool", () => {
|
|
230
232
|
const config = parseToolFilter("-mysql_read_query");
|
|
231
|
-
expect(config.enabledTools.size).toBe(
|
|
233
|
+
expect(config.enabledTools.size).toBe(192);
|
|
232
234
|
expect(config.enabledTools.has("mysql_read_query")).toBe(false);
|
|
233
235
|
expect(config.enabledTools.has("mysql_write_query")).toBe(true);
|
|
234
236
|
});
|
|
235
237
|
|
|
236
238
|
it("should disable a tool group", () => {
|
|
237
239
|
const config = parseToolFilter("-core");
|
|
238
|
-
expect(config.enabledTools.size).toBe(
|
|
240
|
+
expect(config.enabledTools.size).toBe(185); // 193 - 8
|
|
239
241
|
expect(config.enabledTools.has("mysql_read_query")).toBe(false);
|
|
240
242
|
expect(config.enabledTools.has("mysql_json_extract")).toBe(true);
|
|
241
243
|
});
|
|
242
244
|
|
|
243
245
|
it("should disable a meta-group", () => {
|
|
244
246
|
const config = parseToolFilter("-ecosystem");
|
|
245
|
-
expect(config.enabledTools.size).toBe(151); //
|
|
247
|
+
expect(config.enabledTools.size).toBe(151); // 193 - 42
|
|
246
248
|
expect(config.enabledTools.has("mysql_router_status")).toBe(false);
|
|
247
249
|
expect(config.enabledTools.has("proxysql_status")).toBe(false);
|
|
248
250
|
expect(config.enabledTools.has("mysqlsh_version")).toBe(false);
|
|
@@ -258,18 +260,18 @@ describe("parseToolFilter", () => {
|
|
|
258
260
|
it("should handle complex filter chains", () => {
|
|
259
261
|
// Disable all, then enable starter
|
|
260
262
|
const config = parseToolFilter("starter");
|
|
261
|
-
expect(config.enabledTools.size).toBe(
|
|
263
|
+
expect(config.enabledTools.size).toBe(39); // starter has 39 tools
|
|
262
264
|
});
|
|
263
265
|
|
|
264
266
|
it("should handle explicit whitelist syntax (+group)", () => {
|
|
265
267
|
const config = parseToolFilter("+starter");
|
|
266
|
-
expect(config.enabledTools.size).toBe(
|
|
268
|
+
expect(config.enabledTools.size).toBe(39);
|
|
267
269
|
});
|
|
268
270
|
|
|
269
271
|
it("should handle whitelist with exclusion (starter,-json)", () => {
|
|
270
|
-
// starter(
|
|
272
|
+
// starter(39) - json(17) = 22
|
|
271
273
|
const config = parseToolFilter("starter,-json");
|
|
272
|
-
expect(config.enabledTools.size).toBe(
|
|
274
|
+
expect(config.enabledTools.size).toBe(22);
|
|
273
275
|
});
|
|
274
276
|
|
|
275
277
|
it("should process rules left-to-right", () => {
|
|
@@ -278,7 +280,7 @@ describe("parseToolFilter", () => {
|
|
|
278
280
|
const config1 = parseToolFilter("+core,-mysql_read_query");
|
|
279
281
|
expect(config1.enabledTools.has("mysql_read_query")).toBe(false);
|
|
280
282
|
expect(config1.enabledTools.has("mysql_write_query")).toBe(true);
|
|
281
|
-
expect(config1.enabledTools.size).toBe(
|
|
283
|
+
expect(config1.enabledTools.size).toBe(8); // core(8) - 1 + codemode(1) = 8
|
|
282
284
|
});
|
|
283
285
|
|
|
284
286
|
it("should handle whitespace in filter string", () => {
|
|
@@ -286,6 +288,31 @@ describe("parseToolFilter", () => {
|
|
|
286
288
|
expect(config.enabledTools.has("mysql_read_query")).toBe(true);
|
|
287
289
|
expect(config.enabledTools.has("mysql_write_query")).toBe(false);
|
|
288
290
|
});
|
|
291
|
+
|
|
292
|
+
// Codemode auto-injection tests
|
|
293
|
+
it("should auto-inject codemode when using a raw group filter", () => {
|
|
294
|
+
const config = parseToolFilter("core");
|
|
295
|
+
expect(config.enabledTools.has("mysql_execute_code")).toBe(true);
|
|
296
|
+
expect(config.enabledTools.size).toBe(9); // core(8) + codemode(1)
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it("should not inject codemode when explicitly excluded with -codemode", () => {
|
|
300
|
+
const config = parseToolFilter("core,-codemode");
|
|
301
|
+
expect(config.enabledTools.has("mysql_execute_code")).toBe(false);
|
|
302
|
+
expect(config.enabledTools.size).toBe(8); // core(8) only
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("should not inject codemode when mysql_execute_code explicitly excluded", () => {
|
|
306
|
+
const config = parseToolFilter("core,-mysql_execute_code");
|
|
307
|
+
expect(config.enabledTools.has("mysql_execute_code")).toBe(false);
|
|
308
|
+
expect(config.enabledTools.size).toBe(8); // core(8) only
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it("should not inject codemode when all tools are excluded", () => {
|
|
312
|
+
const config = parseToolFilter("-all");
|
|
313
|
+
expect(config.enabledTools.size).toBe(0);
|
|
314
|
+
expect(config.enabledTools.has("mysql_execute_code")).toBe(false);
|
|
315
|
+
});
|
|
289
316
|
});
|
|
290
317
|
|
|
291
318
|
describe("isToolEnabled", () => {
|
|
@@ -355,14 +382,14 @@ describe("filterTools", () => {
|
|
|
355
382
|
|
|
356
383
|
describe("calculateTokenSavings", () => {
|
|
357
384
|
it("should calculate correct savings", () => {
|
|
358
|
-
const result = calculateTokenSavings(
|
|
359
|
-
// (
|
|
385
|
+
const result = calculateTokenSavings(192, 39);
|
|
386
|
+
// (192 - 39) * 200 = 30600 tokens
|
|
360
387
|
expect(result.tokensSaved).toBe(30600);
|
|
361
388
|
expect(result.percentSaved).toBe(80); // ~80% disabled
|
|
362
389
|
});
|
|
363
390
|
|
|
364
391
|
it("should return 0 for no filtering", () => {
|
|
365
|
-
const result = calculateTokenSavings(
|
|
392
|
+
const result = calculateTokenSavings(192, 192);
|
|
366
393
|
expect(result.tokensSaved).toBe(0);
|
|
367
394
|
expect(result.percentSaved).toBe(0);
|
|
368
395
|
});
|
|
@@ -384,7 +411,7 @@ describe("getFilterSummary", () => {
|
|
|
384
411
|
it("should generate summary for no filter", () => {
|
|
385
412
|
const config = parseToolFilter("");
|
|
386
413
|
const summary = getFilterSummary(config);
|
|
387
|
-
expect(summary).toContain("
|
|
414
|
+
expect(summary).toContain("39/193 tools");
|
|
388
415
|
expect(summary).toContain("Token savings");
|
|
389
416
|
});
|
|
390
417
|
|
|
@@ -416,9 +443,9 @@ describe("getFilterSummary", () => {
|
|
|
416
443
|
});
|
|
417
444
|
|
|
418
445
|
describe("getToolGroupInfo", () => {
|
|
419
|
-
it("should return info for all
|
|
446
|
+
it("should return info for all 25 groups", () => {
|
|
420
447
|
const info = getToolGroupInfo();
|
|
421
|
-
expect(info).toHaveLength(
|
|
448
|
+
expect(info).toHaveLength(25);
|
|
422
449
|
});
|
|
423
450
|
|
|
424
451
|
it("should include correct counts", () => {
|
|
@@ -440,7 +467,7 @@ describe("getMetaGroupInfo", () => {
|
|
|
440
467
|
const info = getMetaGroupInfo();
|
|
441
468
|
const starterInfo = info.find((g) => g.metaGroup === "starter");
|
|
442
469
|
expect(starterInfo).toBeDefined();
|
|
443
|
-
expect(starterInfo?.count).toBe(
|
|
470
|
+
expect(starterInfo?.count).toBe(39);
|
|
444
471
|
expect(starterInfo?.groups).toContain("core");
|
|
445
472
|
});
|
|
446
473
|
});
|
package/src/server/McpServer.ts
CHANGED
|
@@ -182,7 +182,7 @@ export class McpServer {
|
|
|
182
182
|
const transport = createHttpTransport(
|
|
183
183
|
{
|
|
184
184
|
port,
|
|
185
|
-
host: "localhost",
|
|
185
|
+
host: this.config.host ?? "localhost",
|
|
186
186
|
corsOrigins: ["*"], // Allow all for now, or make configurable
|
|
187
187
|
// Pass OAuth config if enabled
|
|
188
188
|
...(this.config.oauth?.enabled
|