#!/usr/bin/env node /** * MCP Outline PostgreSQL - Stdio Server * Standard stdio transport for CLI/local access * @author Descomplicar® | @link descomplicar.pt | @copyright 2026 */ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import * as dotenv from 'dotenv'; import { PgClient } from './pg-client.js'; import { getDatabaseConfig } from './config/database.js'; import { createMcpServer, allTools, getToolCounts } from './server/index.js'; import { logger } from './utils/logger.js'; import { startRateLimitCleanup, stopRateLimitCleanup } from './utils/security.js'; dotenv.config(); // Validate all tools have required properties const invalidTools = allTools.filter((tool) => !tool.name || !tool.handler); if (invalidTools.length > 0) { logger.error(`${invalidTools.length} invalid tools found`); process.exit(1); } async function main() { // Get database configuration const config = getDatabaseConfig(); // Initialize PostgreSQL client const pgClient = new PgClient(config); // Test database connection const isConnected = await pgClient.testConnection(); if (!isConnected) { throw new Error('Failed to connect to PostgreSQL database'); } // Create MCP server with shared configuration const server = createMcpServer(pgClient.getPool(), { name: 'mcp-outline-postgresql', version: '1.3.17' }); // Connect stdio transport const transport = new StdioServerTransport(); await server.connect(transport); // Start background tasks startRateLimitCleanup(); // Graceful shutdown handler const shutdown = async () => { stopRateLimitCleanup(); await pgClient.close(); process.exit(0); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); // Log startup (minimal logging for MCP protocol compatibility) if (process.env.LOG_LEVEL !== 'error' && process.env.LOG_LEVEL !== 'none') { logger.info('MCP Server started'); } // Debug logging logger.debug('MCP Outline PostgreSQL Server running', { transport: 'stdio', totalTools: allTools.length, toolsByModule: getToolCounts() }); } main().catch((error) => { logger.error('Fatal error', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }); process.exit(1); });