@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
JavaScript
/**
* 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);
});