Skip to main content
Glama
parameter-cleaner.ts6.65 kB
/** * Instantly MCP Server - Parameter Cleanup Utilities * * This module contains utility functions for cleaning and validating parameters * before sending them to the Instantly.ai API v2. These functions ensure that * only valid parameters are sent to the API to prevent errors. * * Functions: * - cleanupAndValidateParameters: Removes unsupported parameters from API calls * - validateEmailListAgainstAccounts: Validates sender email addresses against eligible accounts */ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { getAllAccounts } from '../services/account-service.js'; /** * CRITICAL: Parameter cleanup and validation for Instantly.ai API v2 compatibility * * This function MUST remove all parameters that don't exist in the official API * to prevent API errors. It also handles parameter conversions for backward compatibility. * * @param args - The arguments object to clean * @returns Object containing cleaned arguments and warnings */ export function cleanupAndValidateParameters(args: any): { cleanedArgs: any; warnings: string[] } { const warnings: string[] = []; const cleanedArgs = { ...args }; console.error('[Instantly MCP] 🧹 CRITICAL: Cleaning parameters for API v2 compatibility...'); // CRITICAL: List of parameters that DO NOT EXIST in Instantly.ai API v2 // These MUST be removed to prevent API errors const unsupportedParams = [ 'continue_thread', // Not supported in API v2 'email_gap_minutes' // This parameter does NOT exist in API v2 - only email_gap exists // NOTE: sequence_steps, step_delay_days, sequence_bodies, sequence_subjects are internal parameters // used to build multi-step sequences and should NOT be removed ]; // Remove unsupported parameters and warn user for (const param of unsupportedParams) { if (cleanedArgs[param] !== undefined) { console.error(`[Instantly MCP] ⚠️ REMOVING invalid parameter: ${param} = ${cleanedArgs[param]}`); // Special handling for email_gap_minutes conversion if (param === 'email_gap_minutes' && cleanedArgs.email_gap === undefined) { cleanedArgs.email_gap = cleanedArgs[param]; warnings.push(`✅ Converted legacy 'email_gap_minutes' to 'email_gap' (${cleanedArgs[param]} minutes) for API v2 compatibility.`); } else { warnings.push(`⚠️ Parameter '${param}' does not exist in Instantly.ai API v2 and has been removed.`); } delete cleanedArgs[param]; } } console.error(`[Instantly MCP] ✅ Parameter cleanup complete. Warnings: ${warnings.length}`); return { cleanedArgs, warnings }; } /** * Helper function to validate sender email addresses against eligible accounts * * email_list contains SENDER email addresses that must be from verified Instantly accounts. * This function validates that all provided sender emails exist in the workspace and are * eligible for sending (active, setup complete, warmup finished). * * @param emailList - Array of sender email addresses to validate * @param apiKey - Instantly.ai API key for fetching accounts * @throws McpError if validation fails */ export async function validateEmailListAgainstAccounts(emailList: string[], apiKey?: string): Promise<void> { try { console.error('[Instantly MCP] 🔍 Validating sender email addresses against accounts...'); // Add timeout protection to prevent hanging - increased to 90 seconds for large account lists const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Account validation timeout after 90 seconds. This may indicate a large number of accounts or slow API response.')), 90000); }); const accountsPromise = getAllAccounts(apiKey); const accountsResult = await Promise.race([accountsPromise, timeoutPromise]) as any; // FIX: getAllAccounts returns { data: [...], metadata: {...} }, not an array directly const accounts = accountsResult.data || accountsResult; if (!accounts || !Array.isArray(accounts) || accounts.length === 0) { throw new McpError( ErrorCode.InvalidParams, 'No accounts found in your workspace. Please add at least one account before creating campaigns.' ); } // Filter to eligible accounts (status=1, not setup_pending, warmup_status=1) const eligibleAccounts = accounts.filter(account => account.status === 1 && !account.setup_pending && account.warmup_status === 1 ); if (eligibleAccounts.length === 0) { const accountIssues = accounts.map(acc => ({ email: acc.email, issues: [ ...(acc.status !== 1 ? ['Account not active'] : []), ...(acc.setup_pending ? ['Setup pending'] : []), ...(acc.warmup_status !== 1 ? ['Warmup not complete'] : []) ] })); throw new McpError( ErrorCode.InvalidParams, `No eligible sender accounts found for campaign creation. Account issues:\n${ accountIssues.map(acc => `• ${acc.email}: ${acc.issues.join(', ')}`).join('\n') }\n\nPlease ensure accounts are active, setup is complete, and warmup is finished before creating campaigns.` ); } // Create set of eligible email addresses for validation const eligibleEmails = new Set<string>(); const eligibleEmailsForDisplay: string[] = []; for (const account of eligibleAccounts) { eligibleEmails.add(account.email.toLowerCase()); eligibleEmailsForDisplay.push(`${account.email} (warmup: ${account.warmup_score || 'N/A'})`); } // Validate each sender email in the provided list const invalidEmails: string[] = []; for (const email of emailList) { if (!eligibleEmails.has(email.toLowerCase())) { invalidEmails.push(email); } } if (invalidEmails.length > 0) { throw new McpError( ErrorCode.InvalidParams, `Invalid sender email addresses found in email_list: ${invalidEmails.join(', ')}\n\n` + `Available eligible sender accounts:\n${eligibleEmailsForDisplay.map(email => `• ${email}`).join('\n')}\n\n` + `Please use only verified sender email addresses from your Instantly workspace. Call list_accounts to see all available accounts.` ); } console.error(`[Instantly MCP] ✅ Validated ${emailList.length} sender email(s) against ${eligibleAccounts.length} eligible accounts`); } catch (error: any) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Failed to validate email addresses: ${error.message}` ); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bcharleson/Instantly-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server