These twelve tools cover Engage’s planning surface: the campaigns you run, the deliverables that make them up, the personas and accounts a campaign is aimed at, and the performance figures that come back afterwards. There is an honest seam running through all of it. These tools plan and record; they do not send. Creating an email deliverable schedules a piece of work — it does not put a message in anybody’s inbox, and no tool here does.
If you are looking for the distribution channels a page publish fans out to, or the merged plan calendar that shows scheduled revisions and deployments alongside campaign work, those live with the publishing tools on MCP Tools: Publishing, Distribution and Users.
All twelve tools are also available in the Leed Assistant, and all gate on the contact:read and contact:write privileges — with one exception noted below, which needs contact:publish and is not on the MCP surface at all.
Campaigns
list_campaigns
GET /api/campaigns · Returns { campaigns } · Confirm-gated: no
Takes no parameters.
create_campaign
POST /api/campaigns · Returns { campaign } · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
name | string, min 1 | Yes | — | Campaign name |
status | draft | scheduled | active | No |
subject | string or null | No | — | Email subject line |
preview | string or null | No | — | Email preview / preheader text |
Only name is required. A new campaign starts in draft, and it is moved to scheduled for you when a deliverable is approved — you rarely need to set status by hand.
update_campaign
PUT /api/campaigns/:id · Returns { campaign }, or 404 · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | Yes | — | Which campaign to edit |
name | string, min 1 | No | unchanged | — |
status | draft | scheduled | active | No |
subject | string or null | No | unchanged | — |
preview | string or null | No | unchanged | — |
Deleting a campaign is not an MCP action — delete_campaign is registered but never shown to an MCP client, because it cascades the campaign’s audience targeting with it.
Deliverables
A deliverable is one dated item on a campaign’s plan: a page to publish, a site to deploy, an email to send.
list_campaign_deliverables
GET /api/campaigns/:id/deliverables · Returns { deliverables } · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | Yes | — | The campaign id |
Ordered by sequence, then by date.
create_campaign_deliverable
POST /api/campaigns/:id/deliverables · Returns 201 with { deliverable } · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | Yes | — | The campaign to add the deliverable to — not a deliverable id |
title | string, min 1 | Yes | — | Deliverable title |
type | new-page | republish | site-update | email |
scheduledDate | integer | Yes | — | Publish or send time, in milliseconds since the epoch |
pageId | string or null | See below | — | A page publish or republish |
deploymentId | integer or null | See below | — | A site deploy |
leadBatchId | string or null | See below | — | An email send |
sequence | integer | No | — | Ordering within the plan |
detail | string or null | No | — | Free-text detail |
assigneeId | string or null | No | — | CMS user id responsible for it |
{
"id": 7,
"title": "Publish the Q3 launch post",
"type": "new-page",
"scheduledDate": 1780272000000,
"sequence": 1,
"pageId": "9f1c0f5e-6b1a-4b2e-9a77-0c2d5a1f8e10",
"assigneeId": "usr_4b2c"
}Approving and deleting a deliverable are not MCP actions
approve_campaign_deliverable and delete_campaign_deliverable are both registered tools that an MCP client is never shown. Approval is the publish-tier gate — it needs contact:publish, and approving any deliverable moves its campaign from draft to scheduled — so it belongs with the other things a person signs off on. Both are available in the Leed Assistant, where they park and wait for your approval; Leed Assistant shows what that looks like. The overlay a person uses to approve a whole campaign’s worth of items at once is described in Campaigns and Deliverables.
Audience
A campaign’s audience is a set of persona ids and account ids. Reading it is ordinary; replacing it is the one tool on this page that stops and asks.
get_campaign_audience
GET /api/campaigns/:id/audience · Returns { personaIds, accountIds } · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | Yes | — | The campaign id |
Ids only. Resolve persona ids with list_personas and account ids with list_engage_accounts.
set_campaign_audience
PUT /api/campaigns/:id/audience · Returns { ok: true } · Confirm-gated: yes, in local mode
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | Yes | — | The campaign to retarget |
personaIds | array of integers | No | [] | Persona ids to target |
accountIds | array of integers | No | [] | Account ids to target |
confirm | boolean | No | false | Omit for a preview; true to execute |
Two-phase confirmation
set_campaign_audience replaces the audience wholesale. Whatever arrays you send become the campaign’s targeting; anything you left out is removed. Omitting personaIds and accountIds entirely defaults them both to [], which clears the audience.
Because MCP clients have no uniform way for a server to interrupt and ask a question, that approval is expressed inside the tool contract instead. This tool is gated in local mode, which means the MCP layer refuses to dispatch the call at all until it is confirmed, and builds the preview itself rather than asking the API route for one. The first call — with confirm omitted or false — changes nothing and returns:
{
"preview": true,
"action": "set_campaign_audience",
"summary": "Replace campaign 7's audience targeting wholesale with 2 persona(s) and 5 account(s).",
"effects": [
"personaIds → [3, 9]",
"accountIds → [11, 12, 14, 21, 33]"
],
"instruction": "This was a preview — nothing was changed. Present this plan to the user and ask for approval; only call set_campaign_audience again with the same arguments plus confirm: true after the user explicitly approves."
}Your client shows you that plan; you approve it; the model calls the tool again with the same arguments plus confirm: true. There is no separate endpoint, no token and no session state to carry — the same arguments, twice. Why the mechanism exists at all, and what the other confirm-gated tool does, is explained once on How Leed’s AI Is Guarded.
Campaign performance
get_campaign_email_metrics
GET /api/campaigns/:id/email-metrics · Returns { summary, batches } · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
id | integer | Yes | — | The campaign id |
Rolls up real per-recipient engagement across every email deliverable in the campaign that has a lead batch behind it. summary totals batches, recipients, sent, opened, clicked, unsubscribed and bounced; batches breaks the same figures out per send.
These are true aggregates, never estimates or placeholders. A campaign that has not sent anything yet returns a zeroed summary and an empty batches array — not an error. Where the open and click numbers come from, and what they can and cannot tell you, is covered in Tracked Links and Open Tracking.
Personas
A persona is a buyer archetype. Engage matches contacts to personas by job title during a score recompute, and campaigns target personas rather than individual people.
list_personas
GET /api/personas · Returns { personas } · Confirm-gated: no
Takes no parameters. Ungated by plan.
create_persona
POST /api/personas · Returns { persona } · Confirm-gated: no
Only name is required.
Every persona field
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
name | string, min 1 | Yes | — | Display name, e.g. “VP of Engineering” |
role | champion | economic | decision | influencer |
summary | string or null | No | — | Who this persona is |
goals | string or null | No | — | What they are trying to achieve |
pains | string or null | No | — | Problems that motivate them |
triggers | string or null | No | — | What makes them start looking |
objections | string or null | No | — | Why they might say no |
preferredContent | string or null | No | — | Formats they engage with |
kpis | string or null | No | — | How they are measured |
Every field except name is free text, so these are as much a brief for the model as a database record — a persona with real pains and objections written out gives a drafting prompt something to work from.
update_persona
PUT /api/personas/:id · Returns { persona } · Confirm-gated: no
Takes id (integer, required) plus any of the fields above. Only what you send changes.
Deleting a persona is not an MCP action; delete_persona is assistant-only. If a persona is deleted, run recompute_engage_scores afterwards — persona assignments on contacts are only rewritten by a recompute, so stale matches survive the deletion until then. Personas covers persona matching from the Engage side.
list_campaigns_for_persona
GET /api/campaigns/for-persona/:personaId · Returns { campaigns } · Confirm-gated: no
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
personaId | integer | Yes | — | The persona id |
The reverse lookup: every campaign that targets this persona. Note that this one lives on the campaign routes and therefore carries the campaign-planner gate, unlike the other three persona tools.
If the tool name you came here for is not on this page, the Operator MCP Tool Index lists every tool alphabetically with the page that documents its parameters.