Skip to content

MCP server

Connect your AI tools, Claude Code, Claude Desktop, Cursor, or anything else that speaks MCP, straight to your Mara workspace. Your agent can read your programs, drafts, sends, and Playbook, and act on your behalf: draft a program, approve a send, pause something that is not working. It runs under the same guardrails as your dashboard chat.

This page is the complete spec, written for humans and for AI coding agents. The raw markdown lives at hiremara.com/docs/mcp.md. The fastest path: open Settings, then Integrations, then MCP (AI tools) in your dashboard, generate a key, and copy the ready-made connect command.

What it is

POST /api/mcp is a remote MCP server over Streamable HTTP. Every call authenticates, resolves your workspace, runs one tool, and returns. There is no separate session to manage; each request carries your key and stands on its own.

Authentication

Auth is a per-workspace key with the prefix mara_mcp_, generated from Settings, Integrations, MCP (AI tools). The raw key is shown exactly once at generation; Mara stores only a hash. You can hold several live keys at once, one per machine or agent, and revoke any of them without touching the others.

Send it as a bearer token:

Authorization: Bearer mara_mcp_...

This is a credential for your own tools, not a public API. Keep it out of source control the same way you would an API key for any other service.

Connect Claude Code

claude mcp add --transport http mara https://hiremara.com/api/mcp --header "Authorization: Bearer <your-mcp-key>"

Run it once from anywhere; Claude Code remembers the connection. Your settings row's copy button fills in your real key.

Connect Claude Desktop

Add an entry to your MCP config (Settings, Developer, Edit Config in Claude Desktop):

{
  "mcpServers": {
    "mara": {
      "url": "https://hiremara.com/api/mcp",
      "headers": {
        "Authorization": "Bearer <your-mcp-key>"
      }
    }
  }
}

Restart Claude Desktop after saving.

Connect Cursor

Cursor reads the same shape. Add it under Settings, MCP:

{
  "mcpServers": {
    "mara": {
      "url": "https://hiremara.com/api/mcp",
      "headers": {
        "Authorization": "Bearer <your-mcp-key>"
      }
    }
  }
}

The approval promise

Nothing sends to a customer without approval in your dashboard queue, unless your own policy gate says otherwise (for example, a reply-autonomy setting you turned on yourself). Drafting tools call a model and can take up to a minute or so to return; everything else is a fast read or a direct database action. A drafted email lands pending_approval exactly the same way it would from chat: you approve it, or Mara's autonomy setting does, never the tool call by itself.

Connect your product

If you self host, or you have no CRM connected, the fastest way in is to hand your coding agent one instruction: set up the Mara API for me. Two tools close the loop end to end, in one conversation, without you ever opening Settings:

  1. setup_events_ingestion mints your ingestion key (or reports its status if one already exists), hands your agent the exact endpoint URL, and optionally maps which event means "a new user signed up."
  2. Your agent writes the integration, using the linked spec at /docs/api.
  3. check_recent_events confirms the test event your agent fires actually landed, with a per-connector health summary, so you get a "done, verified" report instead of a "should be working" guess.

Both tools are MCP-only: they never appear in your dashboard chat, since chat is not the place for a raw ingestion key to surface.

Tools

Ten tools only ever read:

ToolWhat it does
list_pending_draftsList email drafts awaiting your approval.
list_active_programsList programs currently active or paused.
list_draft_programsList programs awaiting your approval, with enough detail to approve one directly.
list_segmentsList saved segments with current sizes.
list_learningsList entries from the Learning Ledger, Mara's Playbook.
list_sentList recent emails from the send queue, with status and failure reasons.
contact_send_historyEverything one contact has been sent or has queued, across all programs.
get_program_detailInspect one program's steps, copy, and live variant arms in depth.
get_journey_spineRead your product journey state spine (funnel stages), in order, with each state's confirmed inbound events.
get_domain_statusRead your sending domain's name, status, DNS records, and whether the send-from mailbox is provisioned.

Twenty-three tools act, each holding to the same approval promise above:

ToolWhat it does
approve_draftApprove one pending email draft so it can send.
reject_draftReject one pending email draft so it will not send.
draft_programDraft a new event-entry program for you to approve.
draft_segment_programDraft a new program that targets an existing saved segment.
approve_programActivate a draft program so it starts firing.
edit_programEdit an existing program's steps, timing, or entry event.
pause_programPause one active program.
resume_programResume one paused program back to active.
archive_programArchive one program for good.
draft_segmentCreate a new saved segment from a plain-English description.
approve_segmentActivate a proposed segment so it can be targeted.
add_learningAdd an entry to the Learning Ledger.
retire_learningRetire an entry from the Learning Ledger.
add_suppressionAdd an email address to the suppression list.
rewrite_variantFix a program variant whose copy keeps failing to send.
retire_variantRetire one program variant; the bandit shifts send-share to the rest.
dismiss_held_sendsClear held sends (permanently failed, never retried) from the Activity feed.
configure_journey_spineAdd, rename, reorder, or remove states on your product journey spine, set a state's kind, and set the goal.
set_event_mappingConfirm or reject what one event means: which state it advances a contact into, or that it is not a step.
register_sending_domainRegister your sending domain and get back the DNS records to add.
set_email_appearanceSet your signature logo and the accent color for your single filled CTA button.
capture_founder_voiceHand Mara 1-3 real emails you wrote so she can distill and draft in your real voice.
refire_contact_into_programRe-enter one contact into a program by re-firing its entry event for them, to recover someone who genuinely missed it.

configure_journey_spine shapes the state spine container only, the funnel stages themselves, not what any event means. Confirming or rejecting what an event means used to be a founder-only decision on the Programs page. It no longer is: set_event_mapping lets your agent make that call directly, on your explicit instruction, the same trust model as approve_program or pause_program. It appends to the same append-only mapping log the Programs page confirm UI writes to, so the latest decision always wins, and nothing is ever silently edited or removed.

register_sending_domain registers through the exact same path the dashboard domain page uses, so it never silently replaces a live domain: registering the same domain again just hands back the existing records, and a different domain already on file is refused with a note that changing it is a dashboard action. It also refuses, without registering anything, if the exact domain is already registered to a DIFFERENT Mara workspace, since domain identity isn't shared across workspaces; that refusal never names or otherwise identifies the other workspace.

set_email_appearance is a partial update: every field is optional and whatever you omit keeps its current saved value. A too-light accent color is accepted and saved rather than rejected, exactly like the Settings editor, since the actual guard is a render-time fallback to a neutral dark button fill, not a save-time rejection.

capture_founder_voice takes raw writing samples only: 1-3 real emails, pasted as-is, plus an optional short note. There is no field for formality, cadence, or any other trait of your voice; Mara infers all of that herself from the samples. It returns only a plain-language summary of what she learned, never the underlying fingerprint. A missing model or a failed distillation returns a clean error and never touches any voice you already captured.

refire_contact_into_program is a real action, not a diagnostic: on success it can result in a real email being drafted and sent to the contact you name, through the exact same pipeline a genuine signup uses. Use it only to recover someone who genuinely missed a program, for example an ingestion failure that swallowed their original signup event. It mints a fresh identity for every call, so calling it twice for the same contact fires twice rather than silently doing nothing the second time; only call it once per contact you mean to recover. It refuses plainly, and never claims a send happened, when the contact is already partway through the program, already received that step, suppressed, or the program has no matching entry trigger.

One tool is Mara herself:

ToolWhat it does
ask_maraHand Mara a question or an instruction and get her real answer back, run through the same model, system prompt, and tool loop as your dashboard chat companion. The turn is saved into your real chat history, so it shows up in your dashboard too.

Two tools set up and verify your own product's event integration. They are MCP-only: they never appear in your dashboard chat, since a raw ingestion key has no business surfacing there.

ToolWhat it does
setup_events_ingestionMint your Mara API ingestion key (or report its current status), hand back the exact endpoint URL, and map your signup event.
check_recent_eventsConfirm recent events actually arrived, with event type, timing, contact identity, and a per-connector health summary.

If you connected before August 2026

The email-sequence tools used to be named *_journey: draft_journey, approve_journey, edit_journey, pause_journey, archive_journey, resume_journey, list_active_journeys, list_draft_journeys, get_journey_detail, draft_segment_journey, refire_contact_into_journey. We renamed them to *_program, because a program is the email sequence Mara runs and a journey is now only ever your customer's path through your product. The full mapping is in the glossary.

Every old name still works, so an agent mid-session does not break. They are marked deprecated in the tool list and will be removed in a future release, so prefer the *_program names in anything you save. get_journey_spine and configure_journey_spine were not renamed: they operate on the customer journey, which is still called a journey.

Rate limits

The endpoint allows 60 calls per minute per key. ask_mara is stricter on top of that: 10 calls per minute per key, and 200 per day per workspace, since each call is a real model turn rather than a cheap read. Over a limit you get a clean tool error naming the wait, not a broken connection.

Verify it landed

Ask your agent to call list_active_programs or list_pending_drafts first. A working connection returns your real workspace data immediately; a wrong or revoked key returns an authorization error before anything else runs.

For AI coding agents

If you are an agent setting this up for a founder, the checklist:

  1. Tell the founder to generate a key from Settings, Integrations, MCP (AI tools), and copy it into your config or the connect command. Never ask for it in plain chat if a copy button is available.
  2. Register the server with the client the founder is using (Claude Code, Claude Desktop, Cursor) using the blocks above.
  3. Confirm the connection with a read-only call (list_active_programs is a good first check).
  4. If the founder self hosts or has no CRM connected, call setup_events_ingestion to mint their key and get the exact endpoint URL, write the integration against /docs/api, then call check_recent_events after firing a test event to confirm it landed. Never mint a second key with rotate: true on a routine check; that revokes the founder's live key.
  5. Remember every action tool still lands pending_approval in the dashboard, or waits on the founder's own autonomy setting. Do not tell the founder something "sent" because a tool call returned; check list_sent or the dashboard for the real outcome.
  6. Treat every key like any other credential: one per machine, revoked the moment a machine is retired.