Skip to main content
Glama
index.ts6.97 kB
/** * @file Main entry point for AI MCP Gateway * @description Intelligent AI Model orchestration gateway supporting multiple operation modes: * * **Operation Modes:** * - **CLI Mode**: Command-line interface for system management (status, models, providers, db, config) * - **MCP Mode**: Model Context Protocol server for AI tool integration (stdio transport) * - **API Mode**: HTTP REST API server for web applications and integrations * * **Architecture:** * - N-layer routing: Routes requests to models based on cost/capability/priority * - Multi-provider support: OpenAI, Anthropic, OpenRouter, Local (Ollama) * - Database-driven configuration: Model priorities stored in PostgreSQL * - Redis caching: Response caching and session management * * @author AI MCP Gateway Team * @version 1.0.0 * @see {@link docs/ARCHITECTURE.md} for system architecture details */ // Make this a module for top-level await support export { }; /** * Command-line arguments passed to the application. * First argument determines the operation mode or CLI command. */ const args = process.argv.slice(2); const firstArg = args[0]?.toLowerCase(); /** * CLI commands that run without server initialization. * These commands use the lightweight CLI module and exit immediately. * @see {@link ./cli/index.ts} for CLI implementation */ const cliCommands = ['help', '--help', '-h', 'status', 'models', 'providers', 'db', 'config', 'mcp-serve', 'mcp', '--version', '-v']; // Early exit for CLI commands - avoids loading heavy server modules (db, redis, etc.) if (firstArg && cliCommands.some(cmd => firstArg === cmd || firstArg.startsWith(cmd))) { // Dynamic import to avoid loading server modules const { runCLI } = await import('./cli/index.js'); await runCLI(args); // If the CLI command was used to start the MCP server, do not exit the process // because the MCP server runs in-process and must keep the event loop alive. if (firstArg === 'mcp-serve') { // Return to allow the MCP server to keep running } else { process.exit(0); } } /** * Server modules - dynamically imported only when running in server mode. * This pattern keeps CLI commands fast by avoiding unnecessary module loading. */ const { apiServer } = await import('./api/server.js'); // MCP adapter provides advanced transport options (stdio/websocket) const { startMcpServer } = await import('./mcp/adapter/index.js'); const { db } = await import('./db/postgres.js'); const { redisCache } = await import('./cache/redis.js'); const { logger } = await import('./logging/logger.js'); const { selfImprovement } = await import('./improvement/manager.js'); const { providerManager } = await import('./config/provider-manager.js'); const { configService } = await import('./services/config/index.js'); const { bootstrapDB } = await import('./db/bootstrap.js'); /** * Main application bootstrap function. * Initializes all services and starts the appropriate server mode. * * @async * @throws {Error} If server initialization fails * * **Initialization sequence:** * 1. Initialize self-improvement tables (learning from past requests) * 2. Load provider configurations from environment variables * 3. Initialize distributed tracing (if database available) * 4. Start server in configured mode (API or MCP) * 5. Register graceful shutdown handlers */ async function main() { try { // Initialize database and configuration service try { await bootstrapDB.initialize(); await configService.initialize(); logger.info('Configuration service initialized from database'); } catch (error) { if (error instanceof Error && error.message.includes('Bootstrap configuration not found')) { console.error('\n❌ No configuration found!'); console.error('Error details:'); console.error(error.message); console.error('\nRun setup first: npm run setup:config\n'); process.exit(1); } logger.warn('ConfigService initialization failed, continuing with .env fallback', { error: error instanceof Error ? error.message : 'Unknown', }); } // Initialize self-improvement tables await selfImprovement.initializeTables(); // Initialize provider configurations from environment if (db.isReady()) { try { await providerManager.initializeFromEnv(); logger.info('Provider configurations initialized from environment'); } catch (error) { logger.warn('Failed to initialize provider configurations', { error: error instanceof Error ? error.message : 'Unknown', }); } } // Initialize tracer if database is available if (db.isReady()) { try { const { initTracer } = await import('./tracing/tracer.js'); initTracer(db.getPool()); logger.info('Tracer initialized successfully'); } catch (error) { logger.warn('Failed to initialize tracer', { error: error instanceof Error ? error.message : 'Unknown', }); } } // Check if running in HTTP API mode const mode = process.env.MODE || 'mcp'; if (mode === 'api') { logger.info('Starting in HTTP API mode'); await apiServer.start(); } else { // Allow selecting transport via environment for containerized deployments const mcpTransport = (process.env.MCP_TRANSPORT || process.env.MCP_TRANSPORT_TYPE || '').toLowerCase(); const wsPort = process.env.MCP_WEBSOCKET_PORT ? parseInt(process.env.MCP_WEBSOCKET_PORT, 10) : undefined; if (mcpTransport === 'websocket') { logger.info(`Starting in MCP mode (websocket) on port ${wsPort || 3001}`); await startMcpServer({ transport: 'websocket', port: wsPort }); } else if (mcpTransport === 'stdio') { logger.info('Starting in MCP mode (stdio)'); await startMcpServer({ transport: 'stdio' }); } else { logger.info('Starting in MCP mode (stdio)'); await startMcpServer(); } } // Graceful shutdown process.on('SIGINT', async () => { logger.info('Shutting down gracefully...'); await redisCache.close(); await db.close(); if (mode === 'api') { await apiServer.stop(); } process.exit(0); }); } catch (error) { logger.error('Failed to start server', { error: error instanceof Error ? error.message : 'Unknown error', }); process.exit(1); } } main();

Latest Blog Posts

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/babasida246/ai-mcp-gateway'

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