UNPKG

inboxassure-mcp-server

Version:

Comprehensive MCP server for InboxAssure email marketing platform with full API coverage including campaigns, replies, and email account management.

566 lines (543 loc) 25.9 kB
import fetch from 'node-fetch'; import readline from 'readline'; // The server URL - point directly to the API server const SERVER_URL = 'https://bison.imnodev.com/api'; export function startMcpBridge(apiKey) { if (!apiKey) { console.error('[MCPX] Error: No API key provided'); process.exit(1); } // Create readline interface for stdio const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false }); console.error(`[MCPX] Bridge initialized and waiting for messages...`); // Listen for input from Claude rl.on('line', async (line) => { try { console.error(`[MCPX] Received message: ${line.substring(0, 50)}...`); // Parse the incoming JSON-RPC message const message = JSON.parse(line); // Handle different MCP methods if (message.method === 'initialize') { console.error(`[MCPX] Handling initialize request with id: ${message.id}`); // Send initialization response console.log(JSON.stringify({ jsonrpc: '2.0', id: message.id, result: { protocolVersion: '2024-11-05', capabilities: { tools: { listChanged: true } }, serverInfo: { name: 'InboxAssure MCP Server', version: '2.1.0', description: 'Comprehensive MCP server for InboxAssure email marketing platform' } } })); } else if (message.method === 'notifications/initialized') { // For notifications, simply log but don't respond // Notifications don't require a response according to JSON-RPC spec console.error(`[MCPX] Handling initialized notification`); // No response needed for notifications } else if (message.method === 'tools/list') { console.error(`[MCPX] Handling tools/list request with id: ${message.id}`); // List all 23 available tools console.log(JSON.stringify({ jsonrpc: '2.0', id: message.id, result: { tools: [ // Original tool { name: 'get_bison_hello', description: 'Test endpoint to verify API connectivity', inputSchema: { type: 'object', properties: { random_string: { type: 'string', description: 'Dummy parameter for no-parameter tools' } }, additionalProperties: false } }, // Campaigns API (11 tools) { name: 'list_campaigns', description: 'List all campaigns in a workspace with optional filtering and pagination', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID to list campaigns for' }, params: { type: 'object', description: 'Optional query parameters', properties: { search: { type: 'string', description: 'Search term for campaign names' }, status: { type: 'string', description: 'Filter by status (active, paused, draft)' }, page: { type: 'number', description: 'Page number for pagination' }, per_page: { type: 'number', description: 'Items per page (max 100)' } } } }, required: ['workspace_id'], additionalProperties: false } }, { name: 'create_campaign', description: 'Create a new email marketing campaign', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID to create the campaign in' }, name: { type: 'string', description: 'Name of the campaign' }, type: { type: 'string', description: 'Type of campaign (default: outbound)', enum: ['outbound', 'inbound'] } }, required: ['workspace_id', 'name'], additionalProperties: false } }, { name: 'get_campaign_details', description: 'Get detailed information about a specific campaign', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to get details for' } }, required: ['workspace_id', 'campaign_id'], additionalProperties: false } }, { name: 'pause_campaign', description: 'Pause a running campaign temporarily', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to pause' } }, required: ['workspace_id', 'campaign_id'], additionalProperties: false } }, { name: 'resume_campaign', description: 'Resume a paused campaign', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to resume' } }, required: ['workspace_id', 'campaign_id'], additionalProperties: false } }, { name: 'get_campaign_stats', description: 'Get detailed performance metrics for a campaign within a date range', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to get stats for' }, start_date: { type: 'string', description: 'Start date in YYYY-MM-DD format' }, end_date: { type: 'string', description: 'End date in YYYY-MM-DD format' } }, required: ['workspace_id', 'campaign_id', 'start_date', 'end_date'], additionalProperties: false } }, { name: 'get_campaign_leads', description: 'View all leads in a campaign with their status and progress', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to get leads for' }, params: { type: 'object', description: 'Optional query parameters', properties: { page: { type: 'number', description: 'Page number for pagination' }, per_page: { type: 'number', description: 'Items per page' }, status: { type: 'string', description: 'Filter by lead status' } } } }, required: ['workspace_id', 'campaign_id'], additionalProperties: false } }, { name: 'create_campaign_schedule', description: 'Set up when your campaign sends emails (days, times, timezone)', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to create schedule for' }, monday: { type: 'boolean', description: 'Send emails on Monday' }, tuesday: { type: 'boolean', description: 'Send emails on Tuesday' }, wednesday: { type: 'boolean', description: 'Send emails on Wednesday' }, thursday: { type: 'boolean', description: 'Send emails on Thursday' }, friday: { type: 'boolean', description: 'Send emails on Friday' }, saturday: { type: 'boolean', description: 'Send emails on Saturday' }, sunday: { type: 'boolean', description: 'Send emails on Sunday' }, start_time: { type: 'string', description: 'Start time in HH:MM format (e.g., 09:00)' }, end_time: { type: 'string', description: 'End time in HH:MM format (e.g., 17:00)' }, timezone: { type: 'string', description: 'Timezone (e.g., America/New_York)' } }, required: ['workspace_id', 'campaign_id', 'start_time', 'end_time', 'timezone'], additionalProperties: false } }, { name: 'get_schedule_templates', description: 'Retrieve predefined schedule templates for quick campaign setup', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' } }, required: ['workspace_id'], additionalProperties: false } }, { name: 'create_sequence_steps', description: 'Define the series of emails that will be sent to leads over time', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to create sequence for' }, title: { type: 'string', description: 'Title for the email sequence' }, sequence_steps: { type: 'array', description: 'Array of email steps in the sequence', items: { type: 'object', properties: { email_subject: { type: 'string', description: 'Subject line for the email' }, email_body: { type: 'string', description: 'Body content of the email' }, wait_in_days: { type: 'number', description: 'Days to wait before sending this email' }, order: { type: 'number', description: 'Order of this step in the sequence' } }, required: ['email_subject', 'email_body', 'wait_in_days', 'order'] } } }, required: ['workspace_id', 'campaign_id', 'title', 'sequence_steps'], additionalProperties: false } }, { name: 'attach_lead_list', description: 'Add an entire existing lead list to your campaign', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, campaign_id: { type: 'string', description: 'The campaign ID to attach leads to' }, lead_list_id: { type: 'string', description: 'The ID of the lead list to attach' } }, required: ['workspace_id', 'campaign_id', 'lead_list_id'], additionalProperties: false } }, // Replies API (5 tools) { name: 'list_replies', description: 'Retrieve all email replies across campaigns with filtering options', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, params: { type: 'object', description: 'Optional query parameters', properties: { search: { type: 'string', description: 'Search term for emails, subjects' }, status: { type: 'string', description: 'Filter by status (interested, not_interested, automated_reply)' }, folder: { type: 'string', description: 'Email folder (inbox, sent, spam, bounced, all)' }, read: { type: 'boolean', description: 'Filter by read status' }, campaign_id: { type: 'string', description: 'Filter by campaign ID' }, page: { type: 'number', description: 'Page number for pagination' }, per_page: { type: 'number', description: 'Items per page' } } } }, required: ['workspace_id'], additionalProperties: false } }, { name: 'get_reply_details', description: 'Get complete details of a specific reply including full message content', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, reply_id: { type: 'string', description: 'The reply ID to get details for' } }, required: ['workspace_id', 'reply_id'], additionalProperties: false } }, { name: 'compose_new_email', description: 'Send a standalone email outside of campaign sequences', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, sender_email_id: { type: 'string', description: 'ID of the sender email account' }, to_emails: { type: 'array', items: { type: 'string' }, description: 'Array of recipient email addresses' }, message: { type: 'string', description: 'The email message content' }, content_type: { type: 'string', description: 'Content type (text/plain or text/html)', enum: ['text/plain', 'text/html'] }, cc_emails: { type: 'array', items: { type: 'string' }, description: 'Array of CC email addresses' }, bcc_emails: { type: 'array', items: { type: 'string' }, description: 'Array of BCC email addresses' } }, required: ['workspace_id', 'sender_email_id', 'to_emails', 'message'], additionalProperties: false } }, { name: 'reply_to_email', description: 'Respond to an incoming email reply, maintaining conversation thread', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, reply_id: { type: 'string', description: 'The reply ID to respond to' }, sender_email_id: { type: 'string', description: 'ID of the sender email account' }, to_emails: { type: 'array', items: { type: 'string' }, description: 'Array of recipient email addresses' }, message: { type: 'string', description: 'The reply message content' }, content_type: { type: 'string', description: 'Content type (text/plain or text/html)', enum: ['text/plain', 'text/html'] } }, required: ['workspace_id', 'reply_id', 'sender_email_id', 'to_emails', 'message'], additionalProperties: false } }, { name: 'get_conversation_thread', description: 'Retrieve the complete email conversation history for context', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, reply_id: { type: 'string', description: 'The reply ID to get conversation thread for' } }, required: ['workspace_id', 'reply_id'], additionalProperties: false } }, // Email Accounts API (6 tools) { name: 'list_email_accounts', description: 'Get all email accounts configured in your workspace with their settings', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, params: { type: 'object', description: 'Optional query parameters', properties: { search: { type: 'string', description: 'Search term for email addresses, names' }, page: { type: 'number', description: 'Page number for pagination' }, per_page: { type: 'number', description: 'Items per page' } } } }, required: ['workspace_id'], additionalProperties: false } }, { name: 'get_email_account_details', description: 'Retrieve detailed configuration and statistics for a specific email account', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, email_id: { type: 'string', description: 'The email account ID to get details for' } }, required: ['workspace_id', 'email_id'], additionalProperties: false } }, { name: 'update_email_account', description: 'Modify email account configuration like daily limits and signatures', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, email_id: { type: 'string', description: 'The email account ID to update' }, daily_limit: { type: 'number', description: 'New daily email sending limit' }, name: { type: 'string', description: 'New display name for the email account' }, email_signature: { type: 'string', description: 'New email signature' } }, required: ['workspace_id', 'email_id'], additionalProperties: false } }, { name: 'get_account_campaigns', description: 'See which campaigns are using this email account for sending', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, email_id: { type: 'string', description: 'The email account ID to get campaigns for' } }, required: ['workspace_id', 'email_id'], additionalProperties: false } }, { name: 'get_account_replies', description: 'View all replies received by this specific email account', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, email_id: { type: 'string', description: 'The email account ID to get replies for' } }, required: ['workspace_id', 'email_id'], additionalProperties: false } }, { name: 'bulk_update_email_signatures', description: 'Update email signatures across multiple accounts simultaneously', inputSchema: { type: 'object', properties: { workspace_id: { type: 'string', description: 'The workspace ID' }, sender_email_ids: { type: 'array', items: { type: 'string' }, description: 'Array of email account IDs to update' }, email_signature: { type: 'string', description: 'New email signature to apply to all selected accounts' } }, required: ['workspace_id', 'sender_email_ids', 'email_signature'], additionalProperties: false } } ] } })); } else if (message.method === 'tools/call') { const toolName = message.params?.name; console.error(`[MCPX] Handling tools/call for ${toolName} with id: ${message.id}`); try { // Call the appropriate API endpoint based on the tool console.error(`[MCPX] Calling ${toolName} on ${SERVER_URL}`); const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 10000); // 10 second timeout let response; const args = message.params.arguments || {}; try { // Route to the correct API endpoint based on tool name if (toolName === 'get_bison_hello') { response = await fetch(`${SERVER_URL}/hello`, { method: 'GET', headers: { 'X-API-Key': apiKey }, signal: controller.signal }); } else if (toolName === 'list_campaigns') { const queryParams = new URLSearchParams(args.params || {}).toString(); const url = `${SERVER_URL}/campaigns/${args.workspace_id}${queryParams ? '?' + queryParams : ''}`; response = await fetch(url, { method: 'GET', headers: { 'X-API-Key': apiKey }, signal: controller.signal }); } else { throw new Error(`Tool ${toolName} not implemented yet in bridge`); } clearTimeout(timeout); if (!response.ok) { throw new Error(`API returned ${response.status}: ${response.statusText}`); } const data = await response.json(); console.error(`[MCPX] Received response from API: ${JSON.stringify(data).substring(0, 100)}...`); // Send the response back to Claude console.log(JSON.stringify({ jsonrpc: '2.0', id: message.id, result: { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] } })); } catch (fetchError) { clearTimeout(timeout); throw fetchError; } } catch (error) { const errorMessage = error.name === 'AbortError' ? 'Request timed out' : error.message; console.error(`[MCPX] Error calling remote server: ${errorMessage}`); console.log(JSON.stringify({ jsonrpc: '2.0', id: message.id, error: { code: -32603, message: `Server error: ${errorMessage}` } })); } } else { // Handle unknown methods console.error(`[MCPX] Unknown method: ${message.method}`); console.log(JSON.stringify({ jsonrpc: '2.0', id: message.id, error: { code: -32601, message: 'Method not found' } })); } } catch (error) { console.error(`[MCPX] Error parsing message: ${error.message}`); // Return parse error console.log(JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32700, message: `Parse error: ${error.message}` } })); } }); // Handle process termination process.on('SIGINT', () => { console.error(`[MCPX] Received SIGINT, shutting down...`); rl.close(); process.exit(0); }); process.on('SIGTERM', () => { console.error(`[MCPX] Received SIGTERM, shutting down...`); rl.close(); process.exit(0); }); }