/** * V3 MCP Transport Factory * * Central factory for creating transport instances: * - Unified transport creation API * - Transport type validation * - Configuration defaults * - Multi-transport support * * Supported transports: * - stdio: Standard I/O (default for CLI) * - http: HTTP/REST with WebSocket upgrade * - websocket: Standalone WebSocket * - in-process: Direct function calls (fastest) */ import { createStdioTransport } from './stdio.js'; import { createHttpTransport } from './http.js'; import { createWebSocketTransport } from './websocket.js'; // Re-export transport classes (values) export { StdioTransport } from './stdio.js'; export { HttpTransport } from './http.js'; export { WebSocketTransport } from './websocket.js'; /** * Create a transport instance based on type */ export function createTransport(type, logger, config) { switch (type) { case 'stdio': return createStdioTransport(logger, config); case 'http': if (!config || !('host' in config) || !('port' in config)) { throw new Error('HTTP transport requires host and port configuration'); } return createHttpTransport(logger, { host: config.host, port: config.port, ...config, }); case 'websocket': if (!config || !('host' in config) || !('port' in config)) { throw new Error('WebSocket transport requires host and port configuration'); } return createWebSocketTransport(logger, { host: config.host, port: config.port, ...config, }); case 'in-process': // In-process transport is handled directly by the server // Return a no-op transport wrapper return createInProcessTransport(logger); default: throw new Error(`Unknown transport type: ${type}`); } } /** * In-process transport (no-op wrapper) * * Used when tools are executed directly without network transport */ class InProcessTransport { logger; type = 'in-process'; constructor(logger) { this.logger = logger; } async start() { this.logger.debug('In-process transport started'); } async stop() { this.logger.debug('In-process transport stopped'); } onRequest() { // No-op - requests are handled directly } onNotification() { // No-op - notifications are handled directly } async getHealthStatus() { return { healthy: true, metrics: { latency: 0, connections: 1, }, }; } } /** * Create in-process transport */ export function createInProcessTransport(logger) { return new InProcessTransport(logger); } /** * Transport manager for multi-transport scenarios */ export class TransportManager { logger; transports = new Map(); running = false; constructor(logger) { this.logger = logger; } /** * Add a transport */ addTransport(name, transport) { if (this.transports.has(name)) { throw new Error(`Transport "${name}" already exists`); } this.transports.set(name, transport); this.logger.debug('Transport added', { name, type: transport.type }); } /** * Remove a transport */ async removeTransport(name) { const transport = this.transports.get(name); if (!transport) { return false; } await transport.stop(); this.transports.delete(name); this.logger.debug('Transport removed', { name }); return true; } /** * Get a transport by name */ getTransport(name) { return this.transports.get(name); } /** * Get all transport names */ getTransportNames() { return Array.from(this.transports.keys()); } /** * Start all transports */ async startAll() { if (this.running) { throw new Error('TransportManager already running'); } this.logger.info('Starting all transports', { count: this.transports.size }); const startPromises = Array.from(this.transports.entries()).map(async ([name, transport]) => { try { await transport.start(); this.logger.info('Transport started', { name, type: transport.type }); } catch (error) { this.logger.error('Failed to start transport', { name, error }); throw error; } }); await Promise.all(startPromises); this.running = true; this.logger.info('All transports started'); } /** * Stop all transports */ async stopAll() { if (!this.running) { return; } this.logger.info('Stopping all transports'); const stopPromises = Array.from(this.transports.entries()).map(async ([name, transport]) => { try { await transport.stop(); this.logger.info('Transport stopped', { name }); } catch (error) { this.logger.error('Error stopping transport', { name, error }); } }); await Promise.all(stopPromises); this.running = false; this.logger.info('All transports stopped'); } /** * Get health status of all transports */ async getHealthStatus() { const results = {}; for (const [name, transport] of this.transports) { try { const status = await transport.getHealthStatus(); results[name] = { healthy: status.healthy, error: status.error }; } catch (error) { results[name] = { healthy: false, error: error instanceof Error ? error.message : 'Unknown error', }; } } return results; } /** * Check if any transport is running */ isRunning() { return this.running; } } /** * Create a transport manager */ export function createTransportManager(logger) { return new TransportManager(logger); } /** * Default transport configurations */ export const DEFAULT_TRANSPORT_CONFIGS = { stdio: {}, http: { host: 'localhost', port: 3000, corsEnabled: true, corsOrigins: ['*'], maxRequestSize: '10mb', requestTimeout: 30000, }, websocket: { host: 'localhost', port: 3001, path: '/ws', maxConnections: 100, heartbeatInterval: 30000, heartbeatTimeout: 10000, maxMessageSize: 10 * 1024 * 1024, }, }; //# sourceMappingURL=index.js.map