@achmadya-dev/mcp-mysql-query 0.2.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +14 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/mysql/config.d.ts +14 -0
  8. package/dist/mysql/config.d.ts.map +1 -0
  9. package/dist/mysql/config.js +14 -0
  10. package/dist/mysql/config.js.map +1 -0
  11. package/dist/mysql/helpers.d.ts +17 -0
  12. package/dist/mysql/helpers.d.ts.map +1 -0
  13. package/dist/mysql/helpers.js +193 -0
  14. package/dist/mysql/helpers.js.map +1 -0
  15. package/dist/mysql/mysql.d.ts +16 -0
  16. package/dist/mysql/mysql.d.ts.map +1 -0
  17. package/dist/mysql/mysql.js +55 -0
  18. package/dist/mysql/mysql.js.map +1 -0
  19. package/dist/mysql/schema.d.ts +33 -0
  20. package/dist/mysql/schema.d.ts.map +1 -0
  21. package/dist/mysql/schema.js +36 -0
  22. package/dist/mysql/schema.js.map +1 -0
  23. package/dist/tools/mysql_ddl.d.ts +2 -0
  24. package/dist/tools/mysql_ddl.d.ts.map +1 -0
  25. package/dist/tools/mysql_ddl.js +31 -0
  26. package/dist/tools/mysql_ddl.js.map +1 -0
  27. package/dist/tools/mysql_delete.d.ts +2 -0
  28. package/dist/tools/mysql_delete.d.ts.map +1 -0
  29. package/dist/tools/mysql_delete.js +23 -0
  30. package/dist/tools/mysql_delete.js.map +1 -0
  31. package/dist/tools/mysql_insert.d.ts +2 -0
  32. package/dist/tools/mysql_insert.d.ts.map +1 -0
  33. package/dist/tools/mysql_insert.js +23 -0
  34. package/dist/tools/mysql_insert.js.map +1 -0
  35. package/dist/tools/mysql_select.d.ts +2 -0
  36. package/dist/tools/mysql_select.d.ts.map +1 -0
  37. package/dist/tools/mysql_select.js +19 -0
  38. package/dist/tools/mysql_select.js.map +1 -0
  39. package/dist/tools/mysql_update.d.ts +2 -0
  40. package/dist/tools/mysql_update.d.ts.map +1 -0
  41. package/dist/tools/mysql_update.js +23 -0
  42. package/dist/tools/mysql_update.js.map +1 -0
  43. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 achmadya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @achmadya-dev/mcp-mysql-query
2
+
3
+ MCP server for MySQL. Runs a single SQL statement per tool call over **stdio**. **Read-only by default** — writes and DDL require explicit env flags.
4
+
5
+ ## Requirements
6
+
7
+ - Node.js **≥ 20**
8
+ - A reachable MySQL server (local, Docker, or remote)
9
+
10
+ ## Install from npm
11
+
12
+ Add to Cursor **Settings → MCP** or `.cursor/mcp.json`:
13
+
14
+ ```json
15
+ {
16
+ "mcpServers": {
17
+ "mysql": {
18
+ "command": "npx",
19
+ "args": ["-y", "@achmadya-dev/mcp-mysql-query"],
20
+ "env": {
21
+ "MYSQL_HOST": "localhost",
22
+ "MYSQL_PORT": "3306",
23
+ "MYSQL_USER": "your_user",
24
+ "MYSQL_PASSWORD": "your_password",
25
+ "MYSQL_DATABASE": "your_database"
26
+ }
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ Or load credentials from a file (Cursor `envFile`):
33
+
34
+ ```json
35
+ {
36
+ "mcpServers": {
37
+ "mysql": {
38
+ "command": "npx",
39
+ "args": ["-y", "@achmadya-dev/mcp-mysql-query"],
40
+ "envFile": "/absolute/path/to/.env"
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Develop from source
47
+
48
+ From the repository root ([`achmadya-dev/mcp`](https://github.com/achmadya-dev/mcp)):
49
+
50
+ ```bash
51
+ cp .env.example .env
52
+ pnpm install
53
+ docker compose up -d mysql
54
+ pnpm --filter @achmadya-dev/mcp-mysql-query run build
55
+ ```
56
+
57
+ Register the built server in `.cursor/mcp.json`:
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "mysql": {
63
+ "command": "node",
64
+ "args": ["${workspaceFolder}/packages/mcp-mysql-query/dist/index.js"],
65
+ "envFile": "${workspaceFolder}/.env"
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ Relevant `.env` keys (defaults match `docker-compose.yml`):
72
+
73
+ ```env
74
+ MYSQL_HOST=localhost
75
+ MYSQL_PORT=3306
76
+ MYSQL_USER=dev
77
+ MYSQL_PASSWORD=devpassword
78
+ MYSQL_DATABASE=devdb
79
+ ```
80
+
81
+ ## Environment variables
82
+
83
+ ### Connection
84
+
85
+ | Variable | Default | Description |
86
+ | ---------------- | ------------ | ------------------------------- |
87
+ | `MYSQL_HOST` | `localhost` | MySQL host |
88
+ | `MYSQL_PORT` | `3306` | Port |
89
+ | `MYSQL_USER` | _(empty)_ | Username |
90
+ | `MYSQL_PASSWORD` | _(empty)_ | Password |
91
+ | `MYSQL_DATABASE` | _(optional)_ | Database selected after connect |
92
+ | `MYSQL_MAX_ROWS` | `500` | Max rows returned for `SELECT` |
93
+
94
+ ### Write access
95
+
96
+ Enabled when the value is `true`, `1`, `yes`, or `on` (case-insensitive). If unset, that operation type is **rejected**.
97
+
98
+ | Variable | Allows |
99
+ | ------------------------ | ---------------------------------- |
100
+ | `ALLOW_INSERT_OPERATION` | `INSERT`, `REPLACE` |
101
+ | `ALLOW_UPDATE_OPERATION` | `UPDATE` |
102
+ | `ALLOW_DELETE_OPERATION` | `DELETE` |
103
+ | `ALLOW_DDL_OPERATION` | DDL (`CREATE`, `ALTER`, `DROP`, …) |
104
+
105
+ ## Tools
106
+
107
+ | Tool | Statements | Env flag |
108
+ | -------------- | ----------------------------------------------- | ------------------------ |
109
+ | `mysql_select` | `SELECT`, `SHOW`, `DESCRIBE`, `EXPLAIN`, `DESC` | always on |
110
+ | `mysql_insert` | `INSERT`, `REPLACE` | `ALLOW_INSERT_OPERATION` |
111
+ | `mysql_update` | `UPDATE` | `ALLOW_UPDATE_OPERATION` |
112
+ | `mysql_delete` | `DELETE` | `ALLOW_DELETE_OPERATION` |
113
+ | `mysql_ddl` | DDL | `ALLOW_DDL_OPERATION` |
114
+
115
+ Each tool accepts one `sql` string. Results are JSON text; `SELECT` output is capped by `MYSQL_MAX_ROWS`.
116
+
117
+ ## Behavior and security
118
+
119
+ - One SQL statement per request (no `;`-separated batches).
120
+ - Dangerous patterns are blocked regardless of flags.
121
+ - Read operations are always permitted.
122
+
123
+ ## Package scripts
124
+
125
+ ```bash
126
+ pnpm run build
127
+ pnpm test
128
+ pnpm start
129
+ ```
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { startMcpServer } from "@achmadya-dev/mcp-core";
3
+ import packageJson from "../package.json" with { type: "json" };
4
+ import { mysql_ddl } from "./tools/mysql_ddl.js";
5
+ import { mysql_delete } from "./tools/mysql_delete.js";
6
+ import { mysql_insert } from "./tools/mysql_insert.js";
7
+ import { mysql_select } from "./tools/mysql_select.js";
8
+ import { mysql_update } from "./tools/mysql_update.js";
9
+ await startMcpServer({
10
+ name: "MySQL Database",
11
+ version: packageJson.version,
12
+ tools: [mysql_select, mysql_insert, mysql_update, mysql_delete, mysql_ddl],
13
+ });
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,MAAM,cAAc,CAAC;IACnB,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,WAAW,CAAC,OAAO;IAC5B,KAAK,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC;CAC3E,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ declare const _default: {
2
+ host: string;
3
+ port: number;
4
+ user: string;
5
+ password: string;
6
+ database: string | undefined;
7
+ maxRows: number;
8
+ allowInsert: boolean;
9
+ allowUpdate: boolean;
10
+ allowDelete: boolean;
11
+ allowDdl: boolean;
12
+ };
13
+ export default _default;
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/mysql/config.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,wBAWE"}
@@ -0,0 +1,14 @@
1
+ import { envBool, envInt, envStr } from "@achmadya-dev/mcp-core";
2
+ export default {
3
+ host: envStr("MYSQL_HOST", "localhost"),
4
+ port: envInt("MYSQL_PORT", 3306),
5
+ user: envStr("MYSQL_USER"),
6
+ password: envStr("MYSQL_PASSWORD", ""),
7
+ database: envStr("MYSQL_DATABASE") || undefined,
8
+ maxRows: envInt("MYSQL_MAX_ROWS", 500),
9
+ allowInsert: envBool("ALLOW_INSERT_OPERATION"),
10
+ allowUpdate: envBool("ALLOW_UPDATE_OPERATION"),
11
+ allowDelete: envBool("ALLOW_DELETE_OPERATION"),
12
+ allowDdl: envBool("ALLOW_DDL_OPERATION"),
13
+ };
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/mysql/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEjE,eAAe;IACb,IAAI,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,IAAI,SAAS;IAC/C,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE,GAAG,CAAC;IACtC,WAAW,EAAE,OAAO,CAAC,wBAAwB,CAAC;IAC9C,WAAW,EAAE,OAAO,CAAC,wBAAwB,CAAC;IAC9C,WAAW,EAAE,OAAO,CAAC,wBAAwB,CAAC;IAC9C,QAAQ,EAAE,OAAO,CAAC,qBAAqB,CAAC;CACzC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Validate and clean up input SQL query and allowed prefixes.
3
+ */
4
+ export declare function validateInputs(sql: string, allowedPrefixes: string[]): {
5
+ cleanSql: string;
6
+ prefixes: string[];
7
+ };
8
+ /**
9
+ * Splits the SQL query, parses syntax, handles quoting/nesting/comments,
10
+ * and extracts the single SQL statement while ensuring syntax correctness.
11
+ */
12
+ export declare function parseSingleStatement(sql: string): string;
13
+ /**
14
+ * Validates the statement prefix and detects dangerous SQL patterns (hardening).
15
+ */
16
+ export declare function validateStatement(statement: string, prefixes: string[]): void;
17
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/mysql/helpers.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,EAAE,GACxB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAY1C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAmIxD;AAiCD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CA+B7E"}
@@ -0,0 +1,193 @@
1
+ import { ToolError } from "@achmadya-dev/mcp-core";
2
+ /**
3
+ * Validate and clean up input SQL query and allowed prefixes.
4
+ */
5
+ export function validateInputs(sql, allowedPrefixes) {
6
+ const cleanSql = sql.trim();
7
+ if (!cleanSql) {
8
+ throw new ToolError("SQL query cannot be empty.");
9
+ }
10
+ if (allowedPrefixes.length === 0) {
11
+ throw new ToolError("allowedPrefixes cannot be empty.");
12
+ }
13
+ const prefixes = allowedPrefixes.map((p) => p.trim().toUpperCase());
14
+ return { cleanSql, prefixes };
15
+ }
16
+ /**
17
+ * Splits the SQL query, parses syntax, handles quoting/nesting/comments,
18
+ * and extracts the single SQL statement while ensuring syntax correctness.
19
+ */
20
+ export function parseSingleStatement(sql) {
21
+ const parts = [];
22
+ let current = "";
23
+ let inSingleQuote = false;
24
+ let inDoubleQuote = false;
25
+ let inBacktick = false;
26
+ let inBracketIdentifier = false;
27
+ let inLineComment = false;
28
+ let inBlockComment = false;
29
+ let escape = false;
30
+ for (let i = 0; i < sql.length; i++) {
31
+ const char = sql[i];
32
+ const next = sql[i + 1];
33
+ if (escape) {
34
+ current += char;
35
+ escape = false;
36
+ continue;
37
+ }
38
+ if (char === "\\" && (inSingleQuote || inDoubleQuote || inBacktick)) {
39
+ current += char;
40
+ escape = true;
41
+ continue;
42
+ }
43
+ if (inLineComment) {
44
+ current += char;
45
+ if (char === "\n") {
46
+ inLineComment = false;
47
+ }
48
+ continue;
49
+ }
50
+ if (inBlockComment) {
51
+ current += char;
52
+ if (char === "*" && next === "/") {
53
+ current += next;
54
+ i++;
55
+ inBlockComment = false;
56
+ }
57
+ continue;
58
+ }
59
+ if (!inSingleQuote && !inDoubleQuote && !inBacktick && !inBracketIdentifier) {
60
+ if (char === "-" && next === "-") {
61
+ current += char + next;
62
+ i++;
63
+ inLineComment = true;
64
+ continue;
65
+ }
66
+ if (char === "/" && next === "*") {
67
+ current += char + next;
68
+ i++;
69
+ inBlockComment = true;
70
+ continue;
71
+ }
72
+ }
73
+ if (char === "'" && !inDoubleQuote && !inBacktick && !inBracketIdentifier) {
74
+ if (inSingleQuote && next === "'") {
75
+ current += "''";
76
+ i++;
77
+ continue;
78
+ }
79
+ inSingleQuote = !inSingleQuote;
80
+ current += char;
81
+ continue;
82
+ }
83
+ if (char === '"' && !inSingleQuote && !inBacktick && !inBracketIdentifier) {
84
+ if (inDoubleQuote && next === '"') {
85
+ current += '""';
86
+ i++;
87
+ continue;
88
+ }
89
+ inDoubleQuote = !inDoubleQuote;
90
+ current += char;
91
+ continue;
92
+ }
93
+ if (char === "`" && !inSingleQuote && !inDoubleQuote && !inBracketIdentifier) {
94
+ inBacktick = !inBacktick;
95
+ current += char;
96
+ continue;
97
+ }
98
+ if (char === "[" && !inSingleQuote && !inDoubleQuote && !inBacktick) {
99
+ inBracketIdentifier = true;
100
+ current += char;
101
+ continue;
102
+ }
103
+ if (char === "]" && inBracketIdentifier) {
104
+ inBracketIdentifier = false;
105
+ current += char;
106
+ continue;
107
+ }
108
+ if (char === ";" && !inSingleQuote && !inDoubleQuote && !inBacktick && !inBracketIdentifier) {
109
+ const trimmed = current.trim();
110
+ if (trimmed.length > 0) {
111
+ parts.push(trimmed);
112
+ }
113
+ current = "";
114
+ continue;
115
+ }
116
+ current += char;
117
+ }
118
+ if (inSingleQuote)
119
+ throw new ToolError("Unterminated single quote string.");
120
+ if (inDoubleQuote)
121
+ throw new ToolError("Unterminated double quote identifier.");
122
+ if (inBacktick)
123
+ throw new ToolError("Unterminated backtick identifier.");
124
+ if (inBracketIdentifier)
125
+ throw new ToolError("Unterminated bracket identifier.");
126
+ if (inBlockComment)
127
+ throw new ToolError("Unterminated block comment.");
128
+ const last = current.trim();
129
+ if (last.length > 0) {
130
+ parts.push(last);
131
+ }
132
+ if (parts.length !== 1) {
133
+ throw new ToolError("Only a single SQL query is allowed per call.");
134
+ }
135
+ return parts[0];
136
+ }
137
+ /**
138
+ * Recursively strips leading single-line and block comments from a SQL statement.
139
+ */
140
+ function stripLeadingComments(sql) {
141
+ let result = sql.trim();
142
+ while (true) {
143
+ if (result.startsWith("--")) {
144
+ const newlineIndex = result.indexOf("\n");
145
+ if (newlineIndex === -1) {
146
+ return "";
147
+ }
148
+ result = result.slice(newlineIndex + 1).trim();
149
+ continue;
150
+ }
151
+ if (result.startsWith("/*")) {
152
+ const endIndex = result.indexOf("*/");
153
+ if (endIndex === -1) {
154
+ throw new ToolError("Unterminated leading block comment.");
155
+ }
156
+ result = result.slice(endIndex + 2).trim();
157
+ continue;
158
+ }
159
+ break;
160
+ }
161
+ return result;
162
+ }
163
+ /**
164
+ * Validates the statement prefix and detects dangerous SQL patterns (hardening).
165
+ */
166
+ export function validateStatement(statement, prefixes) {
167
+ const stripped = stripLeadingComments(statement);
168
+ const match = stripped.match(/^([A-Z]+)/i);
169
+ if (!match) {
170
+ throw new ToolError("Unable to determine SQL statement type.");
171
+ }
172
+ const firstKeyword = match[1].toUpperCase();
173
+ if (!prefixes.includes(firstKeyword)) {
174
+ throw new ToolError(`SQL query is not allowed for this tool. Allowed statements: ${prefixes.join(", ")}`);
175
+ }
176
+ const dangerousPatterns = [
177
+ /\bXP_CMDSHELL\b/i,
178
+ /\bEXEC\b/i,
179
+ /\bEXECUTE\b/i,
180
+ /\bPREPARE\b/i,
181
+ /\bDEALLOCATE\b/i,
182
+ /\bATTACH\s+DATABASE\b/i,
183
+ /\bCOPY\s+.*\s+PROGRAM\b/i,
184
+ /\bLOAD_FILE\s*\(/i,
185
+ /\bINTO\s+OUTFILE\b/i,
186
+ ];
187
+ for (const pattern of dangerousPatterns) {
188
+ if (pattern.test(statement)) {
189
+ throw new ToolError(`Dangerous SQL pattern detected: ${pattern}`);
190
+ }
191
+ }
192
+ }
193
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/mysql/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,eAAyB;IAEzB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACpE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAEhC,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAExB,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,IAAI,IAAI,CAAC;YAChB,MAAM,GAAG,KAAK,CAAC;YACf,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,aAAa,IAAI,aAAa,IAAI,UAAU,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,IAAI,CAAC;YAChB,MAAM,GAAG,IAAI,CAAC;YACd,SAAS;QACX,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,IAAI,IAAI,CAAC;YAChB,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,aAAa,GAAG,KAAK,CAAC;YACxB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,IAAI,IAAI,CAAC;YAChB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjC,OAAO,IAAI,IAAI,CAAC;gBAChB,CAAC,EAAE,CAAC;gBACJ,cAAc,GAAG,KAAK,CAAC;YACzB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,IAAI,CAAC,UAAU,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC5E,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjC,OAAO,IAAI,IAAI,GAAG,IAAI,CAAC;gBACvB,CAAC,EAAE,CAAC;gBACJ,aAAa,GAAG,IAAI,CAAC;gBACrB,SAAS;YACX,CAAC;YAED,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjC,OAAO,IAAI,IAAI,GAAG,IAAI,CAAC;gBACvB,CAAC,EAAE,CAAC;gBACJ,cAAc,GAAG,IAAI,CAAC;gBACtB,SAAS;YACX,CAAC;QACH,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,UAAU,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1E,IAAI,aAAa,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBAClC,OAAO,IAAI,IAAI,CAAC;gBAChB,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,UAAU,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1E,IAAI,aAAa,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBAClC,OAAO,IAAI,IAAI,CAAC;gBAChB,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7E,UAAU,GAAG,CAAC,UAAU,CAAC;YACzB,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,IAAI,CAAC,UAAU,EAAE,CAAC;YACpE,mBAAmB,GAAG,IAAI,CAAC;YAC3B,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,mBAAmB,EAAE,CAAC;YACxC,mBAAmB,GAAG,KAAK,CAAC;YAC5B,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,IAAI,CAAC,UAAU,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC5F,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,GAAG,EAAE,CAAC;YACb,SAAS;QACX,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;IAClB,CAAC;IAED,IAAI,aAAa;QAAE,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAC5E,IAAI,aAAa;QAAE,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;IAChF,IAAI,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IACzE,IAAI,mBAAmB;QAAE,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;IACjF,IAAI,cAAc;QAAE,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAC;IAEvE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,GAAW;IACvC,IAAI,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAExB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/C,SAAS;QACX,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;gBACpB,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,MAAM;IACR,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB,EAAE,QAAkB;IACrE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,SAAS,CACjB,+DAA+D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACrF,CAAC;IACJ,CAAC;IAED,MAAM,iBAAiB,GAAa;QAClC,kBAAkB;QAClB,WAAW;QACX,cAAc;QACd,cAAc;QACd,iBAAiB;QACjB,wBAAwB;QACxB,0BAA0B;QAC1B,mBAAmB;QACnB,qBAAqB;KACtB,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { RowDataPacket } from "mysql2/promise";
2
+ export declare function safeQuery(sql: string, allowedPrefixes: string[]): string;
3
+ export declare function runSql(sql: string): Promise<{
4
+ kind: "resultset";
5
+ columns: string[];
6
+ rowCount: number;
7
+ totalRows: number;
8
+ truncated: boolean;
9
+ maxRows: number;
10
+ rows: RowDataPacket[];
11
+ } | {
12
+ kind: "execute";
13
+ affectedRows: number;
14
+ insertId: string | null;
15
+ }>;
16
+ //# sourceMappingURL=mysql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/mysql/mysql.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgC,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIlF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,MAAM,CAKxE;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAC9C;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,aAAa,EAAE,CAAC;CACvB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CACJ,CAwCA"}
@@ -0,0 +1,55 @@
1
+ import mysql from "mysql2/promise";
2
+ import { ToolError } from "@achmadya-dev/mcp-core";
3
+ import config from "./config.js";
4
+ import * as helpers from "./helpers.js";
5
+ export function safeQuery(sql, allowedPrefixes) {
6
+ const { cleanSql, prefixes } = helpers.validateInputs(sql, allowedPrefixes);
7
+ const statement = helpers.parseSingleStatement(cleanSql);
8
+ helpers.validateStatement(statement, prefixes);
9
+ return statement;
10
+ }
11
+ export async function runSql(sql) {
12
+ let conn;
13
+ try {
14
+ conn = await mysql.createConnection({
15
+ host: config.host,
16
+ port: config.port,
17
+ user: config.user,
18
+ password: config.password,
19
+ database: config.database,
20
+ charset: "utf8mb4",
21
+ multipleStatements: false,
22
+ });
23
+ const [rows, fields] = await conn.execute(sql);
24
+ if (fields && Array.isArray(fields) && fields.length > 0) {
25
+ const columns = fields.map((f) => f.name);
26
+ const all = rows;
27
+ const truncated = all.length > config.maxRows;
28
+ const display = all.slice(0, config.maxRows);
29
+ return {
30
+ kind: "resultset",
31
+ columns,
32
+ rowCount: display.length,
33
+ totalRows: all.length,
34
+ truncated,
35
+ maxRows: config.maxRows,
36
+ rows: display,
37
+ };
38
+ }
39
+ const header = rows;
40
+ const id = header.insertId;
41
+ return {
42
+ kind: "execute",
43
+ affectedRows: header.affectedRows ?? 0,
44
+ insertId: id != null && Number(id) > 0 ? String(id) : null,
45
+ };
46
+ }
47
+ catch (e) {
48
+ throw new ToolError(`MySQL: ${e instanceof Error ? e.message : String(e)}`);
49
+ }
50
+ finally {
51
+ if (conn)
52
+ await conn.end();
53
+ }
54
+ }
55
+ //# sourceMappingURL=mysql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/mysql/mysql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,gBAAgB,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,eAAyB;IAC9D,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACzD,OAAO,CAAC,iBAAiB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC/C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAW;IAgBtC,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC;YAClC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,SAAS;YAClB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,OAAO,GAAI,MAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7D,MAAM,GAAG,GAAG,IAAuB,CAAC;YACpC,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;YAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7C,OAAO;gBACL,IAAI,EAAE,WAAW;gBACjB,OAAO;gBACP,QAAQ,EAAE,OAAO,CAAC,MAAM;gBACxB,SAAS,EAAE,GAAG,CAAC,MAAM;gBACrB,SAAS;gBACT,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,IAAuB,CAAC;QACvC,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,SAAS;YACf,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC;YACtC,QAAQ,EAAE,EAAE,IAAI,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;SAC3D,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CAAC,UAAU,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;YAAS,CAAC;QACT,IAAI,IAAI;YAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ export declare const mysqlQueryInputSchema: z.ZodObject<{
3
+ sql: z.ZodString;
4
+ }, z.core.$strip>;
5
+ export declare const mysqlQueryOutputShape: z.ZodObject<{
6
+ kind: z.ZodEnum<{
7
+ resultset: "resultset";
8
+ execute: "execute";
9
+ }>;
10
+ columns: z.ZodOptional<z.ZodArray<z.ZodString>>;
11
+ rowCount: z.ZodOptional<z.ZodNumber>;
12
+ totalRows: z.ZodOptional<z.ZodNumber>;
13
+ truncated: z.ZodOptional<z.ZodBoolean>;
14
+ maxRows: z.ZodOptional<z.ZodNumber>;
15
+ rows: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>>>;
16
+ affectedRows: z.ZodOptional<z.ZodNumber>;
17
+ insertId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
+ }, z.core.$strip>;
19
+ export declare const mysqlQueryResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
20
+ kind: z.ZodLiteral<"resultset">;
21
+ columns: z.ZodArray<z.ZodString>;
22
+ rowCount: z.ZodNumber;
23
+ totalRows: z.ZodNumber;
24
+ truncated: z.ZodBoolean;
25
+ maxRows: z.ZodNumber;
26
+ rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>>;
27
+ }, z.core.$strip>, z.ZodObject<{
28
+ kind: z.ZodLiteral<"execute">;
29
+ affectedRows: z.ZodNumber;
30
+ insertId: z.ZodNullable<z.ZodString>;
31
+ }, z.core.$strip>], "kind">;
32
+ export type MysqlQueryResult = z.infer<typeof mysqlQueryResultSchema>;
33
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/mysql/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,qBAAqB;;iBAShC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;iBAUhC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;2BAejC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ const rowValue = z.union([z.string(), z.number(), z.boolean(), z.null()]);
3
+ export const mysqlQueryInputSchema = z.object({
4
+ sql: z
5
+ .string()
6
+ .check(z.trim(), z.minLength(1, "SQL cannot be empty"), z.maxLength(100_000, "SQL is too long (max 100,000 characters)"))
7
+ .describe("A single SQL statement. Multiple statements separated by ';' are not allowed."),
8
+ });
9
+ export const mysqlQueryOutputShape = z.object({
10
+ kind: z.enum(["resultset", "execute"]),
11
+ columns: z.array(z.string()).optional(),
12
+ rowCount: z.number().int().nonnegative().optional(),
13
+ totalRows: z.number().int().nonnegative().optional(),
14
+ truncated: z.boolean().optional(),
15
+ maxRows: z.number().int().positive().optional(),
16
+ rows: z.array(z.record(z.string(), rowValue)).optional(),
17
+ affectedRows: z.number().int().nonnegative().optional(),
18
+ insertId: z.string().nullable().optional(),
19
+ });
20
+ export const mysqlQueryResultSchema = z.discriminatedUnion("kind", [
21
+ z.object({
22
+ kind: z.literal("resultset"),
23
+ columns: z.array(z.string()),
24
+ rowCount: z.number().int().nonnegative(),
25
+ totalRows: z.number().int().nonnegative(),
26
+ truncated: z.boolean(),
27
+ maxRows: z.number().int().positive(),
28
+ rows: z.array(z.record(z.string(), rowValue)),
29
+ }),
30
+ z.object({
31
+ kind: z.literal("execute"),
32
+ affectedRows: z.number().int().nonnegative(),
33
+ insertId: z.string().nullable(),
34
+ }),
35
+ ]);
36
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/mysql/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAE1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,KAAK,CACJ,CAAC,CAAC,IAAI,EAAE,EACR,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,qBAAqB,CAAC,EACrC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,0CAA0C,CAAC,CACjE;SACA,QAAQ,CAAC,+EAA+E,CAAC;CAC7F,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACnD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACpD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC/C,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;IACvD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACjE,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QAC5B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QACxC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QACzC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;QACtB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACpC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC;KAC9C,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;QAC1B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;QAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAChC,CAAC;CACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const mysql_ddl: import("@achmadya-dev/mcp-core").RegisterableTool;
2
+ //# sourceMappingURL=mysql_ddl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_ddl.d.ts","sourceRoot":"","sources":["../../src/tools/mysql_ddl.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,SAAS,mDA0BpB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { defineTool, ToolError } from "@achmadya-dev/mcp-core";
2
+ import { runSql, safeQuery } from "../mysql/mysql.js";
3
+ import { mysqlQueryInputSchema, mysqlQueryOutputShape, mysqlQueryResultSchema, } from "../mysql/schema.js";
4
+ import config from "../mysql/config.js";
5
+ export const mysql_ddl = defineTool({
6
+ name: "mysql_ddl",
7
+ description: "Modify the database schema or permissions using CREATE, ALTER, DROP, TRUNCATE, RENAME, GRANT, or REVOKE. Only a single query is allowed. If the operation is rejected as not allowed, you must respect this safety restriction and do not attempt to bypass it via terminal commands, custom scripts, or external tools.",
8
+ inputSchema: mysqlQueryInputSchema,
9
+ outputSchema: mysqlQueryOutputShape,
10
+ handler: async ({ sql }) => {
11
+ if (!config.allowDdl) {
12
+ throw new ToolError("DDL operation is not allowed on this server.");
13
+ }
14
+ const query = safeQuery(sql, [
15
+ "CREATE",
16
+ "ALTER",
17
+ "DROP",
18
+ "TRUNCATE",
19
+ "RENAME",
20
+ "GRANT",
21
+ "REVOKE",
22
+ ]);
23
+ const result = await runSql(query);
24
+ const parsed = mysqlQueryResultSchema.safeParse(result);
25
+ if (!parsed.success) {
26
+ throw new ToolError(`Invalid query result: ${parsed.error.message}`);
27
+ }
28
+ return parsed.data;
29
+ },
30
+ });
31
+ //# sourceMappingURL=mysql_ddl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_ddl.js","sourceRoot":"","sources":["../../src/tools/mysql_ddl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC;IAClC,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,0TAA0T;IAC5T,WAAW,EAAE,qBAAqB;IAClC,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE;YAC3B,QAAQ;YACR,OAAO;YACP,MAAM;YACN,UAAU;YACV,QAAQ;YACR,OAAO;YACP,QAAQ;SACT,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const mysql_delete: import("@achmadya-dev/mcp-core").RegisterableTool;
2
+ //# sourceMappingURL=mysql_delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_delete.d.ts","sourceRoot":"","sources":["../../src/tools/mysql_delete.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,mDAkBvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { defineTool, ToolError } from "@achmadya-dev/mcp-core";
2
+ import { runSql, safeQuery } from "../mysql/mysql.js";
3
+ import { mysqlQueryInputSchema, mysqlQueryOutputShape, mysqlQueryResultSchema, } from "../mysql/schema.js";
4
+ import config from "../mysql/config.js";
5
+ export const mysql_delete = defineTool({
6
+ name: "mysql_delete",
7
+ description: "Delete data from the database using DELETE. Only a single query is allowed. If the operation is rejected as not allowed, you must respect this safety restriction and do not attempt to bypass it via terminal commands, custom scripts, or external tools.",
8
+ inputSchema: mysqlQueryInputSchema,
9
+ outputSchema: mysqlQueryOutputShape,
10
+ handler: async ({ sql }) => {
11
+ if (!config.allowDelete) {
12
+ throw new ToolError("DELETE operation is not allowed on this server.");
13
+ }
14
+ const query = safeQuery(sql, ["DELETE"]);
15
+ const result = await runSql(query);
16
+ const parsed = mysqlQueryResultSchema.safeParse(result);
17
+ if (!parsed.success) {
18
+ throw new ToolError(`Invalid query result: ${parsed.error.message}`);
19
+ }
20
+ return parsed.data;
21
+ },
22
+ });
23
+ //# sourceMappingURL=mysql_delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_delete.js","sourceRoot":"","sources":["../../src/tools/mysql_delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,6PAA6P;IAC/P,WAAW,EAAE,qBAAqB;IAClC,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const mysql_insert: import("@achmadya-dev/mcp-core").RegisterableTool;
2
+ //# sourceMappingURL=mysql_insert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_insert.d.ts","sourceRoot":"","sources":["../../src/tools/mysql_insert.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,mDAkBvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { defineTool, ToolError } from "@achmadya-dev/mcp-core";
2
+ import { runSql, safeQuery } from "../mysql/mysql.js";
3
+ import { mysqlQueryInputSchema, mysqlQueryOutputShape, mysqlQueryResultSchema, } from "../mysql/schema.js";
4
+ import config from "../mysql/config.js";
5
+ export const mysql_insert = defineTool({
6
+ name: "mysql_insert",
7
+ description: "Insert new data into the database using INSERT or REPLACE. Only a single query is allowed. If the operation is rejected as not allowed, you must respect this safety restriction and do not attempt to bypass it via terminal commands, custom scripts, or external tools.",
8
+ inputSchema: mysqlQueryInputSchema,
9
+ outputSchema: mysqlQueryOutputShape,
10
+ handler: async ({ sql }) => {
11
+ if (!config.allowInsert) {
12
+ throw new ToolError("INSERT operation is not allowed on this server.");
13
+ }
14
+ const query = safeQuery(sql, ["INSERT", "REPLACE"]);
15
+ const result = await runSql(query);
16
+ const parsed = mysqlQueryResultSchema.safeParse(result);
17
+ if (!parsed.success) {
18
+ throw new ToolError(`Invalid query result: ${parsed.error.message}`);
19
+ }
20
+ return parsed.data;
21
+ },
22
+ });
23
+ //# sourceMappingURL=mysql_insert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_insert.js","sourceRoot":"","sources":["../../src/tools/mysql_insert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,4QAA4Q;IAC9Q,WAAW,EAAE,qBAAqB;IAClC,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const mysql_select: import("@achmadya-dev/mcp-core").RegisterableTool;
2
+ //# sourceMappingURL=mysql_select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_select.d.ts","sourceRoot":"","sources":["../../src/tools/mysql_select.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY,mDAevB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { defineTool, ToolError } from "@achmadya-dev/mcp-core";
2
+ import { runSql, safeQuery } from "../mysql/mysql.js";
3
+ import { mysqlQueryInputSchema, mysqlQueryOutputShape, mysqlQueryResultSchema, } from "../mysql/schema.js";
4
+ export const mysql_select = defineTool({
5
+ name: "mysql_select",
6
+ description: "Read data from the database using SELECT, SHOW, DESCRIBE, EXPLAIN, or DESC. Only a single query is allowed.",
7
+ inputSchema: mysqlQueryInputSchema,
8
+ outputSchema: mysqlQueryOutputShape,
9
+ handler: async ({ sql }) => {
10
+ const query = safeQuery(sql, ["SELECT", "SHOW", "DESCRIBE", "EXPLAIN", "DESC"]);
11
+ const result = await runSql(query);
12
+ const parsed = mysqlQueryResultSchema.safeParse(result);
13
+ if (!parsed.success) {
14
+ throw new ToolError(`Invalid query result: ${parsed.error.message}`);
15
+ }
16
+ return parsed.data;
17
+ },
18
+ });
19
+ //# sourceMappingURL=mysql_select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_select.js","sourceRoot":"","sources":["../../src/tools/mysql_select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,6GAA6G;IAC/G,WAAW,EAAE,qBAAqB;IAClC,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;QACzB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const mysql_update: import("@achmadya-dev/mcp-core").RegisterableTool;
2
+ //# sourceMappingURL=mysql_update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_update.d.ts","sourceRoot":"","sources":["../../src/tools/mysql_update.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,mDAkBvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { defineTool, ToolError } from "@achmadya-dev/mcp-core";
2
+ import { runSql, safeQuery } from "../mysql/mysql.js";
3
+ import { mysqlQueryInputSchema, mysqlQueryOutputShape, mysqlQueryResultSchema, } from "../mysql/schema.js";
4
+ import config from "../mysql/config.js";
5
+ export const mysql_update = defineTool({
6
+ name: "mysql_update",
7
+ description: "Update existing data in the database using UPDATE. Only a single query is allowed. If the operation is rejected as not allowed, you must respect this safety restriction and do not attempt to bypass it via terminal commands, custom scripts, or external tools.",
8
+ inputSchema: mysqlQueryInputSchema,
9
+ outputSchema: mysqlQueryOutputShape,
10
+ handler: async ({ sql }) => {
11
+ if (!config.allowUpdate) {
12
+ throw new ToolError("UPDATE operation is not allowed on this server.");
13
+ }
14
+ const query = safeQuery(sql, ["UPDATE"]);
15
+ const result = await runSql(query);
16
+ const parsed = mysqlQueryResultSchema.safeParse(result);
17
+ if (!parsed.success) {
18
+ throw new ToolError(`Invalid query result: ${parsed.error.message}`);
19
+ }
20
+ return parsed.data;
21
+ },
22
+ });
23
+ //# sourceMappingURL=mysql_update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql_update.js","sourceRoot":"","sources":["../../src/tools/mysql_update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,oQAAoQ;IACtQ,WAAW,EAAE,qBAAqB;IAClC,YAAY,EAAE,qBAAqB;IACnC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;CACF,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@achmadya-dev/mcp-mysql-query",
3
+ "version": "0.2.0",
4
+ "description": "Model Context Protocol (MCP) server for MySQL to run SQL queries via stdio (read-only by default)",
5
+ "type": "module",
6
+ "author": "achmadya",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/achmadya-dev/mcp-mysql-query.git"
11
+ },
12
+ "keywords": [
13
+ "mcp",
14
+ "model-context-protocol",
15
+ "mysql",
16
+ "database",
17
+ "cursor"
18
+ ],
19
+ "main": "dist/index.js",
20
+ "bin": {
21
+ "mcp-mysql-query": "./dist/index.js"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "engines": {
30
+ "node": ">=20"
31
+ },
32
+ "dependencies": {
33
+ "@achmadya-dev/mcp-core": "^0.3.3",
34
+ "mysql2": "3.11.0",
35
+ "zod": "4.3.6"
36
+ },
37
+ "devDependencies": {
38
+ "@jest/globals": "30.4.1",
39
+ "@types/jest": "30.0.0",
40
+ "@types/node": "22.10.0",
41
+ "jest": "30.4.2",
42
+ "ts-jest": "29.4.11",
43
+ "typescript": "5.7.2",
44
+ "@changesets/cli": "2.29.8"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.build.json",
48
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
49
+ "start": "node dist/index.js",
50
+ "changeset": "changeset",
51
+ "version-packages": "changeset version",
52
+ "publish-packages": "pnpm run build && changeset publish"
53
+ }
54
+ }