#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListResourcesRequestSchema,
ListToolsRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { config, isMultiDbMode } from './config/index.js';
import { DatabaseManager } from './database/manager.js';
import { handleQuery } from './handlers/query.js';
import { handleListResources } from './handlers/resources.js';
import { handleReadResource } from './handlers/read-resource.js';
import { logger } from './utils/logger.js';
// Initialize the MCP server
const server = new Server(
{
name: config.name,
version: config.version,
},
{
capabilities: {
resources: {},
tools: {},
},
}
);
// Tool definitions
const TOOLS = [
{
name: 'mysql_query',
description: `Execute SQL queries against MySQL database${isMultiDbMode ? 's' : ''}.
Supports SELECT, SHOW, DESCRIBE, EXPLAIN queries by default.
${config.server.allowInsert ? 'INSERT operations are enabled. ' : ''}
${config.server.allowUpdate ? 'UPDATE operations are enabled. ' : ''}
${config.server.allowDelete ? 'DELETE operations are enabled. ' : ''}
${config.server.allowDDL ? 'DDL operations (CREATE, ALTER, DROP) are enabled. ' : ''}`,
inputSchema: {
type: 'object',
properties: {
sql: {
type: 'string',
description: 'The SQL query to execute'
},
params: {
type: 'array',
description: 'Optional parameters for prepared statements',
items: {
type: 'any'
}
}
},
required: ['sql']
}
}
];
// Set up request handlers
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: TOOLS };
});
server.setRequestHandler(CallToolRequestSchema, handleQuery);
server.setRequestHandler(ListResourcesRequestSchema, handleListResources);
server.setRequestHandler(ReadResourceRequestSchema, handleReadResource);
// Main startup function
async function main() {
try {
logger.info(`Starting ${config.name} v${config.version}`);
logger.info(`Multi-database mode: ${isMultiDbMode ? 'enabled' : 'disabled'}`);
// Test database connection
const db = DatabaseManager.getInstance();
await db.executeQuery('SELECT 1');
logger.info('Database connection successful');
// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
logger.info('MCP MySQL server started successfully');
} catch (error) {
logger.error('Failed to start server', { error });
process.exit(1);
}
}
// Handle graceful shutdown
process.on('SIGINT', async () => {
logger.info('Shutting down gracefully...');
try {
const db = DatabaseManager.getInstance();
await db.close();
logger.info('Database connections closed');
} catch (error) {
logger.error('Error during shutdown', { error });
}
process.exit(0);
});
process.on('SIGTERM', async () => {
logger.info('Received SIGTERM, shutting down...');
process.exit(0);
});
// Start the server
main().catch((error) => {
logger.error('Unhandled error', { error });
process.exit(1);
});