server.js•4.63 kB
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import mysql from 'mysql2/promise';
async function main() {
console.error('Starting MySQL MCP Server...');
// MySQL 연결 설정
const dbConfig = {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 3306,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'test',
timezone: '+00:00',
connectTimeout: 30000, // 30초 타임아웃
acquireTimeout: 30000,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
};
console.error('DB Config:', {
...dbConfig,
password: '***',
connectTimeout: dbConfig.connectTimeout
});
let connection;
let retryCount = 0;
const maxRetries = 3;
// 재시도 로직
while (retryCount < maxRetries) {
try {
console.error(`Connection attempt ${retryCount + 1}/${maxRetries}...`);
connection = await mysql.createConnection(dbConfig);
console.error('MySQL connection established successfully');
await connection.ping();
console.error('MySQL ping successful');
break;
} catch (error) {
retryCount++;
console.error(`Connection attempt ${retryCount} failed:`, error.message);
if (retryCount >= maxRetries) {
console.error('Failed to connect to MySQL after', maxRetries, 'attempts');
console.error('Possible solutions:');
console.error('1. Check if MySQL server is running');
console.error('2. Verify host:', dbConfig.host, 'port:', dbConfig.port);
console.error('3. Check firewall settings');
console.error('4. Verify user credentials');
console.error('5. Check network connectivity');
process.exit(1);
}
const waitTime = 2000 * retryCount;
console.error(`Waiting ${waitTime}ms before retry...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
const server = new Server(
{ name: "mysql-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "execute_query",
description: "Execute SQL query on MySQL database",
inputSchema: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"]
}
},
{
name: "show_tables",
description: "Show all tables",
inputSchema: { type: "object", properties: {} }
},
{
name: "describe_table",
description: "Describe table structure",
inputSchema: {
type: "object",
properties: { table_name: { type: "string" } },
required: ["table_name"]
}
}
]
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
await connection.ping();
} catch (pingError) {
connection = await mysql.createConnection(dbConfig);
}
try {
if (request.params.name === "execute_query") {
const [rows] = await connection.execute(request.params.arguments.query);
return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
}
if (request.params.name === "show_tables") {
const [rows] = await connection.execute('SHOW TABLES');
return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
}
if (request.params.name === "describe_table") {
const [rows] = await connection.execute(`DESCRIBE \`${request.params.arguments.table_name}\``);
return { content: [{ type: "text", text: JSON.stringify(rows, null, 2) }] };
}
throw new Error(`Unknown tool: ${request.params.name}`);
} catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true
};
}
});
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('MySQL MCP Server is running');
}
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
process.exit(1);
});
main().catch((error) => {
console.error('Server startup error:', error);
process.exit(1);
});