@cano721/mysql-mcp-server 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +42 -0
  2. package/build/index.js +144 -60
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -279,6 +279,48 @@ MySQL 서버에서 접근 가능한 모든 데이터베이스를 나열합니다
279
279
  }
280
280
  ```
281
281
 
282
+ ### explain_query
283
+
284
+ 쿼리 실행 계획을 분석합니다 (MYSQL_ALLOW_EXPLAIN=true 필요).
285
+
286
+ **매개변수**:
287
+ - `query` (필수): 분석할 SQL 쿼리
288
+ - `database` (선택사항): 데이터베이스명
289
+ - `format` (선택사항): 출력 형식 (TRADITIONAL, JSON, TREE)
290
+
291
+ **예제**:
292
+ ```json
293
+ {
294
+ "server_name": "mysql",
295
+ "tool_name": "explain_query",
296
+ "arguments": {
297
+ "database": "my_database",
298
+ "query": "SELECT * FROM users WHERE id = 1",
299
+ "format": "JSON"
300
+ }
301
+ }
302
+ ```
303
+
304
+ ### analyze_table
305
+
306
+ 테이블 통계를 분석합니다 (MYSQL_ALLOW_ANALYZE=true 필요).
307
+
308
+ **매개변수**:
309
+ - `table` (필수): 분석할 테이블명
310
+ - `database` (선택사항): 데이터베이스명
311
+
312
+ **예제**:
313
+ ```json
314
+ {
315
+ "server_name": "mysql",
316
+ "tool_name": "analyze_table",
317
+ "arguments": {
318
+ "database": "my_database",
319
+ "table": "users"
320
+ }
321
+ }
322
+ ```
323
+
282
324
  **SHOW 명령어 예제**:
283
325
  ```json
284
326
  {
package/build/index.js CHANGED
@@ -49,7 +49,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
49
49
  // Check if optional commands are enabled
50
50
  const allowExplain = process.env.MYSQL_ALLOW_EXPLAIN !== 'false';
51
51
  const allowAnalyze = process.env.MYSQL_ALLOW_ANALYZE !== 'false';
52
- // Build allowed commands description
52
+ // Build allowed commands description for execute_query
53
53
  const allowedCommands = ['SELECT', 'SHOW', 'DESCRIBE'];
54
54
  if (allowExplain) {
55
55
  allowedCommands.push('EXPLAIN');
@@ -58,69 +58,116 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
58
58
  allowedCommands.push('ANALYZE');
59
59
  }
60
60
  const commandsDescription = `SQL query (only ${allowedCommands.join(', ')} statements are allowed)`;
61
- return {
62
- tools: [
63
- {
64
- name: "list_databases",
65
- description: "List all accessible databases on the MySQL server",
66
- inputSchema: {
67
- type: "object",
68
- properties: {},
69
- required: []
70
- }
71
- },
72
- {
73
- name: "list_tables",
74
- description: "List all tables in a specified database",
75
- inputSchema: {
76
- type: "object",
77
- properties: {
78
- database: {
79
- type: "string",
80
- description: "Database name (optional, uses default if not specified)"
81
- }
61
+ // Build tools array
62
+ const tools = [
63
+ {
64
+ name: "list_databases",
65
+ description: "List all accessible databases on the MySQL server",
66
+ inputSchema: {
67
+ type: "object",
68
+ properties: {},
69
+ required: []
70
+ }
71
+ },
72
+ {
73
+ name: "list_tables",
74
+ description: "List all tables in a specified database",
75
+ inputSchema: {
76
+ type: "object",
77
+ properties: {
78
+ database: {
79
+ type: "string",
80
+ description: "Database name (optional, uses default if not specified)"
81
+ }
82
+ },
83
+ required: []
84
+ }
85
+ },
86
+ {
87
+ name: "describe_table",
88
+ description: "Show the schema for a specific table",
89
+ inputSchema: {
90
+ type: "object",
91
+ properties: {
92
+ database: {
93
+ type: "string",
94
+ description: "Database name (optional, uses default if not specified)"
82
95
  },
83
- required: []
84
- }
85
- },
86
- {
87
- name: "describe_table",
88
- description: "Show the schema for a specific table",
89
- inputSchema: {
90
- type: "object",
91
- properties: {
92
- database: {
93
- type: "string",
94
- description: "Database name (optional, uses default if not specified)"
95
- },
96
- table: {
97
- type: "string",
98
- description: "Table name"
99
- }
96
+ table: {
97
+ type: "string",
98
+ description: "Table name"
99
+ }
100
+ },
101
+ required: ["table"]
102
+ }
103
+ },
104
+ {
105
+ name: "execute_query",
106
+ description: "Execute a read-only SQL query",
107
+ inputSchema: {
108
+ type: "object",
109
+ properties: {
110
+ query: {
111
+ type: "string",
112
+ description: commandsDescription
100
113
  },
101
- required: ["table"]
102
- }
103
- },
104
- {
105
- name: "execute_query",
106
- description: "Execute a read-only SQL query",
107
- inputSchema: {
108
- type: "object",
109
- properties: {
110
- query: {
111
- type: "string",
112
- description: commandsDescription
113
- },
114
- database: {
115
- type: "string",
116
- description: "Database name (optional, uses default if not specified)"
117
- }
114
+ database: {
115
+ type: "string",
116
+ description: "Database name (optional, uses default if not specified)"
117
+ }
118
+ },
119
+ required: ["query"]
120
+ }
121
+ }
122
+ ];
123
+ // Add explain_query tool if enabled
124
+ if (allowExplain) {
125
+ tools.push({
126
+ name: "explain_query",
127
+ description: "Analyze query execution plan using EXPLAIN",
128
+ inputSchema: {
129
+ type: "object",
130
+ properties: {
131
+ query: {
132
+ type: "string",
133
+ description: "SQL query to analyze (SELECT, UPDATE, DELETE, INSERT, REPLACE statements)"
118
134
  },
119
- required: ["query"]
120
- }
135
+ database: {
136
+ type: "string",
137
+ description: "Database name (optional, uses default if not specified)"
138
+ },
139
+ format: {
140
+ type: "string",
141
+ description: "Output format: TRADITIONAL, JSON, or TREE (optional, default: TRADITIONAL)",
142
+ enum: ["TRADITIONAL", "JSON", "TREE"]
143
+ }
144
+ },
145
+ required: ["query"]
121
146
  }
122
- ]
123
- };
147
+ });
148
+ }
149
+ // Add analyze_query tool if enabled
150
+ if (allowAnalyze) {
151
+ tools.push({
152
+ name: "analyze_table",
153
+ description: "Analyze table statistics for query optimization",
154
+ inputSchema: {
155
+ type: "object",
156
+ properties: {
157
+ table: {
158
+ type: "string",
159
+ description: "Table name to analyze"
160
+ },
161
+ database: {
162
+ type: "string",
163
+ description: "Database name (optional, uses default if not specified)"
164
+ }
165
+ },
166
+ required: ["table"]
167
+ }
168
+ });
169
+ }
170
+ return { tools };
124
171
  });
125
172
  /**
126
173
  * Handler for MySQL database access tools
@@ -181,6 +228,43 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
181
228
  }]
182
229
  };
183
230
  }
231
+ case "explain_query": {
232
+ console.error('[Tool] Executing explain_query');
233
+ const query = request.params.arguments?.query;
234
+ const database = request.params.arguments?.database;
235
+ const format = request.params.arguments?.format;
236
+ if (!query) {
237
+ throw new McpError(ErrorCode.InvalidParams, "Query is required");
238
+ }
239
+ // Build EXPLAIN query
240
+ let explainQuery = 'EXPLAIN';
241
+ if (format && ['JSON', 'TREE'].includes(format.toUpperCase())) {
242
+ explainQuery += ` FORMAT=${format.toUpperCase()}`;
243
+ }
244
+ explainQuery += ` ${query}`;
245
+ const { rows } = await executeQuery(pool, explainQuery, [], database);
246
+ return {
247
+ content: [{
248
+ type: "text",
249
+ text: JSON.stringify(rows, null, 2)
250
+ }]
251
+ };
252
+ }
253
+ case "analyze_table": {
254
+ console.error('[Tool] Executing analyze_table');
255
+ const table = request.params.arguments?.table;
256
+ const database = request.params.arguments?.database;
257
+ if (!table) {
258
+ throw new McpError(ErrorCode.InvalidParams, "Table name is required");
259
+ }
260
+ const { rows } = await executeQuery(pool, `ANALYZE TABLE \`${table}\``, [], database);
261
+ return {
262
+ content: [{
263
+ type: "text",
264
+ text: JSON.stringify(rows, null, 2)
265
+ }]
266
+ };
267
+ }
184
268
  default:
185
269
  throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
186
270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cano721/mysql-mcp-server",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "An MCP server that provides read-only access to MySQL databases.",
5
5
  "type": "module",
6
6
  "bin": {