Skip to content
Browse the docs

Integrating · Published 2026-09-04 · Updated 2026-10-26 · AgentiSend

AgentiSend MCP server — send email from Claude, Cursor and any MCP client

Every tool with the scopes it needs, the rate-limit table, the JSON-RPC error codes, and what an agent cannot do.

AgentiSend is a transactional email API for AI agents. Every tool this MCP server serves, the scopes each one needs, the ceilings it is counted against, and what each refusal means. Generated from the running catalogue: the page, the console tab and the server cannot disagree.

Server URL: https://api.agentisend.com/mcp (streamable HTTP). Bearer API key or OAuth 2.1 — both reach the same tools with the same ceilings. A local stdio launcher is published as @agentisend/mcp-server for clients that only speak stdio; it proxies to this server, so the catalogue is identical.

Each client also has its own page: Cursor, Claude, Claude Code, Claude Desktop, Windsurf, VS Code and GitHub Copilot, Codex, Gemini CLI, Lovable, Bolt, v0, Replit, Zed, OpenCode and Cline.

Claude (web and desktop)

AgentiSend is listed in Claude's connector directory: open https://claude.ai/directory/agentisend in claude.ai or the desktop app and click Connect. To add it by hand instead, open Customize → Connectors, click +, choose Add custom connector and paste https://api.agentisend.com/mcp, then click Connect. Either way, sign in to AgentiSend and approve; Claude holds the connection, so there is no key to copy. Then ask Claude to send a short note from onboarding@agentisend.com to your sign-in address. That sender delivers only to member sign-in addresses, and it needs no domain of yours. An address ending in @simulator.agentisend.com also works before a domain is verified: it costs nothing and reaches nobody.

Claude Desktop's config file runs local servers only, so the URL does not go there; the stdio launcher at the end of the next section does. A connection starts with the same budget as any key, and a person can lower it on the console's Agents screen.

Add it to your client

Every line below carries the same endpoint (https://api.agentisend.com/mcp) and a placeholder key — replace as_YOUR_API_KEY_HERE with a key from the console.

Cursor

cursor://anysphere.cursor-deeplink/mcp/install?name=agentisend&config=eyJ1cmwiOiJodHRwczovL2FwaS5hZ2VudGlzZW5kLmNvbS9tY3AiLCJoZWFkZXJzIjp7IkF1dGhvcml6YXRpb24iOiJCZWFyZXIgYXNfWU9VUl9BUElfS0VZX0hFUkUifX0=

Open this link and Cursor offers to add the server. Replace the placeholder key in Settings → MCP afterwards, or paste the same object into .cursor/mcp.json.

Claude Code

claude mcp add --transport http agentisend https://api.agentisend.com/mcp \
  --header "Authorization: Bearer as_YOUR_API_KEY_HERE"

Or install the plugin, which brings the server and the sending skill together: /plugin marketplace add fortuneflick/agentisend-claude-plugin then /plugin install agentisend@agentisend.

Codex CLI

codex mcp add agentisend --url https://api.agentisend.com/mcp \
  --bearer-token-env-var AGENTISEND_API_KEY

The token stays in your environment; Codex writes only the variable name to ~/.codex/config.toml.

Gemini CLI

gemini mcp add --transport http \
  --header "Authorization: Bearer as_YOUR_API_KEY_HERE" \
  agentisend https://api.agentisend.com/mcp

Check it with gemini mcp list.

VS Code

code --add-mcp '{"name":"agentisend","type":"http","url":"https://api.agentisend.com/mcp","headers":{"Authorization":"Bearer as_YOUR_API_KEY_HERE"}}'

Or write the same server into .vscode/mcp.json under servers.

Windsurf

{
  "mcpServers": {
    "agentisend": {
      "serverUrl": "https://api.agentisend.com/mcp",
      "headers": {
        "Authorization": "Bearer as_YOUR_API_KEY_HERE"
      }
    }
  }
}

Goes in ~/.codeium/windsurf/mcp_config.json, then refresh the MCP panel.

OpenCode

{
  "mcp": {
    "agentisend": {
      "type": "remote",
      "url": "https://api.agentisend.com/mcp",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer {env:AGENTISEND_API_KEY}"
      }
    }
  }
}

Goes in opencode.json; the key is read from your environment rather than written to the file.

Anything else that speaks stdio

AGENTISEND_API_KEY=as_YOUR_API_KEY_HERE npx -y @agentisend/mcp-server

The local launcher proxies to the same server, so the tool list, the budget and the refusals are identical.

Tools (92)

Every tool that changes something accepts idempotency_key: retrying with the same key returns the first result instead of doing the work twice.

Sending

ToolScopesAccepts idempotency_keyDestructive
send_emailemails:sendyes—
send_batchemails:sendyes—
reply_to_emailemails:sendyes—
send_broadcastemails:send, segments:writeyes—

Writes

ToolScopesAccepts idempotency_keyDestructive
create_domaindomains:writeyes—
domains_setup_linkdomains:writeyes—
set_limitlimits:writeyesyes
request_approvalemails:sendyes—
cancel_emailemails:sendyesyes
reschedule_emailemails:sendyes—
verify_domaindomains:writeyes—
add_suppressionsuppressions:writeyes—
remove_suppressionsuppressions:writeyesyes
publish_templatetemplates:writeyes—
upsert_contactcontacts:writeyesyes
delete_contactcontacts:writeyesyes
create_webhookwebhooks:writeyes—
delete_webhookwebhooks:writeyesyes
release_received_emaildomains:writeyes—
revoke_oauth_grant_none_yesyes
replay_webhook_deliverieswebhooks:writeyes—
rotate_webhook_secretwebhooks:writeyesyes
create_templatetemplates:writeyes—
update_templatetemplates:writeyes—
create_broadcastsegments:writeyes—
update_broadcastsegments:writeyes—
cancel_broadcastsegments:writeyesyes
archive_broadcastsegments:writeyes—
create_topictopics:writeyes—
update_topictopics:writeyes—
delete_topictopics:writeyesyes
create_segmentsegments:writeyes—
update_segmentsegments:writeyes—
delete_segmentsegments:writeyesyes
update_domaindomains:writeyesyes
delete_domaindomains:writeyesyes
create_api_keylimits:writeyes—
create_automationsegments:writeyes—
update_automationsegments:writeyes—
enable_automationemails:send, segments:writeyes—
disable_automationsegments:writeyes—
duplicate_automationsegments:writeyes—
stop_automationsegments:writeyes—
delete_automationsegments:writeyesyes
delete_emailemails:sendyesyes
delete_received_emailinbound:readyesyes
domains_inbound_rules_adddomains:writeyes—
domains_inbound_rules_removedomains:writeyesyes

Reads

ToolScopesAccepts idempotency_keyDestructive
get_emailemails:read——
list_emailsemails:read——
get_domaindomains:read——
setup_domaindomains:readyes—
wait_for_domaindomains:read——
get_agent_budgetlimits:read——
get_kill_switch_statelimits:read——
list_pending_approvalslimits:read——
list_agent_actionslimits:read——
explain_emailemails:read——
preflight_emailemails:sendyes—
whoami_none_——
why_was_this_not_sentemails:read——
get_trust_standingtrust:read——
list_domainsdomains:read——
list_suppressionssuppressions:read——
list_templatestemplates:read——
render_templatetemplates:read——
list_segmentssegments:read——
list_contactscontacts:read——
list_webhookswebhooks:read——
list_received_emailsinbound:read——
get_received_emailinbound:read——
list_threadsinbound:read——
list_oauth_grants_none_——
list_more_toolsemails:readyes—
get_email_eventsemails:read——
get_metricstrust:read——
list_logslimits:read——
get_loglimits:read——
list_webhook_deliverieswebhooks:read——
get_templatetemplates:read——
list_broadcastssegments:read——
get_broadcastsegments:read——
list_topicstopics:read——
get_topictopics:read——
get_segmentsegments:read——
list_api_keyslimits:read——
list_automationssegments:read——
get_automationsegments:read——
list_automation_versionssegments:read——
list_automation_runssegments:read——
get_automation_runsegments:read——
domains_inbound_rules_listdomains:read——

Scopes

A key holds scopes; a tool needs some. A tool you cannot call is missing one — whoami returns the scopes this credential holds and the tools they reach.

ScopeWhat it allowsTools
emails:readView messages you have sent, their delivery status and their events6
emails:sendSend email from your verified domains — this delivers real mail to real people and spends the budget on this connection. It also covers asking you to approve a held send10
domains:readView your sending domains, their region and the state of their DNS records5
domains:writeAdd sending domains, change tracking on one, run domain verification, or remove a domain8
webhooks:readView your webhook endpoints and their delivery history2
webhooks:writeCreate, update or remove webhooks, replay deliveries, or rotate a signing secret4
limits:readView the budget, rate ceiling and remaining allowance on each key, the actions waiting for your decision, the keys on this account, and the request log7
limits:writeLower the budget and per-minute ceiling on your keys, which can stop a key sending — raising them, resuming a paused key and creating a new key stay with you2
trust:readView your account standing and the reasons behind it, and the send and delivery counts over a window2
contacts:readView the people in your contact list and what you have recorded about them1
contacts:writeAdd people to your contact list, change what is recorded about them, and remove them2
suppressions:readView the addresses you no longer send to, and why each one is on the list1
suppressions:writeAdd addresses you no longer want contacted, and take one off the list — except where somebody unsubscribed or reported a message as spam, which only you can undo2
templates:readView your templates and preview one with sample values3
templates:writeCreate a template, edit its draft, and publish a version — which decides what the next send using it will say3
segments:readView the groups you have defined and who is currently in them, and the broadcasts and automations on this account9
segments:writeCreate, change or remove contact groups, draft a broadcast to one and send it, and create or enable an automation — sending delivers real mail and spends the budget15
topics:readView the subscription topics contacts can opt into or out of2
topics:writeCreate, rename or remove subscription topics3
inbound:readReceiving is open: turn it on for a verified domain, publish the MX record its page shows, and mail to that domain arrives on your account. Read mail that arrived at your domains — what other people wrote to you, with its attachments — and the conversations it belongs to4

Rate limits

Per-minute ceilings are the same on every plan and are counted per API key, by operation class. What a plan changes is how much you may send in total. No paid plan has a daily cap; delivery to each inbox provider is paced by our sending addresses and rises as they warm.

Operation classCalls per minute per keyTools
read12044
write6044
send304
PlanEmails included per monthPlan daily cap
Free5,000170
Starter30,000none
Pro50,000none
Scale100,000none

JSON-RPC error codes

Every refusal arrives as a tool result carrying code, message, fix, reason, retryable and jsonrpc_code. Branch on jsonrpc_code or reason, never on the message.

CodeNameWhenWhat to doWait hint
-32001insufficient_scopeThe key is valid but was not granted a scope this tool requires.Read missing_scopes in the error data — it names exactly which ones. Ask the person to create a key with those scopes and reconnect. Retrying with the same key fails identically.none
-32002rate_limitedThe per-minute ceiling for this operation class was reached.Wait retry_after_seconds and repeat the same call. This is the ONLY refusal class where waiting is the fix.retry_after_seconds
-32005limit_reachedA configured ceiling was hit — the send budget for the period, or a plan cap.Stop. Waiting does not cure it: a person raises the number or the period rolls over. get_agent_budget says when the period resets.none
-32006not_foundNo such record on this account.Check the id. Do not retry — the same id will be absent next time too.none
-32008conflictThe record already exists, or changed under you.Read the current state and decide again. A blind retry repeats the conflict.none
-32009failed_preconditionThe request is well-formed but something about the account state refuses it — an unverified domain, a suppressed recipient, a paused key, a held send.Read fix: it names the endpoint or the person. This class covers every deliberate stop, and none of them is cured by retrying.none
-32010temporarily_unavailableA dependency was briefly unavailable.Retry once after retry_after_seconds. If it repeats, report it and stop.retry_after_seconds
-32602invalid_paramsThe arguments did not validate. Nothing ran.The issues list names every field to correct. Retrying unchanged fails the same way.none
-32603internal_errorSomething failed that should not have.Retry ONCE after a short pause with the same idempotency_key, then stop and report the request_id from the error. It identifies this exact failure in support.none

The refusals you will actually meet

Error codeJSON-RPCRetryableFix
kill_switch_active-32001no — waiting cannot helpRead GET /trust/standing for why it was paused. Only a person signed in to the console can resume it; the paused key cannot resume itself.
agent_budget_exceeded-32005no — waiting cannot helpWait for the period to reset — get_agent_budget and GET /limits/keys/:id both say when. Raising a budget is a person’s decision, made in the console; a key cannot raise its own.
approval_required-32001no — waiting cannot helpDo not send it again: a person approves or rejects it in the console under Agents → Approvals, and approving sends it — the message then appears in GET /emails. action_id in this error names the held send; the key that asked cannot approve itself, and a retry waits on the same approval.
trust_paused-32001no — waiting cannot helpReview reasons via GET /trust/standing, then file an appeal via POST /trust/appeal.
rate_ceiling_exceeded-32002after 60sWait the seconds below and send the same request again. Raising the ceiling is a person’s decision, made in the console; a key cannot raise its own.
rate_limiter_unavailable-32010after 5sRetry in a few seconds. Nothing was sent and nothing was changed — writes are refused rather than run unmetered against a shared sending reputation.
restricted_api_key-32001no — waiting cannot helpUse a full_access key (POST /api-keys with permission=full_access) for management endpoints.
suppressed_recipient-32009no — waiting cannot helpGET /suppressions says which address and why. A hard bounce you have fixed can be cleared with DELETE /suppressions/:id; an unsubscribe or a spam complaint cannot — that address asked not to be contacted.
domain_not_verified-32001no — waiting cannot helpIf it is pending, publish the required records from GET /domains/:id; checks continue for 72 hours. Test now by sending to an address ending in @simulator.agentisend.com. If it is not registered, POST /domains first. If it is failed, GET /domains/:id names the record to fix, then POST /domains/:id/verify to reopen the window.

What an agent cannot do here

These are deliberate stops with a person on the other end, not gaps.

  • Lift your own kill switch. A rest an agent can cut short is not a rest. _A person, on the Agents screen in the console. You may stop yourself at any time — POST /limits/keys/:id/kill and /limits/kill-all stay open to a key._
  • Approve your own held send. Approval you can grant yourself is not approval. _A person, in the approvals inbox. Use request_approval to ask; list_agent_actions to hear the answer._
  • Raise your own budget or your own per-minute ceiling. A budget an agent can raise is not a budget. _A person, on the Agents screen in the console. set_limit and PATCH /limits/keys/:id still lower a key, so an agent can always cap itself before a job._
  • Raise the account trust standing, or waive a trust pause. Trust is earned by delivery outcomes, not asserted. _Nobody directly — it changes as your sending does. POST /trust/appeal asks a human to look._
  • Read the contents of a message you were stopped from sending. A held-mail queue an agent can read verbatim is a way to read the mail it was stopped from sending. _A person, in the console. Tools see shapes: recipient counts, whether there is a body._
  • Send to an address that asked not to be contacted. Suppression is the whole reason the account is allowed to send at all. _Nobody, while the suppression stands. remove_suppression clears a hard bounce you have fixed; an unsubscribe or a spam complaint is refused, because somebody said no and only they can change that._
  • Send unsolicited mail to people who did not ask for it. Unsolicited mail is refused; there is no tool for it. _Nobody, at any tier, by any route. There is no endpoint for it._