Skip to Content
MCP server

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/mcp

One 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.

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

ToolWhat it does
day3_contextAccount context: audiences, senders, plan state. Call this first.
day3_list_campaignsList campaigns.
day3_get_campaignRead one campaign, including its body.
day3_create_campaignCreate a draft.
day3_update_campaignEdit a draft.
day3_preview_campaignRender it, with theme, merge tags and footer applied.
day3_send_testSend to addresses the caller names. Never the audience.
day3_send_campaignSend to the whole audience. Needs campaigns:send.
day3_schedule_campaignSchedule a send. Needs campaigns:send.
day3_list_automationsList automations, with status and trigger.
day3_enroll_in_automationPut 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.

Last updated on