@imrieul/mysql-mcp-server 1.0.3 → 1.1.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/dist/index.js +231 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,14 +41,20 @@ function parseEnvConfig(env) {
|
|
|
41
41
|
function parseArgs(argv) {
|
|
42
42
|
let connectionString;
|
|
43
43
|
let readonly = false;
|
|
44
|
+
let help = false;
|
|
45
|
+
let version = false;
|
|
44
46
|
for (const arg of argv) {
|
|
45
47
|
if (arg === "--readonly") {
|
|
46
48
|
readonly = true;
|
|
49
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
50
|
+
help = true;
|
|
51
|
+
} else if (arg === "--version") {
|
|
52
|
+
version = true;
|
|
47
53
|
} else if (arg.startsWith("mysql://")) {
|
|
48
54
|
connectionString = arg;
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
|
-
return { connectionString, readonly };
|
|
57
|
+
return { connectionString, readonly, help, version };
|
|
52
58
|
}
|
|
53
59
|
function resolveConfig(argv, env = process.env) {
|
|
54
60
|
const args = parseArgs(argv);
|
|
@@ -175,11 +181,68 @@ function formatError(error) {
|
|
|
175
181
|
${hint[1]}` : `Error: ${message}`;
|
|
176
182
|
}
|
|
177
183
|
|
|
184
|
+
// src/tools/validate-input.ts
|
|
185
|
+
function hasControlChars(str) {
|
|
186
|
+
for (let i = 0; i < str.length; i++) {
|
|
187
|
+
const code = str.charCodeAt(i);
|
|
188
|
+
if (code === 9 || code === 10 || code === 13) continue;
|
|
189
|
+
if (code <= 31 || code === 127) return true;
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
var DANGEROUS_IDENTIFIER_PATTERNS = [
|
|
194
|
+
/;/,
|
|
195
|
+
// SQL statement separator
|
|
196
|
+
/--/,
|
|
197
|
+
// SQL line comment
|
|
198
|
+
/\/\*/,
|
|
199
|
+
// SQL block comment start
|
|
200
|
+
/\*\//,
|
|
201
|
+
// SQL block comment end
|
|
202
|
+
/\\/
|
|
203
|
+
// backslash escape
|
|
204
|
+
];
|
|
205
|
+
function validateSql(sql) {
|
|
206
|
+
if (hasControlChars(sql)) {
|
|
207
|
+
return {
|
|
208
|
+
valid: false,
|
|
209
|
+
message: "Error: SQL contains control characters. Remove non-printable characters (tab and newline are allowed)."
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
return { valid: true };
|
|
213
|
+
}
|
|
214
|
+
function validateIdentifier(name, label) {
|
|
215
|
+
if (!name || name.trim().length === 0) {
|
|
216
|
+
return { valid: false, message: `Error: ${label} name cannot be empty.` };
|
|
217
|
+
}
|
|
218
|
+
if (hasControlChars(name)) {
|
|
219
|
+
return {
|
|
220
|
+
valid: false,
|
|
221
|
+
message: `Error: ${label} name contains control characters.`
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
for (const pattern of DANGEROUS_IDENTIFIER_PATTERNS) {
|
|
225
|
+
if (pattern.test(name)) {
|
|
226
|
+
return {
|
|
227
|
+
valid: false,
|
|
228
|
+
message: `Error: ${label} name contains dangerous characters (${pattern.source}). Use only valid MySQL identifier characters.`
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (name.length > 64) {
|
|
233
|
+
return {
|
|
234
|
+
valid: false,
|
|
235
|
+
message: `Error: ${label} name exceeds MySQL's 64-character limit.`
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { valid: true };
|
|
239
|
+
}
|
|
240
|
+
|
|
178
241
|
// src/tools/query.ts
|
|
179
242
|
var queryToolName = "query";
|
|
180
243
|
var queryToolConfig = {
|
|
181
244
|
title: "Query",
|
|
182
|
-
description:
|
|
245
|
+
description: 'Execute a read-only SQL query (SELECT, SHOW, DESCRIBE, EXPLAIN). LIMIT is auto-appended to SELECT/WITH queries without one (default: server maxRows). Prefer specific columns over SELECT * to reduce response size. For data modification, use the "execute" tool instead.',
|
|
183
246
|
inputSchema: {
|
|
184
247
|
sql: z.string().describe(
|
|
185
248
|
"The SQL query to execute. Only SELECT, SHOW, DESCRIBE, EXPLAIN, and WITH (CTE) statements are allowed."
|
|
@@ -194,6 +257,13 @@ function needsLimit(normalized) {
|
|
|
194
257
|
}
|
|
195
258
|
function createQueryHandler(runner, maxRows) {
|
|
196
259
|
return async ({ sql }) => {
|
|
260
|
+
const validation = validateSql(sql);
|
|
261
|
+
if (!validation.valid) {
|
|
262
|
+
return {
|
|
263
|
+
isError: true,
|
|
264
|
+
content: [{ type: "text", text: validation.message }]
|
|
265
|
+
};
|
|
266
|
+
}
|
|
197
267
|
const normalized = sql.trim().toUpperCase();
|
|
198
268
|
const isAllowed = ALLOWED_PREFIXES.some((prefix) => normalized.startsWith(prefix));
|
|
199
269
|
if (!isAllowed) {
|
|
@@ -233,13 +303,14 @@ import { z as z2 } from "zod";
|
|
|
233
303
|
var executeToolName = "execute";
|
|
234
304
|
var executeToolConfig = {
|
|
235
305
|
title: "Execute",
|
|
236
|
-
description: "Execute a data modification SQL statement (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.).",
|
|
306
|
+
description: "Execute a data modification SQL statement (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.). Set dryRun=true to validate without executing \u2014 uses EXPLAIN for DML, or previews the SQL for DDL. Always confirm destructive operations (DROP, TRUNCATE, DELETE without WHERE) with the user before executing. Not available in read-only mode.",
|
|
237
307
|
inputSchema: {
|
|
238
|
-
sql: z2.string().describe('The SQL statement to execute. SELECT statements are not allowed here; use the "query" tool instead.')
|
|
308
|
+
sql: z2.string().describe('The SQL statement to execute. SELECT statements are not allowed here; use the "query" tool instead.'),
|
|
309
|
+
dryRun: z2.boolean().optional().describe("If true, validates the statement via EXPLAIN without executing it. Defaults to false.")
|
|
239
310
|
}
|
|
240
311
|
};
|
|
241
312
|
function createExecuteHandler(runner, isReadonly) {
|
|
242
|
-
return async ({ sql }) => {
|
|
313
|
+
return async ({ sql, dryRun }) => {
|
|
243
314
|
if (isReadonly) {
|
|
244
315
|
return {
|
|
245
316
|
isError: true,
|
|
@@ -251,6 +322,13 @@ function createExecuteHandler(runner, isReadonly) {
|
|
|
251
322
|
]
|
|
252
323
|
};
|
|
253
324
|
}
|
|
325
|
+
const validation = validateSql(sql);
|
|
326
|
+
if (!validation.valid) {
|
|
327
|
+
return {
|
|
328
|
+
isError: true,
|
|
329
|
+
content: [{ type: "text", text: validation.message }]
|
|
330
|
+
};
|
|
331
|
+
}
|
|
254
332
|
const normalized = sql.trim().toUpperCase();
|
|
255
333
|
if (normalized.startsWith("SELECT") || normalized.startsWith("WITH")) {
|
|
256
334
|
return {
|
|
@@ -263,6 +341,38 @@ function createExecuteHandler(runner, isReadonly) {
|
|
|
263
341
|
]
|
|
264
342
|
};
|
|
265
343
|
}
|
|
344
|
+
if (dryRun) {
|
|
345
|
+
const DDL_PREFIXES = ["CREATE", "DROP", "ALTER", "TRUNCATE", "RENAME"];
|
|
346
|
+
const isDdl = DDL_PREFIXES.some((p) => normalized.startsWith(p));
|
|
347
|
+
if (isDdl) {
|
|
348
|
+
return {
|
|
349
|
+
content: [
|
|
350
|
+
{
|
|
351
|
+
type: "text",
|
|
352
|
+
text: `[dry-run] SQL preview (DDL cannot be validated via EXPLAIN):
|
|
353
|
+
${sql}`
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
const [rows] = await runner.query(`EXPLAIN ${sql}`);
|
|
360
|
+
return {
|
|
361
|
+
content: [
|
|
362
|
+
{
|
|
363
|
+
type: "text",
|
|
364
|
+
text: `[dry-run] Statement validated via EXPLAIN:
|
|
365
|
+
${JSON.stringify(rows, null, 2)}`
|
|
366
|
+
}
|
|
367
|
+
]
|
|
368
|
+
};
|
|
369
|
+
} catch (error) {
|
|
370
|
+
return {
|
|
371
|
+
isError: true,
|
|
372
|
+
content: [{ type: "text", text: `[dry-run] Validation failed: ${formatError(error)}` }]
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
}
|
|
266
376
|
try {
|
|
267
377
|
const [result] = await runner.query(sql);
|
|
268
378
|
const r = result;
|
|
@@ -284,7 +394,7 @@ function createExecuteHandler(runner, isReadonly) {
|
|
|
284
394
|
var listDatabasesToolName = "list_databases";
|
|
285
395
|
var listDatabasesToolConfig = {
|
|
286
396
|
title: "List Databases",
|
|
287
|
-
description: "List all databases on the MySQL server."
|
|
397
|
+
description: "List all databases on the MySQL server. Use this as a starting point to discover available databases before querying. Returns a JSON array of database names."
|
|
288
398
|
};
|
|
289
399
|
function createListDatabasesHandler(runner) {
|
|
290
400
|
return async () => {
|
|
@@ -326,13 +436,22 @@ function quoteStringValue(value) {
|
|
|
326
436
|
var listTablesToolName = "list_tables";
|
|
327
437
|
var listTablesToolConfig = {
|
|
328
438
|
title: "List Tables",
|
|
329
|
-
description: "List all tables in the specified database (or the current database if not specified).",
|
|
439
|
+
description: "List all tables in the specified database (or the current database if not specified). Includes table comments when available. Use this before describe_table to find the exact table name.",
|
|
330
440
|
inputSchema: {
|
|
331
441
|
database: z3.string().optional().describe("Database name. Uses the current database if omitted.")
|
|
332
442
|
}
|
|
333
443
|
};
|
|
334
444
|
function createListTablesHandler(runner) {
|
|
335
445
|
return async ({ database }) => {
|
|
446
|
+
if (database) {
|
|
447
|
+
const dbValidation = validateIdentifier(database, "Database");
|
|
448
|
+
if (!dbValidation.valid) {
|
|
449
|
+
return {
|
|
450
|
+
isError: true,
|
|
451
|
+
content: [{ type: "text", text: dbValidation.message }]
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
}
|
|
336
455
|
try {
|
|
337
456
|
return await runner.withConnection(async (query) => {
|
|
338
457
|
const db = await resolveDatabase(query, database);
|
|
@@ -386,7 +505,7 @@ function formatColumn(col) {
|
|
|
386
505
|
var describeTableToolName = "describe_table";
|
|
387
506
|
var describeTableToolConfig = {
|
|
388
507
|
title: "Describe Table",
|
|
389
|
-
description: "Show the schema/structure of a table, including column names, types, constraints, and comments.",
|
|
508
|
+
description: "Show the schema/structure of a table, including column names, types, constraints, and comments. Use this before writing queries to ensure correct column names and types. For inspecting all tables at once, use describe_all_tables instead.",
|
|
390
509
|
inputSchema: {
|
|
391
510
|
table: z4.string().describe("Table name to describe."),
|
|
392
511
|
database: z4.string().optional().describe("Database name. Uses the current database if omitted.")
|
|
@@ -394,6 +513,22 @@ var describeTableToolConfig = {
|
|
|
394
513
|
};
|
|
395
514
|
function createDescribeTableHandler(runner) {
|
|
396
515
|
return async ({ table, database }) => {
|
|
516
|
+
const tableValidation = validateIdentifier(table, "Table");
|
|
517
|
+
if (!tableValidation.valid) {
|
|
518
|
+
return {
|
|
519
|
+
isError: true,
|
|
520
|
+
content: [{ type: "text", text: tableValidation.message }]
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
if (database) {
|
|
524
|
+
const dbValidation = validateIdentifier(database, "Database");
|
|
525
|
+
if (!dbValidation.valid) {
|
|
526
|
+
return {
|
|
527
|
+
isError: true,
|
|
528
|
+
content: [{ type: "text", text: dbValidation.message }]
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
}
|
|
397
532
|
try {
|
|
398
533
|
return await runner.withConnection(async (query) => {
|
|
399
534
|
const db = await resolveDatabase(query, database);
|
|
@@ -453,13 +588,22 @@ import { z as z5 } from "zod";
|
|
|
453
588
|
var describeAllTablesToolName = "describe_all_tables";
|
|
454
589
|
var describeAllTablesToolConfig = {
|
|
455
590
|
title: "Describe All Tables",
|
|
456
|
-
description: "Show the schema of all tables at once. Much more efficient than calling describe_table for each table individually.",
|
|
591
|
+
description: "Show the schema of all tables at once. Much more efficient than calling describe_table for each table individually. Warning: response can be large for databases with many tables \u2014 prefer describe_table for specific tables when possible.",
|
|
457
592
|
inputSchema: {
|
|
458
593
|
database: z5.string().optional().describe("Database name. Uses the current database if omitted.")
|
|
459
594
|
}
|
|
460
595
|
};
|
|
461
596
|
function createDescribeAllTablesHandler(runner) {
|
|
462
597
|
return async ({ database }) => {
|
|
598
|
+
if (database) {
|
|
599
|
+
const dbValidation = validateIdentifier(database, "Database");
|
|
600
|
+
if (!dbValidation.valid) {
|
|
601
|
+
return {
|
|
602
|
+
isError: true,
|
|
603
|
+
content: [{ type: "text", text: dbValidation.message }]
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
}
|
|
463
607
|
try {
|
|
464
608
|
return await runner.withConnection(async (query) => {
|
|
465
609
|
const db = await resolveDatabase(query, database);
|
|
@@ -517,12 +661,13 @@ import { z as z6 } from "zod";
|
|
|
517
661
|
var addCommentToolName = "add_comment";
|
|
518
662
|
var addCommentToolConfig = {
|
|
519
663
|
title: "Add Comment",
|
|
520
|
-
description: "Safely add a comment to a table or column. This tool only modifies comments \u2014 it cannot alter table structure, column types, or data.",
|
|
664
|
+
description: "Safely add a comment to a table or column. This tool only modifies comments \u2014 it cannot alter table structure, column types, or data. Set dryRun=true to preview the generated SQL without executing it. Use describe_table first to verify column names. Not available in read-only mode.",
|
|
521
665
|
inputSchema: {
|
|
522
666
|
table: z6.string().describe("Table name."),
|
|
523
667
|
column: z6.string().optional().describe("Column name. If omitted, sets a table-level comment."),
|
|
524
668
|
comment: z6.string().describe("Comment text to set."),
|
|
525
|
-
database: z6.string().optional().describe("Database name. Uses the current database if omitted.")
|
|
669
|
+
database: z6.string().optional().describe("Database name. Uses the current database if omitted."),
|
|
670
|
+
dryRun: z6.boolean().optional().describe("If true, returns the generated SQL without executing it. Defaults to false.")
|
|
526
671
|
}
|
|
527
672
|
};
|
|
528
673
|
function createAddCommentHandler(runner, isReadonly) {
|
|
@@ -530,7 +675,8 @@ function createAddCommentHandler(runner, isReadonly) {
|
|
|
530
675
|
table,
|
|
531
676
|
column,
|
|
532
677
|
comment,
|
|
533
|
-
database
|
|
678
|
+
database,
|
|
679
|
+
dryRun
|
|
534
680
|
}) => {
|
|
535
681
|
if (isReadonly) {
|
|
536
682
|
return {
|
|
@@ -543,6 +689,31 @@ function createAddCommentHandler(runner, isReadonly) {
|
|
|
543
689
|
]
|
|
544
690
|
};
|
|
545
691
|
}
|
|
692
|
+
const tableValidation = validateIdentifier(table, "Table");
|
|
693
|
+
if (!tableValidation.valid) {
|
|
694
|
+
return {
|
|
695
|
+
isError: true,
|
|
696
|
+
content: [{ type: "text", text: tableValidation.message }]
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
if (column) {
|
|
700
|
+
const columnValidation = validateIdentifier(column, "Column");
|
|
701
|
+
if (!columnValidation.valid) {
|
|
702
|
+
return {
|
|
703
|
+
isError: true,
|
|
704
|
+
content: [{ type: "text", text: columnValidation.message }]
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (database) {
|
|
709
|
+
const dbValidation = validateIdentifier(database, "Database");
|
|
710
|
+
if (!dbValidation.valid) {
|
|
711
|
+
return {
|
|
712
|
+
isError: true,
|
|
713
|
+
content: [{ type: "text", text: dbValidation.message }]
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
}
|
|
546
717
|
try {
|
|
547
718
|
return await runner.withConnection(async (query) => {
|
|
548
719
|
const db = await resolveDatabase(query, database);
|
|
@@ -561,6 +732,12 @@ function createAddCommentHandler(runner, isReadonly) {
|
|
|
561
732
|
const escapedComment = escapeStringValue(comment);
|
|
562
733
|
if (!column) {
|
|
563
734
|
const sql = `ALTER TABLE ${fullName} COMMENT = '${escapedComment}'`;
|
|
735
|
+
if (dryRun) {
|
|
736
|
+
return {
|
|
737
|
+
content: [{ type: "text", text: `[dry-run] SQL preview:
|
|
738
|
+
${sql}` }]
|
|
739
|
+
};
|
|
740
|
+
}
|
|
564
741
|
await query(sql);
|
|
565
742
|
return {
|
|
566
743
|
content: [{ type: "text", text: `Table comment updated: ${table}` }]
|
|
@@ -587,6 +764,12 @@ Hint: use describe_table to check available columns.`
|
|
|
587
764
|
modifySql += ` DEFAULT '${escapeStringValue(String(colInfo.COLUMN_DEFAULT))}'`;
|
|
588
765
|
if (colInfo.EXTRA) modifySql += ` ${colInfo.EXTRA}`;
|
|
589
766
|
modifySql += ` COMMENT '${escapedComment}'`;
|
|
767
|
+
if (dryRun) {
|
|
768
|
+
return {
|
|
769
|
+
content: [{ type: "text", text: `[dry-run] SQL preview:
|
|
770
|
+
${modifySql}` }]
|
|
771
|
+
};
|
|
772
|
+
}
|
|
590
773
|
await query(modifySql);
|
|
591
774
|
return {
|
|
592
775
|
content: [{ type: "text", text: `Column comment updated: ${table}.${column}` }]
|
|
@@ -653,7 +836,43 @@ function createMcpServer(runner, readonly, maxRows) {
|
|
|
653
836
|
}
|
|
654
837
|
|
|
655
838
|
// src/index.ts
|
|
839
|
+
import { createRequire } from "module";
|
|
840
|
+
var HELP_TEXT = `Usage: mysql-mcp-server [options] [mysql://user:pass@host:port/db]
|
|
841
|
+
|
|
842
|
+
MySQL MCP Server - Model Context Protocol server for MySQL database operations
|
|
843
|
+
|
|
844
|
+
Options:
|
|
845
|
+
--readonly Enable read-only mode (blocks execute and add_comment)
|
|
846
|
+
--help, -h Show this help message
|
|
847
|
+
--version Show version number
|
|
848
|
+
|
|
849
|
+
Environment variables:
|
|
850
|
+
MYSQL_HOST MySQL host (required if no connection string)
|
|
851
|
+
MYSQL_PORT MySQL port (default: 3306)
|
|
852
|
+
MYSQL_USER MySQL user (required if no connection string)
|
|
853
|
+
MYSQL_PASSWORD MySQL password (required if no connection string)
|
|
854
|
+
MYSQL_DATABASE Default database
|
|
855
|
+
MYSQL_READONLY Read-only mode (true/false)
|
|
856
|
+
MYSQL_MAX_ROWS Max rows for SELECT queries (default: 100)
|
|
857
|
+
MYSQL_QUERY_TIMEOUT Query timeout in ms (default: 30000, 0 to disable)
|
|
858
|
+
MYSQL_SSL Enable SSL (true/false)
|
|
859
|
+
|
|
860
|
+
Examples:
|
|
861
|
+
mysql-mcp-server mysql://root:pass@localhost:3306/mydb
|
|
862
|
+
mysql-mcp-server --readonly
|
|
863
|
+
MYSQL_HOST=localhost MYSQL_USER=root MYSQL_PASSWORD=pass mysql-mcp-server`;
|
|
656
864
|
async function main() {
|
|
865
|
+
const args = parseArgs(process.argv.slice(2));
|
|
866
|
+
if (args.help) {
|
|
867
|
+
console.log(HELP_TEXT);
|
|
868
|
+
process.exit(0);
|
|
869
|
+
}
|
|
870
|
+
if (args.version) {
|
|
871
|
+
const require2 = createRequire(import.meta.url);
|
|
872
|
+
const pkg = require2("../package.json");
|
|
873
|
+
console.log(pkg.version);
|
|
874
|
+
process.exit(0);
|
|
875
|
+
}
|
|
657
876
|
const config = resolveConfig(process.argv.slice(2));
|
|
658
877
|
const connectionManager = createConnectionManager(config.mysql, { ssl: config.ssl });
|
|
659
878
|
const runner = createQueryRunner(connectionManager.getPool(), {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/connection.ts","../src/query-runner.ts","../src/server.ts","../src/tools/query.ts","../src/tools/error-hint.ts","../src/tools/execute.ts","../src/tools/list-databases.ts","../src/tools/list-tables.ts","../src/tools/resolve-database.ts","../src/tools/sql-escape.ts","../src/tools/describe-table.ts","../src/tools/format-column.ts","../src/tools/describe-all-tables.ts","../src/tools/add-comment.ts","../src/tools/index.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { resolveConfig } from './config.js';\nimport { createConnectionManager } from './connection.js';\nimport { createQueryRunner } from './query-runner.js';\nimport { createMcpServer } from './server.js';\n\nasync function main(): Promise<void> {\n const config = resolveConfig(process.argv.slice(2));\n const connectionManager = createConnectionManager(config.mysql, { ssl: config.ssl });\n const runner = createQueryRunner(connectionManager.getPool(), {\n readonly: config.readonly,\n queryTimeout: config.queryTimeout,\n });\n\n const server = createMcpServer(runner, config.readonly, config.maxRows);\n const transport = new StdioServerTransport();\n\n const shutdown = async () => {\n await server.close();\n await connectionManager.close();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n process.stdin.on('end', shutdown);\n\n console.error('MySQL MCP Server starting...');\n console.error(`Readonly mode: ${config.readonly}`);\n console.error(`Query timeout: ${config.queryTimeout}ms`);\n console.error(`SSL: ${config.ssl}`);\n\n await server.connect(transport);\n console.error('MySQL MCP Server connected via stdio');\n}\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n","export interface MySQLConfig {\n host: string;\n port: number;\n user: string;\n password: string;\n database?: string;\n}\n\nexport interface AppConfig {\n mysql: MySQLConfig;\n readonly: boolean;\n maxRows: number;\n queryTimeout: number;\n ssl: boolean;\n}\n\nexport function parseConnectionString(connStr: string): MySQLConfig {\n let url: URL;\n try {\n url = new URL(connStr);\n } catch {\n throw new Error(`Invalid connection string: ${connStr}`);\n }\n\n if (url.protocol !== 'mysql:') {\n throw new Error(`Expected mysql:// protocol, got ${url.protocol}`);\n }\n\n const database = url.pathname.slice(1) || undefined;\n\n return {\n host: url.hostname,\n port: url.port ? parseInt(url.port, 10) : 3306,\n user: decodeURIComponent(url.username),\n password: decodeURIComponent(url.password),\n database,\n };\n}\n\nexport function parseEnvConfig(env: Record<string, string | undefined>): MySQLConfig {\n const host = env.MYSQL_HOST;\n const user = env.MYSQL_USER;\n const password = env.MYSQL_PASSWORD;\n\n if (!host) throw new Error('Missing required environment variable: MYSQL_HOST');\n if (!user) throw new Error('Missing required environment variable: MYSQL_USER');\n if (!password) throw new Error('Missing required environment variable: MYSQL_PASSWORD');\n\n return {\n host,\n port: env.MYSQL_PORT ? parseInt(env.MYSQL_PORT, 10) : 3306,\n user,\n password,\n database: env.MYSQL_DATABASE || undefined,\n };\n}\n\nexport function parseArgs(argv: string[]): { connectionString?: string; readonly: boolean } {\n let connectionString: string | undefined;\n let readonly = false;\n\n for (const arg of argv) {\n if (arg === '--readonly') {\n readonly = true;\n } else if (arg.startsWith('mysql://')) {\n connectionString = arg;\n }\n }\n\n return { connectionString, readonly };\n}\n\nexport function resolveConfig(argv: string[], env: Record<string, string | undefined> = process.env): AppConfig {\n const args = parseArgs(argv);\n\n const mysql = args.connectionString ? parseConnectionString(args.connectionString) : parseEnvConfig(env);\n\n const readonly = args.readonly || env.MYSQL_READONLY === 'true';\n const maxRows = env.MYSQL_MAX_ROWS ? parseInt(env.MYSQL_MAX_ROWS, 10) : 100;\n const queryTimeout = env.MYSQL_QUERY_TIMEOUT !== undefined ? parseInt(env.MYSQL_QUERY_TIMEOUT, 10) : 30000;\n const ssl = env.MYSQL_SSL === 'true';\n\n return { mysql, readonly, maxRows, queryTimeout, ssl };\n}\n","import mysql from 'mysql2/promise';\nimport type { Pool } from 'mysql2/promise';\nimport type { MySQLConfig } from './config.js';\n\nexport interface ConnectionManager {\n getPool(): Pool;\n close(): Promise<void>;\n}\n\nexport interface ConnectionOptions {\n ssl?: boolean;\n}\n\nexport function createConnectionManager(config: MySQLConfig, options?: ConnectionOptions): ConnectionManager {\n const poolOptions: mysql.PoolOptions = {\n host: config.host,\n port: config.port,\n user: config.user,\n password: config.password,\n database: config.database,\n connectionLimit: 5,\n waitForConnections: true,\n };\n\n if (options?.ssl) {\n poolOptions.ssl = { rejectUnauthorized: true };\n }\n\n const pool = mysql.createPool(poolOptions);\n\n return {\n getPool() {\n return pool;\n },\n async close() {\n await pool.end();\n },\n };\n}\n","import type { Pool } from 'mysql2/promise';\n\ntype QueryFn = (sql: string) => Promise<[unknown, unknown]>;\n\nexport interface QueryRunner {\n query(sql: string): Promise<[unknown, unknown]>;\n withConnection<T>(fn: (query: QueryFn) => Promise<T>): Promise<T>;\n}\n\nexport class QueryTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Query timeout after ${timeoutMs}ms`);\n this.name = 'QueryTimeoutError';\n }\n}\n\nexport interface QueryRunnerOptions {\n readonly: boolean;\n queryTimeout: number;\n}\n\nfunction withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {\n if (timeoutMs <= 0) return promise;\n\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => setTimeout(() => reject(new QueryTimeoutError(timeoutMs)), timeoutMs)),\n ]);\n}\n\nexport function createQueryRunner(pool: Pool, options: QueryRunnerOptions): QueryRunner {\n const { readonly, queryTimeout } = options;\n\n return {\n async query(sql: string): Promise<[unknown, unknown]> {\n if (!readonly) {\n return withTimeout(pool.query(sql) as Promise<[unknown, unknown]>, queryTimeout);\n }\n\n const conn = await pool.getConnection();\n try {\n await conn.query('SET SESSION TRANSACTION READ ONLY');\n await conn.beginTransaction();\n const result = await withTimeout(conn.query(sql) as Promise<[unknown, unknown]>, queryTimeout);\n await conn.rollback();\n return result;\n } catch (error) {\n try {\n await conn.rollback();\n } catch {\n // rollback 실패 무시\n }\n throw error;\n } finally {\n conn.release();\n }\n },\n\n async withConnection<T>(fn: (query: QueryFn) => Promise<T>): Promise<T> {\n const conn = await pool.getConnection();\n try {\n if (readonly) {\n await conn.query('SET SESSION TRANSACTION READ ONLY');\n await conn.beginTransaction();\n }\n\n const queryFn: QueryFn = (sql: string) =>\n withTimeout(conn.query(sql) as Promise<[unknown, unknown]>, queryTimeout);\n\n const result = await fn(queryFn);\n\n if (readonly) {\n await conn.rollback();\n }\n\n return result;\n } catch (error) {\n if (readonly) {\n try {\n await conn.rollback();\n } catch {\n // rollback 실패 무시\n }\n }\n throw error;\n } finally {\n conn.release();\n }\n },\n };\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { QueryRunner } from './query-runner.js';\nimport { registerAllTools } from './tools/index.js';\n\nexport function createMcpServer(runner: QueryRunner, readonly: boolean, maxRows: number): McpServer {\n const server = new McpServer({\n name: '@imrieul/mysql-mcp-server',\n version: '0.1.0',\n });\n\n registerAllTools(server, runner, readonly, maxRows);\n\n return server;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\n\nexport const queryToolName = 'query';\n\nexport const queryToolConfig = {\n title: 'Query',\n description: 'Execute a read-only SQL query (SELECT, SHOW, DESCRIBE, EXPLAIN).',\n inputSchema: {\n sql: z\n .string()\n .describe(\n 'The SQL query to execute. Only SELECT, SHOW, DESCRIBE, EXPLAIN, and WITH (CTE) statements are allowed.',\n ),\n },\n};\n\nconst ALLOWED_PREFIXES = ['SELECT', 'SHOW', 'DESCRIBE', 'EXPLAIN', 'WITH'];\nconst LIMIT_PREFIXES = ['SELECT', 'WITH'];\n\nfunction needsLimit(normalized: string): boolean {\n if (!LIMIT_PREFIXES.some((p) => normalized.startsWith(p))) return false;\n return !/\\bLIMIT\\b/i.test(normalized);\n}\n\nexport function createQueryHandler(runner: QueryRunner, maxRows: number) {\n return async ({ sql }: { sql: string }) => {\n const normalized = sql.trim().toUpperCase();\n const isAllowed = ALLOWED_PREFIXES.some((prefix) => normalized.startsWith(prefix));\n\n if (!isAllowed) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Only SELECT, SHOW, DESCRIBE, EXPLAIN queries are allowed. Use the \"execute\" tool for data modification.',\n },\n ],\n };\n }\n\n try {\n const finalSql = needsLimit(normalized) ? `${sql.trim()} LIMIT ${maxRows}` : sql;\n const [rows] = await runner.query(finalSql);\n const arr = rows as Record<string, unknown>[];\n if (arr.length === 0) {\n return { content: [{ type: 'text' as const, text: '(empty)' }] };\n }\n const cols = Object.keys(arr[0]);\n const data = arr.map((r) => cols.map((c) => r[c]));\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ columns: cols, rows: data }) }],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","const HINTS: [RegExp, string][] = [\n [/Table '.*' doesn't exist/i, 'Hint: use list_tables to check available tables.'],\n [/Unknown column/i, 'Hint: use describe_table to check column names.'],\n [/Unknown database/i, 'Hint: use list_databases to check available databases.'],\n [/Access denied/i, 'Hint: check database user permissions.'],\n [/ECONNREFUSED|ETIMEDOUT|ENOTFOUND/i, 'Hint: check MYSQL_HOST and MYSQL_PORT settings.'],\n [/ER_PARSE_ERROR/i, 'Hint: check SQL syntax.'],\n [/Query timeout/i, 'Hint: increase MYSQL_QUERY_TIMEOUT or optimize the query.'],\n];\n\nexport function formatError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n const hint = HINTS.find(([pattern]) => pattern.test(message));\n return hint ? `Error: ${message}\\n${hint[1]}` : `Error: ${message}`;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\n\nexport const executeToolName = 'execute';\n\nexport const executeToolConfig = {\n title: 'Execute',\n description: 'Execute a data modification SQL statement (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.).',\n inputSchema: {\n sql: z\n .string()\n .describe('The SQL statement to execute. SELECT statements are not allowed here; use the \"query\" tool instead.'),\n },\n};\n\nexport function createExecuteHandler(runner: QueryRunner, isReadonly: boolean) {\n return async ({ sql }: { sql: string }) => {\n if (isReadonly) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Server is in read-only mode. Data modification is not allowed.',\n },\n ],\n };\n }\n\n const normalized = sql.trim().toUpperCase();\n if (normalized.startsWith('SELECT') || normalized.startsWith('WITH')) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Use the \"query\" tool for SELECT statements.',\n },\n ],\n };\n }\n\n try {\n const [result] = await runner.query(sql);\n const r = result as unknown as Record<string, unknown>;\n return {\n content: [\n { type: 'text' as const, text: `affectedRows: ${r.affectedRows}, changedRows: ${r.changedRows ?? 0}` },\n ],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\n\nexport const listDatabasesToolName = 'list_databases';\n\nexport const listDatabasesToolConfig = {\n title: 'List Databases',\n description: 'List all databases on the MySQL server.',\n};\n\nexport function createListDatabasesHandler(runner: QueryRunner) {\n return async () => {\n try {\n const [rows] = await runner.query('SHOW DATABASES');\n const databases = (rows as Record<string, string>[]).map((r) => Object.values(r)[0]);\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(databases) }],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue } from './sql-escape.js';\n\nexport const listTablesToolName = 'list_tables';\n\nexport const listTablesToolConfig = {\n title: 'List Tables',\n description: 'List all tables in the specified database (or the current database if not specified).',\n inputSchema: {\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createListTablesHandler(runner: QueryRunner) {\n return async ({ database }: { database?: string }) => {\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const sql = `SELECT TABLE_NAME, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ${quoteStringValue(db)} ORDER BY TABLE_NAME`;\n const [rows] = await query(sql);\n const lines = (rows as Record<string, string>[]).map((r) => {\n const comment = r.TABLE_COMMENT;\n return comment ? `${r.TABLE_NAME} -- ${comment}` : r.TABLE_NAME;\n });\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","type QueryFn = (sql: string) => Promise<[unknown, unknown]>;\n\nexport async function resolveDatabase(query: QueryFn, database?: string): Promise<string | null> {\n if (database) return database;\n const [rows] = await query('SELECT DATABASE() AS db');\n const db = (rows as Record<string, unknown>[])[0]?.db;\n return typeof db === 'string' ? db : null;\n}\n","export function escapeStringValue(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"''\");\n}\n\nexport function quoteStringValue(value: string): string {\n return `'${escapeStringValue(value)}'`;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue } from './sql-escape.js';\nimport { formatColumn } from './format-column.js';\n\nexport const describeTableToolName = 'describe_table';\n\nexport const describeTableToolConfig = {\n title: 'Describe Table',\n description: 'Show the schema/structure of a table, including column names, types, constraints, and comments.',\n inputSchema: {\n table: z.string().describe('Table name to describe.'),\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createDescribeTableHandler(runner: QueryRunner) {\n return async ({ table, database }: { table: string; database?: string }) => {\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const sql = `SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${quoteStringValue(db)} AND TABLE_NAME = ${quoteStringValue(table)} ORDER BY ORDINAL_POSITION`;\n const [rows] = await query(sql);\n const typedRows = rows as Record<string, unknown>[];\n\n if (typedRows.length === 0) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: `Error: Table '${table}' doesn't exist in database '${db}'.\\nHint: use list_tables to check available tables.`,\n },\n ],\n };\n }\n\n const columns = typedRows.map((r) =>\n formatColumn({\n name: String(r.COLUMN_NAME),\n type: String(r.COLUMN_TYPE),\n nullable: r.IS_NULLABLE === 'YES',\n key: String(r.COLUMN_KEY ?? ''),\n defaultValue: r.COLUMN_DEFAULT,\n extra: String(r.EXTRA ?? ''),\n comment: String(r.COLUMN_COMMENT ?? ''),\n }),\n );\n return {\n content: [{ type: 'text' as const, text: `${table}:\\n${columns.join('\\n')}` }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","export interface ColumnInfo {\n name: string;\n type: string;\n nullable: boolean;\n key: string;\n defaultValue: unknown;\n extra: string;\n comment: string;\n}\n\nexport function formatColumn(col: ColumnInfo): string {\n let result = `${col.name} ${col.type}`;\n if (!col.nullable) result += ' NOT NULL';\n if (col.key === 'PRI') result += ' PK';\n else if (col.key === 'UNI') result += ' UNIQUE';\n else if (col.key === 'MUL') result += ' INDEX';\n if (col.defaultValue != null) result += ` DEFAULT ${col.defaultValue}`;\n if (col.extra) result += ` ${col.extra}`;\n if (col.comment) result += ` -- ${col.comment}`;\n return result;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue } from './sql-escape.js';\nimport { formatColumn } from './format-column.js';\n\nexport const describeAllTablesToolName = 'describe_all_tables';\n\nexport const describeAllTablesToolConfig = {\n title: 'Describe All Tables',\n description:\n 'Show the schema of all tables at once. Much more efficient than calling describe_table for each table individually.',\n inputSchema: {\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createDescribeAllTablesHandler(runner: QueryRunner) {\n return async ({ database }: { database?: string }) => {\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const sql = `SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${quoteStringValue(db)} ORDER BY TABLE_NAME, ORDINAL_POSITION`;\n const [rows] = await query(sql);\n const typedRows = rows as Record<string, unknown>[];\n\n if (typedRows.length === 0) {\n return { content: [{ type: 'text' as const, text: '(no tables)' }] };\n }\n\n const tableMap = new Map<string, string[]>();\n for (const r of typedRows) {\n const tableName = String(r.TABLE_NAME);\n const line = formatColumn({\n name: String(r.COLUMN_NAME),\n type: String(r.COLUMN_TYPE),\n nullable: r.IS_NULLABLE === 'YES',\n key: String(r.COLUMN_KEY ?? ''),\n defaultValue: r.COLUMN_DEFAULT,\n extra: String(r.EXTRA ?? ''),\n comment: String(r.COLUMN_COMMENT ?? ''),\n });\n if (!tableMap.has(tableName)) {\n tableMap.set(tableName, []);\n }\n tableMap.get(tableName)!.push(line);\n }\n\n const parts = Array.from(tableMap.entries()).map(([table, lines]) => `${table}:\\n${lines.join('\\n')}`);\n\n return {\n content: [{ type: 'text' as const, text: parts.join('\\n\\n') }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue, escapeStringValue } from './sql-escape.js';\n\nexport const addCommentToolName = 'add_comment';\n\nexport const addCommentToolConfig = {\n title: 'Add Comment',\n description:\n 'Safely add a comment to a table or column. This tool only modifies comments — it cannot alter table structure, column types, or data.',\n inputSchema: {\n table: z.string().describe('Table name.'),\n column: z.string().optional().describe('Column name. If omitted, sets a table-level comment.'),\n comment: z.string().describe('Comment text to set.'),\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createAddCommentHandler(runner: QueryRunner, isReadonly: boolean) {\n return async ({\n table,\n column,\n comment,\n database,\n }: {\n table: string;\n column?: string;\n comment: string;\n database?: string;\n }) => {\n if (isReadonly) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Server is in read-only mode. Modifying comments is not allowed.',\n },\n ],\n };\n }\n\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const fullName = `\\`${db}\\`.\\`${table}\\``;\n const escapedComment = escapeStringValue(comment);\n\n if (!column) {\n const sql = `ALTER TABLE ${fullName} COMMENT = '${escapedComment}'`;\n await query(sql);\n return {\n content: [{ type: 'text' as const, text: `Table comment updated: ${table}` }],\n };\n }\n\n const colSql = `SELECT COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${quoteStringValue(db)} AND TABLE_NAME = ${quoteStringValue(table)} AND COLUMN_NAME = ${quoteStringValue(column)}`;\n const [rows] = await query(colSql);\n const colInfo = (rows as Record<string, unknown>[])[0];\n\n if (!colInfo) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: `Error: Column '${column}' doesn't exist in table '${table}'.\\nHint: use describe_table to check available columns.`,\n },\n ],\n };\n }\n\n let modifySql = `ALTER TABLE ${fullName} MODIFY COLUMN \\`${column}\\` ${colInfo.COLUMN_TYPE}`;\n if (colInfo.IS_NULLABLE === 'NO') modifySql += ' NOT NULL';\n if (colInfo.COLUMN_DEFAULT != null)\n modifySql += ` DEFAULT '${escapeStringValue(String(colInfo.COLUMN_DEFAULT))}'`;\n if (colInfo.EXTRA) modifySql += ` ${colInfo.EXTRA}`;\n modifySql += ` COMMENT '${escapedComment}'`;\n\n await query(modifySql);\n return {\n content: [{ type: 'text' as const, text: `Column comment updated: ${table}.${column}` }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { QueryRunner } from '../query-runner.js';\nimport { queryToolName, queryToolConfig, createQueryHandler } from './query.js';\nimport { executeToolName, executeToolConfig, createExecuteHandler } from './execute.js';\nimport { listDatabasesToolName, listDatabasesToolConfig, createListDatabasesHandler } from './list-databases.js';\nimport { listTablesToolName, listTablesToolConfig, createListTablesHandler } from './list-tables.js';\nimport { describeTableToolName, describeTableToolConfig, createDescribeTableHandler } from './describe-table.js';\nimport {\n describeAllTablesToolName,\n describeAllTablesToolConfig,\n createDescribeAllTablesHandler,\n} from './describe-all-tables.js';\nimport { addCommentToolName, addCommentToolConfig, createAddCommentHandler } from './add-comment.js';\n\nexport function registerAllTools(server: McpServer, runner: QueryRunner, readonly: boolean, maxRows: number): void {\n server.tool(\n queryToolName,\n queryToolConfig.description,\n queryToolConfig.inputSchema,\n createQueryHandler(runner, maxRows),\n );\n server.tool(\n executeToolName,\n executeToolConfig.description,\n executeToolConfig.inputSchema,\n createExecuteHandler(runner, readonly),\n );\n server.tool(listDatabasesToolName, listDatabasesToolConfig.description, createListDatabasesHandler(runner));\n server.tool(\n listTablesToolName,\n listTablesToolConfig.description,\n listTablesToolConfig.inputSchema,\n createListTablesHandler(runner),\n );\n server.tool(\n describeTableToolName,\n describeTableToolConfig.description,\n describeTableToolConfig.inputSchema,\n createDescribeTableHandler(runner),\n );\n server.tool(\n describeAllTablesToolName,\n describeAllTablesToolConfig.description,\n describeAllTablesToolConfig.inputSchema,\n createDescribeAllTablesHandler(runner),\n );\n server.tool(\n addCommentToolName,\n addCommentToolConfig.description,\n addCommentToolConfig.inputSchema,\n createAddCommentHandler(runner, readonly),\n );\n}\n"],"mappings":"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","names":["mysql","z","z","z","z","z","z","z","z","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/connection.ts","../src/query-runner.ts","../src/server.ts","../src/tools/query.ts","../src/tools/error-hint.ts","../src/tools/validate-input.ts","../src/tools/execute.ts","../src/tools/list-databases.ts","../src/tools/list-tables.ts","../src/tools/resolve-database.ts","../src/tools/sql-escape.ts","../src/tools/describe-table.ts","../src/tools/format-column.ts","../src/tools/describe-all-tables.ts","../src/tools/add-comment.ts","../src/tools/index.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { parseArgs, resolveConfig } from './config.js';\nimport { createConnectionManager } from './connection.js';\nimport { createQueryRunner } from './query-runner.js';\nimport { createMcpServer } from './server.js';\nimport { createRequire } from 'module';\n\nconst HELP_TEXT = `Usage: mysql-mcp-server [options] [mysql://user:pass@host:port/db]\n\nMySQL MCP Server - Model Context Protocol server for MySQL database operations\n\nOptions:\n --readonly Enable read-only mode (blocks execute and add_comment)\n --help, -h Show this help message\n --version Show version number\n\nEnvironment variables:\n MYSQL_HOST MySQL host (required if no connection string)\n MYSQL_PORT MySQL port (default: 3306)\n MYSQL_USER MySQL user (required if no connection string)\n MYSQL_PASSWORD MySQL password (required if no connection string)\n MYSQL_DATABASE Default database\n MYSQL_READONLY Read-only mode (true/false)\n MYSQL_MAX_ROWS Max rows for SELECT queries (default: 100)\n MYSQL_QUERY_TIMEOUT Query timeout in ms (default: 30000, 0 to disable)\n MYSQL_SSL Enable SSL (true/false)\n\nExamples:\n mysql-mcp-server mysql://root:pass@localhost:3306/mydb\n mysql-mcp-server --readonly\n MYSQL_HOST=localhost MYSQL_USER=root MYSQL_PASSWORD=pass mysql-mcp-server`;\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv.slice(2));\n\n if (args.help) {\n console.log(HELP_TEXT);\n process.exit(0);\n }\n\n if (args.version) {\n const require = createRequire(import.meta.url);\n const pkg = require('../package.json') as { version: string };\n console.log(pkg.version);\n process.exit(0);\n }\n\n const config = resolveConfig(process.argv.slice(2));\n const connectionManager = createConnectionManager(config.mysql, { ssl: config.ssl });\n const runner = createQueryRunner(connectionManager.getPool(), {\n readonly: config.readonly,\n queryTimeout: config.queryTimeout,\n });\n\n const server = createMcpServer(runner, config.readonly, config.maxRows);\n const transport = new StdioServerTransport();\n\n const shutdown = async () => {\n await server.close();\n await connectionManager.close();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n process.stdin.on('end', shutdown);\n\n console.error('MySQL MCP Server starting...');\n console.error(`Readonly mode: ${config.readonly}`);\n console.error(`Query timeout: ${config.queryTimeout}ms`);\n console.error(`SSL: ${config.ssl}`);\n\n await server.connect(transport);\n console.error('MySQL MCP Server connected via stdio');\n}\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n","export interface MySQLConfig {\n host: string;\n port: number;\n user: string;\n password: string;\n database?: string;\n}\n\nexport interface AppConfig {\n mysql: MySQLConfig;\n readonly: boolean;\n maxRows: number;\n queryTimeout: number;\n ssl: boolean;\n}\n\nexport function parseConnectionString(connStr: string): MySQLConfig {\n let url: URL;\n try {\n url = new URL(connStr);\n } catch {\n throw new Error(`Invalid connection string: ${connStr}`);\n }\n\n if (url.protocol !== 'mysql:') {\n throw new Error(`Expected mysql:// protocol, got ${url.protocol}`);\n }\n\n const database = url.pathname.slice(1) || undefined;\n\n return {\n host: url.hostname,\n port: url.port ? parseInt(url.port, 10) : 3306,\n user: decodeURIComponent(url.username),\n password: decodeURIComponent(url.password),\n database,\n };\n}\n\nexport function parseEnvConfig(env: Record<string, string | undefined>): MySQLConfig {\n const host = env.MYSQL_HOST;\n const user = env.MYSQL_USER;\n const password = env.MYSQL_PASSWORD;\n\n if (!host) throw new Error('Missing required environment variable: MYSQL_HOST');\n if (!user) throw new Error('Missing required environment variable: MYSQL_USER');\n if (!password) throw new Error('Missing required environment variable: MYSQL_PASSWORD');\n\n return {\n host,\n port: env.MYSQL_PORT ? parseInt(env.MYSQL_PORT, 10) : 3306,\n user,\n password,\n database: env.MYSQL_DATABASE || undefined,\n };\n}\n\nexport interface ParsedArgs {\n connectionString?: string;\n readonly: boolean;\n help: boolean;\n version: boolean;\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n let connectionString: string | undefined;\n let readonly = false;\n let help = false;\n let version = false;\n\n for (const arg of argv) {\n if (arg === '--readonly') {\n readonly = true;\n } else if (arg === '--help' || arg === '-h') {\n help = true;\n } else if (arg === '--version') {\n version = true;\n } else if (arg.startsWith('mysql://')) {\n connectionString = arg;\n }\n }\n\n return { connectionString, readonly, help, version };\n}\n\nexport function resolveConfig(argv: string[], env: Record<string, string | undefined> = process.env): AppConfig {\n const args = parseArgs(argv);\n\n const mysql = args.connectionString ? parseConnectionString(args.connectionString) : parseEnvConfig(env);\n\n const readonly = args.readonly || env.MYSQL_READONLY === 'true';\n const maxRows = env.MYSQL_MAX_ROWS ? parseInt(env.MYSQL_MAX_ROWS, 10) : 100;\n const queryTimeout = env.MYSQL_QUERY_TIMEOUT !== undefined ? parseInt(env.MYSQL_QUERY_TIMEOUT, 10) : 30000;\n const ssl = env.MYSQL_SSL === 'true';\n\n return { mysql, readonly, maxRows, queryTimeout, ssl };\n}\n","import mysql from 'mysql2/promise';\nimport type { Pool } from 'mysql2/promise';\nimport type { MySQLConfig } from './config.js';\n\nexport interface ConnectionManager {\n getPool(): Pool;\n close(): Promise<void>;\n}\n\nexport interface ConnectionOptions {\n ssl?: boolean;\n}\n\nexport function createConnectionManager(config: MySQLConfig, options?: ConnectionOptions): ConnectionManager {\n const poolOptions: mysql.PoolOptions = {\n host: config.host,\n port: config.port,\n user: config.user,\n password: config.password,\n database: config.database,\n connectionLimit: 5,\n waitForConnections: true,\n };\n\n if (options?.ssl) {\n poolOptions.ssl = { rejectUnauthorized: true };\n }\n\n const pool = mysql.createPool(poolOptions);\n\n return {\n getPool() {\n return pool;\n },\n async close() {\n await pool.end();\n },\n };\n}\n","import type { Pool } from 'mysql2/promise';\n\ntype QueryFn = (sql: string) => Promise<[unknown, unknown]>;\n\nexport interface QueryRunner {\n query(sql: string): Promise<[unknown, unknown]>;\n withConnection<T>(fn: (query: QueryFn) => Promise<T>): Promise<T>;\n}\n\nexport class QueryTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Query timeout after ${timeoutMs}ms`);\n this.name = 'QueryTimeoutError';\n }\n}\n\nexport interface QueryRunnerOptions {\n readonly: boolean;\n queryTimeout: number;\n}\n\nfunction withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {\n if (timeoutMs <= 0) return promise;\n\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => setTimeout(() => reject(new QueryTimeoutError(timeoutMs)), timeoutMs)),\n ]);\n}\n\nexport function createQueryRunner(pool: Pool, options: QueryRunnerOptions): QueryRunner {\n const { readonly, queryTimeout } = options;\n\n return {\n async query(sql: string): Promise<[unknown, unknown]> {\n if (!readonly) {\n return withTimeout(pool.query(sql) as Promise<[unknown, unknown]>, queryTimeout);\n }\n\n const conn = await pool.getConnection();\n try {\n await conn.query('SET SESSION TRANSACTION READ ONLY');\n await conn.beginTransaction();\n const result = await withTimeout(conn.query(sql) as Promise<[unknown, unknown]>, queryTimeout);\n await conn.rollback();\n return result;\n } catch (error) {\n try {\n await conn.rollback();\n } catch {\n // rollback 실패 무시\n }\n throw error;\n } finally {\n conn.release();\n }\n },\n\n async withConnection<T>(fn: (query: QueryFn) => Promise<T>): Promise<T> {\n const conn = await pool.getConnection();\n try {\n if (readonly) {\n await conn.query('SET SESSION TRANSACTION READ ONLY');\n await conn.beginTransaction();\n }\n\n const queryFn: QueryFn = (sql: string) =>\n withTimeout(conn.query(sql) as Promise<[unknown, unknown]>, queryTimeout);\n\n const result = await fn(queryFn);\n\n if (readonly) {\n await conn.rollback();\n }\n\n return result;\n } catch (error) {\n if (readonly) {\n try {\n await conn.rollback();\n } catch {\n // rollback 실패 무시\n }\n }\n throw error;\n } finally {\n conn.release();\n }\n },\n };\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { QueryRunner } from './query-runner.js';\nimport { registerAllTools } from './tools/index.js';\n\nexport function createMcpServer(runner: QueryRunner, readonly: boolean, maxRows: number): McpServer {\n const server = new McpServer({\n name: '@imrieul/mysql-mcp-server',\n version: '0.1.0',\n });\n\n registerAllTools(server, runner, readonly, maxRows);\n\n return server;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { validateSql } from './validate-input.js';\n\nexport const queryToolName = 'query';\n\nexport const queryToolConfig = {\n title: 'Query',\n description:\n 'Execute a read-only SQL query (SELECT, SHOW, DESCRIBE, EXPLAIN). ' +\n 'LIMIT is auto-appended to SELECT/WITH queries without one (default: server maxRows). ' +\n 'Prefer specific columns over SELECT * to reduce response size. ' +\n 'For data modification, use the \"execute\" tool instead.',\n inputSchema: {\n sql: z\n .string()\n .describe(\n 'The SQL query to execute. Only SELECT, SHOW, DESCRIBE, EXPLAIN, and WITH (CTE) statements are allowed.',\n ),\n },\n};\n\nconst ALLOWED_PREFIXES = ['SELECT', 'SHOW', 'DESCRIBE', 'EXPLAIN', 'WITH'];\nconst LIMIT_PREFIXES = ['SELECT', 'WITH'];\n\nfunction needsLimit(normalized: string): boolean {\n if (!LIMIT_PREFIXES.some((p) => normalized.startsWith(p))) return false;\n return !/\\bLIMIT\\b/i.test(normalized);\n}\n\nexport function createQueryHandler(runner: QueryRunner, maxRows: number) {\n return async ({ sql }: { sql: string }) => {\n const validation = validateSql(sql);\n if (!validation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: validation.message! }],\n };\n }\n\n const normalized = sql.trim().toUpperCase();\n const isAllowed = ALLOWED_PREFIXES.some((prefix) => normalized.startsWith(prefix));\n\n if (!isAllowed) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Only SELECT, SHOW, DESCRIBE, EXPLAIN queries are allowed. Use the \"execute\" tool for data modification.',\n },\n ],\n };\n }\n\n try {\n const finalSql = needsLimit(normalized) ? `${sql.trim()} LIMIT ${maxRows}` : sql;\n const [rows] = await runner.query(finalSql);\n const arr = rows as Record<string, unknown>[];\n if (arr.length === 0) {\n return { content: [{ type: 'text' as const, text: '(empty)' }] };\n }\n const cols = Object.keys(arr[0]);\n const data = arr.map((r) => cols.map((c) => r[c]));\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ columns: cols, rows: data }) }],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","const HINTS: [RegExp, string][] = [\n [/Table '.*' doesn't exist/i, 'Hint: use list_tables to check available tables.'],\n [/Unknown column/i, 'Hint: use describe_table to check column names.'],\n [/Unknown database/i, 'Hint: use list_databases to check available databases.'],\n [/Access denied/i, 'Hint: check database user permissions.'],\n [/ECONNREFUSED|ETIMEDOUT|ENOTFOUND/i, 'Hint: check MYSQL_HOST and MYSQL_PORT settings.'],\n [/ER_PARSE_ERROR/i, 'Hint: check SQL syntax.'],\n [/Query timeout/i, 'Hint: increase MYSQL_QUERY_TIMEOUT or optimize the query.'],\n];\n\nexport function formatError(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n const hint = HINTS.find(([pattern]) => pattern.test(message));\n return hint ? `Error: ${message}\\n${hint[1]}` : `Error: ${message}`;\n}\n","/**\n * 에이전트 환각 대비 입력 검증 모듈\n * - 제어문자 거부 (탭/개행/캐리지리턴 제외)\n * - 식별자(테이블/컬럼명) 위험 패턴 거부\n */\n\nfunction hasControlChars(str: string): boolean {\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n // 허용: \\t(9), \\n(10), \\r(13)\n if (code === 9 || code === 10 || code === 13) continue;\n // 제어문자: 0x00-0x1f, 0x7f\n if (code <= 0x1f || code === 0x7f) return true;\n }\n return false;\n}\n\nconst DANGEROUS_IDENTIFIER_PATTERNS = [\n /;/, // SQL statement separator\n /--/, // SQL line comment\n /\\/\\*/, // SQL block comment start\n /\\*\\//, // SQL block comment end\n /\\\\/, // backslash escape\n];\n\nexport interface ValidationResult {\n valid: boolean;\n message?: string;\n}\n\nexport function validateSql(sql: string): ValidationResult {\n if (hasControlChars(sql)) {\n return {\n valid: false,\n message: 'Error: SQL contains control characters. Remove non-printable characters (tab and newline are allowed).',\n };\n }\n return { valid: true };\n}\n\nexport function validateIdentifier(name: string, label: string): ValidationResult {\n if (!name || name.trim().length === 0) {\n return { valid: false, message: `Error: ${label} name cannot be empty.` };\n }\n\n if (hasControlChars(name)) {\n return {\n valid: false,\n message: `Error: ${label} name contains control characters.`,\n };\n }\n\n for (const pattern of DANGEROUS_IDENTIFIER_PATTERNS) {\n if (pattern.test(name)) {\n return {\n valid: false,\n message: `Error: ${label} name contains dangerous characters (${pattern.source}). Use only valid MySQL identifier characters.`,\n };\n }\n }\n\n if (name.length > 64) {\n return {\n valid: false,\n message: `Error: ${label} name exceeds MySQL's 64-character limit.`,\n };\n }\n\n return { valid: true };\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { validateSql } from './validate-input.js';\n\nexport const executeToolName = 'execute';\n\nexport const executeToolConfig = {\n title: 'Execute',\n description:\n 'Execute a data modification SQL statement (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, etc.). ' +\n 'Set dryRun=true to validate without executing — uses EXPLAIN for DML, or previews the SQL for DDL. ' +\n 'Always confirm destructive operations (DROP, TRUNCATE, DELETE without WHERE) with the user before executing. ' +\n 'Not available in read-only mode.',\n inputSchema: {\n sql: z\n .string()\n .describe('The SQL statement to execute. SELECT statements are not allowed here; use the \"query\" tool instead.'),\n dryRun: z\n .boolean()\n .optional()\n .describe('If true, validates the statement via EXPLAIN without executing it. Defaults to false.'),\n },\n};\n\nexport function createExecuteHandler(runner: QueryRunner, isReadonly: boolean) {\n return async ({ sql, dryRun }: { sql: string; dryRun?: boolean }) => {\n if (isReadonly) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Server is in read-only mode. Data modification is not allowed.',\n },\n ],\n };\n }\n\n const validation = validateSql(sql);\n if (!validation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: validation.message! }],\n };\n }\n\n const normalized = sql.trim().toUpperCase();\n if (normalized.startsWith('SELECT') || normalized.startsWith('WITH')) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Use the \"query\" tool for SELECT statements.',\n },\n ],\n };\n }\n\n if (dryRun) {\n const DDL_PREFIXES = ['CREATE', 'DROP', 'ALTER', 'TRUNCATE', 'RENAME'];\n const isDdl = DDL_PREFIXES.some((p) => normalized.startsWith(p));\n\n if (isDdl) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `[dry-run] SQL preview (DDL cannot be validated via EXPLAIN):\\n${sql}`,\n },\n ],\n };\n }\n\n try {\n const [rows] = await runner.query(`EXPLAIN ${sql}`);\n return {\n content: [\n {\n type: 'text' as const,\n text: `[dry-run] Statement validated via EXPLAIN:\\n${JSON.stringify(rows, null, 2)}`,\n },\n ],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: `[dry-run] Validation failed: ${formatError(error)}` }],\n };\n }\n }\n\n try {\n const [result] = await runner.query(sql);\n const r = result as unknown as Record<string, unknown>;\n return {\n content: [\n { type: 'text' as const, text: `affectedRows: ${r.affectedRows}, changedRows: ${r.changedRows ?? 0}` },\n ],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\n\nexport const listDatabasesToolName = 'list_databases';\n\nexport const listDatabasesToolConfig = {\n title: 'List Databases',\n description:\n 'List all databases on the MySQL server. ' +\n 'Use this as a starting point to discover available databases before querying. ' +\n 'Returns a JSON array of database names.',\n};\n\nexport function createListDatabasesHandler(runner: QueryRunner) {\n return async () => {\n try {\n const [rows] = await runner.query('SHOW DATABASES');\n const databases = (rows as Record<string, string>[]).map((r) => Object.values(r)[0]);\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(databases) }],\n };\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue } from './sql-escape.js';\nimport { validateIdentifier } from './validate-input.js';\n\nexport const listTablesToolName = 'list_tables';\n\nexport const listTablesToolConfig = {\n title: 'List Tables',\n description:\n 'List all tables in the specified database (or the current database if not specified). ' +\n 'Includes table comments when available. ' +\n 'Use this before describe_table to find the exact table name.',\n inputSchema: {\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createListTablesHandler(runner: QueryRunner) {\n return async ({ database }: { database?: string }) => {\n if (database) {\n const dbValidation = validateIdentifier(database, 'Database');\n if (!dbValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: dbValidation.message! }],\n };\n }\n }\n\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const sql = `SELECT TABLE_NAME, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = ${quoteStringValue(db)} ORDER BY TABLE_NAME`;\n const [rows] = await query(sql);\n const lines = (rows as Record<string, string>[]).map((r) => {\n const comment = r.TABLE_COMMENT;\n return comment ? `${r.TABLE_NAME} -- ${comment}` : r.TABLE_NAME;\n });\n return {\n content: [{ type: 'text' as const, text: lines.join('\\n') }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","type QueryFn = (sql: string) => Promise<[unknown, unknown]>;\n\nexport async function resolveDatabase(query: QueryFn, database?: string): Promise<string | null> {\n if (database) return database;\n const [rows] = await query('SELECT DATABASE() AS db');\n const db = (rows as Record<string, unknown>[])[0]?.db;\n return typeof db === 'string' ? db : null;\n}\n","export function escapeStringValue(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"''\");\n}\n\nexport function quoteStringValue(value: string): string {\n return `'${escapeStringValue(value)}'`;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue } from './sql-escape.js';\nimport { formatColumn } from './format-column.js';\nimport { validateIdentifier } from './validate-input.js';\n\nexport const describeTableToolName = 'describe_table';\n\nexport const describeTableToolConfig = {\n title: 'Describe Table',\n description:\n 'Show the schema/structure of a table, including column names, types, constraints, and comments. ' +\n 'Use this before writing queries to ensure correct column names and types. ' +\n 'For inspecting all tables at once, use describe_all_tables instead.',\n inputSchema: {\n table: z.string().describe('Table name to describe.'),\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createDescribeTableHandler(runner: QueryRunner) {\n return async ({ table, database }: { table: string; database?: string }) => {\n const tableValidation = validateIdentifier(table, 'Table');\n if (!tableValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: tableValidation.message! }],\n };\n }\n\n if (database) {\n const dbValidation = validateIdentifier(database, 'Database');\n if (!dbValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: dbValidation.message! }],\n };\n }\n }\n\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const sql = `SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${quoteStringValue(db)} AND TABLE_NAME = ${quoteStringValue(table)} ORDER BY ORDINAL_POSITION`;\n const [rows] = await query(sql);\n const typedRows = rows as Record<string, unknown>[];\n\n if (typedRows.length === 0) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: `Error: Table '${table}' doesn't exist in database '${db}'.\\nHint: use list_tables to check available tables.`,\n },\n ],\n };\n }\n\n const columns = typedRows.map((r) =>\n formatColumn({\n name: String(r.COLUMN_NAME),\n type: String(r.COLUMN_TYPE),\n nullable: r.IS_NULLABLE === 'YES',\n key: String(r.COLUMN_KEY ?? ''),\n defaultValue: r.COLUMN_DEFAULT,\n extra: String(r.EXTRA ?? ''),\n comment: String(r.COLUMN_COMMENT ?? ''),\n }),\n );\n return {\n content: [{ type: 'text' as const, text: `${table}:\\n${columns.join('\\n')}` }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","export interface ColumnInfo {\n name: string;\n type: string;\n nullable: boolean;\n key: string;\n defaultValue: unknown;\n extra: string;\n comment: string;\n}\n\nexport function formatColumn(col: ColumnInfo): string {\n let result = `${col.name} ${col.type}`;\n if (!col.nullable) result += ' NOT NULL';\n if (col.key === 'PRI') result += ' PK';\n else if (col.key === 'UNI') result += ' UNIQUE';\n else if (col.key === 'MUL') result += ' INDEX';\n if (col.defaultValue != null) result += ` DEFAULT ${col.defaultValue}`;\n if (col.extra) result += ` ${col.extra}`;\n if (col.comment) result += ` -- ${col.comment}`;\n return result;\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue } from './sql-escape.js';\nimport { formatColumn } from './format-column.js';\nimport { validateIdentifier } from './validate-input.js';\n\nexport const describeAllTablesToolName = 'describe_all_tables';\n\nexport const describeAllTablesToolConfig = {\n title: 'Describe All Tables',\n description:\n 'Show the schema of all tables at once. Much more efficient than calling describe_table for each table individually. ' +\n 'Warning: response can be large for databases with many tables — prefer describe_table for specific tables when possible.',\n inputSchema: {\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n },\n};\n\nexport function createDescribeAllTablesHandler(runner: QueryRunner) {\n return async ({ database }: { database?: string }) => {\n if (database) {\n const dbValidation = validateIdentifier(database, 'Database');\n if (!dbValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: dbValidation.message! }],\n };\n }\n }\n\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const sql = `SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${quoteStringValue(db)} ORDER BY TABLE_NAME, ORDINAL_POSITION`;\n const [rows] = await query(sql);\n const typedRows = rows as Record<string, unknown>[];\n\n if (typedRows.length === 0) {\n return { content: [{ type: 'text' as const, text: '(no tables)' }] };\n }\n\n const tableMap = new Map<string, string[]>();\n for (const r of typedRows) {\n const tableName = String(r.TABLE_NAME);\n const line = formatColumn({\n name: String(r.COLUMN_NAME),\n type: String(r.COLUMN_TYPE),\n nullable: r.IS_NULLABLE === 'YES',\n key: String(r.COLUMN_KEY ?? ''),\n defaultValue: r.COLUMN_DEFAULT,\n extra: String(r.EXTRA ?? ''),\n comment: String(r.COLUMN_COMMENT ?? ''),\n });\n if (!tableMap.has(tableName)) {\n tableMap.set(tableName, []);\n }\n tableMap.get(tableName)!.push(line);\n }\n\n const parts = Array.from(tableMap.entries()).map(([table, lines]) => `${table}:\\n${lines.join('\\n')}`);\n\n return {\n content: [{ type: 'text' as const, text: parts.join('\\n\\n') }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { QueryRunner } from '../query-runner.js';\nimport { formatError } from './error-hint.js';\nimport { resolveDatabase } from './resolve-database.js';\nimport { quoteStringValue, escapeStringValue } from './sql-escape.js';\nimport { validateIdentifier } from './validate-input.js';\n\nexport const addCommentToolName = 'add_comment';\n\nexport const addCommentToolConfig = {\n title: 'Add Comment',\n description:\n 'Safely add a comment to a table or column. This tool only modifies comments — it cannot alter table structure, column types, or data. ' +\n 'Set dryRun=true to preview the generated SQL without executing it. ' +\n 'Use describe_table first to verify column names. Not available in read-only mode.',\n inputSchema: {\n table: z.string().describe('Table name.'),\n column: z.string().optional().describe('Column name. If omitted, sets a table-level comment.'),\n comment: z.string().describe('Comment text to set.'),\n database: z.string().optional().describe('Database name. Uses the current database if omitted.'),\n dryRun: z\n .boolean()\n .optional()\n .describe('If true, returns the generated SQL without executing it. Defaults to false.'),\n },\n};\n\nexport function createAddCommentHandler(runner: QueryRunner, isReadonly: boolean) {\n return async ({\n table,\n column,\n comment,\n database,\n dryRun,\n }: {\n table: string;\n column?: string;\n comment: string;\n database?: string;\n dryRun?: boolean;\n }) => {\n if (isReadonly) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: Server is in read-only mode. Modifying comments is not allowed.',\n },\n ],\n };\n }\n\n const tableValidation = validateIdentifier(table, 'Table');\n if (!tableValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: tableValidation.message! }],\n };\n }\n\n if (column) {\n const columnValidation = validateIdentifier(column, 'Column');\n if (!columnValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: columnValidation.message! }],\n };\n }\n }\n\n if (database) {\n const dbValidation = validateIdentifier(database, 'Database');\n if (!dbValidation.valid) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: dbValidation.message! }],\n };\n }\n }\n\n try {\n return await runner.withConnection(async (query) => {\n const db = await resolveDatabase(query, database);\n if (!db) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: 'Error: No database selected. Specify a database name or set MYSQL_DATABASE.',\n },\n ],\n };\n }\n\n const fullName = `\\`${db}\\`.\\`${table}\\``;\n const escapedComment = escapeStringValue(comment);\n\n if (!column) {\n const sql = `ALTER TABLE ${fullName} COMMENT = '${escapedComment}'`;\n if (dryRun) {\n return {\n content: [{ type: 'text' as const, text: `[dry-run] SQL preview:\\n${sql}` }],\n };\n }\n await query(sql);\n return {\n content: [{ type: 'text' as const, text: `Table comment updated: ${table}` }],\n };\n }\n\n const colSql = `SELECT COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ${quoteStringValue(db)} AND TABLE_NAME = ${quoteStringValue(table)} AND COLUMN_NAME = ${quoteStringValue(column)}`;\n const [rows] = await query(colSql);\n const colInfo = (rows as Record<string, unknown>[])[0];\n\n if (!colInfo) {\n return {\n isError: true as const,\n content: [\n {\n type: 'text' as const,\n text: `Error: Column '${column}' doesn't exist in table '${table}'.\\nHint: use describe_table to check available columns.`,\n },\n ],\n };\n }\n\n let modifySql = `ALTER TABLE ${fullName} MODIFY COLUMN \\`${column}\\` ${colInfo.COLUMN_TYPE}`;\n if (colInfo.IS_NULLABLE === 'NO') modifySql += ' NOT NULL';\n if (colInfo.COLUMN_DEFAULT != null)\n modifySql += ` DEFAULT '${escapeStringValue(String(colInfo.COLUMN_DEFAULT))}'`;\n if (colInfo.EXTRA) modifySql += ` ${colInfo.EXTRA}`;\n modifySql += ` COMMENT '${escapedComment}'`;\n\n if (dryRun) {\n return {\n content: [{ type: 'text' as const, text: `[dry-run] SQL preview:\\n${modifySql}` }],\n };\n }\n\n await query(modifySql);\n return {\n content: [{ type: 'text' as const, text: `Column comment updated: ${table}.${column}` }],\n };\n });\n } catch (error) {\n return {\n isError: true as const,\n content: [{ type: 'text' as const, text: formatError(error) }],\n };\n }\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { QueryRunner } from '../query-runner.js';\nimport { queryToolName, queryToolConfig, createQueryHandler } from './query.js';\nimport { executeToolName, executeToolConfig, createExecuteHandler } from './execute.js';\nimport { listDatabasesToolName, listDatabasesToolConfig, createListDatabasesHandler } from './list-databases.js';\nimport { listTablesToolName, listTablesToolConfig, createListTablesHandler } from './list-tables.js';\nimport { describeTableToolName, describeTableToolConfig, createDescribeTableHandler } from './describe-table.js';\nimport {\n describeAllTablesToolName,\n describeAllTablesToolConfig,\n createDescribeAllTablesHandler,\n} from './describe-all-tables.js';\nimport { addCommentToolName, addCommentToolConfig, createAddCommentHandler } from './add-comment.js';\n\nexport function registerAllTools(server: McpServer, runner: QueryRunner, readonly: boolean, maxRows: number): void {\n server.tool(\n queryToolName,\n queryToolConfig.description,\n queryToolConfig.inputSchema,\n createQueryHandler(runner, maxRows),\n );\n server.tool(\n executeToolName,\n executeToolConfig.description,\n executeToolConfig.inputSchema,\n createExecuteHandler(runner, readonly),\n );\n server.tool(listDatabasesToolName, listDatabasesToolConfig.description, createListDatabasesHandler(runner));\n server.tool(\n listTablesToolName,\n listTablesToolConfig.description,\n listTablesToolConfig.inputSchema,\n createListTablesHandler(runner),\n );\n server.tool(\n describeTableToolName,\n describeTableToolConfig.description,\n describeTableToolConfig.inputSchema,\n createDescribeTableHandler(runner),\n );\n server.tool(\n describeAllTablesToolName,\n describeAllTablesToolConfig.description,\n describeAllTablesToolConfig.inputSchema,\n createDescribeAllTablesHandler(runner),\n );\n server.tool(\n addCommentToolName,\n addCommentToolConfig.description,\n addCommentToolConfig.inputSchema,\n createAddCommentHandler(runner, readonly),\n );\n}\n"],"mappings":"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","names":["mysql","z","z","z","z","z","z","z","z","z","z","require"]}
|