Skip to main content
Glama
bcharleson

Instantly MCP Server

list_campaigns

Retrieve and filter email campaigns from Instantly API with automatic pagination support to access all campaigns efficiently.

Instructions

List campaigns with optional filters and complete pagination support. COMPLETE PAGINATION: To get ALL campaigns, use one of these approaches:

  1. Set limit=100 or higher (automatically triggers complete pagination)

  2. Set get_all=true (forces complete pagination)

  3. Use limit="all" (string triggers complete pagination)

PAGINATION ALGORITHM: When requesting all campaigns, the tool will automatically:

  • Start with limit=100 per page

  • Continue fetching until next_starting_after is null or empty results

  • Report progress: "Retrieved 100... 200... 304 total campaigns"

  • Return summarized data to prevent size limits

  • Use get_campaign for full details of specific campaigns

FILTERS: search and status filters work with both single-page and complete pagination modes.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
get_allNoSet to true to force complete pagination and retrieve ALL campaigns regardless of limit setting.
limitNoNumber of campaigns to return (1-100, default: 20). Use limit=100+ or limit="all" to trigger complete pagination that retrieves ALL campaigns automatically.
searchNoSearch term to filter campaigns by name (works with complete pagination)
starting_afterNoID of the last item from previous page for manual pagination. Not needed when using complete pagination (limit=100+).
statusNoFilter by campaign status (works with complete pagination)

Implementation Reference

  • Main handler execution logic for list_campaigns tool. Makes API call to /campaigns, handles pagination, maps numeric status codes to human-readable labels, adds metadata.
    case 'list_campaigns': {
      console.error('[Instantly MCP] πŸ“‹ Executing list_campaigns (sequential pagination)...');
    
      try {
        const startTime = Date.now();
    
        // Status mapping: API returns numbers, we convert to human-readable labels
        const STATUS_MAP: Record<number, string> = {
          0: 'Draft',
          1: 'Active',
          2: 'Paused',
          3: 'Completed',
          4: 'Running Subsequences',
          '-99': 'Account Suspended',
          '-1': 'Accounts Unhealthy',
          '-2': 'Bounce Protect'
        };
    
        // Build query parameters for single page request
        const queryParams: any = {
          limit: args?.limit || 100, // Default to 100 items per page (max pagination)
        };
    
        // Add cursor if provided (for subsequent pages)
        if (args?.starting_after) {
          queryParams.starting_after = args.starting_after;
          console.error(`[Instantly MCP] πŸ“„ Fetching page with cursor: ${args.starting_after}`);
        } else {
          console.error('[Instantly MCP] πŸ“„ Fetching first page');
        }
    
        // Add API filter parameters
        if (args?.search) queryParams.search = args.search;
        if (args?.tag_ids) queryParams.tag_ids = args.tag_ids;
    
        // Make single API call to /campaigns endpoint
        const response = await makeInstantlyRequest('/campaigns', {
          method: 'GET',
          params: queryParams
        }, apiKey);
    
        const elapsed = Date.now() - startTime;
    
        // Extract data and pagination info from response
        const data = Array.isArray(response) ? response : (response.items || response.data || []);
        const nextCursor = response.next_starting_after || null;
        const hasMore = !!nextCursor;
    
        console.error(`[Instantly MCP] βœ… Retrieved ${data.length} campaigns in ${elapsed}ms (has_more: ${hasMore})`);
    
        // Apply status mapping to all campaigns (convert numeric status to human-readable labels)
        const campaignsWithReadableStatus = data.map((campaign: any) => ({
          ...campaign,
          status_label: STATUS_MAP[campaign.status] || `Unknown (${campaign.status})`,
          status_code: campaign.status // Keep original numeric code for reference
        }));
    
        // Track applied filters
        const filtersApplied: any = {};
        if (args?.search) filtersApplied.search = args.search;
        if (args?.tag_ids) filtersApplied.tag_ids = args.tag_ids;
    
        // Return single page with clear pagination metadata
        return createMCPResponse({
          data: campaignsWithReadableStatus,
          pagination: {
            returned_count: campaignsWithReadableStatus.length,
            has_more: hasMore,
            next_starting_after: nextCursor,
            limit: queryParams.limit,
            current_page_note: hasMore
              ? `Retrieved ${campaignsWithReadableStatus.length} campaigns. More results available. To get next page, call list_campaigns again with starting_after='${nextCursor}'`
              : `Retrieved all available campaigns (${campaignsWithReadableStatus.length} items).`
          },
          filters_applied: Object.keys(filtersApplied).length > 0 ? filtersApplied : undefined,
          metadata: {
            request_time_ms: elapsed,
            success: true,
            status_mapping_note: 'All campaigns include status_label (human-readable) and status_code (numeric) fields'
          },
          success: true
        });
      } catch (error: any) {
        console.error('[Instantly MCP] ❌ Error in list_campaigns:', error.message);
        throw error;
      }
    }
  • MCP tool definition and input schema for list_campaigns, including properties for pagination and filtering.
    {
      name: 'list_campaigns',
      title: 'List Campaigns',
      description: 'List campaigns with pagination. Filter by name search or tags.',
      annotations: { readOnlyHint: true },
      inputSchema: {
        type: 'object',
        properties: {
          limit: { type: 'number', description: '1-100, default: 100' },
          starting_after: { type: 'string', description: 'Cursor from pagination.next_starting_after' },
          search: { type: 'string', description: 'Search by campaign NAME only (not status)' },
          tag_ids: { type: 'string', description: 'Comma-separated tag IDs' }
        }
      }
    },
  • Registration of campaignTools (containing list_campaigns) into the main TOOLS_DEFINITION array used by MCP server.
      return [
        ...accountTools,
        ...campaignTools,
        ...leadTools,
        ...emailTools,
        ...analyticsTools,
      ];
    }
  • Zod validation schema ListCampaignsSchema for input parameters and associated validator function.
     * List campaigns validation schema
     */
    export const ListCampaignsSchema = z.object({
      limit: PaginationLimitSchema, // Already optional in the schema definition
      starting_after: z.string().optional(),
      get_all: z.boolean().optional(),
      search: z.string().optional(),
      status: z.string().optional()
    });

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