UNPKG

jezweb-mcp-core

Version:

Jezweb Model Context Protocol (MCP) Core - A universal server for providing AI tools and resources, designed for seamless integration with various AI models and clients. Features adaptable multi-provider support, comprehensive tool and resource management

195 lines 8.2 kB
/** * NPM Package MCP Handler - Modern ESM Implementation * * This handler uses the shared BaseMCPHandler architecture with the SimpleMCPHandlerConfig * interface for streamlined configuration. It loads configuration from environment variables * using dotenv and provides a clean, modern interface for MCP protocol handling. * * Key features: * - Uses SimpleMCPHandlerConfig for simplified configuration * - Automatic .env file loading via dotenv * - Direct OpenAI API integration via BaseMCPHandler * - Modern ESM module structure * - Simplified error handling and JSON-RPC compliance * - Integrated provider registry system */ import { ErrorCodes, createStandardErrorResponse } from '../../shared/types/index.js'; import { BaseMCPHandler } from '../../shared/core/base-mcp-handler.js'; import { ProviderRegistry } from '../../shared/services/provider-registry.js'; import { openaiProviderFactory } from '../../shared/services/providers/openai.js'; /** * Modern MCP Handler for NPM Package * * This class provides a simplified interface to the BaseMCPHandler using * the SimpleMCPHandlerConfig interface and environment-based configuration. */ export class MCPHandler { baseMCPHandler; config; constructor(apiKey) { // Validate API key if (!apiKey || apiKey.trim().length === 0) { throw new Error('API key is required and cannot be empty'); } // Create simplified configuration using environment variables this.config = { apiKey: apiKey, serverName: process.env.MCP_SERVER_NAME || 'openai-assistants-mcp', serverVersion: process.env.MCP_SERVER_VERSION || '3.0.1', debug: process.env.DEBUG === 'true' || process.env.MCP_DEBUG === 'true', capabilities: { tools: { listChanged: false }, resources: { subscribe: false, listChanged: false }, prompts: { listChanged: false }, completions: {}, }, }; // Create and initialize provider registry const providerRegistry = MCPHandler.createProviderRegistry(apiKey); // Initialize the base handler with provider registry this.baseMCPHandler = new BaseMCPHandler(this.config, providerRegistry); } /** * Create and initialize the provider registry synchronously * This creates the registry and registers the factory, but doesn't initialize providers yet */ static createProviderRegistry(apiKey) { // Create Provider Registry Config (MVP) const registryConfig = { defaultProvider: 'openai', providers: [ { provider: 'openai', enabled: true, config: { apiKey: apiKey }, }, ], // MVP: Advanced features removed - implement later // // Use environment variables for optional settings with defaults // enableHealthChecks: process.env.ENABLE_HEALTH_CHECKS !== 'false', // Default to true // healthCheckInterval: parseInt(process.env.HEALTH_CHECK_INTERVAL || '60000'), // Default 1 minute // maxRetryAttempts: parseInt(process.env.MAX_RETRY_ATTEMPTS || '3'), // retryDelay: parseInt(process.env.RETRY_DELAY || '5000'), // Default 5 seconds }; // Initialize the registry const providerRegistry = new ProviderRegistry(registryConfig); providerRegistry.registerFactory(openaiProviderFactory); // Initialize the registry asynchronously in the background // This is a fire-and-forget operation for backward compatibility setTimeout(async () => { try { await providerRegistry.initialize(); console.log('[MCPHandler] Provider registry initialized successfully'); } catch (error) { console.error('[MCPHandler] Failed to initialize provider registry:', error); } }, 0); return providerRegistry; } /** * Static factory method for proper async initialization * Use this method instead of the constructor when you need to ensure * the provider registry is fully initialized before use */ static async create(apiKey) { // Validate API key if (!apiKey || apiKey.trim().length === 0) { throw new Error('API key is required and cannot be empty'); } // Create simplified configuration using environment variables const config = { apiKey: apiKey, serverName: process.env.MCP_SERVER_NAME || 'jezweb-mcp-core', serverVersion: process.env.MCP_SERVER_VERSION || '3.0.1', debug: process.env.DEBUG === 'true' || process.env.MCP_DEBUG === 'true', capabilities: { tools: { listChanged: false }, resources: { subscribe: false, listChanged: false }, prompts: { listChanged: false }, completions: {}, }, }; // Create Provider Registry Config (MVP) const registryConfig = { defaultProvider: 'openai', providers: [ { provider: 'openai', enabled: true, config: { apiKey: apiKey }, }, ], // MVP: Advanced features removed - implement later // enableHealthChecks: process.env.ENABLE_HEALTH_CHECKS !== 'false', // Default to true // healthCheckInterval: parseInt(process.env.HEALTH_CHECK_INTERVAL || '60000'), // Default 1 minute // maxRetryAttempts: parseInt(process.env.MAX_RETRY_ATTEMPTS || '3'), // retryDelay: parseInt(process.env.RETRY_DELAY || '5000'), // Default 5 seconds }; // Initialize the registry const providerRegistry = new ProviderRegistry(registryConfig); providerRegistry.registerFactory(openaiProviderFactory); await providerRegistry.initialize(); // Properly await initialization // Create handler instance with initialized registry const handler = Object.create(MCPHandler.prototype); handler.config = config; handler.baseMCPHandler = new BaseMCPHandler(config, providerRegistry); return handler; } /** * Handle incoming MCP requests using the shared BaseMCPHandler */ async handleRequest(request) { try { // Validate JSON-RPC 2.0 format if (request.jsonrpc !== '2.0') { return createStandardErrorResponse(request.id, ErrorCodes.INVALID_REQUEST, 'Invalid JSON-RPC version', { expected: '2.0', received: request.jsonrpc, documentation: 'https://www.jsonrpc.org/specification' }); } // Delegate to the shared base handler return await this.baseMCPHandler.handleRequest(request); } catch (error) { return createStandardErrorResponse(request.id, ErrorCodes.INTERNAL_ERROR, 'Internal error', { details: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), mode: 'direct' }); } } /** * Get registry statistics (for debugging) */ getStats() { return this.baseMCPHandler?.getRegistryStats() || { totalHandlers: 0, handlersByCategory: {}, registeredTools: [] }; } /** * Check if handler is initialized */ isInitialized() { return this.baseMCPHandler?.getIsInitialized() || false; } /** * Update API key and reinitialize if needed */ updateApiKey(apiKey) { if (this.baseMCPHandler) { this.baseMCPHandler.updateApiKey(apiKey); this.config.apiKey = apiKey; } } /** * Get current configuration (for debugging) */ getConfig() { return { ...this.config }; } } //# sourceMappingURL=mcp-handler.js.map