import 'dotenv/config';
import { WebSocket } from 'ws';
// @ts-ignore - Polyfill WebSocket for Node.js
global.WebSocket = WebSocket as any;
import { ContextVMMCPBridge } from './core/bridge.js';
import { loadConfig } from './config/index.js';
import { defaultContexts } from './mapping/contexts.js';
import http from 'http';
import pino from 'pino';
const logger = pino({
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:standard',
},
},
});
/**
* Main entry point
*/
async function main() {
try {
// Load configuration
logger.info('Loading configuration...');
const config = loadConfig();
// Load contexts (use default for now)
const contexts = defaultContexts;
logger.info({ contexts: contexts.length }, 'Contexts loaded');
// Create bridge
const bridge = new ContextVMMCPBridge(config, contexts);
// Start bridge
await bridge.start();
// Create health check server
const server = http.createServer((req, res) => {
if (req.url === '/health') {
const stats = bridge.getStats();
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
status: 'healthy',
uptime: process.uptime(),
...stats,
}));
} else if (req.url === '/metrics') {
const stats = bridge.getStats();
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`
# HELP contextvm_bridge_running Bridge running status
# TYPE contextvm_bridge_running gauge
contextvm_bridge_running ${stats.isRunning ? 1 : 0}
# HELP contextvm_bridge_pending_requests Pending DVM requests
# TYPE contextvm_bridge_pending_requests gauge
contextvm_bridge_pending_requests ${stats.pendingRequests}
# HELP contextvm_bridge_contexts Total contexts configured
# TYPE contextvm_bridge_contexts gauge
contextvm_bridge_contexts ${stats.contexts}
`);
} else {
res.writeHead(404);
res.end('Not Found');
}
});
server.listen(config.bridge.port, config.bridge.host, () => {
logger.info(
{ host: config.bridge.host, port: config.bridge.port },
'Health check server started'
);
logger.info('Bridge is ready to accept requests');
});
// Graceful shutdown
const shutdown = async (signal: string) => {
logger.info({ signal }, 'Received shutdown signal');
server.close(() => {
logger.info('Health check server closed');
});
await bridge.stop();
process.exit(0);
};
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
} catch (error) {
console.error('Fatal error:', error);
logger.error({ error: error instanceof Error ? { message: error.message, stack: error.stack } : String(error) }, 'Fatal error');
process.exit(1);
}
}
// Run
main().catch((error) => {
console.error('Unhandled error:', error);
logger.error({ error: error instanceof Error ? { message: error.message, stack: error.stack } : String(error) }, 'Unhandled error');
process.exit(1);
});