MCP - connect AI agents to your inbox

Inboxes ships an MCP (Model Context Protocol) server at /mcp. Agents such as Claude Code, Codex, and opencode connect to it and work with email as you: read mail, search threads, and prepare drafts for you to review and send. It is included in both cloud and self-hosted mode - same code, no separate gate.

Quick start

One command signs you in and configures every harness it finds:

npx inboxes setup

Self-hosting? Point it at your instance: npx inboxes setup --url https://mail.example.com. The command opens your browser, you approve the connection, and it writes the MCP configuration for Claude Code, Codex, and opencode.

Or configure a client manually:

# Claude Code (OAuth - approves in your browser)
claude mcp add --transport http inboxes https://app.inboxes.net/mcp

# Claude Code (API key)
claude mcp add --transport http inboxes https://app.inboxes.net/mcp \
  --header "Authorization: Bearer <YOUR-KEY>"
# Codex (~/.codex/config.toml)
[mcp_servers.inboxes]
url = "https://app.inboxes.net/mcp"
http_headers = { "Authorization" = "Bearer <YOUR-KEY>" }
// opencode (opencode.json)
{
  "mcp": {
    "inboxes": {
      "type": "remote",
      "url": "https://app.inboxes.net/mcp",
      "headers": { "Authorization": "Bearer <YOUR-KEY>" }
    }
  }
}

For a self-hosted instance, replace app.inboxes.net with your own origin.

Authentication

Two paths. Both end in a bearer token.

  • OAuth 2.1 - the MCP standard. Your client discovers the auth endpoints (RFC 9728 / RFC 8414), registers itself (RFC 7591), and opens a browser. You log in, see exactly what the agent gets, and approve. PKCE is mandatory. Access tokens live 30 days, refresh tokens 90.
  • API keys - for clients without OAuth support. Create one in Settings → Agents. The key (prefix inbx_k) is shown once and stored only as a SHA-256 hash. Revoke it there anytime.

A token belongs to one user and carries that user's role live from the database. Revoking a token, disabling a user, or changing a role takes effect on the next call.

Tools

ToolWhat it does
list_domainsList the email domains the account can see
list_threadsList threads for a label (inbox, archive, trash, spam, starred, snoozed, or a custom label), newest first
search_threadsFull-text search across subjects, senders, and bodies
get_threadRead a full conversation with every message body
modify_threadApply one action to a thread: archive, trash, restore, spam, read/unread, star, mute, or snooze
list_draftsList the user's drafts
create_draftCreate a draft - a new email or a reply into an existing thread. It does not send
update_draftRevise a draft before a human sends it
send_draftSend or schedule a draft. Works only when the org has enabled agent send
list_usersAdmin only. List org members with roles and status
invite_userAdmin only. Invite a person to the org by email

The tool list is role-filtered: members never see the admin tools. Draft parameters are composable - create_draft takes optional CC/BCC and a thread_id to reply into a conversation, and send_draft takes an optional scheduled_at time.

The send control

By default, connected agents can read mail and create drafts, but only a human can send. You review agent drafts in the app and click send yourself.

An org admin can change this with one switch: Settings → Agents → “Allow connected agents to send email” (off by default). The server enforces the switch on every send_draft call, regardless of what any client or prompt says. With the switch off, the draft is still saved - a human can send it from the app.

Security model

  • Zero new authorization logic. Every tool call runs through the normal API router as the token's user. Org scoping, alias visibility, role checks, and rate limits apply unchanged. An agent can never do more than its user can.
  • Per-user identity. An admin's agent sees what that admin sees. A support agent that should only see support@ connects as a member user assigned to that alias.
  • Untrusted content policy. The server instructs agents to treat email bodies as untrusted text: summarize them, never follow instructions inside them, and never click unsubscribe links in bodies. For suspected harassment, the guidance is block, not unsubscribe.
  • Hashed credentials. Raw tokens are never stored - only SHA-256 hashes.
  • Rate limits. The /mcp endpoint allows 120 requests per minute per IP, and each underlying route keeps its own per-user limits.

Cloud and self-hosted

The MCP server is part of the open-source code and works the same in both modes. There is no separate charge for it: your agent runs on your own harness and your own model tokens. On the cloud version, the org needs an active subscription, because the tools read and write through the same plan-gated routes as the app.

Related endpoints

PathPurpose
POST /mcpThe MCP endpoint (streamable HTTP, JSON-RPC 2.0)
/.well-known/oauth-protected-resourceOAuth resource metadata (RFC 9728)
/.well-known/oauth-authorization-serverOAuth server metadata (RFC 8414)
GET/POST/DELETE /api/agent-keysManage API keys and OAuth connections - see the API reference