Connect an MCP-compatible agent to Dairo's hosted server to send mail, run inboxes, read messages, and react to events.
Connect your agent to Dairo's hosted MCP server and it can send mail, run inboxes, read messages, and react to events in plain language, with no integration code. Every tool ships a strict JSON Schema, destructive actions ask for confirmation first, and complaint safety is on by default.
Connect a client
Add the hosted endpoint to your MCP client and approve access on first use. The
server lives at https://mcp.dairo.app/mcp over streamable HTTP.
dairo mcp install --client auto configures your installed coding-agent clients
and writes a project .mcp.json where that makes sense.
Once connected, ask in plain language:
"Create an inbox
triage@yourapp.com, then show me the last 10 messages it received."
The agent picks the right tools, confirms before anything changes, and returns structured results.
Read tools and write tools
The server exposes Dairo's surface as verb-first tools, paired so most domains
have one read tool and one write tool. Read tools carry readOnlyHint: true
and never mutate; write tools carry a truthful destructiveHint, and most require
an explicit confirm: true — the message sends are the exception. Most tools take
an action argument that selects the operation within their domain.
Read tools and the action values each accepts:
| Read tool | action values |
|---|---|
read_mailbox | listMessages, getMessage, listThreads, getThread, getAttachmentUrl, getAttachmentLink, downloadAttachment, downloadMessageAttachments |
list_sent_messages | list, get, listEvents, listBounces, listComplaints, diagnose |
list_events | list (pass tail: true to stream only-new events) |
list_inboxes | list, getSchema |
get_verification_codes | list, get |
list_domains | list |
list_webhooks | list, listDeliveries |
list_api_keys | list |
list_templates | list, get |
list_audiences | list, get |
list_contacts | list, get, messages |
list_budgets | list, get |
list_agents | list, get, verify, jwks, listReputation |
list_a2a_messages | list, get |
list_storage | listBuckets, getBucket, listObjects, getObjectUrl, getUploadStatus, listShareOpens, getOrgSlug |
list_letters | list, get, getBatch, listEvents, price |
list_phone_calls | list, get, transcript, recording |
list_phone_numbers | list, get, available |
get_account_info | whoami, usage, storage, getNotifications, listOrganizations |
get_compliance_reports | listAuditLogs, auditExport, getResidency, getErasureJob |
verify_message | (no action — the cross-tenant message-provenance verdict) |
search_voices, search_docs | (no action — query-based) |
Write tools. Most actions require confirm: true (each action's schema says
which); the three message sends — send_message, send_broadcast, and
text_to_speech — are gated by the messages:send scope and take no confirm:
| Write tool | action values |
|---|---|
send_message | (no action — the core outbound send, with sendAt scheduling; gated by scope, no confirm) |
send_broadcast | sends one message to every member of an audience |
manage_sent_messages | cancelScheduled, edit, react, unreact |
delete_messages | batchDeleteMessages (destructive) |
manage_inboxes | create, delete, setSchema, deleteSchema |
await_verification_code | await, cancel — wait for an OTP or signup code to arrive and get it extracted |
manage_domains | create, recheck, delete |
manage_webhooks | create, delete, ping, pause, resume, redrive |
manage_api_keys | create, revoke |
manage_templates | create, publishVersion, archive |
manage_audiences | create, addMembers, delete |
manage_contacts | create, update, addHandle, removeHandle, delete |
manage_budgets | set, delete |
manage_agents | create, bind, delete |
manage_account | updateNotifications, createOrganization, deleteOrganization |
manage_storage | createBucket, deleteBucket, deleteObject, batchDeleteObjects, createUploadLink, createMultipart, completeMultipart, abortMultipart, createShareLink, createShareBundle, revokeShareLink, setOrgSlug, clearOrgSlug |
replay_event | replay — re-delivers a past event to your webhook endpoints |
prepare_letters | requirements (layout spec + compliant starter templates — start here), verify (pre-send layout check), listTemplates, getTemplate, createTemplate, updateTemplate, previewTemplate — template mutations take confirm |
send_letters | send, sendBatch, cancel (physical postal mail — run prepare_letters{action:"verify"} first) |
make_phone_call | (no action — places a real outbound AI call; confirm: true) |
manage_phone_calls | hangup (end a live call) |
manage_phone_numbers | buy, update, release |
text_to_speech | synthesizes speech; find a voice with search_voices |
Creating an organization with manage_account is open only to the owner of a
billing organization (403 otherwise) and stops at 10 owned organizations (409);
the new organization bills to the caller's existing billing organization.
Ask in plain language and the agent picks the right half: "list inboxes" calls
list_inboxes; "create an inbox" calls manage_inboxes with
{ "action": "create", ..., "confirm": true }. Each tool's full JSON Schema,
title, and safety annotations ship in tools/list.
The tool catalog
A machine-readable index lives at GET https://api.dairo.app/v1/mcp/catalog. It
carries toolCount, the families list, the declared scopes, and a
confirmRequiredTools array — plus one entry per tool with name, a one-line
summary, its scopes, and a confirmRequired flag. The full input schema and
annotations stay in tools/list, so the catalog stays small.
Add ?for=me with a bearer key and each tool entry gains an allowed: bool
computed from that key's scopes, so an agent can see up front which tools it may
call. The server also publishes a discovery descriptor at
GET https://mcp.dairo.app/.well-known/mcp.
Schedule and cancel a send
send_message can stage a send for later — pass sendAt, an RFC 3339 timestamp
with an explicit timezone offset, up to 30 days out:
"Schedule the welcome email from
hello@yourapp.comtouser@example.comfor 9am UTC tomorrow."
A scheduled send returns status: "scheduled" with a scheduledAt timestamp.
Cancel it any time before it fires:
"Cancel scheduled email
msg_123."
manage_sent_messages with action: "cancelScheduled" is confirm-required, so the
agent checks first.
Cancel works only while the email is still scheduled. Once it is no longer
scheduled — already sent, queued, or canceled — the tool returns a 409 conflict.
Safe to run on autopilot
Actions that create, delete, or revoke a resource — and real-world spends like
placing a phone call or posting a letter — require an explicit confirm: true, so
an agent cannot accidentally delete a resource, revoke a key, cancel a scheduled
send, or ring a real phone. The message sends — send_message, send_broadcast,
and text_to_speech — are gated by the messages:send scope instead of a confirm
flag, so a key without that scope cannot send at all. Every destructive tool
declares destructiveHint: true in its tools/list annotations, and the catalog's
confirmRequiredTools array names every tool that requires confirmation.
Tool outputs never echo API keys or signing secrets — a newly created secret is shown once, then never again. Attachment tools return download links and metadata, not raw bytes. Strict JSON Schemas give an agent immediate validation instead of a silent mistake.
A send to a recipient who reported your mail as spam, or whose address
hard-bounced, is blocked unless you set ignoreComplaints: true. See Land in the inbox.
More to try
Once connected, drive Dairo entirely in plain language:
"Send a plain-text reply from
support@yourapp.comto messagemsg_123thanking them and asking for their order number."
"Show me every complaint from the past week and which sender it belongs to."
The agent calls the matching tools and reports the results.
Next steps
MCP recipes gives exact tool-call JSON for the flows agents run most. The CLI exposes the same surface from your shell and CI.