Skip to main content
Glama

MCP Database Server

by JuanYin1
MIT License
3,221
1
  • Apple
  • Linux
index.ts8.45 kB
#!/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 database utils import { initDatabase, closeDatabase, getDatabaseMetadata } from './db/index.js'; // Import handlers import { handleListResources, handleReadResource } from './handlers/resourceHandlers.js'; import { handleListTools, handleToolCall } from './handlers/toolHandlers.js'; // Setup a logger that uses stderr instead of stdout to avoid interfering with MCP communications const logger = { log: (...args: any[]) => console.error('[INFO]', ...args), error: (...args: any[]) => console.error('[ERROR]', ...args), warn: (...args: any[]) => console.error('[WARN]', ...args), info: (...args: any[]) => console.error('[INFO]', ...args), }; // Configure the server const server = new Server( { name: "executeautomation/database-server", version: "1.1.0", }, { capabilities: { resources: {}, tools: {}, }, }, ); // Parse command line arguments const args = process.argv.slice(2); if (args.length === 0) { logger.error("Please provide database connection information"); logger.error("Usage for SQLite: node index.js <database_file_path>"); logger.error("Usage for SQL Server: node index.js --sqlserver --server <server> --database <database> [--user <user> --password <password>]"); logger.error("Usage for PostgreSQL: node index.js --postgresql --host <host> --database <database> [--user <user> --password <password> --port <port>]"); logger.error("Usage for MySQL: node index.js --mysql --host <host> --database <database> [--user <user> --password <password> --port <port>]"); process.exit(1); } // Parse arguments to determine database type and connection info let dbType = 'sqlite'; let connectionInfo: any = null; // Check if using SQL Server if (args.includes('--sqlserver')) { dbType = 'sqlserver'; connectionInfo = { server: '', database: '', user: undefined, password: undefined }; // Parse SQL Server connection parameters for (let i = 0; i < args.length; i++) { if (args[i] === '--server' && i + 1 < args.length) { connectionInfo.server = args[i + 1]; } else if (args[i] === '--database' && i + 1 < args.length) { connectionInfo.database = args[i + 1]; } else if (args[i] === '--user' && i + 1 < args.length) { connectionInfo.user = args[i + 1]; } else if (args[i] === '--password' && i + 1 < args.length) { connectionInfo.password = args[i + 1]; } else if (args[i] === '--port' && i + 1 < args.length) { connectionInfo.port = parseInt(args[i + 1], 10); } } // Validate SQL Server connection info if (!connectionInfo.server || !connectionInfo.database) { logger.error("Error: SQL Server requires --server and --database parameters"); process.exit(1); } } // Check if using PostgreSQL else if (args.includes('--postgresql') || args.includes('--postgres')) { dbType = 'postgresql'; connectionInfo = { host: '', database: '', user: undefined, password: undefined, port: undefined, ssl: undefined, connectionTimeout: undefined }; // Parse PostgreSQL connection parameters for (let i = 0; i < args.length; i++) { if (args[i] === '--host' && i + 1 < args.length) { connectionInfo.host = args[i + 1]; } else if (args[i] === '--database' && i + 1 < args.length) { connectionInfo.database = args[i + 1]; } else if (args[i] === '--user' && i + 1 < args.length) { connectionInfo.user = args[i + 1]; } else if (args[i] === '--password' && i + 1 < args.length) { connectionInfo.password = args[i + 1]; } else if (args[i] === '--port' && i + 1 < args.length) { connectionInfo.port = parseInt(args[i + 1], 10); } else if (args[i] === '--ssl' && i + 1 < args.length) { connectionInfo.ssl = args[i + 1] === 'true'; } else if (args[i] === '--connection-timeout' && i + 1 < args.length) { connectionInfo.connectionTimeout = parseInt(args[i + 1], 10); } } // Validate PostgreSQL connection info if (!connectionInfo.host || !connectionInfo.database) { logger.error("Error: PostgreSQL requires --host and --database parameters"); process.exit(1); } } // Check if using MySQL else if (args.includes('--mysql')) { dbType = 'mysql'; connectionInfo = { host: '', database: '', user: undefined, password: undefined, port: undefined, ssl: undefined, connectionTimeout: undefined }; // Parse MySQL connection parameters for (let i = 0; i < args.length; i++) { if (args[i] === '--host' && i + 1 < args.length) { connectionInfo.host = args[i + 1]; } else if (args[i] === '--database' && i + 1 < args.length) { connectionInfo.database = args[i + 1]; } else if (args[i] === '--user' && i + 1 < args.length) { connectionInfo.user = args[i + 1]; } else if (args[i] === '--password' && i + 1 < args.length) { connectionInfo.password = args[i + 1]; } else if (args[i] === '--port' && i + 1 < args.length) { connectionInfo.port = parseInt(args[i + 1], 10); } else if (args[i] === '--ssl' && i + 1 < args.length) { const sslVal = args[i + 1]; if (sslVal === 'true') connectionInfo.ssl = true; else if (sslVal === 'false') connectionInfo.ssl = false; else connectionInfo.ssl = sslVal; } else if (args[i] === '--connection-timeout' && i + 1 < args.length) { connectionInfo.connectionTimeout = parseInt(args[i + 1], 10); } } // Validate MySQL connection info if (!connectionInfo.host || !connectionInfo.database) { logger.error("Error: MySQL requires --host and --database parameters"); process.exit(1); } } else { // SQLite mode (default) dbType = 'sqlite'; connectionInfo = args[0]; // First argument is the SQLite file path logger.info(`Using SQLite database at path: ${connectionInfo}`); } // Set up request handlers server.setRequestHandler(ListResourcesRequestSchema, async () => { return await handleListResources(); }); server.setRequestHandler(ReadResourceRequestSchema, async (request) => { return await handleReadResource(request.params.uri); }); server.setRequestHandler(ListToolsRequestSchema, async () => { return handleListTools(); }); server.setRequestHandler(CallToolRequestSchema, async (request) => { return await handleToolCall(request.params.name, request.params.arguments); }); // Handle shutdown gracefully process.on('SIGINT', async () => { logger.info('Shutting down gracefully...'); await closeDatabase(); process.exit(0); }); process.on('SIGTERM', async () => { logger.info('Shutting down gracefully...'); await closeDatabase(); process.exit(0); }); // Add global error handler process.on('uncaughtException', (error) => { logger.error('Uncaught exception:', error); }); process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled Rejection at:', promise, 'reason:', reason); }); /** * Start the server */ async function runServer() { try { logger.info(`Initializing ${dbType} database...`); if (dbType === 'sqlite') { logger.info(`Database path: ${connectionInfo}`); } else if (dbType === 'sqlserver') { logger.info(`Server: ${connectionInfo.server}, Database: ${connectionInfo.database}`); } else if (dbType === 'postgresql') { logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`); } else if (dbType === 'mysql') { logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`); } // Initialize the database await initDatabase(connectionInfo, dbType); const dbInfo = getDatabaseMetadata(); logger.info(`Connected to ${dbInfo.name} database`); logger.info('Starting MCP server...'); const transport = new StdioServerTransport(); await server.connect(transport); logger.info('Server running. Press Ctrl+C to exit.'); } catch (error) { logger.error("Failed to initialize:", error); process.exit(1); } } // Start the server runServer().catch(error => { logger.error("Server initialization failed:", error); process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JuanYin1/mcp-database-server-with-database'

If you have feedback or need assistance with the MCP directory API, please join our Discord server