Last updated: 2026-08-11.
The map of every tool the Sender MCP server exposes, the conventions
they all share, and the recipes that span multiple tools. Per-tool input schemas are
self-describing (an MCP client discovers them via tools/list); this document is the overview
a human — or an LLM’s system prompt — reads first.
Hashed ids. All identifiers are opaque hashed strings, a hashed id from one tool is valid input to any other.
Timestamps are ISO 8601 UTC.
Pagination is a uniform envelope: {items, page, per_page, total, has_more}.
Failures are readable. Every failure is a tool error with a message written for the
caller — what went wrong, and usually which tool to call next (see list_domains,
use get_event_types, …). No opaque transport errors, no silent partial successes.
Idempotency. Creation tools accept an optional idempotency_key; retrying with the same
key returns the originally created resource instead of duplicating it (24 h window).
Warnings, not surprises. Responses carry a warnings array when something is legal but
probably not what the caller meant (legacy {$…} variables, counts still recalculating).
Round-tripping. What a client writes is what it reads back, in the same vocabulary —
create_segment/get_segment, create_workflow/get_workflow,
update_email_campaign_content/get_email_campaign all share shapes. Stored data the public
vocabulary cannot express is surfaced as {"supported": false, "reason": …, "raw": …} rather
than dropped.
Humanized readbacks. Complex structures come with an English rendering
(conditions_for_humans on segments, steps_for_humans on workflows) so a caller can verify
intent — branch direction, AND/OR scope — without re-deriving it from the structure.
Draft-first. Nothing this server creates sends or runs by itself: campaigns are created
as drafts and never sent here; workflows are created as drafts, and activation is a separate,
deliberate tool call.
Not literal plain text — a simple person-to-person style email in basic HTML (<p>, <br>, <a>), the way a Gmail message looks. Only the inner markup is submitted/stored; a full document wrapper (<html>, <body>, styling) is added automatically at send time
yes
drag_and_drop
Designed in the dashboard’s block builder. The block structure, not the compiled HTML, is the source of truth
read-only; replacing one with html/text requires overwrite: true and permanently discards the design
Personalization is Liquid: {{ firstname }}, {{ email }}, {{ unsubscribe_link }}.
Content is stored exactly as passed; legacy {$variable} tokens are not converted and would
reach subscribers as literal text — every content write scans for them and warns.
Read-backs include content, content_type, and editable_via_mcp.
from_email must be on an account sending domain — list_domains reports each domain’s
status and a ready_to_send flag (the exact conjunction sending/activation requires).
A workflow is a strict tree: a single trigger, linear runs as arrays, conditions branching via
then/else, splits via a/b.
Reading:
Tool
Access
What it does
list_workflows
R
Browse automations with light engagement stats
get_workflow
R
The full graph in the public vocabulary: trigger (with its step id), nested steps, steps_for_humans, incomplete_steps (what blocks activation, with reasons), unreachable-step surfacing. SMS bodies are inlined; email bodies are by reference
get_workflow_report
R
Performance report (+ revenue when entitled)
get_workflow_step_content
R
One email step’s envelope + body (§3), or an SMS step’s text + content_as_sent
Creating & validating:
Tool
Access
What it does
create_workflow
W
The whole graph in one call (title + trigger + nested steps). Always a draft. Steps may carry a key so conditions can reference them (if.step). Throttled at 50 creations/account/day
validate_workflow
R
Dry-run: a document (pre-create structural + reference checks with pathed errors) or an existing workflow (the full activation checklist, all problems at once)
Editing (all refuse while the workflow is active — deactivate first; subscribers keep their
place):
Tool
Access
What it does
rename_workflow
W
Title only
update_workflow_step
W
Reconfigure one step by id. Type is immutable. Per type: email envelope, delay settings, a wholesale condition if, split percentages, action settings, a wholesale trigger object (on the trigger step — replacements that would break context conditions are refused)
add_workflow_steps
W
Insert a steps fragment anywhere — (parent_step_id, branch: next/then/else/a/b). Existing steps in the slot re-attach after the fragment (non-destructive); continue_branch picks the leg when the fragment ends in a branch. Fragment conditions may reference existing steps via if.step_id
delete_workflow_step
D
Splice one step out (children take its place; branching steps need keep_branch — the other branch is deleted) or delete a subtree (delete_children). Refuses to drop subscribers parked on affected steps without force: true; reports dropped_subscribers
update_workflow_email_content
W
An email step’s body (§3 rules)
update_workflow_sms_content
W
An SMS step’s message + sending number (list_phone_numbers); returns content_as_sent (opt-out line, org name applied). Max 1600 chars
Lifecycle:
Tool
Access
What it does
activate_workflow
W
Runs the full pre-flight checklist (shared with the dashboard); if anything blocks, nothing activates and all problems are returned. On success the workflow goes live and mid-journey subscribers resume
deactivate_workflow
W
active → draft. Nothing is lost; required before any editing
Creation is always draft; going live is one deliberate tool (activate_workflow) with a
full pre-flight checklist shared with the dashboard.
Active workflows are immutable through this surface; deactivation preserves all subscriber
progress.
Destructive operations name their blast radius and require an explicit flag
(force for dropping waiting subscribers, overwrite for discarding drag & drop designs).
create_workflow is rate-limited (50/day/account) as an agent-runaway backstop; idempotency
keys make retries safe without consuming quota.