tryaii-mcp-server
Version:
TryAII MCP Server - 15+ AI models with comparison, cost tracking, and collective intelligence
230 lines • 9.57 kB
JavaScript
import { HttpTransport } from '../transports/HttpTransport.js';
import { McpTransport } from '../transports/McpTransport.js';
import { McpProtocolHandler } from '../mcp/McpProtocolHandler.js';
import { sessionManager } from '../services/sessionManager.js';
import { userApiKeyService } from '../services/userApiKeyService.js';
import { databaseService } from '../services/database.js';
import { httpClient } from '../services/httpClient.js';
import { authenticationService } from '../services/AuthenticationService.js';
import { balanceService } from '../services/BalanceService.js';
import { sessionService } from '../services/SessionService.js';
import { config } from '../utils/config.js';
import { logger } from '../utils/logger.js';
export class MultiTransportServer {
transports = new Map();
protocolHandler;
initialized = false;
constructor() {
this.protocolHandler = new McpProtocolHandler(sessionManager, userApiKeyService);
}
async start() {
try {
logger.info('Starting multi-transport server...');
// Initialize services first
await this.initializeServices();
// Start enabled transports
if (config.server.modes.http) {
await this.startHttpTransport();
}
if (config.server.modes.mcp) {
await this.startMcpTransport();
}
// Validate at least one transport is enabled
if (this.transports.size === 0) {
throw new Error('No transports enabled. Enable at least one transport mode (HTTP or MCP).');
}
this.initialized = true;
logger.info('🚀 Multi-transport server started successfully', {
modes: config.server.modes,
transports: Array.from(this.transports.keys()),
transportCount: this.transports.size
});
}
catch (error) {
logger.error('Failed to start multi-transport server', { error });
throw error;
}
}
async initializeServices() {
logger.info('Initializing services...');
// Initialize database connection with dual connections
logger.info('Initializing enhanced database connections...');
try {
await databaseService.connect();
logger.info('✅ Database connections initialized (main + MCP)');
}
catch (error) {
logger.error('Database connection failed', { error });
if (process.env.NODE_ENV === 'production') {
throw error;
}
logger.warn('Continuing without database in development/test mode');
logger.info('💡 To fix this: Install MongoDB locally or set MAIN_DB_URI and MCP_DB_URI');
}
// Initialize our enhanced services
if (databaseService.isHealthy()) {
try {
logger.info('Initializing enhanced authentication service...');
await authenticationService.initialize();
logger.info('✅ Enhanced authentication service initialized');
logger.info('Initializing balance service...');
await balanceService.initialize();
logger.info('✅ Balance service initialized');
logger.info('Initializing session service...');
await sessionService.initialize();
logger.info('✅ Session service initialized');
logger.info('🎉 All enhanced services initialized successfully');
}
catch (error) {
logger.error('Failed to initialize enhanced services', { error });
throw error;
}
}
else {
logger.warn('Skipping enhanced services initialization (database not available)');
}
// Initialize MCP client (skip in test mode if executable doesn't exist)
const skipMCP = process.env.NODE_ENV === 'test' &&
(!config.mcp.executablePath ||
config.mcp.executablePath === '../mcp_tryaii/build/index.js');
// Initialize HTTP client for the new architecture
logger.info('Initializing HTTP client...');
try {
await httpClient.start();
logger.info('HTTP client initialized successfully');
// Initialize session manager with HTTP client
logger.info('Initializing session manager with HTTP client...');
sessionManager.setHttpClient(httpClient);
}
catch (error) {
logger.error('HTTP client initialization failed', { error });
throw error;
}
// Start session manager
logger.info('Starting session manager...');
sessionManager.start();
logger.info('Session manager started successfully');
}
async startHttpTransport() {
logger.info('Starting HTTP transport...');
const httpTransport = new HttpTransport();
this.transports.set('http', httpTransport);
// Set reference to this server in health routes for monitoring
const { setMultiTransportServer } = await import('../routes/health.js');
setMultiTransportServer(this);
// HTTP transport handles its own routing
await httpTransport.start();
logger.info('HTTP transport started successfully');
}
async startMcpTransport() {
logger.info('Starting MCP transport...');
const mcpTransport = new McpTransport();
this.transports.set('mcp', mcpTransport);
// Handle MCP requests
mcpTransport.on('request', async (connectionId, request) => {
try {
const response = await this.protocolHandler.handleRequest(connectionId, request);
// Only send response if it's not null (notifications don't need responses)
if (response !== null) {
await mcpTransport.sendResponse(connectionId, response);
}
}
catch (error) {
logger.error('Error processing MCP request', {
connectionId,
method: request.method,
id: request.id,
error
});
}
});
// Handle MCP connection events
mcpTransport.on('connection', (connectionId) => {
logger.info('New MCP connection', { connectionId });
});
mcpTransport.on('connectionClosed', (connectionId) => {
logger.info('MCP connection closed', { connectionId });
this.protocolHandler.removeConnection(connectionId);
});
mcpTransport.on('connectionError', (connectionId, error) => {
logger.error('MCP connection error', { connectionId, error });
this.protocolHandler.removeConnection(connectionId);
});
await mcpTransport.start();
logger.info('MCP transport started successfully');
}
async stop() {
if (!this.initialized) {
logger.info('Multi-transport server not initialized, nothing to stop');
return;
}
logger.info('Stopping multi-transport server...');
// Stop all transports
for (const [name, transport] of this.transports) {
logger.info(`Stopping ${name} transport...`);
try {
await transport.stop();
logger.info(`${name} transport stopped`);
}
catch (error) {
logger.error(`Error stopping ${name} transport`, { error });
}
}
this.transports.clear();
// Stop services
try {
// Stop session manager
sessionManager.stop();
logger.info('Session manager stopped');
// Stop HTTP client
await httpClient.stop();
logger.info('HTTP client stopped');
// Disconnect from database
await databaseService.disconnect();
logger.info('Database disconnected');
}
catch (error) {
logger.error('Error stopping services', { error });
}
this.initialized = false;
logger.info('Multi-transport server stopped');
}
// Health check methods
isHealthy() {
if (!this.initialized) {
return false;
}
// Check if all enabled transports are healthy
for (const transport of this.transports.values()) {
if (!transport.isHealthy()) {
return false;
}
}
return true;
}
getStatus() {
const transportStatus = {};
for (const [name, transport] of this.transports) {
transportStatus[name] = {
healthy: transport.isHealthy(),
...(name === 'mcp' && {
connections: transport.getConnectionCount(),
activeConnections: transport.getConnections()
})
};
}
return {
initialized: this.initialized,
healthy: this.isHealthy(),
modes: config.server.modes,
transports: transportStatus,
services: {
sessionManager: sessionManager.isRunning(),
mcpProtocolHandler: {
connections: this.protocolHandler.getConnectionCount()
}
}
};
}
}
//# sourceMappingURL=MultiTransportServer.js.map