UNPKG

@iriseller/mcp-server

Version:

Model Context Protocol (MCP) server providing access to IRISeller's AI sales intelligence platform with 7 AI agents, multi-CRM integration, advanced sales workflows, email automation (detection/sending/campaigns), and robust asynchronous agent execution h

177 lines (176 loc) 6.58 kB
#!/usr/bin/env node /** * Dedicated HTTP Server for IRISeller MCP Server * This file always starts the HTTP wrapper server */ import express from 'express'; import cors from 'cors'; import jwt from 'jsonwebtoken'; import { IRISellerAPIService } from './services/iriseller-api.js'; import { ToolHandlers } from './handlers/tool-handlers.js'; import { ALL_TOOLS } from './tools/index.js'; import dotenv from 'dotenv'; // Load environment variables dotenv.config(); const PORT = parseInt(process.env.PORT || '3002', 10); // Configuration const config = { name: process.env.MCP_SERVER_NAME || 'iriseller-mcp-server', version: process.env.MCP_SERVER_VERSION || '1.0.0', iriseller_api_url: process.env.IRISELLER_API_URL || 'http://localhost:3001', crewai_api_url: process.env.CREWAI_API_URL || 'http://localhost:8001', crm_connect_api_url: process.env.CRM_CONNECT_API_URL || 'http://localhost:3001/api/crm-connect', debug: process.env.DEBUG === 'true', jwt_secret: process.env.JWT_SECRET }; // Initialize services const apiService = new IRISellerAPIService(config); const toolHandlers = new ToolHandlers(apiService); // Generate user token if credentials provided async function generateUserToken(email, password, jwtSecret) { if (!email || !password || !jwtSecret) { return undefined; } try { const token = jwt.sign({ email, userId: `mcp-user-${email}`, id: `mcp-user-${email}`, role: 'user', isSystemToken: true, sub: email, iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + (4 * 60 * 60) // 4 hours (will be automatically refreshed) }, jwtSecret); return token; } catch (error) { console.error('[MCP-HTTP] Failed to generate user token:', error); return undefined; } } // Initialize authentication async function initializeAuthentication() { // Generate user token from environment variables const email = process.env.MCP_DEFAULT_USER_EMAIL; const password = process.env.MCP_DEFAULT_USER_PASSWORD; if (!email || !password) { console.warn(`[MCP-HTTP] Warning: No default credentials configured. Set MCP_DEFAULT_USER_EMAIL and MCP_DEFAULT_USER_PASSWORD environment variables.`); return; } const userToken = await generateUserToken(email, password, config.jwt_secret); if (userToken) { toolHandlers.setUserToken(userToken); console.log(`[MCP-HTTP] Generated user token for ${email}`); console.log('[MCP-HTTP] User token configured for authenticated operations'); } else { console.log('[MCP-HTTP] No user token generated - using system authentication'); } } // Create Express app const app = express(); // Middleware app.use(cors()); app.use(express.json({ limit: '10mb' })); // Health check endpoint app.get('/health', async (req, res) => { try { const health = await apiService.checkHealth(); const overallHealth = health.backend && health.crewai && health.crmConnect; res.status(overallHealth ? 200 : 503).json({ status: overallHealth ? 'healthy' : 'degraded', services: health, timestamp: new Date().toISOString(), version: config.version }); } catch (error) { res.status(500).json({ status: 'error', error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }); } }); // Tools endpoint app.post('/tools/:toolName', async (req, res) => { const { toolName } = req.params; // Extract arguments from request body - handle both direct args and nested structure const toolArgs = req.body.arguments || req.body; try { const mcpRequest = { params: { name: toolName, arguments: toolArgs }, method: 'tools/call' }; const result = await toolHandlers.handleToolCall(mcpRequest); res.json({ success: true, tool: toolName, result, timestamp: new Date().toISOString() }); } catch (error) { console.error(`[MCP-HTTP] Error executing tool ${toolName}:`, error); res.status(500).json({ success: false, tool: toolName, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString() }); } }); // Start server async function startServer() { try { console.log(`[MCP-HTTP] Starting ${config.name} v${config.version}`); console.log(`[MCP-HTTP] IRISeller API: ${config.iriseller_api_url}`); console.log(`[MCP-HTTP] CrewAI API: ${config.crewai_api_url}`); console.log(`[MCP-HTTP] CRM Connect API: ${config.crm_connect_api_url}`); console.log(`[MCP-HTTP] Debug mode: ${config.debug}`); console.log(`[MCP-HTTP] Available tools: ${ALL_TOOLS.length}`); // Initialize authentication await initializeAuthentication(); // Test connectivity try { const health = await apiService.checkHealth(); console.log('[MCP-HTTP] Service health check:', { backend: health.backend ? '✅' : '❌', crewai: health.crewai ? '✅' : '❌', crmConnect: health.crmConnect ? '✅' : '❌' }); } catch (error) { console.warn('[MCP-HTTP] Warning: Could not perform initial health check:', error); } // Start HTTP server app.listen(PORT, '0.0.0.0', () => { console.log(`[MCP-HTTP] IRISeller MCP Server HTTP Wrapper started`); console.log(`[MCP-HTTP] Server: http://0.0.0.0:${PORT}`); console.log(`[MCP-HTTP] Health: http://0.0.0.0:${PORT}/health`); console.log(`[MCP-HTTP] Available tools: ${ALL_TOOLS.length}`); }); } catch (error) { console.error('[MCP-HTTP] Failed to start server:', error); process.exit(1); } } // Graceful shutdown process.on('SIGINT', () => { console.log('[MCP-HTTP] Received SIGINT, shutting down gracefully...'); process.exit(0); }); process.on('SIGTERM', () => { console.log('[MCP-HTTP] Received SIGTERM, shutting down gracefully...'); process.exit(0); }); // Start the server startServer().catch((error) => { console.error('[MCP-HTTP] Failed to start server:', error); process.exit(1); });