Skip to main content
Glama
bcharleson

Instantly MCP Server

update_campaign

Modify email campaign settings like sequences, tracking, and sending limits with partial updates to optimize outreach performance.

Instructions

Update campaign settings (partial update).

Common updates:

  • name: Campaign display name

  • sequences: Email sequence steps

  • email_list: Sender account assignments

  • daily_limit: Max emails per day per account

  • email_gap: Minutes between sends

  • open_tracking, link_tracking: Tracking toggles

Only include fields you want to update.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The core handler function that implements the update_campaign tool. It constructs a partial update body from the input parameters and sends a PATCH request to the Instantly API endpoint /campaigns/{campaign_id}.
    async def update_campaign(params: UpdateCampaignInput) -> str:
        """
        Update campaign settings (partial update).
        
        Common updates:
        - name: Campaign display name
        - sequences: Email sequence steps
        - email_list: Sender account assignments
        - daily_limit: Max emails per day per account
        - email_gap: Minutes between sends
        - open_tracking, link_tracking: Tracking toggles
        
        Only include fields you want to update.
        """
        client = get_client()
        
        body = {}
        
        # Add all optional fields if provided
        if params.name is not None:
            body["name"] = params.name
        if params.pl_value is not None:
            body["pl_value"] = params.pl_value
        if params.is_evergreen is not None:
            body["is_evergreen"] = params.is_evergreen
        if params.campaign_schedule is not None:
            body["campaign_schedule"] = params.campaign_schedule
        if params.sequences is not None:
            body["sequences"] = params.sequences
        if params.email_gap is not None:
            body["email_gap"] = params.email_gap
        if params.random_wait_max is not None:
            body["random_wait_max"] = params.random_wait_max
        if params.text_only is not None:
            body["text_only"] = params.text_only
        if params.email_list is not None:
            body["email_list"] = params.email_list
        if params.daily_limit is not None:
            body["daily_limit"] = params.daily_limit
        if params.stop_on_reply is not None:
            body["stop_on_reply"] = params.stop_on_reply
        if params.email_tag_list is not None:
            body["email_tag_list"] = params.email_tag_list
        if params.link_tracking is not None:
            body["link_tracking"] = params.link_tracking
        if params.open_tracking is not None:
            body["open_tracking"] = params.open_tracking
        if params.stop_on_auto_reply is not None:
            body["stop_on_auto_reply"] = params.stop_on_auto_reply
        if params.daily_max_leads is not None:
            body["daily_max_leads"] = params.daily_max_leads
        if params.prioritize_new_leads is not None:
            body["prioritize_new_leads"] = params.prioritize_new_leads
        if params.auto_variant_select is not None:
            body["auto_variant_select"] = params.auto_variant_select
        if params.match_lead_esp is not None:
            body["match_lead_esp"] = params.match_lead_esp
        if params.stop_for_company is not None:
            body["stop_for_company"] = params.stop_for_company
        if params.insert_unsubscribe_header is not None:
            body["insert_unsubscribe_header"] = params.insert_unsubscribe_header
        if params.allow_risky_contacts is not None:
            body["allow_risky_contacts"] = params.allow_risky_contacts
        if params.disable_bounce_protect is not None:
            body["disable_bounce_protect"] = params.disable_bounce_protect
        if params.cc_list is not None:
            body["cc_list"] = params.cc_list
        if params.bcc_list is not None:
            body["bcc_list"] = params.bcc_list
        
        result = await client.patch(f"/campaigns/{params.campaign_id}", json=body)
        return json.dumps(result, indent=2)
  • Pydantic model defining the input schema for the update_campaign tool, including all optional fields for partial updates.
    class UpdateCampaignInput(BaseModel):
        """
        Input for updating campaign settings (partial update).
        
        Common updates: name, sequences, tracking, limits, email_list.
        """
        
        model_config = ConfigDict(str_strip_whitespace=True, extra="ignore")
        
        campaign_id: str = Field(..., description="Campaign to update")
        name: Optional[str] = Field(default=None)
        pl_value: Optional[float] = Field(default=None, description="Pipeline value")
        is_evergreen: Optional[bool] = Field(default=None)
        campaign_schedule: Optional[dict[str, Any]] = Field(
            default=None,
            description="Schedule configuration with 'schedules' array"
        )
        sequences: Optional[list[dict[str, Any]]] = Field(
            default=None,
            description="Email sequence steps"
        )
        email_gap: Optional[int] = Field(default=None, ge=1, le=1440)
        random_wait_max: Optional[int] = Field(default=None)
        text_only: Optional[bool] = Field(default=None)
        email_list: Optional[list[str]] = Field(default=None, description="Sender accounts")
        daily_limit: Optional[int] = Field(default=None, ge=1, le=50)
        stop_on_reply: Optional[bool] = Field(default=None)
        email_tag_list: Optional[list[str]] = Field(default=None)
        link_tracking: Optional[bool] = Field(default=None)
        open_tracking: Optional[bool] = Field(default=None)
        stop_on_auto_reply: Optional[bool] = Field(default=None)
        daily_max_leads: Optional[int] = Field(default=None)
        prioritize_new_leads: Optional[bool] = Field(default=None)
        auto_variant_select: Optional[dict[str, Any]] = Field(default=None)
        match_lead_esp: Optional[bool] = Field(default=None)
        stop_for_company: Optional[bool] = Field(default=None)
        insert_unsubscribe_header: Optional[bool] = Field(default=None)
        allow_risky_contacts: Optional[bool] = Field(default=None)
        disable_bounce_protect: Optional[bool] = Field(default=None)
        cc_list: Optional[list[str]] = Field(default=None)
        bcc_list: Optional[list[str]] = Field(default=None)
  • List of campaign tools including update_campaign, which is imported and registered by the server via get_all_tools().
    CAMPAIGN_TOOLS = [
        create_campaign,
        list_campaigns,
        get_campaign,
        update_campaign,
        activate_campaign,
        pause_campaign,
        delete_campaign,
        search_campaigns_by_contact,
    ]
  • MCP annotation for the update_campaign tool specifying destructiveHint: False, applied during registration.
    "update_campaign": {"destructiveHint": False},
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide 'destructiveHint: false,' indicating it's not destructive, but the description adds useful context: it clarifies this is a 'partial update' and lists common fields that can be updated. However, it doesn't disclose other behavioral traits like authentication needs, rate limits, or what happens if invalid fields are provided. No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded: it starts with the core purpose, then lists common updates in a bulleted format, and ends with a key instruction. Each sentence earns its place, but the bulleted list could be slightly more structured for clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (many parameters) and the presence of an output schema (which handles return values), the description is fairly complete. It covers the purpose, partial update nature, and common parameters, though it could benefit from more behavioral context or error handling info. The annotations provide basic safety, but more details would enhance completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, so the description carries the full burden. It adds significant value by listing common parameters (e.g., name, sequences, email_list) with brief explanations, such as 'Campaign display name' for 'name' and 'Sender account assignments' for 'email_list.' This compensates well for the lack of schema descriptions, though it doesn't cover all parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Update campaign settings (partial update).' It specifies the verb ('update'), resource ('campaign settings'), and scope ('partial update'), which is more specific than just the tool name. However, it doesn't explicitly differentiate from sibling tools like 'update_account' or 'update_lead', though the resource specificity helps.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides implied usage guidance: it mentions 'partial update' and 'Only include fields you want to update,' suggesting this is for modifying specific settings rather than full replacements. However, it doesn't explicitly state when to use this tool versus alternatives like 'create_campaign' or 'delete_campaign,' nor does it mention prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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-python'

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