#!/usr/bin/env node /** * MySQL MCP Server - Node.js 实现 * 提供 execute_sql 工具用于执行 SQL 语句 */ const mysql = require('mysql2/promise'); const readline = require('readline'); const config = { host: process.env.MYSQL_HOST || 'localhost', port: parseInt(process.env.MYSQL_PORT) || 3306, user: process.env.MYSQL_USER || 'root', password: process.env.MYSQL_PASSWORD || '', database: process.env.MYSQL_DATABASE || 'test' }; let pool = null; async function getPool() { if (!pool) { pool = mysql.createPool(config); } return pool; } async function executeSQL(query) { const p = await getPool(); const [rows, fields] = await p.query(query); return { rows, fields }; } function sendResponse(id, result) { const response = { jsonrpc: '2.0', id, result }; process.stdout.write(JSON.stringify(response) + '\n'); } function sendError(id, code, message) { const response = { jsonrpc: '2.0', id, error: { code, message } }; process.stdout.write(JSON.stringify(response) + '\n'); } async function handleRequest(request) { const { id, method, params } = request; try { switch (method) { case 'initialize': sendResponse(id, { protocolVersion: '2024-11-05', capabilities: { tools: {} }, serverInfo: { name: 'mysql-node-mcp', version: '1.0.0' } }); break; case 'tools/list': sendResponse(id, { tools: [{ name: 'execute_sql', description: 'Execute SQL query on MySQL database', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'SQL query to execute' } }, required: ['query'] } }] }); break; case 'tools/call': if (params.name === 'execute_sql') { const query = params.arguments.query; const result = await executeSQL(query); let content; if (Array.isArray(result.rows) && result.rows.length > 0) { content = JSON.stringify(result.rows, null, 2); } else if (result.rows && result.rows.affectedRows !== undefined) { content = `Rows affected: ${result.rows.affectedRows}`; } else { content = 'Query executed successfully'; } sendResponse(id, { content: [{ type: 'text', text: content }] }); } else { sendError(id, -32601, `Unknown tool: ${params.name}`); } break; case 'notifications/initialized': case 'notifications/cancelled': // 忽略通知 break; default: if (id !== undefined) { sendError(id, -32601, `Method not found: ${method}`); } } } catch (err) { if (id !== undefined) { sendError(id, -32000, err.message); } } } const rl = readline.createInterface({ input: process.stdin }); rl.on('line', async (line) => { try { const request = JSON.parse(line); await handleRequest(request); } catch (err) { // 忽略解析错误 } }); process.on('SIGINT', async () => { if (pool) await pool.end(); process.exit(0); });