Skip to content
Scalekit Docs

Lemlist MCP

Vendor MCP124 toolsOAuth 2.1/DCRMarketingCRM & Sales

Connect to Lemlist MCP. Manage outbound sales campaigns, leads, email sequences, and LinkedIn outreach from your AI workflows.

Lemlist MCP connector

  1. Terminal window
    npm install @scalekit-sdk/node

    Full SDK reference: Node.js | Python

  2. Add your Scalekit credentials to your .env file. Find values in app.scalekit.com > Developers > API Credentials.

    .env
    SCALEKIT_ENVIRONMENT_URL=<your-environment-url>
    SCALEKIT_CLIENT_ID=<your-client-id>
    SCALEKIT_CLIENT_SECRET=<your-client-secret>
  3. quickstart.ts
    import { ScalekitClient } from '@scalekit-sdk/node'
    import 'dotenv/config'
    const scalekit = new ScalekitClient(
    process.env.SCALEKIT_ENV_URL,
    process.env.SCALEKIT_CLIENT_ID,
    process.env.SCALEKIT_CLIENT_SECRET,
    )
    const actions = scalekit.actions
    const connector = 'lemlistmcp'
    const identifier = 'user_123'
    // Generate an authorization link for the user
    const { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })
    console.log('Authorize Lemlist MCP:', link)
    process.stdout.write('Press Enter after authorizing...')
    await new Promise(r => process.stdin.once('data', r))
    // Make your first call
    const result = await actions.executeTool({
    connector,
    identifier,
    toolName: 'lemlistmcp_check_domain_health',
    toolInput: {},
    })
    console.log(result)

Connect this agent connector to let your agent:

  • Update watch list, task content, task — Update an existing watch list
  • List transfer campaign leads to, remove contacts from, watch list signals — Add every lead of a campaign to a CRM contact list, in one call
  • Lists suggest watch — Generate AI-suggested watch lists for the current team
  • Strategy set campaign sender — Set the sender-assignment strategy for a campaign — the algorithm that decides which sender (user) is attached to each lead at launch
  • Variant set ab — Set or update the A/B test variant B (subject and/or body) of an EMAIL sequence step
  • Send task, message — Send one OR many message-based tasks now, OR — for a manual campaign step — schedule it via the campaign and mark it done (the “Send & mark done” / “Schedule & mark done” actions on the Tasks / Focus page)

Use the exact tool names from the Tool list below when you call execute_tool. If you’re not sure which name to use, list the tools available for the current user first.

lemlistmcp_add_contacts_to_list#Add existing CRM contacts to a contact list by list ID.2 params

Add existing CRM contacts to a contact list by list ID.

NameTypeRequiredDescription
contactIdsarrayrequiredContact IDs to add to the list (max 1,000)
listIdstringrequiredTarget contact list ID in clt_xxx format. Get valid IDs from get_contact_lists.
lemlistmcp_add_leads_to_campaign#Add one or more leads (max 100) to a campaign. Each lead requires at least one identifying field such as email, first name, last name, or company name.7 params

Add one or more leads (max 100) to a campaign. Each lead requires at least one identifying field such as email, first name, last name, or company name.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign ID (starts with cam_)
leadsarrayrequiredLeads to add (1..100). Each lead must have at least one identifying field.
deduplicatebooleanoptionalAvoid duplicates across campaigns (default: false). When true, existing leads in OTHER campaigns are reported as outcome="skippedDuplicateCrossCampaign".
findEmailbooleanoptional⚠️ COSTS CREDITS per lead: Find email address from other lead data (LinkedIn, name, company)
findPhonebooleanoptional⚠️ COSTS CREDITS per lead: Find phone number from other lead data
linkedinEnrichmentbooleanoptional⚠️ COSTS CREDITS per lead: Enrich each lead with LinkedIn profile data (job title, company info, etc.)
verifyEmailbooleanoptional⚠️ COSTS CREDITS per lead: Verify if the email address is valid and deliverable
lemlistmcp_add_sequence_step#Add a step to an existing campaign sequence. Use only for modifying already-created campaigns — not for initial campaign creation.19 params

Add a step to an existing campaign sequence. Use only for modifying already-created campaigns — not for initial campaign creation.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx)
delaynumberrequiredDays to wait after previous step. Must be 0 for "sendToAnotherCampaign" (the lemlist API does not accept a delay for this type, transfer is immediate).
sequenceIdstringrequiredSequence ID (seq_xxx)
userConfirmedbooleanrequiredMust be true after user confirms
altMessagestringoptionalAlternative message variation for "linkedinSend" steps (used as second-attempt content when applicable).
conditionKeystringoptionalCondition to check (REQUIRED when type is "conditional"). E.g. emailsOpened, linkedinInviteAccepted.
delayTypestringoptionalREQUIRED for all conditional steps. "within" = must happen within delay days, "waitUntil" = wait indefinitely. For field-check conditions (hasEmailAddress, hasLinkedinUrl, etc.), use "within" with delay 0.
emailStatusFilterarrayoptionalOnly for hasEmailAddress condition. Filter by email verification status. E.g. ["deliverable"] to only match leads with deliverable email. Omit to check if any email exists.
indexnumberoptionalZero-based position where to insert the step (0 = first). Omit to append at the end. Use to insert warm-up steps before an existing step (e.g. Like + Comment before an Invite).
messagestringoptionalMessage content (REQUIRED when type is "email", "linkedinSend", "whatsappMessage" or "sms"; OPTIONAL but recommended for "linkedinInvite"). For emails: the HTML body. For LinkedIn/WhatsApp/SMS/tasks: the message text.
methodstringoptionalREQUIRED when type="api". HTTP method (GET or POST) used by the webhook call. Limited to GET/POST to stay iso with the lemlist UI editor.
recordModestringoptionallinkedinVoiceNote only: "ai" generates audio from text via ElevenLabs (user adds the text after); "manual" (default) requires user-recorded audio after step creation.
scoreComparatorstringoptionalOnly for hasScore condition. "$gte" = score is above or equal to threshold, "$lt" = score is below threshold. Defaults to "$gte".
scoreThresholdnumberoptionalOnly for hasScore condition. Score threshold value (0-100). Defaults to 80.
subjectstringoptionalEmail subject line. Required for the first email; omit for follow-ups to send as reply thread. Supports Liquid syntax: {{ firstName }}, {% if condition %}...{% endif %}
targetCampaignIdstringoptionalREQUIRED when type is "sendToAnotherCampaign". Target campaign ID (cam_xxx) the lead is moved to. Must belong to the same team as the parent campaign and not be archived. Avoid cycles (A -> B -> A).
titlestringoptionalTask title (for manual/phone steps). Short label displayed in the review UI.
typestringoptionalType of step. Use "conditional" for branching based on lead behavior, "sendToAnotherCampaign" to move a lead to another campaign, "api" to fire an outbound HTTP webhook (provide method and url).
urlstringoptionalREQUIRED when type="api". Webhook URL fired during sequence execution. Supports Liquid templating against lead variables (e.g. https://example.com/leads/{{ _id }}). For POST, the request body is automatically the lead data; custom bodies and custom headers are not supported.
lemlistmcp_add_unsubscribe#Add email to unsubscribe blocklist. Blocks all future campaign sends. Use delete_unsubscribe to reverse.1 param

Add email to unsubscribe blocklist. Blocks all future campaign sends. Use delete_unsubscribe to reverse.

NameTypeRequiredDescription
emailstringrequiredThe email address to add to the unsubscribe list
lemlistmcp_bulk_enrich_data#Enrich up to 500 contacts with additional data in a single call. Returns a dataRef for polling results asynchronously.1 param

Enrich up to 500 contacts with additional data in a single call. Returns a dataRef for polling results asynchronously.

NameTypeRequiredDescription
itemsarrayrequiredArray of enrichment items (max 500)
lemlistmcp_bulk_get_enrichment_results#Poll the results of one or more enrichment jobs. Provide a dataRef from bulk_enrich_data or a nextPollRef from a previous poll.2 params

Poll the results of one or more enrichment jobs. Provide a dataRef from bulk_enrich_data or a nextPollRef from a previous poll.

NameTypeRequiredDescription
dataRefstringoptionaldataRef from bulk_enrich_data (first poll) OR nextPollRef from a previous poll result (subsequent polls). Mutually exclusive with enrichmentIds.
enrichmentIdsarrayoptionalArray of enrichment IDs to poll (1-500, enr_xxx format). Mutually exclusive with dataRef.
lemlistmcp_calculate_infrastructure#Compute cold-email infrastructure sizing from campaign inputs. Returns: - Peak daily volume + injection rate - Mailbox count (raw and with safety buffer) - ESP split (Google / Microsoft / SMTP) - Domains needed per seat (cap: 3 mailboxes per domain) - Warmup timeline (rampup + 14-day stabilization) - Lemlist slot cost (included + extras at $9/month) - Brand-consistent domain name suggestions - Mailbox naming proposals per SDR (when sdrs provided), with SDR userId echoed back in `sdrPlans[].userId` if it was passed in All math is deterministic — pure domain function, no LLM math. Use in Step 2 of the outreach-infra skill, after gathering campaign inputs via ask_question.10 params

Compute cold-email infrastructure sizing from campaign inputs. Returns: - Peak daily volume + injection rate - Mailbox count (raw and with safety buffer) - ESP split (Google / Microsoft / SMTP) - Domains needed per seat (cap: 3 mailboxes per domain) - Warmup timeline (rampup + 14-day stabilization) - Lemlist slot cost (included + extras at $9/month) - Brand-consistent domain name suggestions - Mailbox naming proposals per SDR (when sdrs provided), with SDR userId echoed back in `sdrPlans[].userId` if it was passed in All math is deterministic — pure domain function, no LLM math. Use in Step 2 of the outreach-infra skill, after gathering campaign inputs via ask_question.

NameTypeRequiredDescription
companyDomainstringrequiredTeam company domain
delayDaysintegerrequiredDays between sequence steps
espChoicestringrequiredESP matching strategy
leadsintegerrequiredTotal leads over the timeline
rampupIncrementintegerrequiredLemwarm daily rampup increment
seatsintegerrequiredSDR seats
sequenceStepsintegerrequiredSteps in the sequence
timelineDaysintegerrequiredCampaign duration in days
domainSuggestionsCountintegeroptionalDomain suggestions to return (default 10)
sdrsarrayoptionalOptional SDR identities for mailbox naming. Each entry may include the SDR lemlist userId — when provided, it is echoed back in `sdrPlans[].userId` so the caller can wire `assignToUser` in provision_mailboxes without name matching.
lemlistmcp_call_api#Make a direct call to the Lemlist API using a specified endpoint and method. Requires load_skill('api-reference') to be called first in the session.4 params

Make a direct call to the Lemlist API using a specified endpoint and method. Requires load_skill('api-reference') to be called first in the session.

NameTypeRequiredDescription
endpointstringrequiredAPI endpoint path starting with /api/
methodstringrequiredHTTP method
bodyobjectoptionalRequest body for POST/PUT/PATCH (optional)
confirmedbooleanoptionalSet to true after user confirms a write/delete action
lemlistmcp_check_domain_health#Check DNS health for email sending domains (MX, SPF, DMARC, blacklists). Returns score (0-100), per-check status, and DNS fix records.3 params

Check DNS health for email sending domains (MX, SPF, DMARC, blacklists). Returns score (0-100), per-check status, and DNS fix records.

NameTypeRequiredDescription
domainstringoptionalDomain to check (e.g. example.com). If omitted, checks domains from team members.
mailboxIdstringoptionalMailbox ID to check DNS for.
scopestringoptionalCheck scope: user (current user) or team (all members). Default: team.
lemlistmcp_configure_domain_dns#Write DNS records for a team-owned domain. Two modes: - Provide **records**: replaces the domain's full record set (SPF / DMARC / MX / CNAME etc.). - Provide **dkimRecord**: appends the DKIM TXT record only (after mailbox provisioning). Use in Step 4 (initial SPF/DMARC/MX) and Step 6 (DKIM after Google/M365 gives the public key) of the outreach-infra skill.3 params

Write DNS records for a team-owned domain. Two modes: - Provide **records**: replaces the domain's full record set (SPF / DMARC / MX / CNAME etc.). - Provide **dkimRecord**: appends the DKIM TXT record only (after mailbox provisioning). Use in Step 4 (initial SPF/DMARC/MX) and Step 6 (DKIM after Google/M365 gives the public key) of the outreach-infra skill.

NameTypeRequiredDescription
domainIdstringrequiredDomain ID (dom_xxx)
dkimRecordstringoptionalDKIM record to append
recordsarrayoptionalFull DNS record set to write
lemlistmcp_connect_email_account#Connect a custom SMTP/IMAP email account for sending and receiving emails in Lemlist campaigns.12 params

Connect a custom SMTP/IMAP email account for sending and receiving emails in Lemlist campaigns.

NameTypeRequiredDescription
imap_hoststringrequiredIMAP server hostname (e.g., "imap.company.com")
imap_loginstringrequiredIMAP authentication login (usually the email address)
imap_passwordstringrequiredIMAP authentication password or app password
imap_portnumberrequiredIMAP server port (typically 993 for TLS)
sender_emailstringrequiredEmail address to send from (e.g., "john@company.com")
sender_namestringrequiredDisplay name for the sender (e.g., "John Doe")
smtp_hoststringrequiredSMTP server hostname (e.g., "smtp.company.com")
smtp_loginstringrequiredSMTP authentication login (usually the email address)
smtp_passwordstringrequiredSMTP authentication password or app password
smtp_portnumberrequiredSMTP server port (typically 587 for TLS or 465 for SSL)
imap_securebooleanoptionalOptional: Use TLS for IMAP connection (default: true)
smtp_securebooleanoptionalOptional: Use TLS for SMTP connection (default: true)
lemlistmcp_copy_campaign_leads#Copy every lead from one campaign into another, in a single call, with FULL fidelity. Prefer this over composing search_campaign_leads + add_leads_to_campaign whenever the user wants to copy / recreate / move / duplicate the leads of a whole campaign into another campaign (e.g. "copy the leads from campaign A into campaign B", "put everyone from the old campaign into the rebuilt one"). Composing the two other tools drops fields (Sales Nav URL, phone, custom variables) and creates new empty contacts — this tool does not. Use when the user asks about: - Copying/recreating a whole campaign's leads into another campaign - Repopulating a freshly duplicated campaign (duplication never copies leads) from the original Contract rules reproduced by the backend: - Works by lead id server-side: it reuses each lead's existing CRM contact (no empty duplicate) and copies every variable (linkedinUrlSalesNav, phone, custom fields). - Both campaigns must belong to the current team; sourceCampaignId and targetCampaignId must be different. - ADDS to the target (source campaign is left untouched). Leads already in the target follow the same dedup rules as a manual push.2 params

Copy every lead from one campaign into another, in a single call, with FULL fidelity. Prefer this over composing search_campaign_leads + add_leads_to_campaign whenever the user wants to copy / recreate / move / duplicate the leads of a whole campaign into another campaign (e.g. "copy the leads from campaign A into campaign B", "put everyone from the old campaign into the rebuilt one"). Composing the two other tools drops fields (Sales Nav URL, phone, custom variables) and creates new empty contacts — this tool does not. Use when the user asks about: - Copying/recreating a whole campaign's leads into another campaign - Repopulating a freshly duplicated campaign (duplication never copies leads) from the original Contract rules reproduced by the backend: - Works by lead id server-side: it reuses each lead's existing CRM contact (no empty duplicate) and copies every variable (linkedinUrlSalesNav, phone, custom fields). - Both campaigns must belong to the current team; sourceCampaignId and targetCampaignId must be different. - ADDS to the target (source campaign is left untouched). Leads already in the target follow the same dedup rules as a manual push.

NameTypeRequiredDescription
sourceCampaignIdstringrequiredCampaign (cam_xxx) to copy leads FROM. Every non-deleted lead in it is copied. Get it from get_campaigns.
targetCampaignIdstringrequiredCampaign (cam_xxx) to copy leads INTO. Must be different from sourceCampaignId. Get it from get_campaigns, or create one first.
lemlistmcp_create_ai_variable_prompt#Create a NEW AI variable column (an AI-generated column in the Leads table: icebreaker, opener, company research, etc.) on a campaign. Provide the column name, the AI-generation prompt, and optionally the model. The column is created team-owned and editable, wired into the campaign so it shows up in the Leads table and generates for leads. Use {{variable}} placeholders in the prompt to reference existing fields or columns. The variable name must be unique on the campaign — creating a duplicate is rejected. To edit an existing column's prompt instead, use update_ai_variable_prompt; to read existing columns, use get_ai_variable_prompts. Creating the column only sets it up — it does NOT generate values. Values are generated per lead later (from the Leads table UI or on import) and that is what consumes credits, not this call. Pass autofill:true to turn the column's auto-generate toggle on, so every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add) generates it automatically; it stays off by default. To scrape LinkedIn profiles for the column, pass tools:["enrich-linkedin"] AND reference {{linkedinUrl}} in the prompt; enabling any tool forces the premium lemlist model and lemlist-credit billing (per lead, at generation). Use when the user asks to: - Add a new AI column / AI variable to a campaign's leads - Generate a new piece of AI content (research, icebreaker, summary) per lead - Have an AI column filled automatically for every lead imported into a campaign This mutates campaign configuration, so confirm the column name and prompt with the user before calling.6 params

Create a NEW AI variable column (an AI-generated column in the Leads table: icebreaker, opener, company research, etc.) on a campaign. Provide the column name, the AI-generation prompt, and optionally the model. The column is created team-owned and editable, wired into the campaign so it shows up in the Leads table and generates for leads. Use {{variable}} placeholders in the prompt to reference existing fields or columns. The variable name must be unique on the campaign — creating a duplicate is rejected. To edit an existing column's prompt instead, use update_ai_variable_prompt; to read existing columns, use get_ai_variable_prompts. Creating the column only sets it up — it does NOT generate values. Values are generated per lead later (from the Leads table UI or on import) and that is what consumes credits, not this call. Pass autofill:true to turn the column's auto-generate toggle on, so every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add) generates it automatically; it stays off by default. To scrape LinkedIn profiles for the column, pass tools:["enrich-linkedin"] AND reference {{linkedinUrl}} in the prompt; enabling any tool forces the premium lemlist model and lemlist-credit billing (per lead, at generation). Use when the user asks to: - Add a new AI column / AI variable to a campaign's leads - Generate a new piece of AI content (research, icebreaker, summary) per lead - Have an AI column filled automatically for every lead imported into a campaign This mutates campaign configuration, so confirm the column name and prompt with the user before calling.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx format) the new AI variable column is added to
promptstringrequiredThe AI-generation prompt for the new column. Use {{variable}} placeholders (e.g. {{firstName}}) to reference fields or other existing columns.
variableNamestringrequiredName of the new AI variable column to create (e.g. "companyNews"). Must be unique on the campaign and a valid identifier (letters, digits, underscores, starting with a letter). The "variables." prefix is optional.
autofillbooleanoptionalSets the column's "auto-generate" toggle. When true, this AI variable is generated for every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add). Defaults to false, leaving generation to be triggered from the Leads table. ⚠️ COSTS CREDITS: with it on, every newly added lead consumes one generation.
modelstringoptionalOptional AI model id powering the column (e.g. "gpt-5.4", "claude-sonnet-4-6", "sonar-pro"). Omit to use the team default model. Use a web-search model (e.g. Perplexity "sonar-pro") for columns that research live data. Ignored when tools are set (tools force the premium lemlist model).
toolsarrayoptionalOptional AI tools the column may use while generating each value. "enrich-linkedin" scrapes the lead's LinkedIn profile (the prompt MUST reference {{linkedinUrl}} or {{linkedinUrlSalesNav}}, otherwise the tool never fires and the column stays empty); "scrape-website" reads a URL; "web-search" searches the live web. ⚠️ COSTS CREDITS: enabling ANY tool forces the premium lemlist model and switches billing to lemlist credits, charged per lead at generation time (not now). Omit for a plain text column.
lemlistmcp_create_campaign_folder#Create one or more campaign folders that share the same parent, in a single call. Use when the user asks about: - Adding one or several folders at the same level (pass them all in `names`). - Creating sub-folders under an existing folder (pass its `parentId`). For a nested chain (A > B > C) call once per level instead, threading each returned folderId as the next `parentId`. Contract rules reproduced by the backend: - Each name must be unique among folders that share the same parent. - Depth is capped at 15 levels, 50 folders per level, 500 folders per team. - Best-effort: valid names are created even if others fail; the response lists `created` and `failed` (with a per-name reason).3 params

Create one or more campaign folders that share the same parent, in a single call. Use when the user asks about: - Adding one or several folders at the same level (pass them all in `names`). - Creating sub-folders under an existing folder (pass its `parentId`). For a nested chain (A > B > C) call once per level instead, threading each returned folderId as the next `parentId`. Contract rules reproduced by the backend: - Each name must be unique among folders that share the same parent. - Depth is capped at 15 levels, 50 folders per level, 500 folders per team. - Best-effort: valid names are created even if others fail; the response lists `created` and `failed` (with a per-name reason).

NameTypeRequiredDescription
namesarrayrequiredNames of the folders to create under the SAME parent (1-50). Pass every sibling folder in one call rather than calling repeatedly. Each name must be unique among folders sharing that parent. (To build a nested chain instead, call once per level, threading each returned folderId as the next parentId.)
colorstringoptionalOptional color (hex) applied to every folder created. Omit for no color.
parentIdstringoptionalParent folder ID (cfo_xxx) all the new folders are nested under. Omit to create them at the root.
lemlistmcp_create_campaign_from_proposal#[STALE: upstream tool 'create_campaign_from_proposal' no longer appears in the lemlist MCP server's live tools/list as of 2026-08-19; likely superseded by propose_sequence + create_campaign_with_sequence. Kept for reference, not for active use.] Create a campaign from a previously validated sequence proposal. Requires a proposal ID generated by propose_sequence.5 params

[STALE: upstream tool 'create_campaign_from_proposal' no longer appears in the lemlist MCP server's live tools/list as of 2026-08-19; likely superseded by propose_sequence + create_campaign_with_sequence. Kept for reference, not for active use.] Create a campaign from a previously validated sequence proposal. Requires a proposal ID generated by propose_sequence.

NameTypeRequiredDescription
sequenceItemIdstringrequiredWorkspace item id of the validated sequence (from propose_sequence)
userConfirmedbooleanrequiredMust be true after the user explicitly approves campaign creation
emojistringoptionalOptional emoji for the campaign
namestringoptionalCampaign name (defaults to the sequence proposal name)
timezonestringoptionalTimezone for the campaign (e.g. Europe/Paris)
lemlistmcp_create_campaign_with_sequence#Create campaign. If subject AND body are provided, creates the first email step. If omitted, creates an empty sequence (use add_sequence_step to add a condition or any step type as the first step). Call add_sequence_step for each additional step. Supports Liquid syntax.5 params

Create campaign. If subject AND body are provided, creates the first email step. If omitted, creates an empty sequence (use add_sequence_step to add a condition or any step type as the first step). Call add_sequence_step for each additional step. Supports Liquid syntax.

NameTypeRequiredDescription
namestringrequiredThe name of the campaign
bodystringoptionalEmail body content for the first email (supports Liquid syntax). Omit both subject and body to create campaign without a first step.
emojistringoptionalOptional emoji for the campaign (e.g., 🚀, 💎, 🔥)
subjectstringoptionalSubject line for the first email (supports Liquid syntax). Omit both subject and body to create campaign without a first step (e.g. when first step is a condition).
timezonestringoptionalTimezone for the campaign (e.g., Europe/Paris, America/New_York)
lemlistmcp_create_contact_list#Create a new static contact list in the CRM to organize and group contacts.1 param

Create a new static contact list in the CRM to organize and group contacts.

NameTypeRequiredDescription
namestringrequiredName of the contact list to create (max 200 characters)
lemlistmcp_create_or_update_company#Create a new company in the user's Lemlist company database, or update an existing one (upsert). Requires both a name AND a domain. If a company with the same domain, LinkedIn URL, or Sales Navigator URL already exists, it will be updated instead of creating a duplicate. Returns the company data and whether it was created or updated.8 params

Create a new company in the user's Lemlist company database, or update an existing one (upsert). Requires both a name AND a domain. If a company with the same domain, LinkedIn URL, or Sales Navigator URL already exists, it will be updated instead of creating a duplicate. Returns the company data and whether it was created or updated.

NameTypeRequiredDescription
domainstringrequiredCompany domain (required)
namestringrequiredCompany name (required)
companyOwnerstringoptionalCompany owner email or user ID (usr_xxx format)
industrystringoptionalCompany industry
linkedinUrlstringoptionalCompany LinkedIn profile URL
linkedinUrlSalesNavstringoptionalCompany LinkedIn Sales Navigator URL (used as an additional matching key for upsert)
locationstringoptionalCompany location or address
picturestringoptionalCompany logo URL
lemlistmcp_create_or_update_contact#Create a new contact in the user's Lemlist contact database, or update an existing one (upsert). Requires at least an email OR linkedinUrl as identifier. If a contact with the same email or LinkedIn URL already exists, it will be updated instead of creating a duplicate. Returns the contact data and whether it was created or updated. Use search_contacts first to check if the contact already exists.14 params

Create a new contact in the user's Lemlist contact database, or update an existing one (upsert). Requires at least an email OR linkedinUrl as identifier. If a contact with the same email or LinkedIn URL already exists, it will be updated instead of creating a duplicate. Returns the contact data and whether it was created or updated. Use search_contacts first to check if the contact already exists.

NameTypeRequiredDescription
companyDomainstringoptionalCompany domain to link the contact to a company (alternative to companyId)
companyIdstringoptionalCompany ID to associate the contact with
companyLinkedinUrlstringoptionalCompany LinkedIn URL to link the contact to a company (alternative to companyId)
contactOwnerstringoptionalContact owner email or user ID (usr_xxx format)
emailstringoptionalContact email address (required if linkedinUrl is not provided)
firstNamestringoptionalContact first name
jobDescriptionstringoptionalContact job description
jobTitlestringoptionalContact job title
lastNamestringoptionalContact last name
linkedinUrlstringoptionalContact LinkedIn profile URL (required if email is not provided)
phonestringoptionalContact phone number
picturestringoptionalContact profile picture URL
salesnavUrlstringoptionalContact LinkedIn Sales Navigator URL (used as an additional matching key for upsert)
timezonestringoptionalContact timezone
lemlistmcp_create_people_database_persona#Create a People Database persona for the current team. Use when the user asks about: - Saving a set of People Database filters as a reusable audience - Defining an ICP / persona to reuse later Contract rules reproduced by the backend: - name must be non-empty and unique within the team (duplicates are rejected) - mode must be "leads": company personas are not supported yet - every filterId must be an exact id from the People Database filter catalog (GET /api/database/filters) - filters gated by a plan the team does not have are silently dropped Returns the created persona id (pdp_xxx).3 params

Create a People Database persona for the current team. Use when the user asks about: - Saving a set of People Database filters as a reusable audience - Defining an ICP / persona to reuse later Contract rules reproduced by the backend: - name must be non-empty and unique within the team (duplicates are rejected) - mode must be "leads": company personas are not supported yet - every filterId must be an exact id from the People Database filter catalog (GET /api/database/filters) - filters gated by a plan the team does not have are silently dropped Returns the created persona id (pdp_xxx).

NameTypeRequiredDescription
filtersarrayrequiredPeople Database filters defining the persona
modestringrequiredSearch mode the filters target. Only "leads" is accepted today.
namestringrequiredPersona display name (non-empty, unique per team)
lemlistmcp_create_upload_url#Get a presigned URL to upload a file from the user's machine to lemlist storage, then reference it by key. Use this to AVOID retyping large file contents through the conversation. Flow: 1. Call this tool with purpose, fileName, and the EXACT fileSize in bytes. 2. Upload the raw file to the returned uploadUrl with an HTTP PUT, e.g.: curl -T leads.csv -H "Content-Type: <contentType>" "<uploadUrl>" 3. Pass the returned uploadKey to the tool that consumes it: - purpose="leadsCsv" → import_leads_to_campaign - purpose="contactsCsv" → import_contacts_from_csv - purpose="companiesCsv" → import_companies_from_csv - purpose="csvData" → read_uploaded_csv The URL is short-lived (expiresInSeconds). fileSize MUST be the real byte size of the file — it is signed into the URL, so a mismatch makes the upload fail, and a size above the limit is rejected up front.4 params

Get a presigned URL to upload a file from the user's machine to lemlist storage, then reference it by key. Use this to AVOID retyping large file contents through the conversation. Flow: 1. Call this tool with purpose, fileName, and the EXACT fileSize in bytes. 2. Upload the raw file to the returned uploadUrl with an HTTP PUT, e.g.: curl -T leads.csv -H "Content-Type: <contentType>" "<uploadUrl>" 3. Pass the returned uploadKey to the tool that consumes it: - purpose="leadsCsv" → import_leads_to_campaign - purpose="contactsCsv" → import_contacts_from_csv - purpose="companiesCsv" → import_companies_from_csv - purpose="csvData" → read_uploaded_csv The URL is short-lived (expiresInSeconds). fileSize MUST be the real byte size of the file — it is signed into the URL, so a mismatch makes the upload fail, and a size above the limit is rejected up front.

NameTypeRequiredDescription
fileNamestringrequiredOriginal file name (e.g., "leads.csv"). Used to derive the extension and MIME type.
fileSizenumberrequiredEXACT file size in bytes. Signed into the URL — the upload fails on mismatch and the call is rejected above the limit.
purposestringrequiredWhat the file is for. "leadsCsv" → import_leads_to_campaign, "contactsCsv" → import_contacts_from_csv, "companiesCsv" → import_companies_from_csv, "csvData" → read_uploaded_csv.
contentTypestringoptionalMIME type override. Defaults to the type inferred from the file extension.
lemlistmcp_create_watch_list#Create a new watch list for the current team. Use when the user asks about: - Starting to monitor a new signal type - Setting up a watch list end-to-end (create + configure + activate) - Creating a draft watch list that the user will configure later in the UI Contract rules reproduced by the backend: - activate=true ⇒ segmentType AND signalProcessingType must be set - signalProcessingType="create_opportunity" ⇒ signalOpportunityTemplate required (and forbidden otherwise) - personaId is accepted ONLY on a company watch list with signalProcessingType="push_to_campaign" (any other config is rejected), and only for teams in the personas beta - personaId is optional there: without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign - get a personaId from list_people_database_personas (or create_people_database_persona); never invent one - Only segmentType="all" is accepted via API (CRM lists and CSV imports are not)9 params

Create a new watch list for the current team. Use when the user asks about: - Starting to monitor a new signal type - Setting up a watch list end-to-end (create + configure + activate) - Creating a draft watch list that the user will configure later in the UI Contract rules reproduced by the backend: - activate=true ⇒ segmentType AND signalProcessingType must be set - signalProcessingType="create_opportunity" ⇒ signalOpportunityTemplate required (and forbidden otherwise) - personaId is accepted ONLY on a company watch list with signalProcessingType="push_to_campaign" (any other config is rejected), and only for teams in the personas beta - personaId is optional there: without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign - get a personaId from list_people_database_personas (or create_people_database_persona); never invent one - Only segmentType="all" is accepted via API (CRM lists and CSV imports are not)

NameTypeRequiredDescription
activatebooleanrequiredWhen true, activates the watch list immediately (advances to VALIDATED step, triggers billing and external watcher setup). Requires segmentType and signalProcessingType to be set.
filtersarrayrequiredConfiguration filters as an array of { filterId, in[], out[] } objects
namestringrequiredWatch list display name (non-empty)
segmentTypestringrequiredSegment type to monitor. Only "all" is supported via API. Required together with signalProcessingType when activate=true.
signalProcessingTypestringrequiredHow signals are processed once the watch list runs. Required together with segmentType when activate=true. When set to "create_opportunity", signalOpportunityTemplate is required (and forbidden for the other types).
typestringrequiredWatch list signal type
emojistringoptionalOptional emoji for the watch list (a random one is picked if omitted)
personaIdstringoptionalPersona (pdp_xxx) used to source contacts from the People Database. Used by a company watch list with signalProcessingType = "push_to_campaign": company signals carry no contact, so the persona is the only way to know who to reach. Optional — without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign. Rejected on any other configuration.
signalOpportunityTemplateobjectoptionalOpportunity template payload, required when signalProcessingType = "create_opportunity"
lemlistmcp_create_webhook#Create a webhook for real-time campaign activity notifications. Max 200 per account, no duplicate URLs. Filter by activity type (emailsSent, emailsOpened, emailsReplied, etc.) and/or campaignId.5 params

Create a webhook for real-time campaign activity notifications. Max 200 per account, no duplicate URLs. Filter by activity type (emailsSent, emailsOpened, emailsReplied, etc.) and/or campaignId.

NameTypeRequiredDescription
targetUrlstringrequiredThe webhook URL to call (must start with http:// or https://)
campaignIdstringoptionalOptional: Filter to call webhook only for specific campaign (e.g., "cam_xxx")
isFirstbooleanoptionalOptional: Call webhook only for first activity of this type
typestringoptionalOptional: Filter to call webhook only for specific activity types (e.g., "emailsReplied", "emailsSent")
zapIdstringoptionalOptional: Zapier integration ID
lemlistmcp_delete_campaign_folder#Delete one or more campaign folders. Campaigns are NEVER deleted — each folder's campaigns and sub-folders move up one level (to the parent folder, or to the root if the folder was at the top). Use when the user asks about: - Removing one or several folders while keeping their campaigns (pass them all in `folderIds`). Contract rules reproduced by the backend: - Deleting a folder is blocked if a sub-folder would collide, by name, with a folder already present in the parent — rename the conflicting sub-folder first. - Best-effort: each id is handled independently; the response lists `deleted` and `failed` (with a per-id reason).1 param

Delete one or more campaign folders. Campaigns are NEVER deleted — each folder's campaigns and sub-folders move up one level (to the parent folder, or to the root if the folder was at the top). Use when the user asks about: - Removing one or several folders while keeping their campaigns (pass them all in `folderIds`). Contract rules reproduced by the backend: - Deleting a folder is blocked if a sub-folder would collide, by name, with a folder already present in the parent — rename the conflicting sub-folder first. - Best-effort: each id is handled independently; the response lists `deleted` and `failed` (with a per-id reason).

NameTypeRequiredDescription
folderIdsarrayrequiredFolder IDs (cfo_xxx) to delete (1-100). Pass every folder in one call rather than deleting one at a time.
lemlistmcp_delete_campaign_leads#Permanently delete leads from ONE campaign in a single bulk call. Irreversible: it also removes each lead's activity and task history in that campaign. Use when the user asks about: - Removing a specific set of leads from a campaign at once (e.g. after moving or segmenting them elsewhere) - Cleaning leads out of a campaign without calling the unitary delete endpoint one lead at a time Two-phase confirmation flow (mandatory): 1. First call WITHOUT confirmed (or confirmed=false): returns the count and a sample of the exact leads that will be deleted, with status="awaiting_confirmation". Show these to the user and get explicit approval via ask_question. 2. Once the user has approved, call again with confirmed=true to actually delete. Contract rules reproduced by the backend: - Scoped to a SINGLE campaignId; a lead id is unique to one campaign (campaignId + email). - Every leadId MUST belong to campaignId. Ids from another campaign (or already deleted) are rejected with an error, not silently skipped. Re-fetch the ids via search_campaign_leads on the target campaign. - At most 1000 lead ids per call. - Never call with confirmed=true without explicit user approval.3 params

Permanently delete leads from ONE campaign in a single bulk call. Irreversible: it also removes each lead's activity and task history in that campaign. Use when the user asks about: - Removing a specific set of leads from a campaign at once (e.g. after moving or segmenting them elsewhere) - Cleaning leads out of a campaign without calling the unitary delete endpoint one lead at a time Two-phase confirmation flow (mandatory): 1. First call WITHOUT confirmed (or confirmed=false): returns the count and a sample of the exact leads that will be deleted, with status="awaiting_confirmation". Show these to the user and get explicit approval via ask_question. 2. Once the user has approved, call again with confirmed=true to actually delete. Contract rules reproduced by the backend: - Scoped to a SINGLE campaignId; a lead id is unique to one campaign (campaignId + email). - Every leadId MUST belong to campaignId. Ids from another campaign (or already deleted) are rejected with an error, not silently skipped. Re-fetch the ids via search_campaign_leads on the target campaign. - At most 1000 lead ids per call. - Never call with confirmed=true without explicit user approval.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign (cam_xxx) to remove leads from. A single campaign only, never a list of campaigns.
leadIdsarrayrequiredLead ids (lea_xxx) to permanently delete from this campaign. Every id MUST belong to campaignId (a lead id is unique to one campaign). Max 1000 per call. Get the ids from search_campaign_leads run on this same campaign.
confirmedbooleanoptionalTwo-phase safety gate. Omit it (or pass false) on the first call to preview exactly what will be deleted; only pass true after the user has explicitly approved the deletion.
lemlistmcp_delete_company#Permanently delete a company record from Lemlist. Only removes the Lemlist record — does not affect any connected CRM.3 params

Permanently delete a company record from Lemlist. Only removes the Lemlist record — does not affect any connected CRM.

NameTypeRequiredDescription
companyIdstringrequiredLemlist company ID to delete (cpn_xxx).
userConfirmedbooleanrequiredREQUIRED: Must be true. Confirms user explicitly approved this deletion. Only set to true after user says yes.
forcebooleanoptionalWhen true, detaches any attached contacts (unsets their companyId) before deleting the company.
lemlistmcp_delete_contact#REQUIRES CONFIRMATION: Delete a lemlist contact by its ID (ctc_xxx) or email. Only the lemlist record is removed — no CRM-side propagation. Deletion cascades to the contact's leads, opportunities, list memberships, inbox conversations and activities. REQUIRES userConfirmed=true. Fails with CONTACT_DELETE_BLOCKED when the contact cannot be deleted right now (e.g. an enrichment is still running — retry once it finishes).2 params

REQUIRES CONFIRMATION: Delete a lemlist contact by its ID (ctc_xxx) or email. Only the lemlist record is removed — no CRM-side propagation. Deletion cascades to the contact's leads, opportunities, list memberships, inbox conversations and activities. REQUIRES userConfirmed=true. Fails with CONTACT_DELETE_BLOCKED when the contact cannot be deleted right now (e.g. an enrichment is still running — retry once it finishes).

NameTypeRequiredDescription
idOrEmailstringrequiredLemlist contact ID (ctc_xxx) or the contact email address to delete.
userConfirmedbooleanrequiredREQUIRED: Must be true. Confirms user explicitly approved this deletion. Only set to true after user says yes.
lemlistmcp_delete_memory#Delete a stored memory entry by topic so it is no longer recalled in future conversations.2 params

Delete a stored memory entry by topic so it is no longer recalled in future conversations.

NameTypeRequiredDescription
topicstringrequiredThe topic key to delete (e.g. "preferred_tone")
scopestringoptionalScope: "user" (default) or "team"
lemlistmcp_delete_people_database_persona#Delete a People Database persona of the current team. The deletion is permanent. Use when the user asks about: - Removing a persona they no longer need - Cleaning up duplicate or outdated personas Important: - Ask the user to confirm before calling this tool; there is no undo. - Use list_people_database_personas to resolve a persona name into its id. - An unknown id, another team's persona, and the auto-generated system persona all fail the same way (not found) — none of them can be deleted here.1 param

Delete a People Database persona of the current team. The deletion is permanent. Use when the user asks about: - Removing a persona they no longer need - Cleaning up duplicate or outdated personas Important: - Ask the user to confirm before calling this tool; there is no undo. - Use list_people_database_personas to resolve a persona name into its id. - An unknown id, another team's persona, and the auto-generated system persona all fail the same way (not found) — none of them can be deleted here.

NameTypeRequiredDescription
personaIdstringrequiredThe persona id to delete (pdp_xxx format)
lemlistmcp_delete_sequence_step#Delete a step from a campaign sequence. Use only when removing a step added by mistake — requires user confirmation.4 params

Delete a step from a campaign sequence. Use only when removing a step added by mistake — requires user confirmation.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign ID (required for status verification)
sequenceIdstringrequiredThe sequence ID (starts with seq_)
stepIdstringrequiredThe step ID to delete (starts with stp_)
userConfirmedbooleanrequiredREQUIRED: Must be true. Confirms user explicitly approved this deletion. Only set to true after user says yes.
lemlistmcp_delete_unsubscribe#Remove an email address from the unsubscribe list, allowing it to be contacted again in future campaigns.2 params

Remove an email address from the unsubscribe list, allowing it to be contacted again in future campaigns.

NameTypeRequiredDescription
emailstringrequiredThe email address to remove from the unsubscribe list
confirmedbooleanoptionalNEVER set this to true on first call. Only set to true after the user has explicitly confirmed the action (e.g. via ask_question).
lemlistmcp_delete_watch_list#Delete a watch list and immediately stop processing signals for it.2 params

Delete a watch list and immediately stop processing signals for it.

NameTypeRequiredDescription
watchListIdstringrequiredThe watch list ID to delete (wat_xxx format)
confirmedbooleanoptionalSet to true only after the user has explicitly confirmed the deletion (e.g. via ask_question).
lemlistmcp_delete_webhook#Delete a webhook from your Lemlist account, stopping all notifications to that endpoint immediately.2 params

Delete a webhook from your Lemlist account, stopping all notifications to that endpoint immediately.

NameTypeRequiredDescription
webhookIdstringrequiredThe webhook ID to delete (starts with hoo_)
confirmedbooleanoptionalSet to true only after the user has explicitly confirmed the deletion (e.g. via ask_question).
lemlistmcp_disconnect_email_account#Disconnect email account. Stops sending immediately. Cannot be undone. Use get_user_channels to find account ID.2 params

Disconnect email account. Stops sending immediately. Cannot be undone. Use get_user_channels to find account ID.

NameTypeRequiredDescription
emailAccountIdstringrequiredThe email account ID to disconnect (starts with usm_)
confirmedbooleanoptionalSet to true only after the user has explicitly confirmed the disconnection (e.g. via ask_question).
lemlistmcp_display_leads#Show leads in an interactive workspace table. Users can select, filter, and push to campaigns. For the two-step pattern (lemleads_search in companies mode with `description` -> display_leads), you MUST pass the returned `dataRef` to this tool. The server resolves it to the full company set server-side and injects a `currentCompanyByIds` filter so the leads table queries leads at those companies. This persists in the workspace item (no 30-min TTL concern). Do NOT copy the `companyIds` array into a `currentCompanyByIds` filter inline — emitting hundreds of IDs inline risks truncation; pass them via the `companyIds` field instead and the server builds the filter for you. FOLLOW-UP TURNS over an existing companies table ("find CEOs of those companies", "now show me leads from this list", "and the marketing directors"): the workspace already holds the company set, so DO NOT re-run lemleads_search. Recovery order: 1. If the companies-mode lemleads_search `dataRef` from earlier is still in your context AND was issued in the last ~30 minutes, pass it as `dataRef`. 2. Otherwise, call `get_workspace_items({ itemType: "companies" })`, read `data.companyIds` from the workspace_companies item, and pass that array via the `companyIds` field on this tool. The server builds `currentCompanyByIds` for you (no truncation risk). Re-running lemleads_search to "re-verify the count" loses the curated set and is what produces the bad / off-topic lead lists. Otherwise (no prior companies table involved), call display_leads directly with filters only — the table loads data dynamically. Pass any combination of `filters`, `dataRef`, and `companyIds` together; they are AND-combined server-side. To modify an existing LEADS search: get_workspace_items -> display_leads with updated filters + replaceItemId. Only pass replaceItemId when the target item is itself a leads table — never to convert a companies/messages/other item into leads. To show a different artifact type alongside, omit replaceItemId so a new item is appended.7 params

Show leads in an interactive workspace table. Users can select, filter, and push to campaigns. For the two-step pattern (lemleads_search in companies mode with `description` -> display_leads), you MUST pass the returned `dataRef` to this tool. The server resolves it to the full company set server-side and injects a `currentCompanyByIds` filter so the leads table queries leads at those companies. This persists in the workspace item (no 30-min TTL concern). Do NOT copy the `companyIds` array into a `currentCompanyByIds` filter inline — emitting hundreds of IDs inline risks truncation; pass them via the `companyIds` field instead and the server builds the filter for you. FOLLOW-UP TURNS over an existing companies table ("find CEOs of those companies", "now show me leads from this list", "and the marketing directors"): the workspace already holds the company set, so DO NOT re-run lemleads_search. Recovery order: 1. If the companies-mode lemleads_search `dataRef` from earlier is still in your context AND was issued in the last ~30 minutes, pass it as `dataRef`. 2. Otherwise, call `get_workspace_items({ itemType: "companies" })`, read `data.companyIds` from the workspace_companies item, and pass that array via the `companyIds` field on this tool. The server builds `currentCompanyByIds` for you (no truncation risk). Re-running lemleads_search to "re-verify the count" loses the curated set and is what produces the bad / off-topic lead lists. Otherwise (no prior companies table involved), call display_leads directly with filters only — the table loads data dynamically. Pass any combination of `filters`, `dataRef`, and `companyIds` together; they are AND-combined server-side. To modify an existing LEADS search: get_workspace_items -> display_leads with updated filters + replaceItemId. Only pass replaceItemId when the target item is itself a leads table — never to convert a companies/messages/other item into leads. To show a different artifact type alongside, omit replaceItemId so a new item is appended.

NameTypeRequiredDescription
titlestringrequiredTitle for the table tab (e.g. "CFOs in France", "SaaS Founders")
columnsarrayoptionalOptional column keys to display as a string[] (e.g. ["name","title","company"]). Pass the key strings, not column-descriptor objects. Defaults to name, title, company, etc.
companyIdsarrayoptionalCompany IDs to scope the leads to. The server builds a currentCompanyByIds filter from these. Accepts both People-Database company IDs (numeric — the recovery path when a prior companies dataRef is expired but the workspace_companies item still holds them: get_workspace_items -> data.companyIds) and lemlist CRM company IDs (cpn_… from search_companies), which the server resolves to People-Database IDs via coreSignalId/domain. When some CRM IDs cannot be resolved, the result reports how many; report that to the user and do NOT claim success on a resultCount of 0. Avoids LLM-side truncation that you would get by inlining a long currentCompanyByIds filter.
dataRefstringoptionalReference to a previous lemleads_search result. For a people-mode search, the server REPLAYS the exact verified filter set, so passing this dataRef guarantees the displayed table matches the totalCount you just verified (no filter drift, no retyping). For a companies-mode (vector) search, the server injects a currentCompanyByIds filter from the resolved company set. Preferred over retyping filters or inlining IDs (avoids LLM truncation and search/display drift).
filtersarrayoptionalPeople Database filters (PREFERRED). Use filters from get_lemleads_filters. Each needs filterId, in, out arrays.
leadIdsarrayoptionalSpecific lead IDs to display. Only use for small known lists (<50). For results from lemleads_search, pass dataRef instead — it avoids truncating large arrays in the tool call arguments.
replaceItemIdstringoptionalID of an existing workspace leads item to replace (use for modifications instead of creating a new item)
lemlistmcp_display_leads_page#Fetch one page of People Database leads for the workspace-leads table. App-only: called by the leads grid iframe (pagination, select-all), not by the agent. Returns the raw Elastic hits the iframe transforms into rows, the total count, and the already-in-campaign / already-in-contacts maps.4 params

Fetch one page of People Database leads for the workspace-leads table. App-only: called by the leads grid iframe (pagination, select-all), not by the agent. Returns the raw Elastic hits the iframe transforms into rows, the total count, and the already-in-campaign / already-in-contacts maps.

NameTypeRequiredDescription
filtersarrayrequiredResolved People Database filters (filterId/in/out) for the search
pagenumberrequired0-based page index (the usage:"ui" API contract)
sizenumberrequiredResults per page (default 25, max 100)
seedstringoptionalOptional ordering seed for stable pagination
lemlistmcp_display_table#Display a data table in the workspace panel. CRITICAL RULES — follow exactly or the table will be empty: 1. dataRef: If the source tool returned a dataRef string, pass it as dataRef (preferred — avoids large data transfer). The rows will be resolved automatically from the stored reference. 2. rows: Only if no dataRef is available. Pass the ORIGINAL data array from the tool result AS-IS. NEVER construct row objects manually or map/transform the array. 3. columns: Use suggestedColumns from the source tool result directly when available. NEVER invent column keys — they must match actual property names in the row objects. PREFERRED: dataRef=result.dataRef, columns=result.suggestedColumns, groupKey=result.groupKey, tableType=result.tableType FALLBACK: rows=result.campaigns, columns=result.suggestedColumns WRONG: rows=result.campaigns.map(c => ({sentCount: c.stats.sentCount})) — this strips data Always forward groupKey and tableType from the source tool when available.7 params

Display a data table in the workspace panel. CRITICAL RULES — follow exactly or the table will be empty: 1. dataRef: If the source tool returned a dataRef string, pass it as dataRef (preferred — avoids large data transfer). The rows will be resolved automatically from the stored reference. 2. rows: Only if no dataRef is available. Pass the ORIGINAL data array from the tool result AS-IS. NEVER construct row objects manually or map/transform the array. 3. columns: Use suggestedColumns from the source tool result directly when available. NEVER invent column keys — they must match actual property names in the row objects. PREFERRED: dataRef=result.dataRef, columns=result.suggestedColumns, groupKey=result.groupKey, tableType=result.tableType FALLBACK: rows=result.campaigns, columns=result.suggestedColumns WRONG: rows=result.campaigns.map(c => ({sentCount: c.stats.sentCount})) — this strips data Always forward groupKey and tableType from the source tool when available.

NameTypeRequiredDescription
columnsarrayrequiredColumn definitions — use suggestedColumns from source tool if available
titlestringrequiredTable title (shown in workspace tab)
appendToItemIdstringoptionalWorkspace item ID of an existing table to append rows to instead of creating a new tab. Use get_workspace_items to find the ID, then pass it here when loading more data.
dataRefstringoptionalReference ID from a source tool (e.g. search_campaign_leads). When provided, rows are resolved automatically from the stored data. Preferred over passing rows directly.
groupKeystringoptionalGrouping key for auto-appending rows. Tables with the same groupKey merge into one tab. Use the source tool result value (e.g. campaignId for leads). Required when paginating.
rowsarrayoptionalFallback: the ORIGINAL data array from the source tool result, passed as-is. Only use when dataRef is not available.
tableTypestringoptionalType of table data. Both values render an "Export as CSV" button for the user: "campaign_leads" for leads coming from search_campaign_leads (server-side export), and "generic" for any other table (the displayed columns and rows are exported client-side). Forward the value from the source tool result when there is one; for a custom table you assembled yourself (e.g. an enriched inbox analysis), set "generic" so the user gets the export button.
lemlistmcp_enrich_lead#Enrich existing campaign lead. ASYNC — poll with bulk_get_enrichment_results (pass enrichmentIds: [id]). For non-campaign contacts use bulk_enrich_data. ALL options COST CREDITS.5 params

Enrich existing campaign lead. ASYNC — poll with bulk_get_enrichment_results (pass enrichmentIds: [id]). For non-campaign contacts use bulk_enrich_data. ALL options COST CREDITS.

NameTypeRequiredDescription
leadIdstringrequiredThe lead ID to enrich (starts with lea_)
findEmailbooleanoptional⚠️ COSTS CREDITS: Find email from lead data
findPhonebooleanoptional⚠️ COSTS CREDITS: Find phone number
linkedinEnrichmentbooleanoptional⚠️ COSTS CREDITS: Enrich with LinkedIn data
verifyEmailbooleanoptional⚠️ COSTS CREDITS: Verify lead email
lemlistmcp_find_watch_list_linkedin_urls#Find real, validated LinkedIn URLs to monitor for a watch list type. Returns LinkedIn URLs (person /in/ or company /company/ depending on the type), sourced and validated from live web search and grounded in the team's business context (AI Context Center). Use when the user asks about: - Pre-filling the LinkedIn URLs for a linkedinPeopleProfile, linkedinCompanyProfile, competitorConnections or competitorReactions watch list - Discovering relevant LinkedIn profiles or company pages to watch Important: - Only the 4 LinkedIn signal types are accepted; any other type is rejected. - Pass an optional "focus" to steer the search; otherwise it falls back to the type's name. - Returns an empty list when no relevant URLs are found. - Rate-limited per user per day (a limited number of calls).2 params

Find real, validated LinkedIn URLs to monitor for a watch list type. Returns LinkedIn URLs (person /in/ or company /company/ depending on the type), sourced and validated from live web search and grounded in the team's business context (AI Context Center). Use when the user asks about: - Pre-filling the LinkedIn URLs for a linkedinPeopleProfile, linkedinCompanyProfile, competitorConnections or competitorReactions watch list - Discovering relevant LinkedIn profiles or company pages to watch Important: - Only the 4 LinkedIn signal types are accepted; any other type is rejected. - Pass an optional "focus" to steer the search; otherwise it falls back to the type's name. - Returns an empty list when no relevant URLs are found. - Rate-limited per user per day (a limited number of calls).

NameTypeRequiredDescription
typestringrequiredWatch list type to find LinkedIn URLs for. Only the 4 LinkedIn signal types are supported: linkedinPeopleProfile (returns /in/ person profiles), linkedinCompanyProfile, competitorConnections, competitorReactions (return /company/ company pages).
focusstringoptionalOptional free-text focus to steer the search (e.g. "HR SaaS in France"). Defaults to the type's feature name when omitted.
lemlistmcp_generate_campaign_for_watch_list#Generate an AI-powered outreach campaign for an existing watch list. Builds a campaign from a predefined sequence template, writes every step's copy with AI (steered by copyStyle and the watch list's signal), links it to the watch list, and returns the campaign with its generated sequences. Use when the user asks about: - Turning a watch list's signals into a ready-to-run outreach campaign - Auto-generating a sequence + AI copy targeted at what the watch list monitors Flow: - Run it on an existing watch list, or create one first (create_watch_list), then call this tool to generate its campaign. - autoLaunch=true launches the campaign immediately; false leaves it in draft. Important: - The watch list (watchListId) must exist for the current team. - reviewBeforeSend only applies when autoLaunch=true.6 params

Generate an AI-powered outreach campaign for an existing watch list. Builds a campaign from a predefined sequence template, writes every step's copy with AI (steered by copyStyle and the watch list's signal), links it to the watch list, and returns the campaign with its generated sequences. Use when the user asks about: - Turning a watch list's signals into a ready-to-run outreach campaign - Auto-generating a sequence + AI copy targeted at what the watch list monitors Flow: - Run it on an existing watch list, or create one first (create_watch_list), then call this tool to generate its campaign. - autoLaunch=true launches the campaign immediately; false leaves it in draft. Important: - The watch list (watchListId) must exist for the current team. - reviewBeforeSend only applies when autoLaunch=true.

NameTypeRequiredDescription
autoLaunchbooleanrequiredLaunch the campaign immediately; false creates it in draft
autoRunbooleanrequiredGenerate an icebreaker AI variable automatically for each new lead
copyStylestringrequiredTone of the AI-generated copy: direct | conversational | insight_led
reviewBeforeSendbooleanrequiredRoute leads to Review before the first step (ignored when autoLaunch=false)
sequenceTypestringrequiredPredefined sequence recipe: email | linkedin | multichannel
watchListIdstringrequiredSource watch list ID (wat_xxx) to build the campaign from
lemlistmcp_get_ai_variable_prompts#Read the AI-generation prompts of a campaign's AI variable columns (the AI-generated columns in the Leads table: icebreakers, openers, contextual openers, etc.). Returns one entry per AI variable: its variable name, the prompt used to generate it, and the AI model. Prompts come back verbatim, with raw {{variable}} placeholders (e.g. {{firstName}}) left unresolved, since a prompt is a template applied across all leads (there is no single lead to resolve against). Use when the user asks to: - See how an AI column (icebreaker, opener, ...) is generated for a campaign - Review or audit the prompt behind a campaign's AI variables before editing it Read-only: no credits consumed, nothing is changed. To edit a prompt, use update_ai_variable_prompt; to add a new column, use create_ai_variable_prompt.1 param

Read the AI-generation prompts of a campaign's AI variable columns (the AI-generated columns in the Leads table: icebreakers, openers, contextual openers, etc.). Returns one entry per AI variable: its variable name, the prompt used to generate it, and the AI model. Prompts come back verbatim, with raw {{variable}} placeholders (e.g. {{firstName}}) left unresolved, since a prompt is a template applied across all leads (there is no single lead to resolve against). Use when the user asks to: - See how an AI column (icebreaker, opener, ...) is generated for a campaign - Review or audit the prompt behind a campaign's AI variables before editing it Read-only: no credits consumed, nothing is changed. To edit a prompt, use update_ai_variable_prompt; to add a new column, use create_ai_variable_prompt.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx format) whose AI variable prompts to read
lemlistmcp_get_business_context#Return the published business context for the current team — markdown describing the company, its value propositions, ICP, products, etc., generated from the team's website. Use BEFORE: - crafting any messaging, sequence step, or persona suggestion - recommending watch list types (so the AI knows what the team sells and to whom) - onboarding flows that need to reference the team's business Response shape: - data: null → no business context generated yet (suggest running the onboarding generation) - data: { markdown, sourceUrl, generatedAt, lastEditedAt, updatedAt }0 params

Return the published business context for the current team — markdown describing the company, its value propositions, ICP, products, etc., generated from the team's website. Use BEFORE: - crafting any messaging, sequence step, or persona suggestion - recommending watch list types (so the AI knows what the team sells and to whom) - onboarding flows that need to reference the team's business Response shape: - data: null → no business context generated yet (suggest running the onboarding generation) - data: { markdown, sourceUrl, generatedAt, lastEditedAt, updatedAt }

lemlistmcp_get_call_activities#List call activities from the lemlist dialer (cold calls), with filtering and pagination. Use when the user asks about: - Calls made or received through the lemlist dialer - Filtering calls by campaign, lead, contact, user, status/disposition, direction, or date range - Reviewing call outcomes, durations, or which leads were called Each call includes direction, duration, status/disposition, phone provider, whether a recording exists, the AI transcript summary, and the associated lead/contact/campaign/user IDs. Use get_call_details with an activityId to fetch the recording URL and full transcript for a single call.10 params

List call activities from the lemlist dialer (cold calls), with filtering and pagination. Use when the user asks about: - Calls made or received through the lemlist dialer - Filtering calls by campaign, lead, contact, user, status/disposition, direction, or date range - Reviewing call outcomes, durations, or which leads were called Each call includes direction, duration, status/disposition, phone provider, whether a recording exists, the AI transcript summary, and the associated lead/contact/campaign/user IDs. Use get_call_details with an activityId to fetch the recording URL and full transcript for a single call.

NameTypeRequiredDescription
callStatusstringoptionalFilter by call status/disposition key (e.g. "interested", "no-answer"). The status keys returned by get_call_activities are the valid values.
campaignIdstringoptionalFilter calls by campaign ID (cam_xxx)
contactIdstringoptionalFilter calls by contact ID (ctc_xxx)
dateFromstringoptionalInclude calls created on/after this ISO 8601 datetime (e.g. "2026-01-01T00:00:00Z")
dateTostringoptionalInclude calls created on/before this ISO 8601 datetime
directionstringoptionalFilter by call direction (inbound or outbound)
leadIdstringoptionalFilter calls by lead ID (lea_xxx)
limitintegeroptionalMax calls per page (default 50, max 100)
pageintegeroptionalPage number (1-based, default 1)
userIdstringoptionalFilter by the lemlist user who made or received the call (usr_xxx)
lemlistmcp_get_call_details#Get full details for ONE dialer call by its activity ID, including the recording URL and transcript. Use when the user asks about: - The recording or transcript of a specific call - The full context of a call (lead, contact, company, campaign, call note, disposition) Returns call metadata, the associated lead/contact/company/campaign/user, the manual call note (if any), and — unless includeRecording is false — a temporary recording URL plus the full transcript. Use get_call_activities first to find the activityId.2 params

Get full details for ONE dialer call by its activity ID, including the recording URL and transcript. Use when the user asks about: - The recording or transcript of a specific call - The full context of a call (lead, contact, company, campaign, call note, disposition) Returns call metadata, the associated lead/contact/company/campaign/user, the manual call note (if any), and — unless includeRecording is false — a temporary recording URL plus the full transcript. Use get_call_activities first to find the activityId.

NameTypeRequiredDescription
activityIdstringrequiredThe call activity ID (act_xxx) — from get_call_activities
includeRecordingbooleanoptionalWhen true (default), also fetch the recording URL and full transcript. Set false to return only call metadata (faster, no recording fetch).
lemlistmcp_get_call_statuses#List this team's configured call statuses (dispositions) — the valid KEYS for update_call_status. Use when: - BEFORE update_call_status, to pick a valid status key for this team (keys are team-specific: defaults plus any custom statuses) - The user asks which call dispositions / statuses exist Returns each status with its key (what update_call_status expects), label, and side effects: whether it marks the lead answered / positive / negative and whether it pauses campaigns.0 params

List this team's configured call statuses (dispositions) — the valid KEYS for update_call_status. Use when: - BEFORE update_call_status, to pick a valid status key for this team (keys are team-specific: defaults plus any custom statuses) - The user asks which call dispositions / statuses exist Returns each status with its key (what update_call_status expects), label, and side effects: whether it marks the lead answered / positive / negative and whether it pauses campaigns.

lemlistmcp_get_campaign_details#Get configuration and settings for ONE campaign (timezone, emoji, labels, senders, sequences). For metrics use get_campaigns_stats, for email content use get_campaign_sequences.1 param

Get configuration and settings for ONE campaign (timezone, emoji, labels, senders, sequences). For metrics use get_campaigns_stats, for email content use get_campaign_sequences.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign ID (cam_xxx format)
lemlistmcp_get_campaign_sequences#Get the email sequences and their content (subject, body) for a specific campaign. Useful for reviewing copywriting and email flow.1 param

Get the email sequences and their content (subject, body) for a specific campaign. Useful for reviewing copywriting and email flow.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign ID (cam_xxx format)
lemlistmcp_get_campaigns#List campaigns with optional search, filtering by labels, and sorting.7 params

List campaigns with optional search, filtering by labels, and sorting.

NameTypeRequiredDescription
createdBystringoptionalFilter by creator user ID (usr_xxx format). Use your own user ID from Context to find campaigns you created.
labelsarrayoptionalFilter by labels/tags. OR semantics: returns campaigns matching at least one. Accepts label names ("q2") or IDs ("lab_xxx") — both can be mixed.
limitnumberoptionalMaximum number of campaigns to return (default: 20)
offsetnumberoptionalNumber of campaigns to skip for pagination (default: 0). Use with limit to paginate through all campaigns.
searchstringoptionalSearch campaigns by name (case-insensitive)
sortOrderstringoptionalSort by creation date (default: newest first)
statusstringoptionalFilter by status. OMIT this parameter to get ALL campaigns regardless of status.
lemlistmcp_get_campaigns_reports#Get lifetime stats for MULTIPLE campaigns in one call. Returns metadata, sender info, and 65+ metrics per campaign. No date filtering - for time-based analysis use get_campaigns_stats.1 param

Get lifetime stats for MULTIPLE campaigns in one call. Returns metadata, sender info, and 65+ metrics per campaign. No date filtering - for time-based analysis use get_campaigns_stats.

NameTypeRequiredDescription
campaignIdsarrayrequiredArray of campaign IDs to get reports for (e.g., ["cam_xxx", "cam_yyy"])
lemlistmcp_get_campaigns_stats#Get detailed stats for one or more campaigns including lead funnel metrics, message counts, and per-step breakdowns.7 params

Get detailed stats for one or more campaigns including lead funnel metrics, message counts, and per-step breakdowns.

NameTypeRequiredDescription
campaignIdsarrayrequiredArray of campaign IDs (cam_xxx format)
ABSelectedstringoptionalOptional: Filter by A/B test variant
channelsarrayoptionalOptional: Filter stats by channels (mirrors the UI dropdown filter). When provided, both top-level totals and messageMetrics.perChannel are restricted to the requested channels. Omit to get the full breakdown across all 5 channels.
endDatestringoptionalEnd date. Either a calendar day "YYYY-MM-DD" (interpreted as end-of-day in the resolved timezone) or a full ISO 8601 datetime with offset (used as-is). Omit for all-time stats.
sendUserstringoptionalOptional: Filter by send user (format: usr_xxx|email@example.com)
startDatestringoptionalStart date. Either a calendar day "YYYY-MM-DD" (interpreted as start-of-day in the resolved timezone) or a full ISO 8601 datetime with offset like "2026-04-01T00:00:00+05:30" / "2026-04-01T00:00:00Z" (used as-is, the timezone arg is ignored for that bound). Omit for all-time stats.
timezonestringoptionalIANA timezone (e.g. "Asia/Kolkata", "America/New_York") used to interpret startDate/endDate ONLY when they are calendar days (YYYY-MM-DD). Ignored for full ISO 8601 datetimes. If omitted, falls back to the calling user's profile.timezone (if set), then to Europe/Paris. To exactly mirror what the Lemlist UI displays, prefer passing the same ISO 8601 strings the UI uses (capture from the campaignReportsTimePeriod session).
lemlistmcp_get_contact_fields_schema#Get the list of available fields and relations on a contact (lead) or a company. Returns: - standardFields: scalar fields always present on the entity (email, firstName, … / name, domain, …) - customFields: team-specific scalar fields defined by the user - relations: one-to-many relations available as 'include' on search_campaign_leads (contact only) - csvImportTargets: the field keys a CSV column can be mapped to for this entity Use this BEFORE calling search_campaign_leads to know which 'fields' (scalar) and 'include' (relations) values are valid, and BEFORE import_contacts_from_csv / import_companies_from_csv to build columnMapping.1 param

Get the list of available fields and relations on a contact (lead) or a company. Returns: - standardFields: scalar fields always present on the entity (email, firstName, … / name, domain, …) - customFields: team-specific scalar fields defined by the user - relations: one-to-many relations available as 'include' on search_campaign_leads (contact only) - csvImportTargets: the field keys a CSV column can be mapped to for this entity Use this BEFORE calling search_campaign_leads to know which 'fields' (scalar) and 'include' (relations) values are valid, and BEFORE import_contacts_from_csv / import_companies_from_csv to build columnMapping.

NameTypeRequiredDescription
entitystringrequiredEntity type to describe: 'contact' (default) or 'company'.
lemlistmcp_get_contact_lists#Retrieve available CRM contact lists with optional search filtering.1 param

Retrieve available CRM contact lists with optional search filtering.

NameTypeRequiredDescription
searchstringoptionalFilter lists by name (case-insensitive)
lemlistmcp_get_domain_dns#Read the current DNS records for a domain (MX, SPF, DMARC, DKIM, CNAME, A…). Use in Step 4 of the outreach-infra skill to audit DNS state before writing new records, and to confirm the apex A record is healthy.1 param

Read the current DNS records for a domain (MX, SPF, DMARC, DKIM, CNAME, A…). Use in Step 4 of the outreach-infra skill to audit DNS state before writing new records, and to confirm the apex A record is healthy.

NameTypeRequiredDescription
domainIdstringrequiredDomain ID (dom_xxx)
lemlistmcp_get_inbox_conversation#Get the full conversation thread for a specific contact across all channels (email, LinkedIn, WhatsApp, SMS).4 params

Get the full conversation thread for a specific contact across all channels (email, LinkedIn, WhatsApp, SMS).

NameTypeRequiredDescription
contactIdstringrequiredThe contact ID (ctc_xxx format) to get the conversation thread for. Do not use leadId or any other ID type.
limitnumberoptionalNumber of activities per page (default: 20, max: 50)
markAsReadbooleanoptionalWhether to mark the conversation as read (default: false). Note: this mutates state.
pagenumberoptionalPage number for pagination (default: 1)
lemlistmcp_get_inbox_conversations#List inbox conversations with contact info and last message preview, with optional filtering by list type.5 params

List inbox conversations with contact info and last message preview, with optional filtering by list type.

NameTypeRequiredDescription
limitnumberoptionalNumber of conversations per page (default: 20, max: 50)
listIdstringoptionalWhich inbox list to fetch: myConversations (default), unRead, favorites, snoozed, archived, sentOnly, teamConversations
pagenumberoptionalPage number for pagination (default: 1)
searchstringoptionalSearch query to filter conversations by contact name or email
userIdstringoptionalThe user ID (usr_xxx format). Optional — defaults to the current authenticated user if omitted.
lemlistmcp_get_inbox_placement_result#Read the result of an inbox placement test started with run_inbox_placement_test. The test is asynchronous, so call this with the testId until state is "completed". When completed, it returns the per-provider breakdown (Google / Microsoft / SMTP) of where the email landed (inbox / promotions / spam / unreceived percentages), the overall split, and a deterministic `pattern` — trust this field, do not re-derive the thresholds: - "content_borderline": Google/Microsoft inbox but SMTP in spam → fix content, not infra - "deeper_issue": Google/Microsoft also failing → warmup, blacklist, or egregious copy - "all_clean": no content issue, look elsewhere - "mixed": no single dominant pattern; report the per-provider numbers1 param

Read the result of an inbox placement test started with run_inbox_placement_test. The test is asynchronous, so call this with the testId until state is "completed". When completed, it returns the per-provider breakdown (Google / Microsoft / SMTP) of where the email landed (inbox / promotions / spam / unreceived percentages), the overall split, and a deterministic `pattern` — trust this field, do not re-derive the thresholds: - "content_borderline": Google/Microsoft inbox but SMTP in spam → fix content, not infra - "deeper_issue": Google/Microsoft also failing → warmup, blacklist, or egregious copy - "all_clean": no content issue, look elsewhere - "mixed": no single dominant pattern; report the per-provider numbers

NameTypeRequiredDescription
testIdstringrequiredInbox placement test ID (ipt_xxx) returned by run_inbox_placement_test
lemlistmcp_get_lemleads_filters#Get available filters for People Database searches. Call this FIRST before lemleads_search or display_leads/display_companies. Returns filter IDs with valid values.0 params

Get available filters for People Database searches. Call this FIRST before lemleads_search or display_leads/display_companies. Returns filter IDs with valid values.

lemlistmcp_get_settings#Retrieve settings for a campaign or warmup mailbox entity.2 params

Retrieve settings for a campaign or warmup mailbox entity.

NameTypeRequiredDescription
typestringrequiredThe type of settings to retrieve.
idstringoptionalEntity ID. Required for "campaign" (cam_xxx) and "lemwarm" (usm_xxx). Ignored for "sending" and "team".
lemlistmcp_get_statistics#Retrieve statistics for one or more entities of the same type (lemwarm, campaign, lead, etc.).3 params

Retrieve statistics for one or more entities of the same type (lemwarm, campaign, lead, etc.).

NameTypeRequiredDescription
idsarrayrequiredFor "lemwarm": mailbox IDs (usm_xxx) — same ids used with get_settings type="lemwarm". 1-20 items.
typestringrequiredThe type of statistics to retrieve. Only "lemwarm" is supported for now.
daysnumberoptionalLookback window in days (1-60). Defaults to 30. Applied to every id.
lemlistmcp_get_task_content#Load the effective message content (subject + body) of a message-based task (opportunity) — the exact content the Focus-mode editor would show and that send_task would send. Use when the user asks about: - Previewing what an email / LinkedIn / WhatsApp task will actually send - Checking whether a task already has content before sending or editing it Where the content comes from: - The per-lead draft override if one exists, otherwise the task's template. This is the real outgoing body — NOT the 'content'/'text' fields from get_tasks, which are null for message tasks and must NOT be read as "empty". What it returns: - 'subject'/'message': the effective content ('subject' only for email tasks). - 'hasContent': false ONLY when the body is genuinely empty (the real "no content" case). - 'sendable': true when the content is ready for an immediate send_task (message-based, NON-manual task with a body — and a subject for email). Status, contact and sender are still validated by send_task itself. - 'schedulable': true when the task is a manual campaign step of a message type — it cannot be sent immediately, but send_task will schedule it via the campaign and mark it done ("Schedule & mark done"). A message task is either sendable or schedulable, never both. Read-only: it never edits or sends. Only email / linkedinSend / whatsappMessage tasks carry content; other types return empty content and sendable=false.1 param

Load the effective message content (subject + body) of a message-based task (opportunity) — the exact content the Focus-mode editor would show and that send_task would send. Use when the user asks about: - Previewing what an email / LinkedIn / WhatsApp task will actually send - Checking whether a task already has content before sending or editing it Where the content comes from: - The per-lead draft override if one exists, otherwise the task's template. This is the real outgoing body — NOT the 'content'/'text' fields from get_tasks, which are null for message tasks and must NOT be read as "empty". What it returns: - 'subject'/'message': the effective content ('subject' only for email tasks). - 'hasContent': false ONLY when the body is genuinely empty (the real "no content" case). - 'sendable': true when the content is ready for an immediate send_task (message-based, NON-manual task with a body — and a subject for email). Status, contact and sender are still validated by send_task itself. - 'schedulable': true when the task is a manual campaign step of a message type — it cannot be sent immediately, but send_task will schedule it via the campaign and mark it done ("Schedule & mark done"). A message task is either sendable or schedulable, never both. Read-only: it never edits or sends. Only email / linkedinSend / whatsappMessage tasks carry content; other types return empty content and sendable=false.

NameTypeRequiredDescription
opportunityIdstringrequiredThe task (opportunity) ID to read (opp_xxx format).
lemlistmcp_get_tasks#List the team's pending tasks (call/phone, manual, LinkedIn, email tasks...) from the Tasks page. Use when the user asks about: - Their pending or upcoming tasks ("what tasks do I have", "my call tasks this week") - Counting tasks by priority ("how many high-priority tasks") - Tasks for a specific campaign, assignee, type, or due-date range Filters: - 'type' filters by task type (call/phone, manual, email, linkedin*, sms, whatsappMessage) - 'assignedTo' (usr_xxx) restricts to one user. Omit for the whole team. - 'dueDateFrom'/'dueDateTo' (ISO 8601) bound the due date. - 'campaignId' / 'campaignState' filter by source campaign. - 'priority' (none/low/medium/high) is applied in the handler (the API has no server-side priority filter). The response always includes 'priorityCounts' (distribution over the fetched tasks) so you can answer "how many high-priority tasks". Only pending tasks that are due or upcoming are returned. Tasks are scanned up to a page cap; when 'truncated' is true, counts and totals are partial — narrow with filters for complete results. To show the tasks in a table, call display_table with dataRef=result.dataRef, columns=result.suggestedColumns, tableType=result.tableType. Pass the dataRef — do NOT pass result.tasks as rows: 'tasks' is a truncated preview for your reasoning only, and the full rows are resolved from dataRef (this keeps the table call small and fast). The table surfaces each task's title in a clickable Task column (opens Focus Mode) so the user can reference and open an opportunity. IMPORTANT — 'content'/'text' are NOT the outgoing message body for email / linkedinSend / whatsappMessage tasks: they are usually null here because the real subject/body lives in the task's template (loaded lazily at send time). A null 'content' here does NOT mean the task is empty. To preview what will be sent, call get_task_content; to send, call send_task (it loads the existing content automatically). The 'content'/'text' fields are only meaningful for manual tasks.7 params

List the team's pending tasks (call/phone, manual, LinkedIn, email tasks...) from the Tasks page. Use when the user asks about: - Their pending or upcoming tasks ("what tasks do I have", "my call tasks this week") - Counting tasks by priority ("how many high-priority tasks") - Tasks for a specific campaign, assignee, type, or due-date range Filters: - 'type' filters by task type (call/phone, manual, email, linkedin*, sms, whatsappMessage) - 'assignedTo' (usr_xxx) restricts to one user. Omit for the whole team. - 'dueDateFrom'/'dueDateTo' (ISO 8601) bound the due date. - 'campaignId' / 'campaignState' filter by source campaign. - 'priority' (none/low/medium/high) is applied in the handler (the API has no server-side priority filter). The response always includes 'priorityCounts' (distribution over the fetched tasks) so you can answer "how many high-priority tasks". Only pending tasks that are due or upcoming are returned. Tasks are scanned up to a page cap; when 'truncated' is true, counts and totals are partial — narrow with filters for complete results. To show the tasks in a table, call display_table with dataRef=result.dataRef, columns=result.suggestedColumns, tableType=result.tableType. Pass the dataRef — do NOT pass result.tasks as rows: 'tasks' is a truncated preview for your reasoning only, and the full rows are resolved from dataRef (this keeps the table call small and fast). The table surfaces each task's title in a clickable Task column (opens Focus Mode) so the user can reference and open an opportunity. IMPORTANT — 'content'/'text' are NOT the outgoing message body for email / linkedinSend / whatsappMessage tasks: they are usually null here because the real subject/body lives in the task's template (loaded lazily at send time). A null 'content' here does NOT mean the task is empty. To preview what will be sent, call get_task_content; to send, call send_task (it loads the existing content automatically). The 'content'/'text' fields are only meaningful for manual tasks.

NameTypeRequiredDescription
assignedTostringoptionalRestrict to one user (usr_xxx). Omit to return the whole team's tasks.
campaignIdstringoptionalFilter by source campaign (cam_xxx)
campaignStatearrayoptionalFilter by source campaign state (e.g. running, paused, ended)
dueDateFromstringoptionalOnly tasks due on/after this date (ISO 8601, e.g. 2026-06-01)
dueDateTostringoptionalOnly tasks due on/before this date (ISO 8601, e.g. 2026-06-30)
priorityarrayoptionalFilter by priority label(s): none, low, medium, high (applied after fetch)
typearrayoptionalFilter by task type(s): call/phone, manual, email, linkedin variants, sms, whatsappMessage
lemlistmcp_get_team_info#Get basic team info (ID, name, plan, credits remaining) and minimal identity of the caller (current user id + email). For full user details call get_users with userIds: ["me"] for the caller, userIds: ["all"] for the full member list, or userIds: ["usr_xxx", ...] for one or more team members.0 params

Get basic team info (ID, name, plan, credits remaining) and minimal identity of the caller (current user id + email). For full user details call get_users with userIds: ["me"] for the caller, userIds: ["all"] for the full member list, or userIds: ["usr_xxx", ...] for one or more team members.

lemlistmcp_get_team_overview#Account summary: campaign count by status. Use get_campaigns for the full list with names and details.0 params

Account summary: campaign count by status. Use get_campaigns for the full list with names and details.

lemlistmcp_get_unsubscribes#List unsubscribed emails with pagination. Use delete_unsubscribe to re-enable.2 params

List unsubscribed emails with pagination. Use delete_unsubscribe to re-enable.

NameTypeRequiredDescription
limitnumberoptionalMaximum number of unsubscribes to return
offsetnumberoptionalNumber of unsubscribes to skip (for pagination)
lemlistmcp_get_user_channels#Check connected sending channels (email, LinkedIn, WhatsApp). Returns connection status, plan availability, and accounts. WhatsApp requires separate addon purchase. Use show_connect_channel to guide setup (one channel at a time).0 params

Check connected sending channels (email, LinkedIn, WhatsApp). Returns connection status, plan availability, and accounts. WhatsApp requires separate addon purchase. Use show_connect_channel to guide setup (one channel at a time).

lemlistmcp_get_users#Retrieve team member details by user IDs, or pass 'all' to fetch all team members.1 param

Retrieve team member details by user IDs, or pass 'all' to fetch all team members.

NameTypeRequiredDescription
userIdsarrayrequiredList of userIds to fetch. Each item is "all" (every team member, lightweight), "me" (caller, full profile), or a usr_xxx id (full profile). 1-20 items.
lemlistmcp_get_watch_list_filter_value#Resolve the valid values for one or more watch list filterIds. ALWAYS call this tool to get correctly formatted values before passing them to create_watch_list or update_watch_list. Do not guess or hardcode values. filterId MUST come from list_watch_list_filters — call it first to discover which filterIds are valid for the signal type you are configuring. BATCH your lookups: pass every value you need across every filterId in a single call via "requests" (one entry per filterId, with all its queries grouped in "queries"). Do NOT call this tool repeatedly one value at a time. The backend automatically picks the right resolution strategy for each filter. Pass query strings when searching for specific values (e.g. job titles, companies, locations). Each filterId returns the deduplicated union of its queries' matches. An empty results array means no match — do not invent values. The returned matches are candidates, not a selection: a single query can resolve to many values. Do NOT pass all of them back — keep only the ones that actually fit the watch list you are configuring, and drop the rest. If an entry comes back with a non-empty "error" and results null, fix what it describes (e.g. provide a query) and call this tool once more for that filterId.1 param

Resolve the valid values for one or more watch list filterIds. ALWAYS call this tool to get correctly formatted values before passing them to create_watch_list or update_watch_list. Do not guess or hardcode values. filterId MUST come from list_watch_list_filters — call it first to discover which filterIds are valid for the signal type you are configuring. BATCH your lookups: pass every value you need across every filterId in a single call via "requests" (one entry per filterId, with all its queries grouped in "queries"). Do NOT call this tool repeatedly one value at a time. The backend automatically picks the right resolution strategy for each filter. Pass query strings when searching for specific values (e.g. job titles, companies, locations). Each filterId returns the deduplicated union of its queries' matches. An empty results array means no match — do not invent values. The returned matches are candidates, not a selection: a single query can resolve to many values. Do NOT pass all of them back — keep only the ones that actually fit the watch list you are configuring, and drop the rest. If an entry comes back with a non-empty "error" and results null, fix what it describes (e.g. provide a query) and call this tool once more for that filterId.

NameTypeRequiredDescription
requestsarrayrequiredOne entry per filterId, each grouping every value to resolve for it. Batch ALL the lookups you need into this single call — do not call the tool repeatedly one value at a time.
lemlistmcp_get_webhooks#List all configured webhooks. Returns array with _id, targetUrl, createdAt, type, campaignId, isFirst.0 params

List all configured webhooks. Returns array with _id, targetUrl, createdAt, type, campaignId, isFirst.

lemlistmcp_import_companies_from_csv#Import companies into a company list from an uploaded CSV. Use when the user asks about: - Loading a CSV/spreadsheet of companies or accounts into a company list - Bulk-adding companies to the CRM Company columns are mapped to their bare keys here (name, domain, industry, …) — the company-prefixed form belongs to a contact CSV. Flow (3 steps, in order): 1. create_upload_url → get an uploadUrl + uploadKey 2. PUT the raw CSV to uploadUrl 3. this tool with the uploadKey Contract rules reproduced by the backend: - the list must exist, hold this entity type, and not be dynamic (filter-driven lists are filled by their own sync) - uploadKey must come from create_upload_url; a made-up key is rejected - at least one column must be mapped, and no mapping may target a reserved key (_id, teamId, …) - a "customField" target only lands if that custom field already exists on the team - every imported entity — created, updated or unchanged — is added to the list A target that matches no field is re-resolved server-side from the header and a sample value (so an export header like companyWebsite still fills companyDomain). Whatever it corrects comes back as repairedColumns; anything it cannot place comes back as ignoredColumns — those columns were NOT imported, so check them before reporting success.4 params

Import companies into a company list from an uploaded CSV. Use when the user asks about: - Loading a CSV/spreadsheet of companies or accounts into a company list - Bulk-adding companies to the CRM Company columns are mapped to their bare keys here (name, domain, industry, …) — the company-prefixed form belongs to a contact CSV. Flow (3 steps, in order): 1. create_upload_url → get an uploadUrl + uploadKey 2. PUT the raw CSV to uploadUrl 3. this tool with the uploadKey Contract rules reproduced by the backend: - the list must exist, hold this entity type, and not be dynamic (filter-driven lists are filled by their own sync) - uploadKey must come from create_upload_url; a made-up key is rejected - at least one column must be mapped, and no mapping may target a reserved key (_id, teamId, …) - a "customField" target only lands if that custom field already exists on the team - every imported entity — created, updated or unchanged — is added to the list A target that matches no field is re-resolved server-side from the header and a sample value (so an export header like companyWebsite still fills companyDomain). Whatever it corrects comes back as repairedColumns; anything it cannot place comes back as ignoredColumns — those columns were NOT imported, so check them before reporting success.

NameTypeRequiredDescription
columnMappingobjectrequiredMaps each CSV header to the field it fills: { "CSV header": "fieldKey" }. Valid fieldKeys come from get_contact_fields_schema (csvImportTargets). Use "customField" to store a column in the custom field named after that header. Columns left out of the map are not imported.
listIdstringrequiredTarget list ID (clt_xxx format). Get it from get_contact_lists.
uploadKeystringrequireduploadKey returned by create_upload_url. The CSV must already be uploaded.
upsertModestringoptionalHow existing entities are handled: "createAndUpdate" (default) creates new ones and updates matches, "createOnly" skips matches, "updateOnly" only updates and creates nothing.
lemlistmcp_import_contacts_from_csv#Import contacts into a contact list from an uploaded CSV. Use when the user asks about: - Loading a CSV/spreadsheet of people into a contact list - Bulk-adding contacts to the CRM without starting a campaign (To put leads into a campaign instead, use import_leads_to_campaign.) A contact CSV can also carry the company columns: map them to the company-prefixed keys (companyName, companyDomain, …) and the company is created and linked in the same pass. Flow (3 steps, in order): 1. create_upload_url → get an uploadUrl + uploadKey 2. PUT the raw CSV to uploadUrl 3. this tool with the uploadKey Contract rules reproduced by the backend: - the list must exist, hold this entity type, and not be dynamic (filter-driven lists are filled by their own sync) - uploadKey must come from create_upload_url; a made-up key is rejected - at least one column must be mapped, and no mapping may target a reserved key (_id, teamId, …) - a "customField" target only lands if that custom field already exists on the team - every imported entity — created, updated or unchanged — is added to the list A target that matches no field is re-resolved server-side from the header and a sample value (so an export header like companyWebsite still fills companyDomain). Whatever it corrects comes back as repairedColumns; anything it cannot place comes back as ignoredColumns — those columns were NOT imported, so check them before reporting success.4 params

Import contacts into a contact list from an uploaded CSV. Use when the user asks about: - Loading a CSV/spreadsheet of people into a contact list - Bulk-adding contacts to the CRM without starting a campaign (To put leads into a campaign instead, use import_leads_to_campaign.) A contact CSV can also carry the company columns: map them to the company-prefixed keys (companyName, companyDomain, …) and the company is created and linked in the same pass. Flow (3 steps, in order): 1. create_upload_url → get an uploadUrl + uploadKey 2. PUT the raw CSV to uploadUrl 3. this tool with the uploadKey Contract rules reproduced by the backend: - the list must exist, hold this entity type, and not be dynamic (filter-driven lists are filled by their own sync) - uploadKey must come from create_upload_url; a made-up key is rejected - at least one column must be mapped, and no mapping may target a reserved key (_id, teamId, …) - a "customField" target only lands if that custom field already exists on the team - every imported entity — created, updated or unchanged — is added to the list A target that matches no field is re-resolved server-side from the header and a sample value (so an export header like companyWebsite still fills companyDomain). Whatever it corrects comes back as repairedColumns; anything it cannot place comes back as ignoredColumns — those columns were NOT imported, so check them before reporting success.

NameTypeRequiredDescription
columnMappingobjectrequiredMaps each CSV header to the field it fills: { "CSV header": "fieldKey" }. Valid fieldKeys come from get_contact_fields_schema (csvImportTargets). Use "customField" to store a column in the custom field named after that header. Columns left out of the map are not imported.
listIdstringrequiredTarget list ID (clt_xxx format). Get it from get_contact_lists.
uploadKeystringrequireduploadKey returned by create_upload_url. The CSV must already be uploaded.
upsertModestringoptionalHow existing entities are handled: "createAndUpdate" (default) creates new ones and updates matches, "createOnly" skips matches, "updateOnly" only updates and creates nothing.
lemlistmcp_import_leads_to_campaign#Import leads into a campaign from a CSV uploaded with create_upload_url — the fast path for files of hundreds/thousands of leads (no lead data passes through the conversation). Flow: 1. create_upload_url({ purpose: "leadsCsv", fileName, fileSize }) → uploadUrl + uploadKey 2. PUT the file to uploadUrl (curl -T) 3. import_leads_to_campaign({ campaignId, uploadKey, columnMapping }) columnMapping maps each CSV header to a lead field (read the file's header row to build it). The server downloads, parses, dedups, optionally enriches, and bulk-inserts in one pass, then returns compact counters ({ total, added, updated, skipped, failed }) plus a capped list of failure rows — NOT the full list of imported leads. ⚠️ Credit cost, charged only on success — a lookup that returns nothing costs 0: findEmail 5 per email found, linkedinEnrichment 1 per profile enriched, findPhone 20 per phone number found, verifyEmail 1 per email verified. Multiply by the number of imported rows to quote a maximum before enabling them.9 params

Import leads into a campaign from a CSV uploaded with create_upload_url — the fast path for files of hundreds/thousands of leads (no lead data passes through the conversation). Flow: 1. create_upload_url({ purpose: "leadsCsv", fileName, fileSize }) → uploadUrl + uploadKey 2. PUT the file to uploadUrl (curl -T) 3. import_leads_to_campaign({ campaignId, uploadKey, columnMapping }) columnMapping maps each CSV header to a lead field (read the file's header row to build it). The server downloads, parses, dedups, optionally enriches, and bulk-inserts in one pass, then returns compact counters ({ total, added, updated, skipped, failed }) plus a capped list of failure rows — NOT the full list of imported leads. ⚠️ Credit cost, charged only on success — a lookup that returns nothing costs 0: findEmail 5 per email found, linkedinEnrichment 1 per profile enriched, findPhone 20 per phone number found, verifyEmail 1 per email verified. Multiply by the number of imported rows to quote a maximum before enabling them.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign ID (starts with cam_)
columnMappingobjectrequiredCSV header → target lead field, e.g. {"Email pro":"email","LinkedIn":"linkedinUrl"}. Targets: built-in fields, any custom variable name, or "customField". Unmapped columns are ignored.
uploadKeystringrequiredStorage key returned by create_upload_url (purpose="leadsCsv").
deduplicatebooleanoptionalAvoid duplicates across campaigns (default: false).
findEmailbooleanoptionalCOSTS CREDITS: Find email address from other lead data.
findPhonebooleanoptionalCOSTS CREDITS: Find phone number from other lead data.
linkedinEnrichmentbooleanoptionalCOSTS CREDITS: Enrich each lead with LinkedIn profile data.
maxRowsnumberoptionalMax rows to import (default 10000, capped at 40000).
verifyEmailbooleanoptionalCOSTS CREDITS: Verify the email address is valid.
lemlistmcp_list_campaign_folders#List all campaign folders for the current team, with their hierarchy (parentId). Use when the user asks about: - Seeing their campaign folder structure. - Finding a folder's ID before renaming / moving / deleting it, or before filing campaigns into it. The hierarchy is expressed by `parentId` (absent = root-level folder).0 params

List all campaign folders for the current team, with their hierarchy (parentId). Use when the user asks about: - Seeing their campaign folder structure. - Finding a folder's ID before renaming / moving / deleting it, or before filing campaigns into it. The hierarchy is expressed by `parentId` (absent = root-level folder).

lemlistmcp_list_domains#List all domains owned by the team (registrar, status, mailbox count). Use to audit the team's existing sending surface before proposing new purchases in the outreach-infra skill.0 params

List all domains owned by the team (registrar, status, mailbox count). Use to audit the team's existing sending surface before proposing new purchases in the outreach-infra skill.

lemlistmcp_list_mailboxes#List the team's mailboxes with their IDs (dem_xxx), email, status, and currently assigned SDR (assignedToUserId). Optionally filter by domainId. Use to audit which user owns each mailbox — and as the discovery step before `update_mailbox` when the user wants to re-assign mailboxes (e.g. when an outreach infrastructure was provisioned without per-SDR `assignToUser` and every mailbox ended up on the API key owner). Each mailbox also carries a deterministic `ageDays` (no date math needed), and the response includes a `providerMix` summary { google, microsoft, smtp, total, smtpSharePct, smtpHeavy } where `smtpHeavy` is true when SMTP > 70% (structurally disadvantaged). Trust these computed fields.1 param

List the team's mailboxes with their IDs (dem_xxx), email, status, and currently assigned SDR (assignedToUserId). Optionally filter by domainId. Use to audit which user owns each mailbox — and as the discovery step before `update_mailbox` when the user wants to re-assign mailboxes (e.g. when an outreach infrastructure was provisioned without per-SDR `assignToUser` and every mailbox ended up on the API key owner). Each mailbox also carries a deterministic `ageDays` (no date math needed), and the response includes a `providerMix` summary { google, microsoft, smtp, total, smtpSharePct, smtpHeavy } where `smtpHeavy` is true when SMTP > 70% (structurally disadvantaged). Trust these computed fields.

NameTypeRequiredDescription
domainIdstringoptionalOptional domain ID (dom_xxx) to scope the listing to one domain
lemlistmcp_list_people_database_personas#List the People Database personas saved by the current team. A persona is a named, reusable set of People Database filters (an audience definition). Call this FIRST whenever a persona id is needed — a persona id (pdp_xxx) can only be obtained from this tool or from create_people_database_persona. Use when the user asks about: - Which personas / saved audiences the team has - Applying "our ICP" or a persona by name (resolve the name to its id here) - Picking the persona to attach to another resource Each entry returns _id, name, mode, filters, createdAt and updatedAt.1 param

List the People Database personas saved by the current team. A persona is a named, reusable set of People Database filters (an audience definition). Call this FIRST whenever a persona id is needed — a persona id (pdp_xxx) can only be obtained from this tool or from create_people_database_persona. Use when the user asks about: - Which personas / saved audiences the team has - Applying "our ICP" or a persona by name (resolve the name to its id here) - Picking the persona to attach to another resource Each entry returns _id, name, mode, filters, createdAt and updatedAt.

NameTypeRequiredDescription
modestringoptionalRestrict to personas of one mode. Omit to return every persona of the team.
lemlistmcp_list_voice_profiles#List the AI voice profiles available for LinkedIn AI voice note steps (recordMode="ai"): lemlist default voices and the team's own cloned voices. Use this BEFORE setting a voice on a linkedinVoiceNote step. Pass the returned `voiceId` to add_sequence_step (or in a propose_sequence step) together with recordMode="ai" and the script in `message`. Only ids returned here are accepted; a voiceId from another team is rejected.0 params

List the AI voice profiles available for LinkedIn AI voice note steps (recordMode="ai"): lemlist default voices and the team's own cloned voices. Use this BEFORE setting a voice on a linkedinVoiceNote step. Pass the returned `voiceId` to add_sequence_step (or in a propose_sequence step) together with recordMode="ai" and the script in `message`. Only ids returned here are accepted; a voiceId from another team is rejected.

lemlistmcp_list_watch_list_filters#Return, for each watch list type, the filters is allowed to set. Each filter entry includes: - filterId (e.g. "title", "companyIndustries", "location") - name (human-readable label) - properties: which sides (in / out) the form exposes for this filter - required (optional): sides that must be non-empty for the watch list to be valid - requiresQuery (optional): when true, get_watch_list_filter_value MUST be called with a query for this filter; when absent/false, omit the query to get the full set Use BEFORE create_watch_list or update_watch_list to pick valid filterId values and to know which "in"/"out" sides to populate. Omit "type" to get the matrix for all types.1 param

Return, for each watch list type, the filters is allowed to set. Each filter entry includes: - filterId (e.g. "title", "companyIndustries", "location") - name (human-readable label) - properties: which sides (in / out) the form exposes for this filter - required (optional): sides that must be non-empty for the watch list to be valid - requiresQuery (optional): when true, get_watch_list_filter_value MUST be called with a query for this filter; when absent/false, omit the query to get the full set Use BEFORE create_watch_list or update_watch_list to pick valid filterId values and to know which "in"/"out" sides to populate. Omit "type" to get the matrix for all types.

NameTypeRequiredDescription
typestringoptionalRestrict to a single signal type. Omit to return filters for all types.
lemlistmcp_list_watch_list_library#List the catalog of watch list signal types available on the platform. Use BEFORE create_watch_list to: - know which "type" values are valid (e.g. "companyIsHiring", "jobChange", "linkedinKeywords") - understand what each type monitors (title, description) Each entry includes type, title and description.0 params

List the catalog of watch list signal types available on the platform. Use BEFORE create_watch_list to: - know which "type" values are valid (e.g. "companyIsHiring", "jobChange", "linkedinKeywords") - understand what each type monitors (title, description) Each entry includes type, title and description.

lemlistmcp_list_watch_list_signals#List the signals captured by watch lists for the current team, with filtering and pagination. Use when the user asks about: - Reviewing newly received signals - Filtering signals by type, status, watch list, or date range - Paginating through historical signals Each signal includes its watch list, type, computed status, received date, and the enriched entity (contact or company).9 params

List the signals captured by watch lists for the current team, with filtering and pagination. Use when the user asks about: - Reviewing newly received signals - Filtering signals by type, status, watch list, or date range - Paginating through historical signals Each signal includes its watch list, type, computed status, received date, and the enriched entity (contact or company).

NameTypeRequiredDescription
limitintegeroptionalMax signals per page (default 50, max 100)
pageintegeroptionalPage number (1-based, default 1)
receivedAtFromstringoptionalInclude signals received on/after this ISO 8601 datetime (with timezone offset)
receivedAtTostringoptionalInclude signals received on/before this ISO 8601 datetime (with timezone offset)
sortBystringoptionalField to sort by (default: receivedAt)
sortOrderstringoptionalSort direction (default: desc)
statusstringoptionalComma-separated list of computed statuses to filter. Accepted values: new, old, handled, ignored.
typestringoptionalComma-separated list of signal types to filter (e.g. "companyIsHiring,jobChange"). Accepted values: companyIsHiring, companyRaisedFunds, jobChange, newHire, companyEmployeeVisitedMyWebsite, linkedinProfile, linkedinTopic, customSignals, competitorConnections, technologyChange, linkedinPeopleProfile, linkedinCompanyProfile, mergersAcquisitions, promotion, linkedinKeywords, externalSignalContact, externalSignalCompany.
watchListIdstringoptionalScope results to a single watch list (wat_xxx format)
lemlistmcp_list_watch_lists#List watch lists for the current team with optional type, status, and pagination filters.4 params

List watch lists for the current team with optional type, status, and pagination filters.

NameTypeRequiredDescription
limitintegeroptionalMax watch lists per page (default 50, max 100)
pageintegeroptionalPage number (1-based, default 1)
statusstringoptionalComma-separated list of statuses to filter. Accepted values: active, inactive, draft, insufficient_credits, empty_crm_lists, error. Excludes soft-deleted by default.
typestringoptionalComma-separated list of watch list types (e.g. "companyIsHiring,jobChange")
lemlistmcp_load_skill#Load specialized guidance for a specific domain (e.g. campaign-builder, api-reference) to assist with complex tasks.2 params

Load specialized guidance for a specific domain (e.g. campaign-builder, api-reference) to assist with complex tasks.

NameTypeRequiredDescription
skillNamestringrequiredName of the skill to load
sectionstringoptionalOptional: specific reference section to load
lemlistmcp_move_campaign_folder#Move a campaign folder (and its whole subtree) under a different parent folder, or to the root. Use when the user asks about: - Reorganizing their folder hierarchy. - Moving a folder out of its current parent (omit newParentId for the root). Contract rules reproduced by the backend: - A folder cannot be moved into itself or one of its own sub-folders. - The resulting depth must stay within 15 levels, and the target level within 50 folders. - The folder name must stay unique at the target level.2 params

Move a campaign folder (and its whole subtree) under a different parent folder, or to the root. Use when the user asks about: - Reorganizing their folder hierarchy. - Moving a folder out of its current parent (omit newParentId for the root). Contract rules reproduced by the backend: - A folder cannot be moved into itself or one of its own sub-folders. - The resulting depth must stay within 15 levels, and the target level within 50 folders. - The folder name must stay unique at the target level.

NameTypeRequiredDescription
folderIdstringrequiredFolder ID (cfo_xxx) to move.
newParentIdstringoptionalTarget parent folder ID (cfo_xxx). Omit to move the folder to the root.
lemlistmcp_move_campaigns_to_folder#Move one or more campaigns into a folder, or out to the root (the drag-and-drop equivalent). Use when the user asks about: - Filing campaigns into a folder. - Taking campaigns out of a folder (omit folderId to move them to the root). Contract rules reproduced by the backend: - Only campaigns owned by the current team are moved; unknown ids are skipped.2 params

Move one or more campaigns into a folder, or out to the root (the drag-and-drop equivalent). Use when the user asks about: - Filing campaigns into a folder. - Taking campaigns out of a folder (omit folderId to move them to the root). Contract rules reproduced by the backend: - Only campaigns owned by the current team are moved; unknown ids are skipped.

NameTypeRequiredDescription
campaignIdsarrayrequiredCampaign IDs (cam_xxx) to move (1-100). Pass every campaign in one call.
folderIdstringoptionalTarget folder ID (cfo_xxx) to file the campaigns into. Omit to move them out to the root.
lemlistmcp_people_database_search_count#Use ONLY in the People Database scope. Return the exact number of People Database documents (leads or companies) that match a set of filters, without returning the documents themselves. Use it when: - The user asks how many people or companies match a set of criteria. - To refine a set of filters after people_database_nl_to_filters. - To size an audience before running a full search or building a campaign. - To compare how restrictive two filter sets are. Every filterId must be an exact id returned by people_database_nl_to_filters.2 params

Use ONLY in the People Database scope. Return the exact number of People Database documents (leads or companies) that match a set of filters, without returning the documents themselves. Use it when: - The user asks how many people or companies match a set of criteria. - To refine a set of filters after people_database_nl_to_filters. - To size an audience before running a full search or building a campaign. - To compare how restrictive two filter sets are. Every filterId must be an exact id returned by people_database_nl_to_filters.

NameTypeRequiredDescription
filtersarrayrequiredThe People Database query — the same "filters" array people_database_nl_to_filters returns. Each filter needs at least one in/out value.
modestringrequiredSearch mode: 'leads' for people/contacts, 'companies' for companies. Must match the mode the filters were built for.
lemlistmcp_preview_email#Preview how an email step renders for a SPECIFIC lead. Compiles a sequence step's subject + body for one lead: the lead's {{variables}} are substituted and Liquid conditionals ({% if jobTitle contains "Founder" %}...{% endif %}) are evaluated, exactly like the lemlist UI email preview. Use when the user asks to: - See the final email a given lead will receive - Check how variables / Liquid resolve for a real lead - Spot empty variables or broken Liquid before sending Read-only: no credits consumed, nothing is sent. The lead's campaign is inferred from the lead unless campaignId is passed to override it.3 params

Preview how an email step renders for a SPECIFIC lead. Compiles a sequence step's subject + body for one lead: the lead's {{variables}} are substituted and Liquid conditionals ({% if jobTitle contains "Founder" %}...{% endif %}) are evaluated, exactly like the lemlist UI email preview. Use when the user asks to: - See the final email a given lead will receive - Check how variables / Liquid resolve for a real lead - Spot empty variables or broken Liquid before sending Read-only: no credits consumed, nothing is sent. The lead's campaign is inferred from the lead unless campaignId is passed to override it.

NameTypeRequiredDescription
leadIdstringrequiredThe lead ID (lea_xxx format) whose variables are used to compile the email
stepIdstringrequiredThe sequence step ID (stp_xxx format) whose subject + message are compiled
campaignIdstringoptionalOptional campaign ID (cam_xxx format). Defaults to the lead's own campaign; only pass it to override.
lemlistmcp_preview_sequence_update#SAFE READ-ONLY: Preview what would change in an email sequence step before applying modifications. Shows current vs proposed content and campaign status. Must call this before update_sequence_step.5 params

SAFE READ-ONLY: Preview what would change in an email sequence step before applying modifications. Shows current vs proposed content and campaign status. Must call this before update_sequence_step.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx)
sequenceIdstringrequiredSequence ID (seq_xxx)
stepIdstringrequiredStep ID (stp_xxx)
newMessagestringoptionalProposed new message body
newSubjectstringoptionalProposed new subject line
lemlistmcp_propose_sequence#Propose a sequence with full tree structure for user review. Displays visual tree in workspace. To update an existing sequence: get_workspace_items → propose_sequence with replaceItemId. Format: provide an array of sequences. The main sequence contains the root steps. Conditional steps reference sub-sequences by ID via their "conditions" array. Example with condition: - sequences: [ { _id: "seq_main", steps: [{ _id: "s1", type: "email", delay: 0, name: "Initial email" }, { _id: "s2", type: "conditional", delay: 3, delayType: "within", conditions: [{ sequenceId: "seq_yes", key: "emailsOpened", label: "Opened" }, { sequenceId: "seq_no", fallback: true, label: "Not opened" }] }] }, { _id: "seq_yes", steps: [{ _id: "s3", type: "linkedinSend", delay: 2, name: "LinkedIn follow-up" }] }, { _id: "seq_no", steps: [{ _id: "s4", type: "email", delay: 3, name: "Reminder email", subject: "Following up" }] } ] - mainSequenceId: "seq_main" CRITICAL RULES: - TREE STRUCTURE ONLY: each sub-sequence must be referenced by exactly ONE condition branch. NEVER reuse the same sequenceId in multiple conditions. If two branches need similar steps, duplicate the sub-sequence with different IDs (e.g. "seq_breakup_1", "seq_breakup_2"). - BRANCH CONVERGENCE: to converge multiple branches on a common closing step (e.g. an "Email Breakup"), place that step AFTER the conditional in the PARENT sequence — do NOT duplicate it in every branch. The engine resumes the lead at the parent's next step when a sub-sequence ends. Example: seq_main = [email, conditional(YES->seq_engaged, NO->seq_breakup), email "Final goodbye"] — the final email runs for both branches. - Max 10 levels of nested conditions (a conditional inside a sub-sequence of another conditional, chained up to 10 deep). Nest as deep as the campaign logic genuinely needs within that ceiling; prefer a flatter structure when it expresses the same flow. EDITING AN EXISTING CAMPAIGN (desired-state): when the user asks to review/edit a campaign you already have context for, the proposal must be the FULL intended sequence — describe what the campaign should look like AFTER the edit: - Keep a step: include it with `existing: true` and `sourceStepId` set to its real id (the "id:" shown in get_campaign_context). Do NOT recompose its message — its content is preserved automatically. - Replace a step: same `existing: true` + `sourceStepId`, plus the new content (bind a messageId via compose_messages) and/or a changed `delay`. - Add a step: include it with NO `existing` flag (a brand-new step), at the position you want. - Remove a step: simply OMIT it from the proposal (any live step you don't reference is deleted). On a DRAFT campaign with no launched leads, the full set of edits above is applied. On a RUNNING/PAUSED or lead-populated campaign, only non-destructive edits are accepted: you may replace a step's content and APPEND new steps after the last existing step, but you must keep every existing step (reference each with `existing: true` + `sourceStepId`) and may NOT insert a step between existing ones or remove one — for those, use add_sequence_step (with an explicit index) or delete_sequence_step. Condition types — every conditional step ALWAYS requires `delay`, `delayType` and a non-fallback branch with `key`: - Field-check (hasEmailAddress, hasLinkedinUrl, hasPhoneNumber): check lead data instantly. Use `delayType: "within"` and `delay: 0`. - Action (hasScore, emailsOpened, emailsClicked, emailsUnsubscribed, meetingBooked, linkedinInviteAccepted, linkedinOpened, aircallDone): track lead behavior over time. Use `delayType: "within"` (must occur within `delay` days) or `delayType: "waitUntil"` (wait indefinitely). - Async (linkedinNetworkCheck, hasWhatsappAccount): external API check. Use `delayType: "within"` and `delay: 0`. Step types: email (needs subject), linkedinVisit, linkedinFollow, linkedinInvite, linkedinLikeLastPost, linkedinCommentLastPost (AI-generated comment on the lead's last LinkedIn post; user reviews via Opportunity before publish), linkedinSend, linkedinEndorse, linkedinVoiceNote (LinkedIn voice message. recordMode = how the audio is produced, manual = the "Mark as manual" toggle, independent of each other. recordMode="ai" generates the audio from a composed script via ElevenLabs (also set a voiceId via list_voice_profiles). When no AI voice is available, set `manual: true` so the step becomes a per-lead recording task and the campaign stays launchable - do NOT compose a script or set a voiceId for it), phone, sms, whatsappMessage, manual, conditional, enrichment (⚠️ COSTS CREDITS: automatically enriches leads at this step; provide workflowIds, e.g. ["find_email_01", "find_phone_01"]; requires MULTI plan).5 params

Propose a sequence with full tree structure for user review. Displays visual tree in workspace. To update an existing sequence: get_workspace_items → propose_sequence with replaceItemId. Format: provide an array of sequences. The main sequence contains the root steps. Conditional steps reference sub-sequences by ID via their "conditions" array. Example with condition: - sequences: [ { _id: "seq_main", steps: [{ _id: "s1", type: "email", delay: 0, name: "Initial email" }, { _id: "s2", type: "conditional", delay: 3, delayType: "within", conditions: [{ sequenceId: "seq_yes", key: "emailsOpened", label: "Opened" }, { sequenceId: "seq_no", fallback: true, label: "Not opened" }] }] }, { _id: "seq_yes", steps: [{ _id: "s3", type: "linkedinSend", delay: 2, name: "LinkedIn follow-up" }] }, { _id: "seq_no", steps: [{ _id: "s4", type: "email", delay: 3, name: "Reminder email", subject: "Following up" }] } ] - mainSequenceId: "seq_main" CRITICAL RULES: - TREE STRUCTURE ONLY: each sub-sequence must be referenced by exactly ONE condition branch. NEVER reuse the same sequenceId in multiple conditions. If two branches need similar steps, duplicate the sub-sequence with different IDs (e.g. "seq_breakup_1", "seq_breakup_2"). - BRANCH CONVERGENCE: to converge multiple branches on a common closing step (e.g. an "Email Breakup"), place that step AFTER the conditional in the PARENT sequence — do NOT duplicate it in every branch. The engine resumes the lead at the parent's next step when a sub-sequence ends. Example: seq_main = [email, conditional(YES->seq_engaged, NO->seq_breakup), email "Final goodbye"] — the final email runs for both branches. - Max 10 levels of nested conditions (a conditional inside a sub-sequence of another conditional, chained up to 10 deep). Nest as deep as the campaign logic genuinely needs within that ceiling; prefer a flatter structure when it expresses the same flow. EDITING AN EXISTING CAMPAIGN (desired-state): when the user asks to review/edit a campaign you already have context for, the proposal must be the FULL intended sequence — describe what the campaign should look like AFTER the edit: - Keep a step: include it with `existing: true` and `sourceStepId` set to its real id (the "id:" shown in get_campaign_context). Do NOT recompose its message — its content is preserved automatically. - Replace a step: same `existing: true` + `sourceStepId`, plus the new content (bind a messageId via compose_messages) and/or a changed `delay`. - Add a step: include it with NO `existing` flag (a brand-new step), at the position you want. - Remove a step: simply OMIT it from the proposal (any live step you don't reference is deleted). On a DRAFT campaign with no launched leads, the full set of edits above is applied. On a RUNNING/PAUSED or lead-populated campaign, only non-destructive edits are accepted: you may replace a step's content and APPEND new steps after the last existing step, but you must keep every existing step (reference each with `existing: true` + `sourceStepId`) and may NOT insert a step between existing ones or remove one — for those, use add_sequence_step (with an explicit index) or delete_sequence_step. Condition types — every conditional step ALWAYS requires `delay`, `delayType` and a non-fallback branch with `key`: - Field-check (hasEmailAddress, hasLinkedinUrl, hasPhoneNumber): check lead data instantly. Use `delayType: "within"` and `delay: 0`. - Action (hasScore, emailsOpened, emailsClicked, emailsUnsubscribed, meetingBooked, linkedinInviteAccepted, linkedinOpened, aircallDone): track lead behavior over time. Use `delayType: "within"` (must occur within `delay` days) or `delayType: "waitUntil"` (wait indefinitely). - Async (linkedinNetworkCheck, hasWhatsappAccount): external API check. Use `delayType: "within"` and `delay: 0`. Step types: email (needs subject), linkedinVisit, linkedinFollow, linkedinInvite, linkedinLikeLastPost, linkedinCommentLastPost (AI-generated comment on the lead's last LinkedIn post; user reviews via Opportunity before publish), linkedinSend, linkedinEndorse, linkedinVoiceNote (LinkedIn voice message. recordMode = how the audio is produced, manual = the "Mark as manual" toggle, independent of each other. recordMode="ai" generates the audio from a composed script via ElevenLabs (also set a voiceId via list_voice_profiles). When no AI voice is available, set `manual: true` so the step becomes a per-lead recording task and the campaign stays launchable - do NOT compose a script or set a voiceId for it), phone, sms, whatsappMessage, manual, conditional, enrichment (⚠️ COSTS CREDITS: automatically enriches leads at this step; provide workflowIds, e.g. ["find_email_01", "find_phone_01"]; requires MULTI plan).

NameTypeRequiredDescription
mainSequenceIdstringrequiredID of the root/main sequence
sequencesarrayrequiredAll sequences. Main sequence + sub-sequences for conditional branches.
namestringoptionalName for this sequence
replaceItemIdstringoptionalID of an existing sequence item to update (from get_workspace_items). Reuse it to modify a sequence instead of creating a new tab.
skipPlanbooleanoptionalSet to true ONLY when the user explicitly asked to skip the campaign plan and go straight to the sequence. It waives the plan-first requirement for a brand-new campaign. Leave unset otherwise — the default flow presents a display_document strategy brief first.
lemlistmcp_provision_mailboxes#Create mailbox orders on a team-owned domain. Call this IMMEDIATELY after purchase_domain for each domain — do not wait for the domain to become Active first. The mailbox type is locked by the domain's provider (set at purchase and irreversible): - "google" domain → Google Workspace mailboxes only - "m365" domain → Microsoft 365 mailboxes only - "infraforge" domain → SMTP mailboxes only Both domain and mailbox orders are processed asynchronously by background cron jobs (Ordered → Paid → Registered → Pending → Active). This can take minutes to hours (M365: up to 2 days). After calling this tool, tell the user to wait until their domains show as Active before proceeding with DNS configuration. **DESTRUCTIVE — IRREVERSIBLE CHARGE.** Creates real mailbox orders and bills the team. Only call after the user has explicitly confirmed the full infrastructure plan. Returns `{ added, mailboxes: [{ _id, email, assignToUser }] }` — keep the `_id` (`dem_xxx`) of each created mailbox if any later `update_mailbox` call is anticipated (e.g. recovery, re-assignment).2 params

Create mailbox orders on a team-owned domain. Call this IMMEDIATELY after purchase_domain for each domain — do not wait for the domain to become Active first. The mailbox type is locked by the domain's provider (set at purchase and irreversible): - "google" domain → Google Workspace mailboxes only - "m365" domain → Microsoft 365 mailboxes only - "infraforge" domain → SMTP mailboxes only Both domain and mailbox orders are processed asynchronously by background cron jobs (Ordered → Paid → Registered → Pending → Active). This can take minutes to hours (M365: up to 2 days). After calling this tool, tell the user to wait until their domains show as Active before proceeding with DNS configuration. **DESTRUCTIVE — IRREVERSIBLE CHARGE.** Creates real mailbox orders and bills the team. Only call after the user has explicitly confirmed the full infrastructure plan. Returns `{ added, mailboxes: [{ _id, email, assignToUser }] }` — keep the `_id` (`dem_xxx`) of each created mailbox if any later `update_mailbox` call is anticipated (e.g. recovery, re-assignment).

NameTypeRequiredDescription
domainIdstringrequiredDomain ID (dom_xxx)
emailsarrayrequiredMailboxes to create
lemlistmcp_purchase_domain#Purchase (or transfer) a domain at the registrar. Charges the team via Stripe. **DESTRUCTIVE — IRREVERSIBLE CHARGE.** Only call after the user has explicitly confirmed the full infrastructure plan (Step 7 of the outreach-infra skill). The plan must include price, provider, and any pre-set DNS records. **CRITICAL: The provider locks the mailbox type for this domain permanently.** A domain purchased with "google" can ONLY have Google Workspace mailboxes. A domain purchased with "m365" can ONLY have Microsoft 365 mailboxes. A domain purchased with "infraforge" can ONLY have SMTP mailboxes. This choice is irreversible — you cannot change the provider after purchase. Choose carefully based on the ESP split from calculate_infrastructure. **Registrant contact:** the registrar requires a billing/registrant contact. On the team's FIRST purchase, pass `billingContact` (collected from the user). It is stored on the team and reused for later domains, so omit it once set. Purchasing without a contact (and none stored) fails with a clear error.6 params

Purchase (or transfer) a domain at the registrar. Charges the team via Stripe. **DESTRUCTIVE — IRREVERSIBLE CHARGE.** Only call after the user has explicitly confirmed the full infrastructure plan (Step 7 of the outreach-infra skill). The plan must include price, provider, and any pre-set DNS records. **CRITICAL: The provider locks the mailbox type for this domain permanently.** A domain purchased with "google" can ONLY have Google Workspace mailboxes. A domain purchased with "m365" can ONLY have Microsoft 365 mailboxes. A domain purchased with "infraforge" can ONLY have SMTP mailboxes. This choice is irreversible — you cannot change the provider after purchase. Choose carefully based on the ESP split from calculate_infrastructure. **Registrant contact:** the registrar requires a billing/registrant contact. On the team's FIRST purchase, pass `billingContact` (collected from the user). It is stored on the team and reused for later domains, so omit it once set. Purchasing without a contact (and none stored) fails with a clear error.

NameTypeRequiredDescription
domainstringrequiredDomain to purchase
providerstringrequiredLocks the mailbox type permanently: "google" = Google Workspace only, "m365" = Microsoft 365 only, "infraforge" = SMTP only. Irreversible.
authCodestringoptionalTransfer auth code (if isTransfer)
billingContactobjectoptionalDomain registrant/billing contact. Required on the team's first purchase (the registrar needs it); stored and reused afterwards, so omit it once set. Providing it overwrites the existing contact.
dnsRecordsarrayoptionalOptional initial DNS records
isTransferbooleanoptionalTransfer an existing domain instead of registering
lemlistmcp_push_leads_to_contacts#Push leads from the People Database into your CRM contacts, optionally adding them to a contact list.3 params

Push leads from the People Database into your CRM contacts, optionally adding them to a contact list.

NameTypeRequiredDescription
profileIdsarrayrequiredPeople Database lead IDs to push to contacts (max 1,000)
enrichFeaturesarrayoptional⚠️ COSTS CREDITS: Enrichment features to apply when pushing leads
listIdstringoptionalTarget contact list ID in clt_xxx format. Omit to push to "all contacts". Get valid IDs from get_contact_lists — never invent or pass aliases like "all".
lemlistmcp_recall_memory#Retrieve stored memories from previous conversations to restore context about user preferences or past decisions.1 param

Retrieve stored memories from previous conversations to restore context about user preferences or past decisions.

NameTypeRequiredDescription
topicstringoptionalExact topic key to retrieve (e.g. "preferred_tone"). Omit to retrieve all memories.
lemlistmcp_remove_contacts_from_list#Remove existing CRM contacts from a contact list. **When to use:** - User wants to take contacts out of a list (e.g. clean up duplicates, drop a wrong segment) - After searching a list with search_contacts (listId filter), user wants to remove a subset **Parameters:** - contactIds: Contact IDs in ctc_xxx format (required, max 1,000) - listId: Contact list ID in clt_xxx format to remove them from (required) **IMPORTANT:** - This removes list membership ONLY. It does NOT delete the contacts themselves. - To get the contacts currently in a list, call search_contacts with that listId, then keep the ones to remove (e.g. those without a LinkedIn URL) and pass their ids here. - To get a valid listId, call get_contact_lists first — never invent or guess a list ID. - Contacts that are not in the list are silently skipped (no error). - The list must be a static contact list; you cannot manually remove from a dynamic list. **Example:** { "contactIds": ["ctc_abc123", "ctc_def456"], "listId": "clt_xyz789" }2 params

Remove existing CRM contacts from a contact list. **When to use:** - User wants to take contacts out of a list (e.g. clean up duplicates, drop a wrong segment) - After searching a list with search_contacts (listId filter), user wants to remove a subset **Parameters:** - contactIds: Contact IDs in ctc_xxx format (required, max 1,000) - listId: Contact list ID in clt_xxx format to remove them from (required) **IMPORTANT:** - This removes list membership ONLY. It does NOT delete the contacts themselves. - To get the contacts currently in a list, call search_contacts with that listId, then keep the ones to remove (e.g. those without a LinkedIn URL) and pass their ids here. - To get a valid listId, call get_contact_lists first — never invent or guess a list ID. - Contacts that are not in the list are silently skipped (no error). - The list must be a static contact list; you cannot manually remove from a dynamic list. **Example:** { "contactIds": ["ctc_abc123", "ctc_def456"], "listId": "clt_xyz789" }

NameTypeRequiredDescription
contactIdsarrayrequiredContact IDs to remove from the list (max 1,000)
listIdstringrequiredContact list ID in clt_xxx format to remove the contacts from. Get valid IDs from get_contact_lists.
lemlistmcp_rename_campaign_folder#Rename a campaign folder and/or change its color. Use when the user asks about: - Renaming a folder. - Changing a folder's color. Contract rules reproduced by the backend: - The new name must be unique among folders that share the same parent.3 params

Rename a campaign folder and/or change its color. Use when the user asks about: - Renaming a folder. - Changing a folder's color. Contract rules reproduced by the backend: - The new name must be unique among folders that share the same parent.

NameTypeRequiredDescription
folderIdstringrequiredFolder ID (cfo_xxx) to update.
colorstringoptionalNew folder color (hex).
namestringoptionalNew folder name. Must stay unique among folders sharing the same parent.
lemlistmcp_report_unsupported_case#Report a feature request or unsupported use case to the product team. Use this ONLY when the user's request is something lemlist should support but the copilot cannot do yet, AND the user has agreed to have their feedback reported. Do NOT use for off-topic requests unrelated to lemlist. Always provide inputs in English, translate if needed.2 params

Report a feature request or unsupported use case to the product team. Use this ONLY when the user's request is something lemlist should support but the copilot cannot do yet, AND the user has agreed to have their feedback reported. Do NOT use for off-topic requests unrelated to lemlist. Always provide inputs in English, translate if needed.

NameTypeRequiredDescription
descriptionstringrequiredWhat the user asked for that is not supported yet (MUST be in English)
conversationContextstringoptionalBrief summary of the conversation context leading to this request (MUST be in English)
lemlistmcp_run_deliverability_audit#Run the full deliverability audit for the current team and return the complete structured report (header, every phase, verdict). This IS the deliverability playbook — the same deterministic engine the lemgod audit page runs, so both surfaces always agree on the same account. Use when the user wants to: - Audit an account's deliverability, or diagnose why open/reply rates dropped or emails land in spam (the deliverability-audit skill) - Get a health check of a sending setup (DNS, warmup, sending volume, content, targeting) The report is READ-ONLY: it never modifies a mailbox, domain, or campaign, and sends nothing. It contains: - header: team, mailbox/domain/campaign counts, account age, lemwarm usage - phases: one result per phase (triage, technical, sending stats, campaign settings, content, warmup), each with a status (ok / minor / broken / skipped) and concrete findings - verdict: root cause, ranked actions, optional recovery plan, and a prose summary Contract rules reproduced by the backend: - All phases always run (no early bail-out); a phase that cannot run returns status "skipped" with a reason — never fabricate data for it. - The verdict's root cause, severity, ranked actions, and recovery plan are computed deterministically; trust them and present them, do not re-derive the thresholds. - Phase 6 (inbox placement) is NOT part of this tool — it sends a real email and is a separate, explicitly-confirmed action (run_inbox_placement_test).0 params

Run the full deliverability audit for the current team and return the complete structured report (header, every phase, verdict). This IS the deliverability playbook — the same deterministic engine the lemgod audit page runs, so both surfaces always agree on the same account. Use when the user wants to: - Audit an account's deliverability, or diagnose why open/reply rates dropped or emails land in spam (the deliverability-audit skill) - Get a health check of a sending setup (DNS, warmup, sending volume, content, targeting) The report is READ-ONLY: it never modifies a mailbox, domain, or campaign, and sends nothing. It contains: - header: team, mailbox/domain/campaign counts, account age, lemwarm usage - phases: one result per phase (triage, technical, sending stats, campaign settings, content, warmup), each with a status (ok / minor / broken / skipped) and concrete findings - verdict: root cause, ranked actions, optional recovery plan, and a prose summary Contract rules reproduced by the backend: - All phases always run (no early bail-out); a phase that cannot run returns status "skipped" with a reason — never fabricate data for it. - The verdict's root cause, severity, ranked actions, and recovery plan are computed deterministically; trust them and present them, do not re-derive the thresholds. - Phase 6 (inbox placement) is NOT part of this tool — it sends a real email and is a separate, explicitly-confirmed action (run_inbox_placement_test).

lemlistmcp_run_inbox_placement_test#Run an inbox placement (spam) test: send one email from a mailbox to ~25 seed inboxes across Google, Microsoft, and SMTP, to measure where it lands (inbox / promotions / spam) per provider. Use when the user wants to: - Test whether a campaign's content lands in spam (Phase 6 of the deliverability-audit skill) - Compare placement of two campaigns to quantify a content change - Diagnose a "Google fine but SMTP spam" content issue This SENDS A REAL EMAIL and consumes 100 credits. Confirm with the user first. Pull the real campaign subject + body (get_campaign_sequences / preview_email) so the test mirrors production content. The test is asynchronous: this returns a testId with state "pending". Poll get_inbox_placement_result with that testId until it reports "completed" to read the per-provider breakdown.5 params

Run an inbox placement (spam) test: send one email from a mailbox to ~25 seed inboxes across Google, Microsoft, and SMTP, to measure where it lands (inbox / promotions / spam) per provider. Use when the user wants to: - Test whether a campaign's content lands in spam (Phase 6 of the deliverability-audit skill) - Compare placement of two campaigns to quantify a content change - Diagnose a "Google fine but SMTP spam" content issue This SENDS A REAL EMAIL and consumes 100 credits. Confirm with the user first. Pull the real campaign subject + body (get_campaign_sequences / preview_email) so the test mirrors production content. The test is asynchronous: this returns a testId with state "pending". Poll get_inbox_placement_result with that testId until it reports "completed" to read the per-provider breakdown.

NameTypeRequiredDescription
messagestringrequiredEmail body to test (use the real campaign content)
subjectstringrequiredSubject line to test (use the real campaign subject)
userMailboxIdstringrequiredSender mailbox (usm_xxx) the test email is sent from — its reputation is what gets measured
campaignIdstringoptionalOptional campaign (cam_xxx) this test is linked to, for reporting
stepIdstringoptionalOptional sequence step (stp_xxx) the content comes from
lemlistmcp_save_business_context#Save the user business context for future conversations. Use this after collecting company information from the user to remember it across conversations.9 params

Save the user business context for future conversations. Use this after collecting company information from the user to remember it across conversations.

NameTypeRequiredDescription
companyNamestringrequiredCompany name
mainActivitystringoptionalWhat the company does
painPointsSolvedarrayoptionalPain points the company solves for customers
shortDescriptionstringoptionalCompany and offering summary
targetCompanySizesarrayoptionalTarget sizes (1-10, 11-50, etc.)
targetIndustriesarrayoptionalTarget industries
targetJobTitlesarrayoptionalTarget job titles
valuePropositionstringoptionalMain value proposition of the company
websiteUrlstringoptionalWebsite URL
lemlistmcp_save_memory#Save a piece of information to persistent memory so it can be recalled in future conversations.3 params

Save a piece of information to persistent memory so it can be recalled in future conversations.

NameTypeRequiredDescription
contentstringrequiredThe information to remember (max 5000 chars, in the user language)
topicstringrequiredUnique topic key in snake_case english (e.g. "preferred_tone", "icp_details", "campaign_naming")
scopestringoptionalScope: "user" (default, personal) or "team" (shared with all team members)
lemlistmcp_search_campaign_leads#Find leads in your campaigns by email, lead ID, or by listing all leads in a campaign.5 params

Find leads in your campaigns by email, lead ID, or by listing all leads in a campaign.

NameTypeRequiredDescription
campaignIdstringoptionalCampaign ID. Required when listing all leads (no email/id). Optional filter when searching by email/id.
emailstringoptionalLead email address to search for
idstringoptionalLead ID to search for (alternative to email)
limitnumberoptionalMax leads to return (default: 50, max: 100).
offsetnumberoptionalPagination offset (default: 0). Use nextOffset from a previous result to load more.
lemlistmcp_search_companies#Search your team's Lemlist companies. Returns a paginated list with each company's id, domain, name, owner, and a curated `crmSync` block describing how the record is synced to your active CRM (Hubspot, Salesforce, or Pipedrive). Use the `crmSyncStatus` filter to find companies in a specific sync state — most notably `unique_index_error_company` to list lemlist companies blocked from syncing because another lemlist company already occupies their CRM record. For each result in that state, look at `crmSync.errors[].metadata.alreadyExistingCompanyId` — that is the canonical lemlist company you should remap contacts to before deleting the duplicate (see `search_contacts` with companyId, then `delete_company`).6 params

Search your team's Lemlist companies. Returns a paginated list with each company's id, domain, name, owner, and a curated `crmSync` block describing how the record is synced to your active CRM (Hubspot, Salesforce, or Pipedrive). Use the `crmSyncStatus` filter to find companies in a specific sync state — most notably `unique_index_error_company` to list lemlist companies blocked from syncing because another lemlist company already occupies their CRM record. For each result in that state, look at `crmSync.errors[].metadata.alreadyExistingCompanyId` — that is the canonical lemlist company you should remap contacts to before deleting the duplicate (see `search_contacts` with companyId, then `delete_company`).

NameTypeRequiredDescription
crmSyncStatusstringoptionalFilter by CRM sync status. Requires a CRM (Hubspot, Salesforce, Pipedrive) to be connected on the team — otherwise the call returns NO_CRM_CONNECTED.
limitnumberoptionalMax companies per page (1-100, default 100).
pagenumberoptionalPage number (1-based, default 1).
searchstringoptionalFree-text search on the company name (case insensitive, accent insensitive).
sortBystringoptionalSort field (default `createdAt`).
sortOrderstringoptionalSort direction (default `desc`).
lemlistmcp_search_contacts#Search or list your team's Lemlist contacts by name, email, contact list, or attached company. Returns matching contacts with their details (ID, name, email, phone, job title, company, campaign count). All filters are optional — calling the tool without any filter returns the paginated list of all contacts of the team (useful for discovery, e.g. obtaining a Record ID before associating it with another resource). Use this to find if a contact already exists in Lemlist before creating a new one. You can filter by a specific contact list using listId (get valid IDs from get_contact_lists first). Use notInAnyCampaign=true to find contacts that are not part of any campaign (orphan contacts). To list contacts attached to a given company, use companyId (cpn_xxx) or one of companyDomain / companyLinkedinUrl / companySalesnavUrl — only one company* filter at a time. URL/domain filters return an empty list if no company matches. For searching leads WITHIN campaigns, use search_campaign_leads instead. For prospecting NEW leads from the People Database, use lemleads_search instead.10 params

Search or list your team's Lemlist contacts by name, email, contact list, or attached company. Returns matching contacts with their details (ID, name, email, phone, job title, company, campaign count). All filters are optional — calling the tool without any filter returns the paginated list of all contacts of the team (useful for discovery, e.g. obtaining a Record ID before associating it with another resource). Use this to find if a contact already exists in Lemlist before creating a new one. You can filter by a specific contact list using listId (get valid IDs from get_contact_lists first). Use notInAnyCampaign=true to find contacts that are not part of any campaign (orphan contacts). To list contacts attached to a given company, use companyId (cpn_xxx) or one of companyDomain / companyLinkedinUrl / companySalesnavUrl — only one company* filter at a time. URL/domain filters return an empty list if no company matches. For searching leads WITHIN campaigns, use search_campaign_leads instead. For prospecting NEW leads from the People Database, use lemleads_search instead.

NameTypeRequiredDescription
companyDomainstringoptionalFilter contacts by their company's website domain (resolved to a companyId). Empty list if no company matches.
companyIdstringoptionalFilter contacts by attached lemlist company ID (cpn_xxx). Mutually exclusive with companyDomain/companyLinkedinUrl/companySalesnavUrl.
companyLinkedinUrlstringoptionalFilter contacts by their company's LinkedIn URL (resolved to a companyId). Empty list if no company matches.
companySalesnavUrlstringoptionalFilter contacts by their company's LinkedIn Sales Navigator URL (resolved to a companyId). Empty list if no company matches.
emailstringoptionalExact email address to search for (takes priority over search parameter)
limitnumberoptionalMaximum number of contacts to return (1-100, default: 20)
listIdstringoptionalFilter by contact list ID (clt_xxx format). Can be combined with search/email, or used alone to list all contacts in a list. Get valid IDs from get_contact_lists.
notInAnyCampaignbooleanoptionalWhen true, only returns contacts that are not part of any campaign. Can be used alone or combined with other filters.
offsetnumberoptionalNumber of contacts to skip for pagination (default: 0)
searchstringoptionalFree-text search: matches against contact full name or email address (min 2 chars, case-insensitive)
lemlistmcp_search_domains#Check availability of a domain at the registrar (and optionally return suggestions). Use in Step 3 of the outreach-infra skill — after calculate_infrastructure has produced a shortlist of brand-consistent candidates, call this tool for each candidate to confirm availability + pricing before presenting the plan to the user.2 params

Check availability of a domain at the registrar (and optionally return suggestions). Use in Step 3 of the outreach-infra skill — after calculate_infrastructure has produced a shortlist of brand-consistent candidates, call this tool for each candidate to confirm availability + pricing before presenting the plan to the user.

NameTypeRequiredDescription
basestringrequiredBase domain (e.g. "getacme.com")
includeSuggestionsbooleanoptionalInclude alternative suggestions from the registrar
lemlistmcp_search_help_center#Search the lemlist help center for official documentation and guides. Use this when you need to provide guidance on how to do something in lemlist that you cannot do directly via tools. Returns relevant help center articles with content excerpts and links. Do NOT use this for questions you can answer from context or tools.1 param

Search the lemlist help center for official documentation and guides. Use this when you need to provide guidance on how to do something in lemlist that you cannot do directly via tools. Returns relevant help center articles with content excerpts and links. Do NOT use this for questions you can answer from context or tools.

NameTypeRequiredDescription
querystringrequiredSearch query in English using 1-3 keywords (e.g., "inbox rotation", "email provider", "signals")
lemlistmcp_send_message#Send a message to a contact or lead via email, LinkedIn, WhatsApp, or SMS from the Lemlist inbox.11 params

Send a message to a contact or lead via email, LinkedIn, WhatsApp, or SMS from the Lemlist inbox.

NameTypeRequiredDescription
channelstringrequiredChannel to send through.
messagestringrequiredMessage content (channel-specific format).
sendUserIdstringrequiredUser ID sending the message (usr_xxx format).
ccarrayoptionalchannel="email": optional list of CC email addresses.
contactIdstringoptionalContact ID to send to. Required if leadId is not provided.
fromstringoptionalchannel="sms": sender phone number.
leadIdstringoptionalLead ID to send to. Alternative to contactId.
sendUserEmailstringoptionalchannel="email": email address to send from.
sendUserMailboxIdstringoptionalchannel="email": mailbox ID (usm_xxx) to use for sending.
sendUserWhatsappAccountIdstringoptionalchannel="whatsapp": WhatsApp account ID (uwa_xxx) to use for sending.
subjectstringoptionalchannel="email": email subject line.
lemlistmcp_send_task#Send one OR many message-based tasks now, OR — for a manual campaign step — schedule it via the campaign and mark it done (the "Send & mark done" / "Schedule & mark done" actions on the Tasks / Focus page). Use when the user asks to actually SEND an email, LinkedIn message or WhatsApp message task (not merely close it), or to schedule/complete a manual campaign step. Pass opportunityId as a single task ID or an array of task IDs. The same sender is applied to every task; the result is always the aggregate { total, succeeded, failed, results[] } — each entry carries channel/sent/scheduled or an error code, and a bad task fails on its own without failing the others. With an array this contacts MULTIPLE leads at once — only call it after the user has approved sending to all of them. What it sends: - The task's current content: the per-lead draft override if one exists, otherwise the task's template. Edit it first with update_task_content if needed. Contract rules reproduced by the backend: - Regular (non-manual) email, linkedinSend and whatsappMessage tasks are sent immediately; this requires the per-channel sender fields, a contact and non-empty content (email needs a subject). Returns sent=true, scheduled=false. - A manual campaign step is NOT sent immediately: it is handed back to the campaign to send at its scheduled time and marked done. Sender fields, contact and content are NOT required (the campaign step's own content is used at send time). Returns sent=false, scheduled=true. - Still only email, linkedinSend and whatsappMessage types are handled; phone, SMS, generic manual and other types are rejected — close those with update_task status="done". - The task must be open (due/upcoming); paused or already-closed tasks are rejected. - Sender details for a direct send: email needs sendUserEmail + sendUserMailboxId; whatsapp needs sendUserWhatsappAccountId; linkedin needs only sendUserId. Discover valid sender ids/mailboxes with get_users / get_user_channels. - This actually contacts the lead (now, or at the scheduled time) — only call it after the user has approved sending.6 params

Send one OR many message-based tasks now, OR — for a manual campaign step — schedule it via the campaign and mark it done (the "Send & mark done" / "Schedule & mark done" actions on the Tasks / Focus page). Use when the user asks to actually SEND an email, LinkedIn message or WhatsApp message task (not merely close it), or to schedule/complete a manual campaign step. Pass opportunityId as a single task ID or an array of task IDs. The same sender is applied to every task; the result is always the aggregate { total, succeeded, failed, results[] } — each entry carries channel/sent/scheduled or an error code, and a bad task fails on its own without failing the others. With an array this contacts MULTIPLE leads at once — only call it after the user has approved sending to all of them. What it sends: - The task's current content: the per-lead draft override if one exists, otherwise the task's template. Edit it first with update_task_content if needed. Contract rules reproduced by the backend: - Regular (non-manual) email, linkedinSend and whatsappMessage tasks are sent immediately; this requires the per-channel sender fields, a contact and non-empty content (email needs a subject). Returns sent=true, scheduled=false. - A manual campaign step is NOT sent immediately: it is handed back to the campaign to send at its scheduled time and marked done. Sender fields, contact and content are NOT required (the campaign step's own content is used at send time). Returns sent=false, scheduled=true. - Still only email, linkedinSend and whatsappMessage types are handled; phone, SMS, generic manual and other types are rejected — close those with update_task status="done". - The task must be open (due/upcoming); paused or already-closed tasks are rejected. - Sender details for a direct send: email needs sendUserEmail + sendUserMailboxId; whatsapp needs sendUserWhatsappAccountId; linkedin needs only sendUserId. Discover valid sender ids/mailboxes with get_users / get_user_channels. - This actually contacts the lead (now, or at the scheduled time) — only call it after the user has approved sending.

NameTypeRequiredDescription
opportunityIdstringrequiredA single task ID (opp_xxx) or an array of task IDs. The same change is applied to every task; results are returned per task (partial success — a bad task fails on its own without failing the others).
sendUserIdstringrequiredUser ID (usr_xxx) sending the message. Required for every channel. Ignored for a manual campaign step (scheduling uses the campaign step's own sender).
ccarrayoptionalCC email addresses (email tasks only).
sendUserEmailstringoptionalSending email address. REQUIRED for email tasks; ignored otherwise.
sendUserMailboxIdstringoptionalMailbox ID (usm_xxx) to send from. REQUIRED for email tasks; ignored otherwise.
sendUserWhatsappAccountIdstringoptionalWhatsApp account ID (uwa_xxx). REQUIRED for WhatsApp tasks; ignored otherwise.
lemlistmcp_set_ab_variant#Set or update the A/B test variant B (subject and/or body) of an EMAIL sequence step. Use when the user asks to: - A/B test an email step (two subjects, two bodies, or both) - Add or edit the variant B of an email step Behaviour: - If the step has no A/B test yet, this enables it: variant B starts as a copy of variant A (same subject, body, CC), then the fields you pass are applied on top. Fields you omit stay inherited from A. - If a variant B already exists, only the fields you pass are changed; the rest of B is left untouched. - Pass no field to just enable A/B with variant B identical to A. Scope: this tool covers email steps only, which is NOT the same as "A/B testing is email-only". - LinkedIn invitation (e.g. variant A with a note vs variant B without), LinkedIn chat message, LinkedIn InMail, SMS and WhatsApp chat message steps all support A/B testing in the product; no tool exposes it yet. - For those channels, answer that it is possible and hand over the manual path: open the campaign in the sequence editor, select the step, turn on its A/B test, then edit variant B there. - Never tell the user that a non-email step cannot be A/B tested. Contract rules reproduced by the backend: - Calling this tool on a step that is not an email step is rejected (SEQUENCE_AB_ONLY_EMAIL). The public REST A/B endpoint carries the same limit. - A running campaign can reject edits to steps that have already launched: pause it first.7 params

Set or update the A/B test variant B (subject and/or body) of an EMAIL sequence step. Use when the user asks to: - A/B test an email step (two subjects, two bodies, or both) - Add or edit the variant B of an email step Behaviour: - If the step has no A/B test yet, this enables it: variant B starts as a copy of variant A (same subject, body, CC), then the fields you pass are applied on top. Fields you omit stay inherited from A. - If a variant B already exists, only the fields you pass are changed; the rest of B is left untouched. - Pass no field to just enable A/B with variant B identical to A. Scope: this tool covers email steps only, which is NOT the same as "A/B testing is email-only". - LinkedIn invitation (e.g. variant A with a note vs variant B without), LinkedIn chat message, LinkedIn InMail, SMS and WhatsApp chat message steps all support A/B testing in the product; no tool exposes it yet. - For those channels, answer that it is possible and hand over the manual path: open the campaign in the sequence editor, select the step, turn on its A/B test, then edit variant B there. - Never tell the user that a non-email step cannot be A/B tested. Contract rules reproduced by the backend: - Calling this tool on a step that is not an email step is rejected (SEQUENCE_AB_ONLY_EMAIL). The public REST A/B endpoint carries the same limit. - A running campaign can reject edits to steps that have already launched: pause it first.

NameTypeRequiredDescription
sequenceIdstringrequiredSequence ID (seq_xxx) that contains the email step.
stepIdstringrequiredEmail step ID (stp_xxx) to set variant B on.
altMessagestringoptionalVariant-B plain-text alternative body. Rarely needed; omit to inherit from A or keep B unchanged.
ccarrayoptionalVariant-B CC recipients (email addresses or {{variables}}). Omit to inherit from A or keep B unchanged.
messagestringoptionalVariant-B email body as HTML. Omit to inherit variant A's body (on creation) or keep B unchanged (on update).
plainTextbooleanoptionalSend variant B as plain text instead of HTML. Omit to inherit from A or keep B unchanged.
subjectstringoptionalVariant-B subject line. Omit to inherit variant A's subject (on creation) or keep B unchanged (on update).
lemlistmcp_set_campaign_sender_strategy#Set the sender-assignment strategy for a campaign — the algorithm that decides which sender (user) is attached to each lead at launch. Keywords: sender strategy, dynamic sender assignment, round-robin sender, contact owner sender, custom variable sender, per-lead sender routing. Use when the user asks about: - Configuring HOW senders are assigned to leads (as opposed to WHICH users are in the send pool — that is set_campaign_senders). - Routing sends by a per-lead custom variable (e.g. "send from the account manager listed on each lead"). - Using the CRM contact owner as the sender. - Using the user who imported the lead as the sender. - Switching between random / round-robin and any of the dynamic strategies above. This tool decides HOW senders are picked. To change WHO is in the eligible pool, use set_campaign_senders. Contract rules: - "customField:<fieldName>" requires the field to exist as a team custom field of type "user", AND each lead must have variables.<fieldName> populated with a valid userId. Leads missing that value are silently dropped from launch with a "noAssignment" diagnostic (they will not be sent to). - Changing the strategy on a running campaign does NOT reassign already-resolved leads; it only applies to leads reviewed/launched after the change. - No user confirmation required.2 params

Set the sender-assignment strategy for a campaign — the algorithm that decides which sender (user) is attached to each lead at launch. Keywords: sender strategy, dynamic sender assignment, round-robin sender, contact owner sender, custom variable sender, per-lead sender routing. Use when the user asks about: - Configuring HOW senders are assigned to leads (as opposed to WHICH users are in the send pool — that is set_campaign_senders). - Routing sends by a per-lead custom variable (e.g. "send from the account manager listed on each lead"). - Using the CRM contact owner as the sender. - Using the user who imported the lead as the sender. - Switching between random / round-robin and any of the dynamic strategies above. This tool decides HOW senders are picked. To change WHO is in the eligible pool, use set_campaign_senders. Contract rules: - "customField:<fieldName>" requires the field to exist as a team custom field of type "user", AND each lead must have variables.<fieldName> populated with a valid userId. Leads missing that value are silently dropped from launch with a "noAssignment" diagnostic (they will not be sent to). - Changing the strategy on a running campaign does NOT reassign already-resolved leads; it only applies to leads reviewed/launched after the change. - No user confirmation required.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx) to update.
senderStrategystringrequiredHow senders are picked for each lead at launch. One of: "random" (round-robin over the campaign send pool), "contactOwner" (use each lead's CRM contact owner), "leadImporter" (use the user who imported the lead), or "customField:<fieldName>" (read the sender userId from lead.variables.<fieldName>).
lemlistmcp_set_campaign_senders#Assign team members as senders for a campaign's outreach messages.2 params

Assign team members as senders for a campaign's outreach messages.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx format)
senderIdsarrayrequiredArray of user IDs (usr_xxx format) to assign as senders. Get IDs from get_users (userIds: ["all"]).
lemlistmcp_set_campaign_state#Start, pause, archive, or unarchive a campaign to change its running state.3 params

Start, pause, archive, or unarchive a campaign to change its running state.

NameTypeRequiredDescription
actionstringrequired"start" to launch the campaign, "pause" to pause a running campaign, "archive" to archive a campaign, "unarchive" to restore an archived campaign
campaignIdstringrequiredThe campaign ID (cam_xxx format)
userConfirmedbooleanoptionalREQUIRED for action="start" and action="archive": Must be true. Confirms user explicitly approved the action. Not required for pause or unarchive.
lemlistmcp_suggest_watch_lists#Generate AI-suggested watch lists for the current team. Returns scored, ready-to-create watch list configurations — each with a relevance score, a reason and an estimated monthly signal volume — tailored to the team's ICP. Use when the user asks about: - Recommendations on which signals / watch lists to set up - Discovering the most relevant watch list types for their business Important: - Requires the team's business context (AI Context Center) to be set, otherwise it errors. - Consumes one daily AI suggestion session (the team has a limited daily quota). - Returns suggestions only; creating or activating them is a separate step (create_watch_list).0 params

Generate AI-suggested watch lists for the current team. Returns scored, ready-to-create watch list configurations — each with a relevance score, a reason and an estimated monthly signal volume — tailored to the team's ICP. Use when the user asks about: - Recommendations on which signals / watch lists to set up - Discovering the most relevant watch list types for their business Important: - Requires the team's business context (AI Context Center) to be set, otherwise it errors. - Consumes one daily AI suggestion session (the team has a limited daily quota). - Returns suggestions only; creating or activating them is a separate step (create_watch_list).

lemlistmcp_test_email_account#Test SMTP/IMAP connectivity of an email account. No actual email sent. Use get_user_channels to find account ID.1 param

Test SMTP/IMAP connectivity of an email account. No actual email sent. Use get_user_channels to find account ID.

NameTypeRequiredDescription
emailAccountIdstringrequiredThe email account ID to test (starts with usm_)
lemlistmcp_transfer_campaign_leads_to_list#Add every lead of a campaign to a CRM contact list, in one call. Each campaign lead is backed by a CRM contact; this resolves those contacts server-side and adds them to the list. You do NOT need to fetch or enumerate lead/contact IDs first. **When to use:** - User wants to move/copy a whole campaign's leads into a contact list (e.g. "add everyone in campaign X to my 'Hot leads' list") - After identifying a campaign and a target list, to populate the list from the campaign **Parameters:** - campaignId: Campaign ID in cam_xxx format (required). Get it from get_campaigns. - listId: Target contact list ID in clt_xxx format (required). Get it from get_contact_lists, or create one with create_contact_list. Never invent or guess a list ID. **IMPORTANT:** - This ADDS (copies) contacts to the list; it does not remove leads from the campaign or move them off any other list. - Contacts already in the list are silently skipped (idempotent, no duplicates). - The target list must be a static contact list; dynamic lists are rejected. - Leads that have no associated contact are skipped. **Example:** { "campaignId": "cam_abc123def456", "listId": "clt_xyz789" }2 params

Add every lead of a campaign to a CRM contact list, in one call. Each campaign lead is backed by a CRM contact; this resolves those contacts server-side and adds them to the list. You do NOT need to fetch or enumerate lead/contact IDs first. **When to use:** - User wants to move/copy a whole campaign's leads into a contact list (e.g. "add everyone in campaign X to my 'Hot leads' list") - After identifying a campaign and a target list, to populate the list from the campaign **Parameters:** - campaignId: Campaign ID in cam_xxx format (required). Get it from get_campaigns. - listId: Target contact list ID in clt_xxx format (required). Get it from get_contact_lists, or create one with create_contact_list. Never invent or guess a list ID. **IMPORTANT:** - This ADDS (copies) contacts to the list; it does not remove leads from the campaign or move them off any other list. - Contacts already in the list are silently skipped (idempotent, no duplicates). - The target list must be a static contact list; dynamic lists are rejected. - Leads that have no associated contact are skipped. **Example:** { "campaignId": "cam_abc123def456", "listId": "clt_xyz789" }

NameTypeRequiredDescription
campaignIdstringrequiredSource campaign ID in cam_xxx format. Every lead in this campaign is transferred. Get valid IDs from get_campaigns.
listIdstringrequiredTarget contact list ID in clt_xxx format. Must be a static contact list. Get valid IDs from get_contact_lists; never invent or guess a list ID.
lemlistmcp_update_ai_variable_prompt#Edit the AI-generation prompt of ONE AI variable column on a campaign (icebreaker, opener, contextual opener, etc.). Replaces the existing prompt entirely with the provided one. Use get_ai_variable_prompts first to read the current prompt and the exact variable names. Keep the {{variable}} placeholders (e.g. {{firstName}}) in the new prompt, and only reference variables or AI columns that already exist on the campaign. Only prompts owned by your team (the per-campaign copy) can be edited. Shared lemlist/system prompts are read-only and will be rejected. Pass tools to change the column's tools (e.g. tools:["enrich-linkedin"] to scrape LinkedIn — the prompt must reference {{linkedinUrl}}). Enabling any tool forces the premium lemlist model and lemlist-credit billing. Pass an empty array ([]) to remove all tools; the column reverts to your team's default model and billing (still charged in lemlist credits if your team has no own AI provider key, otherwise billed via your own API key). Omitting tools leaves the existing tools untouched and only replaces the prompt. Pass autofill to switch the column's auto-generate toggle: true fills this AI variable for every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add), false turns that off. Omitting autofill leaves the toggle as it is. Use when the user asks to: - Change how an AI column is generated for a campaign - Tweak / rewrite an icebreaker or opener prompt - Turn auto-generation on new/imported leads on or off for an AI column This mutates campaign configuration, so confirm the change with the user before calling.5 params

Edit the AI-generation prompt of ONE AI variable column on a campaign (icebreaker, opener, contextual opener, etc.). Replaces the existing prompt entirely with the provided one. Use get_ai_variable_prompts first to read the current prompt and the exact variable names. Keep the {{variable}} placeholders (e.g. {{firstName}}) in the new prompt, and only reference variables or AI columns that already exist on the campaign. Only prompts owned by your team (the per-campaign copy) can be edited. Shared lemlist/system prompts are read-only and will be rejected. Pass tools to change the column's tools (e.g. tools:["enrich-linkedin"] to scrape LinkedIn — the prompt must reference {{linkedinUrl}}). Enabling any tool forces the premium lemlist model and lemlist-credit billing. Pass an empty array ([]) to remove all tools; the column reverts to your team's default model and billing (still charged in lemlist credits if your team has no own AI provider key, otherwise billed via your own API key). Omitting tools leaves the existing tools untouched and only replaces the prompt. Pass autofill to switch the column's auto-generate toggle: true fills this AI variable for every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add), false turns that off. Omitting autofill leaves the toggle as it is. Use when the user asks to: - Change how an AI column is generated for a campaign - Tweak / rewrite an icebreaker or opener prompt - Turn auto-generation on new/imported leads on or off for an AI column This mutates campaign configuration, so confirm the change with the user before calling.

NameTypeRequiredDescription
campaignIdstringrequiredCampaign ID (cam_xxx format) that owns the AI variable
promptstringrequiredThe new AI-generation prompt. Replaces the existing prompt entirely. Keep {{variable}} placeholders for the fields/columns it should reference.
variableNamestringrequiredName of the AI variable column to edit (e.g. "icebreaker"). The "variables." prefix is optional.
autofillbooleanoptionalSwitches the column's "auto-generate" toggle: true generates this AI variable for every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add), false turns that off. Omit to leave the current setting untouched. ⚠️ COSTS CREDITS: with it on, every newly added lead consumes one generation.
toolsarrayoptionalOptional AI tools the column may use while generating each value. "enrich-linkedin" scrapes the lead's LinkedIn profile (the prompt MUST reference {{linkedinUrl}} or {{linkedinUrlSalesNav}}, otherwise the tool never fires and the column stays empty); "scrape-website" reads a URL; "web-search" searches the live web. ⚠️ COSTS CREDITS: enabling ANY tool forces the premium lemlist model and switches billing to lemlist credits, charged per lead at generation time (not now). Omit for a plain text column.
lemlistmcp_update_call_status#Set the disposition (call status) on a single dialer call activity. Use when the user asks to: - Log or correct the outcome of a call (e.g. after reading its transcript) - Back-fill a missing status on a call that was dialed but never dispositioned Typical flow: get_call_activities (find calls, spot empty statuses) → get_call_details (read the transcript) → get_call_statuses (get the valid keys) → update_call_status (set the key). Setting a status is NOT cosmetic: depending on how the team configured that status, it can mark the lead interested / not-interested and pause campaigns, and it syncs to the connected CRM — exactly like a rep clicking it in the UI.2 params

Set the disposition (call status) on a single dialer call activity. Use when the user asks to: - Log or correct the outcome of a call (e.g. after reading its transcript) - Back-fill a missing status on a call that was dialed but never dispositioned Typical flow: get_call_activities (find calls, spot empty statuses) → get_call_details (read the transcript) → get_call_statuses (get the valid keys) → update_call_status (set the key). Setting a status is NOT cosmetic: depending on how the team configured that status, it can mark the lead interested / not-interested and pause campaigns, and it syncs to the connected CRM — exactly like a rep clicking it in the UI.

NameTypeRequiredDescription
activityIdstringrequiredThe call activity ID (act_xxx) — from get_call_activities or get_call_details
callStatusstringrequiredThe call status KEY to set (e.g. "left-voicemail", "connected-positive"). Must be one of the team's configured status keys — call get_call_statuses first to get them. An invalid key returns the list of valid keys so you can retry.
lemlistmcp_update_lead#Update standard fields on an existing lead (firstName, lastName, jobTitle, companyName, email, phone, linkedinUrl, picture, timezone, jobDescription, companyDomain). Requires leadId + at least one field to update. For custom variables, use update_lead_variables instead.12 params

Update standard fields on an existing lead (firstName, lastName, jobTitle, companyName, email, phone, linkedinUrl, picture, timezone, jobDescription, companyDomain). Requires leadId + at least one field to update. For custom variables, use update_lead_variables instead.

NameTypeRequiredDescription
leadIdstringrequiredThe lead ID (starts with lea_)
companyDomainstringoptionalLead company domain
companyNamestringoptionalLead company name
emailstringoptionalLead email address
firstNamestringoptionalLead first name
jobDescriptionstringoptionalLead job description
jobTitlestringoptionalLead job title
lastNamestringoptionalLead last name
linkedinUrlstringoptionalLead LinkedIn profile URL
phonestringoptionalLead phone number
picturestringoptionalLead profile picture URL
timezonestringoptionalLead timezone
lemlistmcp_update_lead_variables#Set custom variables on an existing lead (upsert). Requires leadId + variables (key-value pairs of non-empty strings). Automatically handles both updating existing variables and adding new ones. IMPORTANT: Do NOT pass standard lead fields as variables — the following keys are FORBIDDEN and will be rejected: email, firstName, lastName, picture, phone, linkedinUrl, timezone, jobTitle, jobDescription, companyName, companyDomain. To update these fields, use the update_lead tool instead. Empty string values are rejected — omit the variable instead.2 params

Set custom variables on an existing lead (upsert). Requires leadId + variables (key-value pairs of non-empty strings). Automatically handles both updating existing variables and adding new ones. IMPORTANT: Do NOT pass standard lead fields as variables — the following keys are FORBIDDEN and will be rejected: email, firstName, lastName, picture, phone, linkedinUrl, timezone, jobTitle, jobDescription, companyName, companyDomain. To update these fields, use the update_lead tool instead. Empty string values are rejected — omit the variable instead.

NameTypeRequiredDescription
leadIdstringrequiredThe lead ID (starts with lea_)
variablesobjectrequiredCustom variables as key-value pairs to set (e.g., {"comicFrame": "panel_3", "tone": "friendly"}). Values must be non-empty strings — omit the variable rather than passing an empty string.
lemlistmcp_update_mailbox#Update a team mailbox. Currently supports assignment to a specific SDR (lemlist user); the schema is extensible for future updates (settings, status, …). Idempotent — re-applying the same update is safe. Use in Step 5 of the outreach-infra skill once mailboxes have been provisioned, to wire each mailbox to its intended SDR before warmup starts.2 params

Update a team mailbox. Currently supports assignment to a specific SDR (lemlist user); the schema is extensible for future updates (settings, status, …). Idempotent — re-applying the same update is safe. Use in Step 5 of the outreach-infra skill once mailboxes have been provisioned, to wire each mailbox to its intended SDR before warmup starts.

NameTypeRequiredDescription
assignToUserIdstringrequiredlemlist userId (usr_xxx) to assign the mailbox to
mailboxIdstringrequiredDomain mailbox ID (dem_xxx)
lemlistmcp_update_sequence_step#Update a step in an existing campaign sequence. Requires user confirmation for email or content step changes.15 params

Update a step in an existing campaign sequence. Requires user confirmation for email or content step changes.

NameTypeRequiredDescription
campaignIdstringrequiredThe campaign ID (required for status verification)
sequenceIdstringrequiredThe sequence ID (starts with seq_)
stepIdstringrequiredThe step ID to update (starts with stp_)
userConfirmedbooleanrequiredREQUIRED: Must be true. Confirms user explicitly approved this change after seeing the preview. Only set to true after user says yes.
conditionKeystringoptionalNew condition key (for conditional steps only)
delaynumberoptionalNew delay value in days
delayTypestringoptionalNew delay type for conditional steps. "within" = must happen within delay days, "waitUntil" = wait indefinitely. For field-check conditions, use "within" with delay 0.
emailStatusFilterarrayoptionalOnly for hasEmailAddress condition. Filter by email status: ["deliverable","risky","undeliverable","unverified"].
messagestringoptionalNew email body content (for email steps, supports Liquid syntax)
methodstringoptionalNew HTTP method for "api" (webhook) steps. Limited to GET/POST to stay iso with the lemlist UI editor. Ignored on non-api steps.
scoreComparatorstringoptionalOnly for hasScore condition. "$gte" = score above or equal, "$lt" = score below.
scoreThresholdnumberoptionalOnly for hasScore condition. Score threshold (0-100).
subjectstringoptionalNew subject line (supports Liquid syntax: {{ firstName }}, {% if condition %}...{% endif %})
titlestringoptionalNew task title (for manual/phone steps). Short label displayed in the review UI.
urlstringoptionalNew webhook URL for "api" steps. Supports Liquid templating against lead variables (e.g. https://example.com/leads/{{ _id }}). Ignored on non-api steps.
lemlistmcp_update_settings#Update settings for a campaign or warmup mailbox entity.7 params

Update settings for a campaign or warmup mailbox entity.

NameTypeRequiredDescription
idstringrequiredEntity ID. For "lemwarm": the mailbox ID (usm_xxx) — the same id used with get_settings type="lemwarm".
typestringrequiredThe type of settings to update. Only "lemwarm" is supported for now.
actionstringoptionalOptional state change. "start" activates warmup, "pause" stops it. Omit when only updating settings.
internalCommunicationPercentnumberoptionalPercentage of warmup emails sent to internal participants (0-100). Only applied when the team has the lemwarmInternalCommunication beta.
userConfirmedbooleanoptionalREQUIRED when action="start": must be true after user confirms activating warmup.
warmEmailMaxnumberoptionalDaily warmup email target (0-40). Server enforces 1-40 unless the team has the lemwarm0limit beta.
warmEmailRampupnumberoptionalRamp-up increment per day (0-40). Server enforces 1-40 unless the team has the lemwarm0limit beta.
lemlistmcp_update_task#Update a single editable field on one OR many tasks (opportunities) on the Tasks / Focus page. Use when the user asks about: - Reassigning a task to a teammate (or unassigning it) - Changing a task's priority (none/low/medium/high) - Snoozing a task to a later date - Marking a task done or ignored - Marking a task read or unread Pass opportunityId as a single task ID or an array of task IDs. The same field/value is applied to every task; the result is always the aggregate { field, total, succeeded, failed, results[] } — each entry carries updated or an error code, and a bad task fails on its own without failing the others. Contract rules reproduced by the backend: - Exactly ONE of assignedTo / priority / dueDate / status / read must be provided per call (applied to every task). - assignedTo must be a teammate of the current team, or "unassign". - A paused task cannot be marked "done" (use "ignored"); it also cannot be snoozed (resume it first). - dueDate must be a future ISO 8601 date. - status="done" ONLY marks the task complete — it does NOT send the message. For an email/LinkedIn/WhatsApp task where the message should actually be sent to the lead, use send_task (which sends the content AND marks done). Use status="done" here only to close a task without sending (the "mark as done only" action). For a manual campaign step, send_task schedules-and-marks-done (same end state as status="done"), so both paths converge. - To edit a task's subject or body, use update_task_content instead.6 params

Update a single editable field on one OR many tasks (opportunities) on the Tasks / Focus page. Use when the user asks about: - Reassigning a task to a teammate (or unassigning it) - Changing a task's priority (none/low/medium/high) - Snoozing a task to a later date - Marking a task done or ignored - Marking a task read or unread Pass opportunityId as a single task ID or an array of task IDs. The same field/value is applied to every task; the result is always the aggregate { field, total, succeeded, failed, results[] } — each entry carries updated or an error code, and a bad task fails on its own without failing the others. Contract rules reproduced by the backend: - Exactly ONE of assignedTo / priority / dueDate / status / read must be provided per call (applied to every task). - assignedTo must be a teammate of the current team, or "unassign". - A paused task cannot be marked "done" (use "ignored"); it also cannot be snoozed (resume it first). - dueDate must be a future ISO 8601 date. - status="done" ONLY marks the task complete — it does NOT send the message. For an email/LinkedIn/WhatsApp task where the message should actually be sent to the lead, use send_task (which sends the content AND marks done). Use status="done" here only to close a task without sending (the "mark as done only" action). For a manual campaign step, send_task schedules-and-marks-done (same end state as status="done"), so both paths converge. - To edit a task's subject or body, use update_task_content instead.

NameTypeRequiredDescription
opportunityIdstringrequiredA single task ID (opp_xxx) or an array of task IDs. The same change is applied to every task; results are returned per task (partial success — a bad task fails on its own without failing the others).
assignedTostringoptionalReassign the task: a teammate user ID (usr_xxx), or "unassign" to clear the assignee. The user must belong to the current team.
dueDatestringoptionalSnooze the task until this ISO 8601 date/time (e.g. "2026-07-10T09:00:00Z"). Must be in the future.
prioritystringoptionalTask priority. "none" clears the priority.
readbooleanoptionalMark the task read (true) or unread (false).
statusstringoptionalClose the task: "done" (completed) or "ignored" (skipped). Paused tasks cannot be marked "done" — use "ignored".
lemlistmcp_update_task_content#Update the message content (subject and/or body) of a message-based task (opportunity). Use when the user asks about: - Rewriting or tweaking the body of an email, LinkedIn or WhatsApp task - Changing the subject line of an email task Contract rules reproduced by the backend: - Only message-based task types are supported: email, linkedinSend, whatsappMessage. - subject is only allowed on email tasks. - Provide at least one of subject or message; the untouched field is preserved. - Pass the task's type so the body is formatted for its channel (email body kept as HTML, LinkedIn/WhatsApp as plain text). - For campaign-step tasks the edit is stored as a per-lead override (the shared campaign template is untouched); standalone tasks edit their own template.4 params

Update the message content (subject and/or body) of a message-based task (opportunity). Use when the user asks about: - Rewriting or tweaking the body of an email, LinkedIn or WhatsApp task - Changing the subject line of an email task Contract rules reproduced by the backend: - Only message-based task types are supported: email, linkedinSend, whatsappMessage. - subject is only allowed on email tasks. - Provide at least one of subject or message; the untouched field is preserved. - Pass the task's type so the body is formatted for its channel (email body kept as HTML, LinkedIn/WhatsApp as plain text). - For campaign-step tasks the edit is stored as a per-lead override (the shared campaign template is untouched); standalone tasks edit their own template.

NameTypeRequiredDescription
opportunityIdstringrequiredThe task (opportunity) ID to update (opp_xxx format).
typestringrequiredThe task type — must match the task's actual type (from get_tasks or get_task_content). Used to format the body for its channel: email is HTML (newlines become <br>), LinkedIn and WhatsApp are plain text.
messagestringoptionalNew message body / content (email body, LinkedIn or WhatsApp message).
subjectstringoptionalNew email subject. Only valid for email tasks; rejected for other types.
lemlistmcp_update_watch_list#Update an existing watch list. Use when the user asks about: - Renaming or changing the emoji of a watch list - Adjusting filters of a watch list - Changing how signals are processed (manual, create_opportunity, push_to_campaign) Contract rules reproduced by the backend: - personaId is accepted ONLY on a company watch list with signalProcessingType="push_to_campaign" (any other config is rejected), and only for teams in the personas beta - personaId is optional there: without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign - get a personaId from list_people_database_personas (or create_people_database_persona); never invent one8 params

Update an existing watch list. Use when the user asks about: - Renaming or changing the emoji of a watch list - Adjusting filters of a watch list - Changing how signals are processed (manual, create_opportunity, push_to_campaign) Contract rules reproduced by the backend: - personaId is accepted ONLY on a company watch list with signalProcessingType="push_to_campaign" (any other config is rejected), and only for teams in the personas beta - personaId is optional there: without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign - get a personaId from list_people_database_personas (or create_people_database_persona); never invent one

NameTypeRequiredDescription
activatebooleanrequiredWhen true, activates the watch list immediately (advances to VALIDATED step, triggers billing and external watcher setup). Requires segmentType and signalProcessingType to be set.
filtersarrayrequiredConfiguration filters as an array of { filterId, in[], out[] } objects
namestringrequiredNew watch list name (non-empty)
signalProcessingTypestringrequiredNew signal processing type
watchListIdstringrequiredThe watch list ID to update (wat_xxx format)
emojistringoptionalNew emoji
personaIdstringoptionalPersona (pdp_xxx) used to source contacts from the People Database. Used by a company watch list with signalProcessingType = "push_to_campaign": company signals carry no contact, so the persona is the only way to know who to reach. Optional — without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign. Rejected on any other configuration.
signalOpportunityTemplateobjectoptionalOpportunity template payload, required when signalProcessingType = "create_opportunity"
lemlistmcp_validate_campaign_readiness#Validate that a campaign is ready to launch by checking step content, sender configuration, DNS health, and daily limits.2 params

Validate that a campaign is ready to launch by checking step content, sender configuration, DNS health, and daily limits.

NameTypeRequiredDescription
campaignIdstringoptionalCampaign ID (cam_xxx format). Provide this or campaignName.
campaignNamestringoptionalCampaign name to search for. Provide this or campaignId.