MCP server
day3 runs a Model Context Protocol server, so an AI editor can work with your campaigns and automations directly. A draft lands in day3 as editable composer blocks rather than opaque HTML, so what the assistant writes is still yours to edit by hand.
https://go.day3.app/api/mcpOne HTTP endpoint, authenticated with the same API key as the REST API. There is nothing to install and nothing to run locally.
Setup
All three editors do the same thing, which is point at one URL and attach the key as a header. They just disagree about where that gets written down.
Claude Code
Run this in your project, then ask Claude to write you an email.
claude mcp add --transport http day3 https://go.day3.app/api/mcp --header "Authorization: Bearer $DAY3_API_KEY"Keep this on one line, however long it gets. A \ continuation is bash
syntax: cmd.exe wants ^ and PowerShell a backtick, so on Windows the second
line runs as its own command and the --header never arrives. That fails in the
worst way, silently. The server is added without a credential, so it returns 401,
the client falls back to OAuth discovery, hits our HTML 404, and reports
Invalid OAuth error response: Unrecognized token '<', which says nothing at all
about a missing header.
Tools
| Tool | What it does |
|---|---|
day3_context | Account context: audiences, senders, plan state. Call this first. |
day3_list_campaigns | List campaigns. |
day3_get_campaign | Read one campaign, including its body. |
day3_create_campaign | Create a draft. |
day3_update_campaign | Edit a draft. |
day3_preview_campaign | Render it, with theme, merge tags and footer applied. |
day3_send_test | Send to addresses the caller names. Never the audience. |
day3_send_campaign | Send to the whole audience. Needs campaigns:send. |
day3_schedule_campaign | Schedule a send. Needs campaigns:send. |
day3_list_automations | List automations, with status and trigger. |
day3_enroll_in_automation | Put one person into a flow. Needs automations:enroll. |
Sending is off by default
day3_send_campaign and day3_schedule_campaign require a key with the
campaigns:send scope, and day3_enroll_in_automation requires
automations:enroll. Both are off unless you explicitly enabled them when
minting the key.
This matters more for an agent than for a script. A script does what its author wrote. An agent holding the same key decides for itself, and “email everyone on the list” is not a decision to hand over by default.
Enrolling is scoped by the same test: it puts mail in a stranger’s inbox, and one call promises them every email in the flow. Listing automations is not scoped, because it names flows rather than people.
day3_send_test is deliberately not scoped. It only reaches addresses the
caller names, it is capped and rate-limited, and it is the whole point of letting
an editor iterate on an email. So the default setup gives your assistant a full
write-draft-preview-test loop and stops exactly at the audience.
If you do want an agent to be able to send, mint a second key with the scope on. It cannot be added to a key that already exists, which keeps the grant visible in your key list rather than buried in an edit history.
A typical session
Once the server is connected, this works:
Read our last three campaigns, then draft an August release note in the same voice. Cover sending domains and the new API. Preview it and send me a test.
The assistant calls day3_context to find your audience and sender,
day3_list_campaigns and day3_get_campaign to pick up the voice,
day3_create_campaign to write the draft in day3
Markdown, day3_preview_campaign to check it renders,
and day3_send_test to put it in your inbox.
The draft is then sitting in day3 waiting for you, as real composer blocks. Nothing has reached your list.
Keeping the key out of prompts
Do not paste an API key into a prompt. Prompts get copied into third-party chat tools, into issue trackers, and into logs.
Set DAY3_API_KEY in your environment and let the editor’s config read it, as in
the Claude Code and VS Code examples above. When you want an assistant to use the
REST API directly rather than MCP, tell it to read the key from the environment
rather than handing it over.