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 setupSelf-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
| Tool | What it does |
|---|---|
list_domains | List the email domains the account can see |
list_threads | List threads for a label (inbox, archive, trash, spam, starred, snoozed, or a custom label), newest first |
search_threads | Full-text search across subjects, senders, and bodies |
get_thread | Read a full conversation with every message body |
modify_thread | Apply one action to a thread: archive, trash, restore, spam, read/unread, star, mute, or snooze |
list_drafts | List the user's drafts |
create_draft | Create a draft - a new email or a reply into an existing thread. It does not send |
update_draft | Revise a draft before a human sends it |
send_draft | Send or schedule a draft. Works only when the org has enabled agent send |
list_users | Admin only. List org members with roles and status |
invite_user | Admin 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
/mcpendpoint 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
| Path | Purpose |
|---|---|
POST /mcp | The MCP endpoint (streamable HTTP, JSON-RPC 2.0) |
/.well-known/oauth-protected-resource | OAuth resource metadata (RFC 9728) |
/.well-known/oauth-authorization-server | OAuth server metadata (RFC 8414) |
GET/POST/DELETE /api/agent-keys | Manage API keys and OAuth connections - see the API reference |