@imrieul/mysql-mcp-server 1.1.2 → 2.0.0-rc.1

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/README.md CHANGED
@@ -1,9 +1,30 @@
1
1
  # @imrieul/mysql-mcp-server
2
2
 
3
- [한국어](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.ko.md) | [日本語](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.ja.md) | [中文](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.zh.md) | [Español](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.es.md) | [Português](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.pt.md) | [Français](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.fr.md) | [Русский](https://github.com/ImRieul/mysql-mcp-server/blob/main/docs/translations/README.ru.md)
3
+ [한국어](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.ko.md) | [日本語](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.ja.md) | [中文](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.zh.md) | [Español](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.es.md) | [Português](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.pt.md) | [Français](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.fr.md) | [Русский](https://github.com/ImRieul/mysql-mcp-server/blob/release/2.x/docs/translations/README.ru.md)
4
4
 
5
5
  A simple MySQL [MCP](https://modelcontextprotocol.io/) server.
6
6
 
7
+ ## Release channels and support
8
+
9
+ The 2.x line is currently a prerelease. It uses MCP TypeScript SDK v2 and requires
10
+ Node.js 20 or newer; Node.js 24 LTS is recommended. Local stdio transport and all
11
+ seven MySQL tools are retained. Node.js 20 is a compatibility target, not a
12
+ recommendation to use an end-of-life runtime.
13
+
14
+ | Channel | Install / MCP argument | Support |
15
+ |---------|------------------------|---------|
16
+ | Stable 1.x | `@imrieul/mysql-mcp-server@1` | Node.js 18+; security and critical bug fixes only |
17
+ | Preview 2.x | `@imrieul/mysql-mcp-server@next` | Node.js 20+; SDK v2 migration and new development |
18
+
19
+ `latest` remains on 1.1.2 during the preview. Pin `@1` to stay on the 1.x line
20
+ when 2.0.0 becomes stable. Supporting compatibility with Node.js 18 does not
21
+ provide security updates for Node.js itself. Maintenance of 1.x depends on the
22
+ availability of safe upstream fixes; indefinite support is not promised.
23
+
24
+ The `maintenance/1.x` branch retains 1.x; `release/2.x` contains the preview.
25
+ Backport only security and critical bug fixes to 1.x. Publish maintenance updates
26
+ with the `v1` npm tag so they do not replace a newer stable major version.
27
+
7
28
  ## Features
8
29
 
9
30
  - **LLM-friendly** — compact column/row format, auto LIMIT, error hints with next-action suggestions
@@ -22,7 +43,7 @@ Add to your MCP config (`.mcp.json` or `claude_desktop_config.json`):
22
43
  "mcpServers": {
23
44
  "mysql": {
24
45
  "command": "npx",
25
- "args": ["-y", "@imrieul/mysql-mcp-server"],
46
+ "args": ["-y", "@imrieul/mysql-mcp-server@next"],
26
47
  "env": {
27
48
  "MYSQL_HOST": "localhost",
28
49
  "MYSQL_PORT": "3306",
@@ -42,7 +63,7 @@ Or with a connection string:
42
63
  "mcpServers": {
43
64
  "mysql": {
44
65
  "command": "npx",
45
- "args": ["-y", "@imrieul/mysql-mcp-server", "mysql://root:password@localhost:3306/mydb"]
66
+ "args": ["-y", "@imrieul/mysql-mcp-server@next", "mysql://root:password@localhost:3306/mydb"]
46
67
  }
47
68
  }
48
69
  }
@@ -55,7 +76,7 @@ Codex uses TOML config, not `mcpServers` JSON. Add this to `~/.codex/config.toml
55
76
  ```toml
56
77
  [mcp_servers.mysql]
57
78
  command = "npx"
58
- args = ["-y", "@imrieul/mysql-mcp-server"]
79
+ args = ["-y", "@imrieul/mysql-mcp-server@next"]
59
80
 
60
81
  [mcp_servers.mysql.env]
61
82
  MYSQL_HOST = "localhost"
@@ -75,7 +96,7 @@ Add this to `opencode.json` or `opencode.jsonc`:
75
96
  "mcp": {
76
97
  "mysql": {
77
98
  "type": "local",
78
- "command": ["npx", "-y", "@imrieul/mysql-mcp-server"],
99
+ "command": ["npx", "-y", "@imrieul/mysql-mcp-server@next"],
79
100
  "enabled": true,
80
101
  "environment": {
81
102
  "MYSQL_HOST": "localhost",
@@ -96,7 +117,7 @@ Add this to `opencode.json` or `opencode.jsonc`:
96
117
  "mcpServers": {
97
118
  "mysql": {
98
119
  "command": "npx",
99
- "args": ["-y", "@imrieul/mysql-mcp-server", "--readonly"],
120
+ "args": ["-y", "@imrieul/mysql-mcp-server@next", "--readonly"],
100
121
  "env": {
101
122
  "MYSQL_HOST": "db.example.com",
102
123
  "MYSQL_USER": "readonly_user",
@@ -120,6 +141,7 @@ Add this to `opencode.json` or `opencode.jsonc`:
120
141
  | `list_tables` | List tables in a database | Allowed |
121
142
  | `describe_table` | Show table schema | Allowed |
122
143
  | `describe_all_tables` | Show all table schemas at once | Allowed |
144
+ | `add_comment` | Update table or column comments | Blocked |
123
145
 
124
146
  ## Configuration
125
147
 
@@ -145,6 +167,23 @@ mysql://user:password@host:port/database
145
167
 
146
168
  Passed as the first CLI argument. Takes priority over environment variables.
147
169
 
170
+ ## Development verification
171
+
172
+ Run `npm run build` and `npm run check` before packaging. To check the real database
173
+ boundary, use a disposable local MySQL database named `mcp_test` and run:
174
+
175
+ ```sh
176
+ MYSQL_TEST_PORT=<local-port> MYSQL_TEST_PASSWORD=<test-root-password> \
177
+ node scripts/verify-mysql.mjs
178
+ ```
179
+
180
+ This check launches the built MCP server outside the repository directory and
181
+ exercises all seven tools, writes and reads a uniquely named test table, checks
182
+ read-only rejection, verifies dry-run does not write, and tests timeout recovery.
183
+ It connects only to `127.0.0.1` and drops its test table when finished. Do not use a
184
+ production database. For the legacy SDK client, set `MCP_TEST_LEGACY=true` and
185
+ `MCP_TEST_CLIENT_PACKAGE` to the installed v1 SDK package name.
186
+
148
187
  ## License
149
188
 
150
189
  MIT
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { serveStdio } from "@modelcontextprotocol/server/stdio";
5
5
 
6
6
  // src/config.ts
7
7
  function parseConnectionString(connStr) {
@@ -160,7 +160,7 @@ function createQueryRunner(pool, options) {
160
160
 
161
161
  // src/server.ts
162
162
  import { createRequire } from "module";
163
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
163
+ import { McpServer } from "@modelcontextprotocol/server";
164
164
 
165
165
  // src/tools/query.ts
166
166
  import { z } from "zod";
@@ -244,11 +244,11 @@ var queryToolName = "query";
244
244
  var queryToolConfig = {
245
245
  title: "Query",
246
246
  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.',
247
- inputSchema: {
247
+ inputSchema: z.object({
248
248
  sql: z.string().describe(
249
249
  "The SQL query to execute. Only SELECT, SHOW, DESCRIBE, EXPLAIN, and WITH (CTE) statements are allowed."
250
250
  )
251
- }
251
+ })
252
252
  };
253
253
  var ALLOWED_PREFIXES = ["SELECT", "SHOW", "DESCRIBE", "EXPLAIN", "WITH"];
254
254
  var LIMIT_PREFIXES = ["SELECT", "WITH"];
@@ -305,10 +305,10 @@ var executeToolName = "execute";
305
305
  var executeToolConfig = {
306
306
  title: "Execute",
307
307
  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.",
308
- inputSchema: {
308
+ inputSchema: z2.object({
309
309
  sql: z2.string().describe('The SQL statement to execute. SELECT statements are not allowed here; use the "query" tool instead.'),
310
310
  dryRun: z2.boolean().optional().describe("If true, validates the statement via EXPLAIN without executing it. Defaults to false.")
311
- }
311
+ })
312
312
  };
313
313
  function createExecuteHandler(runner, isReadonly) {
314
314
  return async ({ sql, dryRun }) => {
@@ -438,9 +438,9 @@ var listTablesToolName = "list_tables";
438
438
  var listTablesToolConfig = {
439
439
  title: "List Tables",
440
440
  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.",
441
- inputSchema: {
441
+ inputSchema: z3.object({
442
442
  database: z3.string().optional().describe("Database name. Uses the current database if omitted.")
443
- }
443
+ })
444
444
  };
445
445
  function createListTablesHandler(runner) {
446
446
  return async ({ database }) => {
@@ -507,10 +507,10 @@ var describeTableToolName = "describe_table";
507
507
  var describeTableToolConfig = {
508
508
  title: "Describe Table",
509
509
  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.",
510
- inputSchema: {
510
+ inputSchema: z4.object({
511
511
  table: z4.string().describe("Table name to describe."),
512
512
  database: z4.string().optional().describe("Database name. Uses the current database if omitted.")
513
- }
513
+ })
514
514
  };
515
515
  function createDescribeTableHandler(runner) {
516
516
  return async ({ table, database }) => {
@@ -590,9 +590,9 @@ var describeAllTablesToolName = "describe_all_tables";
590
590
  var describeAllTablesToolConfig = {
591
591
  title: "Describe All Tables",
592
592
  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.",
593
- inputSchema: {
593
+ inputSchema: z5.object({
594
594
  database: z5.string().optional().describe("Database name. Uses the current database if omitted.")
595
- }
595
+ })
596
596
  };
597
597
  function createDescribeAllTablesHandler(runner) {
598
598
  return async ({ database }) => {
@@ -663,13 +663,13 @@ var addCommentToolName = "add_comment";
663
663
  var addCommentToolConfig = {
664
664
  title: "Add Comment",
665
665
  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.",
666
- inputSchema: {
666
+ inputSchema: z6.object({
667
667
  table: z6.string().describe("Table name."),
668
668
  column: z6.string().optional().describe("Column name. If omitted, sets a table-level comment."),
669
669
  comment: z6.string().describe("Comment text to set."),
670
670
  database: z6.string().optional().describe("Database name. Uses the current database if omitted."),
671
671
  dryRun: z6.boolean().optional().describe("If true, returns the generated SQL without executing it. Defaults to false.")
672
- }
672
+ })
673
673
  };
674
674
  function createAddCommentHandler(runner, isReadonly) {
675
675
  return async ({
@@ -787,41 +787,66 @@ ${modifySql}` }]
787
787
 
788
788
  // src/tools/index.ts
789
789
  function registerAllTools(server, runner, readonly, maxRows) {
790
- server.tool(
790
+ server.registerTool(
791
791
  queryToolName,
792
- queryToolConfig.description,
793
- queryToolConfig.inputSchema,
792
+ {
793
+ title: queryToolConfig.title,
794
+ description: queryToolConfig.description,
795
+ inputSchema: queryToolConfig.inputSchema
796
+ },
794
797
  createQueryHandler(runner, maxRows)
795
798
  );
796
- server.tool(
799
+ server.registerTool(
797
800
  executeToolName,
798
- executeToolConfig.description,
799
- executeToolConfig.inputSchema,
801
+ {
802
+ title: executeToolConfig.title,
803
+ description: executeToolConfig.description,
804
+ inputSchema: executeToolConfig.inputSchema
805
+ },
800
806
  createExecuteHandler(runner, readonly)
801
807
  );
802
- server.tool(listDatabasesToolName, listDatabasesToolConfig.description, createListDatabasesHandler(runner));
803
- server.tool(
808
+ server.registerTool(
809
+ listDatabasesToolName,
810
+ {
811
+ title: listDatabasesToolConfig.title,
812
+ description: listDatabasesToolConfig.description
813
+ },
814
+ createListDatabasesHandler(runner)
815
+ );
816
+ server.registerTool(
804
817
  listTablesToolName,
805
- listTablesToolConfig.description,
806
- listTablesToolConfig.inputSchema,
818
+ {
819
+ title: listTablesToolConfig.title,
820
+ description: listTablesToolConfig.description,
821
+ inputSchema: listTablesToolConfig.inputSchema
822
+ },
807
823
  createListTablesHandler(runner)
808
824
  );
809
- server.tool(
825
+ server.registerTool(
810
826
  describeTableToolName,
811
- describeTableToolConfig.description,
812
- describeTableToolConfig.inputSchema,
827
+ {
828
+ title: describeTableToolConfig.title,
829
+ description: describeTableToolConfig.description,
830
+ inputSchema: describeTableToolConfig.inputSchema
831
+ },
813
832
  createDescribeTableHandler(runner)
814
833
  );
815
- server.tool(
834
+ server.registerTool(
816
835
  describeAllTablesToolName,
817
- describeAllTablesToolConfig.description,
818
- describeAllTablesToolConfig.inputSchema,
836
+ {
837
+ title: describeAllTablesToolConfig.title,
838
+ description: describeAllTablesToolConfig.description,
839
+ inputSchema: describeAllTablesToolConfig.inputSchema
840
+ },
819
841
  createDescribeAllTablesHandler(runner)
820
842
  );
821
- server.tool(
843
+ server.registerTool(
822
844
  addCommentToolName,
823
- addCommentToolConfig.description,
824
- addCommentToolConfig.inputSchema,
845
+ {
846
+ title: addCommentToolConfig.title,
847
+ description: addCommentToolConfig.description,
848
+ inputSchema: addCommentToolConfig.inputSchema
849
+ },
825
850
  createAddCommentHandler(runner, readonly)
826
851
  );
827
852
  }
@@ -880,10 +905,9 @@ async function main() {
880
905
  readonly: config.readonly,
881
906
  queryTimeout: config.queryTimeout
882
907
  });
883
- const server = createMcpServer(runner, config.readonly, config.maxRows);
884
- const transport = new StdioServerTransport();
908
+ const stdioServer = serveStdio(() => createMcpServer(runner, config.readonly, config.maxRows));
885
909
  const shutdown = async () => {
886
- await server.close();
910
+ await stdioServer.close();
887
911
  await connectionManager.close();
888
912
  process.exit(0);
889
913
  };
@@ -894,7 +918,6 @@ async function main() {
894
918
  console.error(`Readonly mode: ${config.readonly}`);
895
919
  console.error(`Query timeout: ${config.queryTimeout}ms`);
896
920
  console.error(`SSL: ${config.ssl}`);
897
- await server.connect(transport);
898
921
  console.error("MySQL MCP Server connected via stdio");
899
922
  }
900
923
  main().catch((error) => {
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/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 { createRequire } from 'module';\nimport { 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: (createRequire(import.meta.url)('../package.json') as { version: string }).version,\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","createRequire","require"]}
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 { serveStdio } from '@modelcontextprotocol/server/stdio';\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 stdioServer = serveStdio(() => createMcpServer(runner, config.readonly, config.maxRows));\n\n const shutdown = async () => {\n await stdioServer.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 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 { createRequire } from 'module';\nimport { McpServer } from '@modelcontextprotocol/server';\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: (createRequire(import.meta.url)('../package.json') as { version: string }).version,\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: z.object({\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: z.object({\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: z.object({\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: z.object({\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: z.object({\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: z.object({\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/server';\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.registerTool(\n queryToolName,\n {\n title: queryToolConfig.title,\n description: queryToolConfig.description,\n inputSchema: queryToolConfig.inputSchema,\n },\n createQueryHandler(runner, maxRows),\n );\n server.registerTool(\n executeToolName,\n {\n title: executeToolConfig.title,\n description: executeToolConfig.description,\n inputSchema: executeToolConfig.inputSchema,\n },\n createExecuteHandler(runner, readonly),\n );\n server.registerTool(\n listDatabasesToolName,\n {\n title: listDatabasesToolConfig.title,\n description: listDatabasesToolConfig.description,\n },\n createListDatabasesHandler(runner),\n );\n server.registerTool(\n listTablesToolName,\n {\n title: listTablesToolConfig.title,\n description: listTablesToolConfig.description,\n inputSchema: listTablesToolConfig.inputSchema,\n },\n createListTablesHandler(runner),\n );\n server.registerTool(\n describeTableToolName,\n {\n title: describeTableToolConfig.title,\n description: describeTableToolConfig.description,\n inputSchema: describeTableToolConfig.inputSchema,\n },\n createDescribeTableHandler(runner),\n );\n server.registerTool(\n describeAllTablesToolName,\n {\n title: describeAllTablesToolConfig.title,\n description: describeAllTablesToolConfig.description,\n inputSchema: describeAllTablesToolConfig.inputSchema,\n },\n createDescribeAllTablesHandler(runner),\n );\n server.registerTool(\n addCommentToolName,\n {\n title: addCommentToolConfig.title,\n description: addCommentToolConfig.description,\n inputSchema: addCommentToolConfig.inputSchema,\n },\n createAddCommentHandler(runner, readonly),\n );\n}\n"],"mappings":";;;AAAA,SAAS,kBAAkB;;;ACgBpB,SAAS,sBAAsB,SAA8B;AAClE,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,OAAO;AAAA,EACvB,QAAQ;AACN,UAAM,IAAI,MAAM,8BAA8B,OAAO,EAAE;AAAA,EACzD;AAEA,MAAI,IAAI,aAAa,UAAU;AAC7B,UAAM,IAAI,MAAM,mCAAmC,IAAI,QAAQ,EAAE;AAAA,EACnE;AAEA,QAAM,WAAW,IAAI,SAAS,MAAM,CAAC,KAAK;AAE1C,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,IACV,MAAM,IAAI,OAAO,SAAS,IAAI,MAAM,EAAE,IAAI;AAAA,IAC1C,MAAM,mBAAmB,IAAI,QAAQ;AAAA,IACrC,UAAU,mBAAmB,IAAI,QAAQ;AAAA,IACzC;AAAA,EACF;AACF;AAEO,SAAS,eAAe,KAAsD;AACnF,QAAM,OAAO,IAAI;AACjB,QAAM,OAAO,IAAI;AACjB,QAAM,WAAW,IAAI;AAErB,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,mDAAmD;AAC9E,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,mDAAmD;AAC9E,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,uDAAuD;AAEtF,SAAO;AAAA,IACL;AAAA,IACA,MAAM,IAAI,aAAa,SAAS,IAAI,YAAY,EAAE,IAAI;AAAA,IACtD;AAAA,IACA;AAAA,IACA,UAAU,IAAI,kBAAkB;AAAA,EAClC;AACF;AASO,SAAS,UAAU,MAA4B;AACpD,MAAI;AACJ,MAAI,WAAW;AACf,MAAI,OAAO;AACX,MAAI,UAAU;AAEd,aAAW,OAAO,MAAM;AACtB,QAAI,QAAQ,cAAc;AACxB,iBAAW;AAAA,IACb,WAAW,QAAQ,YAAY,QAAQ,MAAM;AAC3C,aAAO;AAAA,IACT,WAAW,QAAQ,aAAa;AAC9B,gBAAU;AAAA,IACZ,WAAW,IAAI,WAAW,UAAU,GAAG;AACrC,yBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,SAAO,EAAE,kBAAkB,UAAU,MAAM,QAAQ;AACrD;AAEO,SAAS,cAAc,MAAgB,MAA0C,QAAQ,KAAgB;AAC9G,QAAM,OAAO,UAAU,IAAI;AAE3B,QAAMA,SAAQ,KAAK,mBAAmB,sBAAsB,KAAK,gBAAgB,IAAI,eAAe,GAAG;AAEvG,QAAM,WAAW,KAAK,YAAY,IAAI,mBAAmB;AACzD,QAAM,UAAU,IAAI,iBAAiB,SAAS,IAAI,gBAAgB,EAAE,IAAI;AACxE,QAAM,eAAe,IAAI,wBAAwB,SAAY,SAAS,IAAI,qBAAqB,EAAE,IAAI;AACrG,QAAM,MAAM,IAAI,cAAc;AAE9B,SAAO,EAAE,OAAAA,QAAO,UAAU,SAAS,cAAc,IAAI;AACvD;;;AChGA,OAAO,WAAW;AAaX,SAAS,wBAAwB,QAAqB,SAAgD;AAC3G,QAAM,cAAiC;AAAA,IACrC,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,UAAU,OAAO;AAAA,IACjB,UAAU,OAAO;AAAA,IACjB,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,EACtB;AAEA,MAAI,SAAS,KAAK;AAChB,gBAAY,MAAM,EAAE,oBAAoB,KAAK;AAAA,EAC/C;AAEA,QAAM,OAAO,MAAM,WAAW,WAAW;AAEzC,SAAO;AAAA,IACL,UAAU;AACR,aAAO;AAAA,IACT;AAAA,IACA,MAAM,QAAQ;AACZ,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AACF;;;AC7BO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAAY,WAAmB;AAC7B,UAAM,uBAAuB,SAAS,IAAI;AAC1C,SAAK,OAAO;AAAA,EACd;AACF;AAOA,SAAS,YAAe,SAAqB,WAA+B;AAC1E,MAAI,aAAa,EAAG,QAAO;AAE3B,SAAO,QAAQ,KAAK;AAAA,IAClB;AAAA,IACA,IAAI,QAAe,CAAC,GAAG,WAAW,WAAW,MAAM,OAAO,IAAI,kBAAkB,SAAS,CAAC,GAAG,SAAS,CAAC;AAAA,EACzG,CAAC;AACH;AAEO,SAAS,kBAAkB,MAAY,SAA0C;AACtF,QAAM,EAAE,UAAU,aAAa,IAAI;AAEnC,SAAO;AAAA,IACL,MAAM,MAAM,KAA0C;AACpD,UAAI,CAAC,UAAU;AACb,eAAO,YAAY,KAAK,MAAM,GAAG,GAAkC,YAAY;AAAA,MACjF;AAEA,YAAM,OAAO,MAAM,KAAK,cAAc;AACtC,UAAI;AACF,cAAM,KAAK,MAAM,mCAAmC;AACpD,cAAM,KAAK,iBAAiB;AAC5B,cAAM,SAAS,MAAM,YAAY,KAAK,MAAM,GAAG,GAAkC,YAAY;AAC7F,cAAM,KAAK,SAAS;AACpB,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI;AACF,gBAAM,KAAK,SAAS;AAAA,QACtB,QAAQ;AAAA,QAER;AACA,cAAM;AAAA,MACR,UAAE;AACA,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AAAA,IAEA,MAAM,eAAkB,IAAgD;AACtE,YAAM,OAAO,MAAM,KAAK,cAAc;AACtC,UAAI;AACF,YAAI,UAAU;AACZ,gBAAM,KAAK,MAAM,mCAAmC;AACpD,gBAAM,KAAK,iBAAiB;AAAA,QAC9B;AAEA,cAAM,UAAmB,CAAC,QACxB,YAAY,KAAK,MAAM,GAAG,GAAkC,YAAY;AAE1E,cAAM,SAAS,MAAM,GAAG,OAAO;AAE/B,YAAI,UAAU;AACZ,gBAAM,KAAK,SAAS;AAAA,QACtB;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,UAAU;AACZ,cAAI;AACF,kBAAM,KAAK,SAAS;AAAA,UACtB,QAAQ;AAAA,UAER;AAAA,QACF;AACA,cAAM;AAAA,MACR,UAAE;AACA,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;;;AC1FA,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;;;ACD1B,SAAS,SAAS;;;ACAlB,IAAM,QAA4B;AAAA,EAChC,CAAC,6BAA6B,kDAAkD;AAAA,EAChF,CAAC,mBAAmB,iDAAiD;AAAA,EACrE,CAAC,qBAAqB,wDAAwD;AAAA,EAC9E,CAAC,kBAAkB,wCAAwC;AAAA,EAC3D,CAAC,qCAAqC,iDAAiD;AAAA,EACvF,CAAC,mBAAmB,yBAAyB;AAAA,EAC7C,CAAC,kBAAkB,2DAA2D;AAChF;AAEO,SAAS,YAAY,OAAwB;AAClD,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,QAAM,OAAO,MAAM,KAAK,CAAC,CAAC,OAAO,MAAM,QAAQ,KAAK,OAAO,CAAC;AAC5D,SAAO,OAAO,UAAU,OAAO;AAAA,EAAK,KAAK,CAAC,CAAC,KAAK,UAAU,OAAO;AACnE;;;ACRA,SAAS,gBAAgB,KAAsB;AAC7C,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,OAAO,IAAI,WAAW,CAAC;AAE7B,QAAI,SAAS,KAAK,SAAS,MAAM,SAAS,GAAI;AAE9C,QAAI,QAAQ,MAAQ,SAAS,IAAM,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,IAAM,gCAAgC;AAAA,EACpC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAOO,SAAS,YAAY,KAA+B;AACzD,MAAI,gBAAgB,GAAG,GAAG;AACxB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO,EAAE,OAAO,KAAK;AACvB;AAEO,SAAS,mBAAmB,MAAc,OAAiC;AAChF,MAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,WAAW,GAAG;AACrC,WAAO,EAAE,OAAO,OAAO,SAAS,UAAU,KAAK,yBAAyB;AAAA,EAC1E;AAEA,MAAI,gBAAgB,IAAI,GAAG;AACzB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS,UAAU,KAAK;AAAA,IAC1B;AAAA,EACF;AAEA,aAAW,WAAW,+BAA+B;AACnD,QAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS,UAAU,KAAK,wCAAwC,QAAQ,MAAM;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,SAAS,IAAI;AACpB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS,UAAU,KAAK;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,KAAK;AACvB;;;AFhEO,IAAM,gBAAgB;AAEtB,IAAM,kBAAkB;AAAA,EAC7B,OAAO;AAAA,EACP,aACE;AAAA,EAIF,aAAa,EAAE,OAAO;AAAA,IACpB,KAAK,EACF,OAAO,EACP;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AACH;AAEA,IAAM,mBAAmB,CAAC,UAAU,QAAQ,YAAY,WAAW,MAAM;AACzE,IAAM,iBAAiB,CAAC,UAAU,MAAM;AAExC,SAAS,WAAW,YAA6B;AAC/C,MAAI,CAAC,eAAe,KAAK,CAAC,MAAM,WAAW,WAAW,CAAC,CAAC,EAAG,QAAO;AAClE,SAAO,CAAC,aAAa,KAAK,UAAU;AACtC;AAEO,SAAS,mBAAmB,QAAqB,SAAiB;AACvE,SAAO,OAAO,EAAE,IAAI,MAAuB;AACzC,UAAM,aAAa,YAAY,GAAG;AAClC,QAAI,CAAC,WAAW,OAAO;AACrB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,WAAW,QAAS,CAAC;AAAA,MAChE;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,KAAK,EAAE,YAAY;AAC1C,UAAM,YAAY,iBAAiB,KAAK,CAAC,WAAW,WAAW,WAAW,MAAM,CAAC;AAEjF,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,WAAW,UAAU,IAAI,GAAG,IAAI,KAAK,CAAC,UAAU,OAAO,KAAK;AAC7E,YAAM,CAAC,IAAI,IAAI,MAAM,OAAO,MAAM,QAAQ;AAC1C,YAAM,MAAM;AACZ,UAAI,IAAI,WAAW,GAAG;AACpB,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,UAAU,CAAC,EAAE;AAAA,MACjE;AACA,YAAM,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC;AAC/B,YAAM,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjD,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,MAC1F;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;AG3EA,SAAS,KAAAC,UAAS;AAKX,IAAM,kBAAkB;AAExB,IAAM,oBAAoB;AAAA,EAC/B,OAAO;AAAA,EACP,aACE;AAAA,EAIF,aAAaC,GAAE,OAAO;AAAA,IACpB,KAAKA,GACF,OAAO,EACP,SAAS,qGAAqG;AAAA,IACjH,QAAQA,GACL,QAAQ,EACR,SAAS,EACT,SAAS,uFAAuF;AAAA,EACrG,CAAC;AACH;AAEO,SAAS,qBAAqB,QAAqB,YAAqB;AAC7E,SAAO,OAAO,EAAE,KAAK,OAAO,MAAyC;AACnE,QAAI,YAAY;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,YAAY,GAAG;AAClC,QAAI,CAAC,WAAW,OAAO;AACrB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,WAAW,QAAS,CAAC;AAAA,MAChE;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,KAAK,EAAE,YAAY;AAC1C,QAAI,WAAW,WAAW,QAAQ,KAAK,WAAW,WAAW,MAAM,GAAG;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,YAAM,eAAe,CAAC,UAAU,QAAQ,SAAS,YAAY,QAAQ;AACrE,YAAM,QAAQ,aAAa,KAAK,CAAC,MAAM,WAAW,WAAW,CAAC,CAAC;AAE/D,UAAI,OAAO;AACT,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,EAAiE,GAAG;AAAA,YAC5E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AACF,cAAM,CAAC,IAAI,IAAI,MAAM,OAAO,MAAM,WAAW,GAAG,EAAE;AAClD,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,EAA+C,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,YACpF;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,gCAAgC,YAAY,KAAK,CAAC,GAAG,CAAC;AAAA,QACjG;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,CAAC,MAAM,IAAI,MAAM,OAAO,MAAM,GAAG;AACvC,YAAM,IAAI;AACV,aAAO;AAAA,QACL,SAAS;AAAA,UACP,EAAE,MAAM,QAAiB,MAAM,iBAAiB,EAAE,YAAY,kBAAkB,EAAE,eAAe,CAAC,GAAG;AAAA,QACvG;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;ACzGO,IAAM,wBAAwB;AAE9B,IAAM,0BAA0B;AAAA,EACrC,OAAO;AAAA,EACP,aACE;AAGJ;AAEO,SAAS,2BAA2B,QAAqB;AAC9D,SAAO,YAAY;AACjB,QAAI;AACF,YAAM,CAAC,IAAI,IAAI,MAAM,OAAO,MAAM,gBAAgB;AAClD,YAAM,YAAa,KAAkC,IAAI,CAAC,MAAM,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;AACnF,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,SAAS,EAAE,CAAC;AAAA,MACtE;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;AC5BA,SAAS,KAAAC,UAAS;;;ACElB,eAAsB,gBAAgB,OAAgB,UAA2C;AAC/F,MAAI,SAAU,QAAO;AACrB,QAAM,CAAC,IAAI,IAAI,MAAM,MAAM,yBAAyB;AACpD,QAAM,KAAM,KAAmC,CAAC,GAAG;AACnD,SAAO,OAAO,OAAO,WAAW,KAAK;AACvC;;;ACPO,SAAS,kBAAkB,OAAuB;AACvD,SAAO,MAAM,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,IAAI;AACxD;AAEO,SAAS,iBAAiB,OAAuB;AACtD,SAAO,IAAI,kBAAkB,KAAK,CAAC;AACrC;;;AFCO,IAAM,qBAAqB;AAE3B,IAAM,uBAAuB;AAAA,EAClC,OAAO;AAAA,EACP,aACE;AAAA,EAGF,aAAaC,GAAE,OAAO;AAAA,IACpB,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACjG,CAAC;AACH;AAEO,SAAS,wBAAwB,QAAqB;AAC3D,SAAO,OAAO,EAAE,SAAS,MAA6B;AACpD,QAAI,UAAU;AACZ,YAAM,eAAe,mBAAmB,UAAU,UAAU;AAC5D,UAAI,CAAC,aAAa,OAAO;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,aAAa,QAAS,CAAC;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,aAAO,MAAM,OAAO,eAAe,OAAO,UAAU;AAClD,cAAM,KAAK,MAAM,gBAAgB,OAAO,QAAQ;AAChD,YAAI,CAAC,IAAI;AACP,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,MAAM,wFAAwF,iBAAiB,EAAE,CAAC;AACxH,cAAM,CAAC,IAAI,IAAI,MAAM,MAAM,GAAG;AAC9B,cAAM,QAAS,KAAkC,IAAI,CAAC,MAAM;AAC1D,gBAAM,UAAU,EAAE;AAClB,iBAAO,UAAU,GAAG,EAAE,UAAU,OAAO,OAAO,KAAK,EAAE;AAAA,QACvD,CAAC;AACD,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QAC7D;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;AGhEA,SAAS,KAAAC,UAAS;;;ACUX,SAAS,aAAa,KAAyB;AACpD,MAAI,SAAS,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI;AACpC,MAAI,CAAC,IAAI,SAAU,WAAU;AAC7B,MAAI,IAAI,QAAQ,MAAO,WAAU;AAAA,WACxB,IAAI,QAAQ,MAAO,WAAU;AAAA,WAC7B,IAAI,QAAQ,MAAO,WAAU;AACtC,MAAI,IAAI,gBAAgB,KAAM,WAAU,YAAY,IAAI,YAAY;AACpE,MAAI,IAAI,MAAO,WAAU,IAAI,IAAI,KAAK;AACtC,MAAI,IAAI,QAAS,WAAU,OAAO,IAAI,OAAO;AAC7C,SAAO;AACT;;;ADZO,IAAM,wBAAwB;AAE9B,IAAM,0BAA0B;AAAA,EACrC,OAAO;AAAA,EACP,aACE;AAAA,EAGF,aAAaC,GAAE,OAAO;AAAA,IACpB,OAAOA,GAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,IACpD,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACjG,CAAC;AACH;AAEO,SAAS,2BAA2B,QAAqB;AAC9D,SAAO,OAAO,EAAE,OAAO,SAAS,MAA4C;AAC1E,UAAM,kBAAkB,mBAAmB,OAAO,OAAO;AACzD,QAAI,CAAC,gBAAgB,OAAO;AAC1B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,gBAAgB,QAAS,CAAC;AAAA,MACrE;AAAA,IACF;AAEA,QAAI,UAAU;AACZ,YAAM,eAAe,mBAAmB,UAAU,UAAU;AAC5D,UAAI,CAAC,aAAa,OAAO;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,aAAa,QAAS,CAAC;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,aAAO,MAAM,OAAO,eAAe,OAAO,UAAU;AAClD,cAAM,KAAK,MAAM,gBAAgB,OAAO,QAAQ;AAChD,YAAI,CAAC,IAAI;AACP,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,MAAM,wJAAwJ,iBAAiB,EAAE,CAAC,qBAAqB,iBAAiB,KAAK,CAAC;AACpO,cAAM,CAAC,IAAI,IAAI,MAAM,MAAM,GAAG;AAC9B,cAAM,YAAY;AAElB,YAAI,UAAU,WAAW,GAAG;AAC1B,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,iBAAiB,KAAK,gCAAgC,EAAE;AAAA;AAAA,cAChE;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,UAAU,UAAU;AAAA,UAAI,CAAC,MAC7B,aAAa;AAAA,YACX,MAAM,OAAO,EAAE,WAAW;AAAA,YAC1B,MAAM,OAAO,EAAE,WAAW;AAAA,YAC1B,UAAU,EAAE,gBAAgB;AAAA,YAC5B,KAAK,OAAO,EAAE,cAAc,EAAE;AAAA,YAC9B,cAAc,EAAE;AAAA,YAChB,OAAO,OAAO,EAAE,SAAS,EAAE;AAAA,YAC3B,SAAS,OAAO,EAAE,kBAAkB,EAAE;AAAA,UACxC,CAAC;AAAA,QACH;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,GAAG,KAAK;AAAA,EAAM,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC;AAAA,QAC/E;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;AE/FA,SAAS,KAAAC,UAAS;AAQX,IAAM,4BAA4B;AAElC,IAAM,8BAA8B;AAAA,EACzC,OAAO;AAAA,EACP,aACE;AAAA,EAEF,aAAaC,GAAE,OAAO;AAAA,IACpB,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,EACjG,CAAC;AACH;AAEO,SAAS,+BAA+B,QAAqB;AAClE,SAAO,OAAO,EAAE,SAAS,MAA6B;AACpD,QAAI,UAAU;AACZ,YAAM,eAAe,mBAAmB,UAAU,UAAU;AAC5D,UAAI,CAAC,aAAa,OAAO;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,aAAa,QAAS,CAAC;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,aAAO,MAAM,OAAO,eAAe,OAAO,UAAU;AAClD,cAAM,KAAK,MAAM,gBAAgB,OAAO,QAAQ;AAChD,YAAI,CAAC,IAAI;AACP,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,MAAM,oKAAoK,iBAAiB,EAAE,CAAC;AACpM,cAAM,CAAC,IAAI,IAAI,MAAM,MAAM,GAAG;AAC9B,cAAM,YAAY;AAElB,YAAI,UAAU,WAAW,GAAG;AAC1B,iBAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,cAAc,CAAC,EAAE;AAAA,QACrE;AAEA,cAAM,WAAW,oBAAI,IAAsB;AAC3C,mBAAW,KAAK,WAAW;AACzB,gBAAM,YAAY,OAAO,EAAE,UAAU;AACrC,gBAAM,OAAO,aAAa;AAAA,YACxB,MAAM,OAAO,EAAE,WAAW;AAAA,YAC1B,MAAM,OAAO,EAAE,WAAW;AAAA,YAC1B,UAAU,EAAE,gBAAgB;AAAA,YAC5B,KAAK,OAAO,EAAE,cAAc,EAAE;AAAA,YAC9B,cAAc,EAAE;AAAA,YAChB,OAAO,OAAO,EAAE,SAAS,EAAE;AAAA,YAC3B,SAAS,OAAO,EAAE,kBAAkB,EAAE;AAAA,UACxC,CAAC;AACD,cAAI,CAAC,SAAS,IAAI,SAAS,GAAG;AAC5B,qBAAS,IAAI,WAAW,CAAC,CAAC;AAAA,UAC5B;AACA,mBAAS,IAAI,SAAS,EAAG,KAAK,IAAI;AAAA,QACpC;AAEA,cAAM,QAAQ,MAAM,KAAK,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,GAAG,KAAK;AAAA,EAAM,MAAM,KAAK,IAAI,CAAC,EAAE;AAErG,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,MAAM,KAAK,MAAM,EAAE,CAAC;AAAA,QAC/D;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;ACtFA,SAAS,KAAAC,UAAS;AAOX,IAAM,qBAAqB;AAE3B,IAAM,uBAAuB;AAAA,EAClC,OAAO;AAAA,EACP,aACE;AAAA,EAGF,aAAaC,GAAE,OAAO;AAAA,IACpB,OAAOA,GAAE,OAAO,EAAE,SAAS,aAAa;AAAA,IACxC,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,IAC7F,SAASA,GAAE,OAAO,EAAE,SAAS,sBAAsB;AAAA,IACnD,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sDAAsD;AAAA,IAC/F,QAAQA,GACL,QAAQ,EACR,SAAS,EACT,SAAS,6EAA6E;AAAA,EAC3F,CAAC;AACH;AAEO,SAAS,wBAAwB,QAAqB,YAAqB;AAChF,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAMM;AACJ,QAAI,YAAY;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAkB,mBAAmB,OAAO,OAAO;AACzD,QAAI,CAAC,gBAAgB,OAAO;AAC1B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,gBAAgB,QAAS,CAAC;AAAA,MACrE;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,YAAM,mBAAmB,mBAAmB,QAAQ,QAAQ;AAC5D,UAAI,CAAC,iBAAiB,OAAO;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,iBAAiB,QAAS,CAAC;AAAA,QACtE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU;AACZ,YAAM,eAAe,mBAAmB,UAAU,UAAU;AAC5D,UAAI,CAAC,aAAa,OAAO;AACvB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,aAAa,QAAS,CAAC;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,aAAO,MAAM,OAAO,eAAe,OAAO,UAAU;AAClD,cAAM,KAAK,MAAM,gBAAgB,OAAO,QAAQ;AAChD,YAAI,CAAC,IAAI;AACP,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,WAAW,KAAK,EAAE,QAAQ,KAAK;AACrC,cAAM,iBAAiB,kBAAkB,OAAO;AAEhD,YAAI,CAAC,QAAQ;AACX,gBAAM,MAAM,eAAe,QAAQ,eAAe,cAAc;AAChE,cAAI,QAAQ;AACV,mBAAO;AAAA,cACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM;AAAA,EAA2B,GAAG,GAAG,CAAC;AAAA,YAC7E;AAAA,UACF;AACA,gBAAM,MAAM,GAAG;AACf,iBAAO;AAAA,YACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,0BAA0B,KAAK,GAAG,CAAC;AAAA,UAC9E;AAAA,QACF;AAEA,cAAM,SAAS,+GAA+G,iBAAiB,EAAE,CAAC,qBAAqB,iBAAiB,KAAK,CAAC,sBAAsB,iBAAiB,MAAM,CAAC;AAC5O,cAAM,CAAC,IAAI,IAAI,MAAM,MAAM,MAAM;AACjC,cAAM,UAAW,KAAmC,CAAC;AAErD,YAAI,CAAC,SAAS;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,kBAAkB,MAAM,6BAA6B,KAAK;AAAA;AAAA,cAClE;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,YAAY,eAAe,QAAQ,oBAAoB,MAAM,MAAM,QAAQ,WAAW;AAC1F,YAAI,QAAQ,gBAAgB,KAAM,cAAa;AAC/C,YAAI,QAAQ,kBAAkB;AAC5B,uBAAa,aAAa,kBAAkB,OAAO,QAAQ,cAAc,CAAC,CAAC;AAC7E,YAAI,QAAQ,MAAO,cAAa,IAAI,QAAQ,KAAK;AACjD,qBAAa,aAAa,cAAc;AAExC,YAAI,QAAQ;AACV,iBAAO;AAAA,YACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM;AAAA,EAA2B,SAAS,GAAG,CAAC;AAAA,UACnF;AAAA,QACF;AAEA,cAAM,MAAM,SAAS;AACrB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,2BAA2B,KAAK,IAAI,MAAM,GAAG,CAAC;AAAA,QACzF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,YAAY,KAAK,EAAE,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;;;AC3IO,SAAS,iBAAiB,QAAmB,QAAqB,UAAmB,SAAuB;AACjH,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,gBAAgB;AAAA,MACvB,aAAa,gBAAgB;AAAA,MAC7B,aAAa,gBAAgB;AAAA,IAC/B;AAAA,IACA,mBAAmB,QAAQ,OAAO;AAAA,EACpC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,kBAAkB;AAAA,MACzB,aAAa,kBAAkB;AAAA,MAC/B,aAAa,kBAAkB;AAAA,IACjC;AAAA,IACA,qBAAqB,QAAQ,QAAQ;AAAA,EACvC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,wBAAwB;AAAA,MAC/B,aAAa,wBAAwB;AAAA,IACvC;AAAA,IACA,2BAA2B,MAAM;AAAA,EACnC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,qBAAqB;AAAA,MAC5B,aAAa,qBAAqB;AAAA,MAClC,aAAa,qBAAqB;AAAA,IACpC;AAAA,IACA,wBAAwB,MAAM;AAAA,EAChC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,wBAAwB;AAAA,MAC/B,aAAa,wBAAwB;AAAA,MACrC,aAAa,wBAAwB;AAAA,IACvC;AAAA,IACA,2BAA2B,MAAM;AAAA,EACnC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,4BAA4B;AAAA,MACnC,aAAa,4BAA4B;AAAA,MACzC,aAAa,4BAA4B;AAAA,IAC3C;AAAA,IACA,+BAA+B,MAAM;AAAA,EACvC;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO,qBAAqB;AAAA,MAC5B,aAAa,qBAAqB;AAAA,MAClC,aAAa,qBAAqB;AAAA,IACpC;AAAA,IACA,wBAAwB,QAAQ,QAAQ;AAAA,EAC1C;AACF;;;AbxEO,SAAS,gBAAgB,QAAqB,UAAmB,SAA4B;AAClG,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAU,cAAc,YAAY,GAAG,EAAE,iBAAiB,EAA0B;AAAA,EACtF,CAAC;AAED,mBAAiB,QAAQ,QAAQ,UAAU,OAAO;AAElD,SAAO;AACT;;;AJTA,SAAS,iBAAAC,sBAAqB;AAE9B,IAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBlB,eAAe,OAAsB;AACnC,QAAM,OAAO,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAE5C,MAAI,KAAK,MAAM;AACb,YAAQ,IAAI,SAAS;AACrB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,KAAK,SAAS;AAChB,UAAMC,WAAUD,eAAc,YAAY,GAAG;AAC7C,UAAM,MAAMC,SAAQ,iBAAiB;AACrC,YAAQ,IAAI,IAAI,OAAO;AACvB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,cAAc,QAAQ,KAAK,MAAM,CAAC,CAAC;AAClD,QAAM,oBAAoB,wBAAwB,OAAO,OAAO,EAAE,KAAK,OAAO,IAAI,CAAC;AACnF,QAAM,SAAS,kBAAkB,kBAAkB,QAAQ,GAAG;AAAA,IAC5D,UAAU,OAAO;AAAA,IACjB,cAAc,OAAO;AAAA,EACvB,CAAC;AAED,QAAM,cAAc,WAAW,MAAM,gBAAgB,QAAQ,OAAO,UAAU,OAAO,OAAO,CAAC;AAE7F,QAAM,WAAW,YAAY;AAC3B,UAAM,YAAY,MAAM;AACxB,UAAM,kBAAkB,MAAM;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAC9B,UAAQ,MAAM,GAAG,OAAO,QAAQ;AAEhC,UAAQ,MAAM,8BAA8B;AAC5C,UAAQ,MAAM,kBAAkB,OAAO,QAAQ,EAAE;AACjD,UAAQ,MAAM,kBAAkB,OAAO,YAAY,IAAI;AACvD,UAAQ,MAAM,QAAQ,OAAO,GAAG,EAAE;AAElC,UAAQ,MAAM,sCAAsC;AACtD;AAEA,KAAK,EAAE,MAAM,CAAC,UAAU;AACtB,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["mysql","z","z","z","z","z","z","z","z","z","z","createRequire","require"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imrieul/mysql-mcp-server",
3
- "version": "1.1.2",
3
+ "version": "2.0.0-rc.1",
4
4
  "description": "MySQL MCP Server - Simple Model Context Protocol server for MySQL database operations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,6 +16,7 @@
16
16
  "test": "vitest run",
17
17
  "test:watch": "vitest",
18
18
  "test:coverage": "vitest run --coverage",
19
+ "test:integration": "npm run build && vitest run --config tests/vitest.integration.config.ts",
19
20
  "typecheck": "tsc --noEmit",
20
21
  "lint": "eslint src/ tests/",
21
22
  "lint:fix": "eslint --fix src/ tests/",
@@ -45,12 +46,14 @@
45
46
  },
46
47
  "license": "MIT",
47
48
  "dependencies": {
48
- "@modelcontextprotocol/sdk": "^1.30.0",
49
+ "@modelcontextprotocol/server": "^2.0.0",
49
50
  "mysql2": "^3.24.4",
50
- "zod": "^3.25.0"
51
+ "zod": "^4.2.0"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@eslint/js": "^9.39.2",
55
+ "@modelcontextprotocol/client": "^2.0.0",
56
+ "@modelcontextprotocol/sdk": "^1.30.0",
54
57
  "@types/node": "^18.19.130",
55
58
  "@vitest/coverage-v8": "^3.2.7",
56
59
  "eslint": "^9.39.2",
@@ -65,6 +68,6 @@
65
68
  "vitest": "^3.2.7"
66
69
  },
67
70
  "engines": {
68
- "node": ">=18"
71
+ "node": ">=20"
69
72
  }
70
73
  }