mcp-product-manager
Version:
MCP Orchestrator for task and project management with web interface
119 lines (100 loc) • 3.95 kB
JavaScript
// 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;