> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dairo.app/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

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

<CodeGroup>
  ```bash title="Claude Code" theme={null}
  claude mcp add --transport http dairo https://mcp.dairo.app/mcp
  ```

  ```json title="mcp.json" theme={null}
  {
    "mcpServers": {
      "dairo": {
        "type": "http",
        "url": "https://mcp.dairo.app/mcp"
      }
    }
  }
  ```

  ```bash title="Dairo CLI" theme={null}
  # Wire up Dairo MCP across your installed coding agents in one command
  printf '%s' "$DAIRO_API_KEY" | dairo auth token set
  dairo mcp install --client auto
  ```
</CodeGroup>

`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`, `importMembers`, `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`                                                                                                                                                                                       |

<Tip>
  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`.
</Tip>

## 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.com` to `user@example.com` for
> 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.

<Note>
  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.
</Note>

## 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 is blocked unless you set
`ignoreComplaints: true`. See [Land in the inbox](/webhooks/deliverability).

## More to try

Once connected, drive Dairo entirely in plain language:

> "Send a plain-text reply from `support@yourapp.com` to message `msg_123`
> thanking 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](/agent-first/mcp-recipes) gives exact tool-call JSON for the flows
agents run most. The [CLI](/agent-first/cli) exposes the same surface from your
shell and CI.
