Announcing CIMD support for MCP Client registration
Learn more

Lemlist MCP vs Lemlist API for AI Agents (2026)

TL;DR

  • Lemlist's hosted MCP server is a copilot surface, not a thin API wrapper. Scalekit's connector catalogues 62 MCP tools; the v2 REST reference documents roughly 120 endpoints. Schedules, tasks, activity history, CSV exports, inbox drafts and labels, Signal Agent signals, and the entire lead state machine (pause, resume, launch, mark interested) exist only on the API.
  • The auth comparison inverts the usual pattern. The MCP server supports OAuth with dynamic client registration and PKCE, plus a static X-API-Key header. The documented REST authentication method is HTTP Basic with an empty username and your API key as the password. MCP is the only Lemlist path that gives you a real per-user delegated grant.
  • The MCP surface is not a scoping boundary by default. It includes lemlistmcp_call_api, a generic HTTP escape hatch that reaches any REST endpoint. Expose the full server and tool-level least privilege is nominal.
  • A Lemlist API key resolves to exactly one account, with no account parameter and no separate login step. In a multi-tenant B2B agent, that is one credential per customer account, whichever path you pick.
  • Scalekit's Lemlist MCP connector handles the OAuth flow, per-tenant token storage, and refresh, and its Virtual MCP servers let you publish a 6-tool endpoint instead of a 62-tool one. The MCP versus API decision does not change your auth infrastructure.

Your agent needs to run outbound in Lemlist: audit campaigns, source leads, rewrite a failing sequence step, pause a campaign that is burning sender reputation. Lemlist ships a hosted MCP server at app.lemlist.com/mcp and a REST API at api.lemlist.com/api. Most MCP-versus-API comparisons resolve into "MCP is easier, the API is more powerful, and the API has better auth." For Lemlist, the last part is backwards. Here is the actual decision framework.

What Lemlist MCP and Lemlist API actually are

These are two different products from the same vendor, aimed at two different consumers. One was designed for a chat client with a human watching. The other was designed for a backend integration that runs unattended.

Lemlist MCP

The official Lemlist MCP server is hosted by Lemlist at https://app.lemlist.com/mcp and speaks JSON-RPC 2.0 over HTTP. Authentication has two modes: browser-based OAuth, where the client handles discovery, dynamic client registration, consent, PKCE token exchange, and refresh; or a static API key sent in the X-API-Key header.

On the OAuth path, the consent screen asks the user to select a team, and Lemlist documents an access token lifetime of about one hour with a refresh token lasting about 30 days. Lemlist does not document per-tool scope selection on that grant.

Lemlist API

The Lemlist REST API lives at https://api.lemlist.com/api and covers the full platform: campaigns, sequences, leads, contacts, companies, schedules, tasks, inbox, enrichment, lemwarm, unsubscribes, webhooks, and the People Database.

Authentication is HTTP Basic, and the details matter: the username is always empty, the password is your API key, and you Base64 encode the string :YourApiKey including the leading colon. There are two API versions, and v1 is deprecated. Some endpoints still default to v1, so you pass version=v2 as a query parameter on those routes.

Comparing them where it matters for agents

Four dimensions decide this for an agent: what the tools can reach, whether the tool surface is actually a boundary, what credential model each path forces on you, and what breaks in production.

What your agent can actually do

The MCP server covers the operator loop well. The gaps are concentrated in scheduling, task management, bulk data movement, and the lead state machine.

Capability
Lemlist MCP
Lemlist API
List campaigns, read stats and reports
Yes
Yes
Create campaign and edit sequence steps
Yes
Yes
Start, pause, archive a campaign
Yes
Yes
Search the People Database and push leads to contacts
Yes
Yes
Enrich leads and verify emails (credit-consuming)
Yes
Yes
Send inbox messages across email, LinkedIn, WhatsApp, SMS
Yes
Yes
Domain and DNS health scoring (MX, SPF, DMARC, blacklists)
Yes
No composite endpoint
Composite campaign readiness validation
Yes
Partial, via campaign statutes
Persistent server-side memory and business context
Yes
No
Lead state transitions: pause, resume, launch, mark interested
No
Yes
Campaign and contact CSV exports, plus export status polling
No
Yes
Schedules: create, update, associate with a campaign
No
Yes
Tasks and opportunities
No
Yes
Full activity history across campaigns
No
Yes
Inbox drafts and conversation labels
No
Yes
Signal Agent signals (watch list results)
No
Yes
Bulk unsubscribe of up to 10,000 variables
No
Yes
Import leads from a connected CRM
No
Yes

The copilot surface versus the CRUD surface

The gaps are not random. Lemlist built the MCP server for a human in a chat window, so it composes multi-step operations and omits the machinery a backend integration needs.

lemlistmcp_validate_campaign_readiness checks step content, sender configuration, DNS health, and daily limits in one call. lemlistmcp_check_domain_health returns a 0 to 100 score with per-check status and the DNS records needed to fix failures. lemlistmcp_preview_sequence_update is a mandatory read-only diff before lemlistmcp_update_sequence_step. There are also memory tools that persist user and team context across conversations, and lemlistmcp_load_skill, which pulls in domain guidance on demand.

None of that composition exists in the REST API. Equally, none of the API's scheduling, export, or lead-lifecycle control exists in the MCP tool list.

The escape hatch inside the tool surface

There is one exception, and it is the single most important thing to understand before you hand this server to an agent.

lemlistmcp_call_api takes an endpoint path, an HTTP method, and an optional body, and makes a direct call to the Lemlist API. It is gated only by requiring lemlistmcp_load_skill('api-reference') to have run earlier in the session. That gate is a session precondition, not an authorization check.

The consequence is structural. If you expose the full MCP server to an agent, every capability in the "No" column above becomes reachable anyway, and every allowlist you thought you had at the tool level stops meaning anything. Tool-level least privilege on this connector only holds if lemlistmcp_call_api is excluded from the surface.

The auth path each one puts you on

Here is where Lemlist diverges from Notion, Slack, and Salesforce. On those platforms the MCP server is the auth-constrained path and the REST API is the flexible one. Lemlist is the reverse.

The MCP server accepts OAuth with dynamic client registration and PKCE, and it accepts a static API key. The REST API's documented method is Basic auth with an API key, full stop. Lemlist's CLI offers an OAuth login for profile management, but the API reference documents Basic auth as the way to authenticate a request.

That means the MCP path is the only Lemlist path where a user grants your agent access through a consent flow instead of pasting a secret into your product. For a B2B product onboarding customers, that difference is the onboarding funnel.

Where the two paths converge again

The multiple accounts guide states the constraint plainly: a Lemlist credential resolves to exactly one account, there is no account parameter, and there is no separate login step. The credential is the account selector.

Both paths inherit this. On MCP with OAuth, you add one connection per account and the consent screen binds it to a team. On the API, you hold one key per account and switch keys to switch accounts. Forty customer accounts means forty credentials either way.

One more identity detail deserves attention: lemlistmcp_send_message requires an explicit sendUserId in usr_xxx format, and lemlistmcp_set_campaign_senders takes an arbitrary array of team member IDs. Sender identity on those tools is a model-supplied parameter, not something the transport derives from who authorized the grant.

What you own in production

Lemlist maintains the MCP server, its tool schemas, and the composite logic behind tools like readiness validation. Lemlist explicitly notes that the tool set evolves and tells clients to re-enumerate rather than hardcode. That is a managed contract without a version pin.

The REST API gives you the opposite tradeoff. You pin version=v2 and control your own migration, but you own request construction, pagination, retries, and error handling. Rate limits are 20 requests per 2 seconds per API key on all routes, with Retry-After, X-RateLimit-Remaining, and X-RateLimit-Reset on every response. Lemlist does not document separate limits for MCP.

Both paths leave you with token storage, refresh, revocation detection, and tenant isolation.

The confirmation flags are model-side, not server-side

Several destructive and expensive Lemlist tools take a userConfirmed or confirmed boolean: deleting a company, deleting a sequence step, disconnecting an email account, starting or archiving a campaign, and reversing an unsubscribe.

Read the flow carefully. The tool description instructs the model to set the flag only after the user says yes. The model sets the flag. Nothing outside the model verifies that a human ever saw the question.

For an interactive assistant with a person watching, that is reasonable. For a background agent, a prompt-level gate on a tool that spends enrichment credits or archives a live campaign is not a control you can put in a security questionnaire. Enforcement has to happen at the tool surface, before the call.

When to use MCP, when to use the API

The split follows the two products rather than the two protocols.

Use Lemlist MCP when:

  • You are building an interactive outbound copilot where a rep asks for a campaign audit, a sequence rewrite, or an ICP search, and is present to approve changes
  • You want the composite tools: readiness validation, domain health scoring, and preview-before-update, which you would otherwise assemble from several REST calls
  • You are onboarding customers into a multi-tenant product and want an OAuth consent screen instead of an API key paste box
  • Your agent orchestrates Lemlist alongside a CRM and Slack, and you want one transport across all of them

Use the Lemlist API directly when:

  • Your agent drives the lead state machine on a schedule: pausing, resuming, launching, or re-marking leads based on external signals
  • You need schedules, tasks, activity history, inbox drafts and labels, or Signal Agent signals, none of which have MCP tools
  • You are moving data in bulk: campaign exports, contact list exports, or unsubscribing up to 10,000 variables in one request
  • You need a pinned contract, because version=v2 migrating on your timeline beats a managed tool schema that changes under you
  • Your pipeline is throughput-bound and you want direct control of the 20-requests-per-2-seconds budget with your own backoff

The credential problem that exists on both paths

Both paths hand you a credential per Lemlist account. Neither hands you a vault, a rotation loop, or a revocation flow.

Why N accounts means N credentials

Your product serves 40 customers, each with their own Lemlist account. On the MCP path that is 40 OAuth grants, each with an access token expiring roughly hourly and a refresh token expiring in about 30 days. On the API path it is 40 API keys, each shown once at generation and never displayed again.

The MCP grant's roughly 30-day refresh window is the one that bites quietly. It does not fail on deploy. It fails on day 31, for one tenant, inside a scheduled run, with no user present to complete a browser consent flow.

What neither path gives you

Storage, encrypted at rest and namespaced per tenant, so one customer's credential is not reachable from another's execution path. Proactive refresh driven by expiry rather than by catching a 401 across concurrent agent threads. Revocation detection, because a Lemlist user regenerating an API key or revoking a consent grant does not notify your system.

Scalekit's Lemlist MCP connector handles the OAuth flow, per-tenant token storage, and refresh, so the MCP versus API decision does not change your auth infrastructure.

Building Lemlist agents with Scalekit

Scalekit's catalog currently lists one Lemlist connector, lemlistmcp, with OAuth 2.1 and dynamic client registration as the authorization type. If you need the REST-only surface, the bring your own connector path covers it with the same connected-account model, so both surfaces sit behind one credential layer.

Connect the user, then make a call

Create the connection once in AgentKit > Connections. The connection_name you pass in code must match the connection name configured in the Scalekit dashboard exactly; this is the most common integration error.

import os from scalekit.client import ScalekitClient from dotenv import load_dotenv load_dotenv() scalekit_client = ScalekitClient( env_url=os.getenv("SCALEKIT_ENV_URL"), client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), ) actions = scalekit_client.actions connection_name = "lemlistmcp" # must match the connection name in the Scalekit dashboard identifier = "user_123" # your app's stable identifier for this user link_response = actions.get_authorization_link( connection_name=connection_name, identifier=identifier, ) print("Authorize Lemlist:", link_response.link) input("Press Enter after the user authorizes...") result = actions.execute_tool( tool_name="lemlistmcp_check_domain_health", tool_input={"scope": "team"}, connection_name=connection_name, identifier=identifier, ) print(result.data)

Retrieve the authorized surface before you build the agent

Before any tools reach the model, retrieve the tools this user's connected account is authorized to call. This is not exploration of an unknown surface; it is a scoped, deterministic list derived from one user's grant.

scoped = scalekit_client.actions.tools.list_scoped_tools( identifier="user_123", page_size=100, # the Lemlist connector exceeds the default page size ) for tool in scoped.tools: print(tool.name, "-", tool.description)

Scope the surface, then run the agent

The Lemlist MCP connector catalogues 62 tools. At Scalekit's working estimate of roughly 200 tokens per tool definition, that is around 12,400 tokens consumed before the agent does any work, on every run. A campaign audit agent needs five of them.

Surface reduction is the lever here, and it is an accuracy lever before it is a cost lever. A model choosing among 62 outbound tools, several of which spend enrichment credits and several of which mutate live campaigns, will pick wrong more often than a model choosing among five read-and-preview tools. Note that lemlistmcp_call_api is absent from the list below by design.

from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, ToolMessage tools = actions.langchain.get_tools( identifier="user_123", connection_names=["lemlistmcp"], tool_names=[ "lemlistmcp_get_campaigns", "lemlistmcp_get_campaigns_stats", "lemlistmcp_get_campaign_sequences", "lemlistmcp_validate_campaign_readiness", "lemlistmcp_preview_sequence_update", ], page_size=100, ) tool_map = {t.name: t for t in tools} llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [ HumanMessage( "Audit my active campaigns from the last 30 days. " "Flag any campaign with a reply rate under 2% and show me the " "current copy for its first two steps." ) ] while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tool_call in response.tool_calls: output = tool_map[tool_call["name"]].invoke(tool_call["args"]) messages.append( ToolMessage(content=str(output), tool_call_id=tool_call["id"]) )

Scalekit injects the user's Lemlist credential server-side on each call. The token never enters the agent runtime and never appears in LLM context.

One endpoint for multi-tool, multi-tenant agents

A real outbound agent is not Lemlist-only. It reads Lemlist campaign stats, then posts a digest to Slack. Virtual MCP servers let you declare that combined surface once, as a single scoped endpoint, instead of wiring two MCP servers and two credential paths per user.

Two objects drive the model. The server is created once per agent role and returns a static mcp_server_url. The session token is minted before each run and binds that static endpoint to one specific user's connected accounts.

from datetime import timedelta from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = scalekit_client.actions.mcp.create_config( name="outbound-ops-agent", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="lemlistmcp", tools=[ "lemlistmcp_get_campaigns", "lemlistmcp_get_campaigns_stats", "lemlistmcp_validate_campaign_readiness", "lemlistmcp_set_campaign_state", ], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_send_message"], ), ], ) config_id = vmcp.config.id mcp_server_url = vmcp.config.mcp_server_url

Before each run, confirm the user's connections are still active, then mint a short-lived token. This is where a revoked Lemlist grant or an expired refresh token surfaces as an actionable auth link instead of a mid-run failure.

accounts = scalekit_client.actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier="user_123", include_auth_link=True, ) for account in accounts.connected_accounts: if account.connected_account_status != "ACTIVE": raise SystemExit( f"{account.connection_name} needs re-auth: {account.authentication_link}" ) token_response = scalekit_client.actions.mcp.create_session_token( mcp_config_id=config_id, identifier="user_123", expiry=timedelta(minutes=30), ) mcp_server = { "url": mcp_server_url, "headers": {"Authorization": f"Bearer {token_response.token}"}, }

One server definition serves every tenant. The endpoint is static; the identity is not.

Observability for downstream tool calls

Enforcement without evidence does not survive a security review. Every execute_tool call returns an execution_id, and Scalekit's auth logs record authentication and token events across users, agents, and machine clients, filterable by user, organization, method, and status, and streamable to your SIEM or warehouse.

For an outbound tool this matters more than usual. When a campaign gets archived or 500 leads get enriched at cost, "which agent run, acting for which user, under which connected account, called which tool" is the question you need answered in minutes, not the three weeks it takes to reconstruct from application logs. This is exactly the observability challenge production agent teams face.

Which one to build against

If your Lemlist agent is interactive and the user is present, build on the MCP server. The composite tools save you real REST assembly work, and OAuth with dynamic client registration is the only Lemlist path that gives you a proper delegated grant instead of a collected secret.

If your agent runs on a schedule, drives lead state transitions, or exports data, build against the REST API. Those capabilities have no MCP tools, and a pinned version=v2 contract beats composite convenience in a deterministic pipeline.

Most production outbound agents end up on both. What does not change is the credential layer: one credential per Lemlist account, stored, refreshed, and revoked outside your agent runtime, behind a scoped tool surface with an audit trail attached to a real user.

Get help from other Lemlist agent builders

Bring your architecture questions to the people solving them right now. Join the Scalekit Slack community to compare notes with other agent developers, or talk to us if you want help wiring a multi-tenant Lemlist agent this week.

Browse the Scalekit Lemlist MCP connector and the connector documentation.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
zero upfront cost.

Every feature unlocked. No hidden fees.