UNPKG

mcp-product-manager

Version:

MCP Orchestrator for task and project management with web interface

119 lines (100 loc) 3.95 kB
// rest-server.js - Main REST API server with modular architecture import express from 'express'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import apiRouter from './api/index.js'; import { requestLogger } from './api/middleware/logging.js'; import { errorHandler, notFoundHandler } from './api/middleware/errorHandler.js'; import { DB_PATH, db } from './api/utils/database.js'; import { UsageTrackingService } from './api/services/usageTracking.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const app = express(); // Initialize services const initializeServices = async () => { try { // Initialize database connection // db is actually getDatabase function, need to call it // This will either get real database or mock database app.locals.db = await db(); // Initialize usage tracking service (optional - can be disabled) if (process.env.USAGE_TRACKING_DISABLED === 'true') { console.log('⏭️ Skipping usage tracking service (USAGE_TRACKING_DISABLED=true)'); app.locals.usageService = null; } else { try { const usageService = new UsageTrackingService(DB_PATH); await usageService.initialize(); app.locals.usageService = usageService; console.log('✅ Usage tracking service initialized'); } catch (usageError) { console.warn('⚠️ Usage tracking service disabled:', usageError.message); console.log(' (This is normal when running via npx - the service is optional)'); app.locals.usageService = null; } } console.log('✅ Core services initialized successfully'); } catch (error) { console.error('❌ Failed to initialize core services:', error); process.exit(1); } }; // Import RBAC and legacy adapter middleware import { rbacMiddleware } from './api/middleware/rbac.js'; import { legacyAdapterMiddleware } from './api/middleware/legacyAdapter.js'; // Middleware app.use(express.json()); app.use(requestLogger); // Add legacy adapter middleware (before RBAC to handle endpoint transformation) app.use(legacyAdapterMiddleware({ enableDeprecationWarnings: true, blockDeprecatedEndpoints: process.env.NODE_ENV === 'production', logDeprecationUsage: true })); // Add RBAC middleware (after legacy adapter, before API routes) app.use('/api', rbacMiddleware({ enforceLogging: true, allowDevelopmentBypass: process.env.NODE_ENV === 'development' })); // Serve static files from public directory app.use(express.static(join(__dirname, 'public'))); // Serve MCP Terminal at /terminal app.get('/terminal', (req, res) => { res.sendFile(join(__dirname, 'public', 'terminal.html')); }); // Mount API routes app.use(apiRouter); // Error handlers (must be last) app.use(notFoundHandler); app.use(errorHandler); // Start server const PORT = process.env.PORT || 1234; // Graceful shutdown process.on('SIGTERM', () => { console.log('🛑 SIGTERM received, shutting down gracefully...'); if (app.locals.usageService && app.locals.usageService.stop) { app.locals.usageService.stop(); } process.exit(0); }); // Initialize and start server const start = async () => { await initializeServices(); app.listen(PORT, () => { console.log(`🚀 REST API server running on http://localhost:${PORT}`); console.log(`📊 Using database: ${DB_PATH}`); console.log(`📚 API documentation available at http://localhost:${PORT}/api`); console.log(`🖥️ MCP Terminal available at http://localhost:${PORT}/terminal`); if (app.locals.usageService) { console.log(`💰 Usage tracking service active - monitoring block transitions`); } }); }; // Only start if this is the main module if (import.meta.url === `file://${process.argv[1]}`) { start().catch(error => { console.error('Failed to start server:', error); process.exit(1); }); } export default app;