Connecting Claude Code & Cursor
Hosted on the customer API, so there is nothing to install and nothing to keep running. The transport is streamable HTTP: one endpoint, and the JSON-RPC travels on POST.
Authentication is the same bearer key you use against the REST API. Native agents send no Origin header and need no local bridge software.
claude mcp add --transport http sadasend https://mcp.sadasend.com \
--header "Authorization: Bearer sada_live_sk_…"The 10 tools an agent gets
Every tool is dynamically filtered by the scopes on the key you connect with. A read-only key sees strictly read tools and never sees send tools — an agent cannot plan around or retry an action it will always be refused.
| Tool | Scope | Does |
|---|---|---|
| send_email | send | Send transactional email with automatic channel ("mcp") and agent attribution, subject to allowlist, quota, and approval mode |
| preview_email | send | Preflight dry run — renders and validates recipients, never sends |
| get_email_status | read | Delivery state and event timeline without leaking email body |
| search_emails | read | Find messages by recipient, subject, tag, or status |
| list_domains | read | Sending domains on the account and verification state |
| check_domain_setup | domains | Live DNS lookup for SPF, DKIM, and DMARC with remediation advice |
| list_templates | read | Registered templates on the account with versions |
| render_template | read | Render a Liquid template with variables without sending |
| check_suppression | read | Whether an address is suppressed (bounce, complaint, unsubscribe) and why |
| get_stats | read | Bounce and complaint rates over a window up to 90 days |
Automatic agent attribution & provenance
Every email dispatched via MCP is automatically stamped with channel: "mcp" and source: "agent".
The agent can pass an optional agent_name argument (e.g. "Refund Assistant" or "Support Agent"). If omitted, SadaSend auto-resolves the name from the client handshake (claude-code, cursor) or the key’s configured agent persona.
These dimensions are indexed immediately and roll up into GET /account/stats?provenance=true, giving human operators real-time breakdown matrices by channel, source, and top agent across their entire organization.
{
"name": "send_email",
"arguments": {
"from": "support@yourdomain.com",
"to": "customer@example.com",
"subject": "Ticket #4092 resolved",
"html": "<p>Your inquiry has been resolved.</p>",
"agent_name": "Support Agent",
"tags": ["support", "resolution"]
}
}Model reasonability: refusals vs transport faults
When a guardrail blocks an action — an unauthorized recipient, an unverified domain, or a missing scope — SadaSend answers with standard JSON-RPC tool content flagged with isError: true.
Returned as tool text, the model reads "Recipient stranger@external.com is outside this key's allowlist" and can reason about the restriction or self-correct. Returned as a transport fault, the agent treats the server as broken and retries blindly.
Approval mode: human-in-the-loop
A key minted in approval mode (sada_agent_sk_…) accepts sends and marks them pending_approval. The agent receives confirmation that the email was accepted and held in the account queue.
Nothing hits the wire until a person reviews the draft in the dashboard and clicks Approve. This allows autonomous agents to operate with full drafting power and zero public blast radius.
What is deliberately absent
There is no create_api_key, no delete_domain, and no remove_suppression tool. Not scope-gated — completely absent. Any attempt to invoke them returns standard JSON-RPC -32601 METHOD_NOT_FOUND.
An agent that can mint its own credentials has no ceiling, and one that can remove a suppression can burn your domain reputation with mailbox providers. Those actions live strictly in the dashboard with human session authentication.
Transport security
The server sends no unsolicited notifications, so GET requests for SSE are declined with 405 sse_not_offered. Clients fall back to POST without complaint.
Origin headers from untrusted browser domains are refused with 403 origin_not_allowed to protect against DNS rebinding attacks. Native clients (Claude Code, Cursor) send no Origin header and connect cleanly.