Skip to main content
Glama
error-handler.ts6.24 kB
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; export interface InstantlyApiError { status: number; message: string; code?: string; details?: any; } export class InstantlyError extends Error { status: number; code?: string; details?: any; constructor(error: InstantlyApiError) { super(error.message); this.name = 'InstantlyError'; this.status = error.status; this.code = error.code; this.details = error.details; } } export function handleInstantlyError(error: any, toolName: string): never { // Handle different error scenarios // Handle timeout errors specifically if (error.name === 'AbortError' || error.message?.includes('timeout')) { throw new McpError( ErrorCode.InternalError, `Request timeout: The ${toolName} operation took too long to complete. ` + `This may be due to a large number of accounts, slow network connection, or API server issues. ` + `Please try again in a few moments.` ); } if (error instanceof InstantlyError) { // Map Instantly API errors to MCP errors with tool-specific guidance switch (error.status) { case 400: // Enhanced guidance for create_campaign 400 errors if (toolName === 'create_campaign') { throw new McpError( ErrorCode.InvalidParams, `Campaign creation failed (400): ${error.message}. ` + `SOLUTION: First call list_accounts to get valid sending email addresses, then use ONLY those emails in the email_list parameter. ` + `Invalid or unverified email addresses will cause this error.` ); } throw new McpError( ErrorCode.InvalidParams, `Bad request (400): ${error.message}. Please check your parameters and try again.` ); case 401: throw new McpError( ErrorCode.InvalidRequest, `Authentication failed (401): ${error.message}. Please check your API key is valid and has not expired.` ); case 403: // Enhanced guidance for specific tools if (toolName === 'verify_email') { throw new McpError( ErrorCode.InvalidRequest, `Email verification access forbidden (403): ${error.message}. ` + `This feature requires a premium Instantly plan. Check: 1) Your plan includes email verification, 2) API key has required scopes, 3) Contact Instantly support.` ); } throw new McpError( ErrorCode.InvalidRequest, `Access forbidden (403): ${error.message}. You may not have permission for this operation or it may require a premium plan.` ); case 404: // Enhanced guidance for list_leads if (toolName === 'list_leads') { throw new McpError( ErrorCode.InvalidRequest, `Leads not found (404): ${error.message}. ` + `This may indicate the endpoint or parameters are incorrect. Try creating a lead first with create_lead.` ); } throw new McpError( ErrorCode.InvalidRequest, `Resource not found (404): ${error.message}. The requested resource may not exist or you may not have access to it.` ); case 422: throw new McpError( ErrorCode.InvalidParams, `Validation error (422): ${error.message}${error.details ? `. Details: ${JSON.stringify(error.details)}` : ''}. ` + `Please check that all required fields are provided and in the correct format.` ); case 429: throw new McpError( ErrorCode.InvalidRequest, `Rate limit exceeded (429): ${error.message}. Please wait before retrying. ` + `Consider reducing the frequency of requests or upgrading your Instantly plan for higher limits.` ); case 500: case 502: case 503: case 504: throw new McpError( ErrorCode.InternalError, `Instantly API server error (${error.status}): ${error.message}. ` + `This is a temporary server issue. Please try again in a few moments.` ); default: throw new McpError( ErrorCode.InternalError, `Instantly API error (${error.status}): ${error.message}. ` + `If this persists, please check the Instantly API documentation or contact support.` ); } } // Handle network errors if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') { throw new McpError( ErrorCode.InternalError, `Cannot connect to Instantly API: ${error.message}` ); } if (error.code === 'ETIMEDOUT') { throw new McpError( ErrorCode.InternalError, `Request to Instantly API timed out` ); } // Handle MCP errors (re-throw them) if (error instanceof McpError) { throw error; } // Generic error handling throw new McpError( ErrorCode.InternalError, `Failed to execute ${toolName}: ${error instanceof Error ? error.message : 'Unknown error'}` ); } export async function parseInstantlyResponse(response: Response): Promise<any> { const contentType = response.headers.get('content-type'); if (contentType?.includes('application/json')) { try { const data = await response.json(); if (!response.ok) { throw new InstantlyError({ status: response.status, message: data.error || data.message || response.statusText, code: data.code, details: data.details || data.errors, }); } return data; } catch (error) { if (error instanceof InstantlyError) { throw error; } // JSON parsing error throw new InstantlyError({ status: response.status, message: `Failed to parse response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, }); } } else { // Non-JSON response const text = await response.text(); if (!response.ok) { throw new InstantlyError({ status: response.status, message: text || response.statusText, }); } return text; } }

Implementation Reference

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