{
  "markdown": "# MCPEmails\n\n**Give your AI agent an inbox.** A hosted [Model Context Protocol](https://modelcontextprotocol.io) server that lets Claude, Cursor, or any MCP‑compatible client read, search, send, organize, and schedule email through your existing mailboxes — without ever storing your mail.\n\n[![Glama quality grade](https://glama.ai/mcp/servers/Albretsen/MCPEmails/badge)](https://glama.ai/mcp/servers/Albretsen/MCPEmails)\n[![npm version](https://img.shields.io/npm/v/mcpemails)](https://www.npmjs.com/package/mcpemails)\n[![MCP registry](https://img.shields.io/badge/MCP%20registry-com.mcpemails%2Femails-blue)](https://registry.modelcontextprotocol.io/v0/servers?search=mcpemails)\n[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE)\n\n> Connect a mailbox once, paste one URL into your agent, and it can work your inbox live. Email is fetched on demand and never retained; credentials are encrypted at rest and decrypted only at call time inside an isolated edge function.\n\n🔗 **[mcpemails.com](https://mcpemails.com)** · 📚 **[Docs](https://mcpemails.com/docs)** · 💳 **[Pricing](https://mcpemails.com/pricing)**\n\n---\n\n## Contents\n\n- [How it works](#how-it-works)\n- [Quick start (connecting an agent)](#quick-start-connecting-an-agent)\n- [Capabilities](#capabilities)\n- [Tools](#tools)\n- [OAuth scopes](#oauth-scopes)\n- [Supported providers](#supported-providers)\n- [Pricing](#pricing)\n- [Architecture](#architecture)\n- [Repository layout](#repository-layout)\n- [Local development](#local-development)\n- [Environment variables](#environment-variables)\n- [Database & migrations](#database--migrations)\n- [Deployment](#deployment)\n- [Self-hosting](#self-hosting)\n- [Internationalization](#internationalization)\n- [Security model](#security-model)\n\n---\n\n## How it works\n\n1. **Connect a mailbox.** Sign in at [mcpemails.com](https://mcpemails.com) and connect Gmail (one‑click OAuth) or any IMAP/SMTP account (app password). Credentials are encrypted with AES‑256‑GCM before they touch the database.\n2. **Get access.** OAuth‑capable clients (claude.ai, Claude Desktop, Cursor) connect in one click via OAuth 2.0 + PKCE. Everything else uses a scoped API key (`mcpe_…`).\n3. **Point your client at the server.** The MCP endpoint is a single URL:\n   ```\n   https://mcpemails.com/api/mcp\n   ```\n4. **Your agent works the inbox.** It calls tools like `inbox_list`, `email_read` (`action: \"search\"`), `email_compose` (`action: \"send\"`), and `schedule` (`action: \"create\"`). Each request fetches live from your provider — nothing is mirrored or cached server‑side.\n\nPermissions are scoped per key, so you can hand an agent `read:email` only, or grant it send and folder management without ever exposing delete.\n\n## Quick start (connecting an agent)\n\n**Claude Desktop / Cursor (OAuth):** add a remote MCP server pointing at `https://mcpemails.com/api/mcp` and approve the consent screen. Pick the scopes the agent should have.\n\n**API key (any MCP client):** create a key in the dashboard, choose its scopes and (optionally) restrict it to specific inboxes, then send it as a bearer token:\n\n```jsonc\n// Example MCP client config\n{\n  \"mcpServers\": {\n    \"mcpemails\": {\n      \"url\": \"https://mcpemails.com/api/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer mcpe_your_key_here\" }\n    }\n  }\n}\n```\n\nThe protocol is JSON‑RPC 2.0 over HTTP (MCP `2025-06-18`, Streamable transport). Start every session with `inbox_list` — it returns the inboxes the key can reach, their per‑provider capabilities, and a versioned compatibility profile. The profile marks normalized operations as `exact`, `different`, or `unavailable`, so agents can preserve provider differences rather than silently weakening a request.\n\n### Setup guides\n\nCopy‑paste instructions per client, including where each one keeps its config file: **[mcpemails.com/docs/clients](https://mcpemails.com/docs/clients)**.\n\n[Claude](https://mcpemails.com/docs/claude) · [Claude Code](https://mcpemails.com/docs/claude-code) · [ChatGPT](https://mcpemails.com/docs/chatgpt) · [Cursor](https://mcpemails.com/docs/cursor) · [VS Code](https://mcpemails.com/docs/vscode) · [Cline](https://mcpemails.com/docs/cline) · [Windsurf](https://mcpemails.com/docs/windsurf) · [Gemini CLI](https://mcpemails.com/docs/gemini-cli) · [Zed](https://mcpemails.com/docs/zed) · [JetBrains](https://mcpemails.com/docs/jetbrains) · [Raycast](https://mcpemails.com/docs/raycast) · [Warp](https://mcpemails.com/docs/warp) · [curl](https://mcpemails.com/docs/curl)\n\n## Capabilities\n\n- **Live, never stored** — email is read straight from your provider on each call; no message bodies are persisted.\n- **Multi‑provider** — Gmail via OAuth, plus any IMAP/SMTP mailbox (Fastmail, iCloud, Yahoo, Zoho, Yandex, self‑hosted…) via app password.\n- **No relay** — outbound mail is sent through *your* provider's SMTP/API, from your real address.\n- **Granular scopes** — eight permission scopes, grantable independently per API key and per inbox.\n- **Batch & search‑and‑act** — read, move, delete, or flag up to hundreds of messages in one call, including \"search then move/delete\" combinators.\n- **Drafts & scheduling** — compose drafts and queue messages for future send (server‑side dispatch).\n- **Provider‑agnostic search** — Gmail syntax, IMAP `SEARCH`, and JMAP are normalized behind one `email_read` (`action: \"search\"`) interface.\n- **Team‑ready**: workspaces, members, roles, SSO, and an audit log on the Team plan.\n\n## Tools\n\n11 tools. Most are resource-oriented and take an `action` argument that selects the specific operation (and, for actions that need different privileges, the required scope):\n\n- `inbox_list` - Lists the inboxes the key can reach, with each one's provider capabilities.\n- `email_read` - Lists, reads and searches messages, in batches, plus attachments, extracted attachment text and the original `.eml`.\n- `email_organize` - Moves, copies, flags and archives messages, singly, in batches, or by search.\n- `email_delete` - Trashes or permanently deletes messages, singly, in batches, or by search.\n- `email_compose` - Sends, replies and forwards through your own provider, from your real address.\n- `folder` - Lists, creates, renames and deletes folders (labels on Gmail).\n- `draft` - Lists, creates, updates, sends and deletes drafts, including provider‑native replies.\n- `schedule` - Queues a message for future delivery, lists what is queued, and cancels it.\n- `signature` - Reads and sets the signature appended to outbound mail.\n- `automation` - Creates and manages unattended triage rules, with no model in the loop.\n- `contact_search` - Looks up contacts by scanning recent mail live, with no stored address book.\n\n| Tool | Actions | Scope(s) |\n| --- | --- | --- |\n| `inbox_list` | *(single action)* | `read:email` |\n| `email_read` | `list`, `read`, `read_batch`, `search`, `attachment`, `extract`, `original` | `read:email` (`search` also accepts `search:email`) |\n| `email_organize` | `move`, `move_batch`, `copy`, `copy_batch`, `flag`, `archive`, `search_and_move` | `manage:folders` (move/copy/search_and_move), `send:email` (flag/archive) |\n| `email_delete` | `delete`, `delete_batch`, `search_and_delete` | `delete:email` |\n| `email_compose` | `send`, `reply`, `forward` | `send:email` |\n| `folder` | `list`, `create`, `rename`, `delete` | `read:email` (list), `manage:folders` (create/rename/delete) |\n| `draft` | `list`, `create`, `reply`, `update`, `send`, `delete` | `manage:drafts` (list/create/reply/update/delete), `read:email` (reply also), `send:email` (send) |\n| `schedule` | `create`, `list`, `cancel` | `schedule:email` |\n| `signature` | `get`, `set` | `read:email` (get), `send:email` (set) |\n| `automation` | `create`, `list`, `get`, `update`, `enable`, `disable`, `delete`, `runs`, `preview` | `manage:automations` |\n| `contact_search` | *(single action)* | `manage:contacts` |\n\nNotes:\n- Tools accept either an explicit `inbox_id` (UUID) or an `inbox` email address; single‑inbox keys auto‑resolve the target.\n- Batch actions cap at 50 (`email_read`'s `read_batch`) to 500 (move/delete/flag) messages per call.\n- For a targeted mutation, first use `email_read` with `action: \"search\"`, then pass the returned `message_id` or `message_ids` to `email_organize` or `email_delete`. Search fields are accepted only by `search_and_move` and `search_and_delete` mutation actions.\n- `contact_search` scans recent mail live — there is no stored address book.\n- `email_read`'s `original` action returns one complete provider-stored MIME message as a portable `.eml` file (up to 25 MB). It is read-only and never marks the message as read.\n- `draft`'s `send` action requires `send:email`, not `manage:drafts` — so a key that can only manage drafts can't use them to bypass the send‑mail consent.\n- `draft`'s `reply` action creates an unsent, provider-native reply in the source conversation. It needs both `manage:drafts` and `read:email`, and defaults to replying only to the sender.\n- `automation` manages unattended scheduled triage rules: a stored search plus one fixed action, evaluated on a cadence with no model in the loop. There is no delete action, a `forward` always waits for human approval, and `draft_reply` only ever writes a draft. See `docs/automations-trust-boundary.md`.\n- `tools/list` only returns the tools your key (or OAuth token) is actually scoped for.\n\n## OAuth scopes\n\n| Scope | Grants |\n| --- | --- |\n| `read:email` | List inboxes & folders; list, read, and search messages |\n| `search:email` | Narrower alternative that grants only `email_read`'s `search` action |\n| `send:email` | Send, reply, forward, flag, archive; also required to send a draft |\n| `manage:folders` | Create/rename/delete folders; move/copy messages |\n| `delete:email` | Trash or permanently expunge messages |\n| `manage:drafts` | Create, edit, and delete drafts (sending one also requires `send:email`) |\n| `manage:contacts` | Live contact lookup from recent mail |\n| `schedule:email` | Queue messages for future delivery |\n| `manage:automations` | Create and manage unattended scheduled triage rules (no delete action; forwards stay approval-gated) |\n\n## Supported providers\n\n| Provider | Connect via | Read/Search | Send | Folders | Permanent delete | Drafts |\n| --- | --- | --- | --- | --- | --- | --- |\n| **Gmail / Google Workspace** | OAuth 2.0 | ✅ | ✅ | Labels | Trash only | ✅ |\n| **Fastmail** | App password (IMAP/SMTP) | ✅ | ✅ | ✅ | ✅ | ✅ |\n| **iCloud, Yahoo, Zoho, Yandex** | App password (IMAP/SMTP) | ✅ | ✅ | ✅ | ✅ | ✅ |\n| **Any IMAP/SMTP mailbox** | App password | ✅ | ✅ | ✅ | ✅ | ✅ |\n| **Outlook / Microsoft 365** | OAuth 2.0 | 🚧 built, gated pending verification | | | | |\n\n> Outlook OAuth is implemented end‑to‑end but currently gated behind Microsoft publisher verification; it is hidden from the connect UI until it ships.\n\n## Pricing\n\nThe value metric is **connected inboxes**. Free connects one mailbox, Personal connects up to three, Pro connects every mailbox you own, and Team adds people, roles, and a separate workspace per client. Annual billing saves about 20%.\n\n| | **Free** | **Personal** | **Pro** | **Team** |\n| --- | --- | --- | --- | --- |\n| Price | $0 | $5/mo · $48/yr ($4/mo) | $15/mo · $144/yr ($12/mo) | $79/mo · $756/yr ($63/mo) |\n| Connected inboxes | 1 | 3 | Unlimited | Unlimited |\n| API keys | Unlimited | Unlimited | Unlimited | Unlimited |\n| Members | 1 (owner only) | 1 (owner only) | 1 (owner only) | Unlimited, with roles |\n| Fair‑use rate limit | 60 req/min | 120 req/min | 300 req/min | 1,000 req/min |\n| Team roles & workspaces | No | No | No | ✅ |\n| SSO (SAML/OIDC) + audit log | No | No | No | ✅ |\n| Support | Community | Email | Email | Priority |\n\nPer‑API‑key limits also apply (100 req/min · 1,000/hr · 10,000/day). Rate limits are retryable: they come back as JSON-RPC error `-32003` with `data.retry_after` in seconds.\n\nEvery workspace additionally has a **fair-use ceiling** on billable actions per billing period. It is an abuse guard, not a plan feature: it sits far above any observed real usage, is never shown to customers, and cannot be bought past. Hitting it is not retryable and not a JSON-RPC error: it comes back as a normal tool result with `isError: true` and a `_meta[\"com.mcpemails/usage_limit\"]` block, and clears at `reset_at`.\n\nInternal plan ids predate the names: `solo` is sold as **Pro** and `pro` is sold as **Team**. The newer `personal` id is the only one that matches its display name, **Personal**. Every user who existed before the 2026-08-19 repricing keeps unlimited inboxes for free, permanently. See [`apps/web/src/lib/stripe/plans.ts`](apps/web/src/lib/stripe/plans.ts).\n\n## Architecture\n\n```mermaid\nflowchart LR\n    Agent[\"MCP client<br/>(Claude, Cursor, …)\"] -->|\"JSON-RPC / OAuth or API key\"| Web\n\n    subgraph Vercel[\"Vercel — Next.js 16\"]\n      Web[\"/api/mcp route<br/>+ marketing site + dashboard\"]\n    end\n\n    subgraph Supabase\n      Edge[\"mcp-server<br/>edge function (Deno)\"]\n      DB[(\"Postgres<br/>RLS + encrypted creds\")]\n      Cron[\"token-refresh<br/>edge functions\"]\n    end\n\n    Web -->|proxies| Edge\n    Edge -->|decrypt creds, fetch live| Providers[\"Email providers<br/>Gmail API · IMAP/SMTP\"]\n    Edge --> DB\n    Cron --> DB\n    Web --> Stripe[(\"Stripe<br/>billing\")]\n```\n\n- **`/api/mcp`** is a thin Next.js route handler that proxies to the Supabase edge function `mcp-server` — the real MCP implementation, where credentials are decrypted and provider calls are made.\n- **The Postgres database** stores workspaces, members, inboxes (encrypted tokens/passwords), hashed API keys, OAuth clients, scheduled sends, and an activity log — all guarded by Row‑Level Security.\n- **Cron edge functions** refresh Gmail/Outlook OAuth tokens before expiry.\n\n**Stack:** Next.js 16 (App Router) · React 19 · next‑intl 4 · Supabase (Auth, Postgres, Edge Functions) · Stripe · Resend · TypeScript. Email parsing/sanitization via `mailparser`, `jsdom`, and `isomorphic-dompurify`.\n\n## Repository layout\n\n```\n.\n├── apps/\n│   └── web/                     # Next.js 16 app (marketing, dashboard, /api/mcp proxy)\n│       ├── app/                 # App Router routes ([locale], dashboard, api, auth)\n│       ├── components/          # marketing/ + dashboard/ React components\n│       ├── messages/            # next-intl translations (en, nb, es, fr, zh)\n│       ├── src/lib/             # stripe/, supabase/, blog/, crypto helpers\n│       └── proxy.ts             # middleware: i18n + Supabase session + CDN cache\n├── supabase/\n│   ├── functions/\n│   │   ├── mcp-server/          # the MCP server (tools, auth, scopes)\n│   │   ├── gmail-token-refresh/\n│   │   └── outlook-token-refresh/\n│   └── migrations/              # SQL migrations (schema + RLS)\n└── package.json                 # npm workspaces (apps/*)\n```\n\n## Local development\n\n**Prerequisites:** Node.js 20+, npm, and the [Supabase CLI](https://supabase.com/docs/guides/cli) (for migrations and edge functions).\n\n```bash\n# 1. Install (npm workspaces — run from the repo root)\nnpm install\n\n# 2. Configure environment\ncp .env.example apps/web/.env.local\n#   then fill in the values (see below) and generate the two secrets:\nopenssl rand -hex 32   # ENCRYPTION_KEY\nopenssl rand -hex 32   # CSRF_SECRET\n\n# 3. Run the web app (http://localhost:3000)\nnpm run dev\n\n# 4. Production build\nnpm run build\n```\n\n> `next.config.js` validates required env vars at build/start and rejects weak `ENCRYPTION_KEY` values, so a misconfigured environment fails fast instead of at runtime.\n\n## Environment variables\n\nCopy [`.env.example`](.env.example) and fill in real values. Required in every environment:\n\n| Variable | Purpose |\n| --- | --- |\n| `NEXT_PUBLIC_SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Supabase client (public) |\n| `SUPABASE_SERVICE_ROLE_KEY` | Server‑side admin key (bypasses RLS) — **secret** |\n| `NEXT_PUBLIC_APP_URL` | Canonical base URL; drives OAuth redirect URIs |\n| `GOOGLE_SITE_VERIFICATION` *(optional)* | Google Search Console HTML-tag verification token; set only in production |\n| `ENCRYPTION_KEY` | 64‑hex AES‑256‑GCM key for credentials at rest — **secret** |\n| `CSRF_SECRET` | 64‑hex HMAC key for CSRF tokens (distinct from above) — **secret** |\n\nFeature‑dependent:\n\n| Variable(s) | Needed for |\n| --- | --- |\n| `GMAIL_CLIENT_ID` / `GMAIL_CLIENT_SECRET` | Gmail OAuth (`gmail.readonly`, `gmail.send`, `gmail.modify`) |\n| `OUTLOOK_CLIENT_ID` / `OUTLOOK_CLIENT_SECRET` / `OUTLOOK_TENANT_ID` | Outlook OAuth (`Mail.Read`, `Mail.Send`, `Mail.ReadWrite`, `offline_access`) |\n| `NEXT_PUBLIC_OAUTH_VERIFICATION_PENDING` | Shows the unverified‑app warning until Google/Microsoft verification completes |\n| `STRIPE_SECRET_KEY` / `STRIPE_WEBHOOK_SECRET` / `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY` | Billing |\n| `STRIPE_PRICE_PERSONAL_MONTHLY` / `_YEARLY`, `STRIPE_PRICE_SOLO_MONTHLY` / `_YEARLY`, `STRIPE_PRICE_PRO_MONTHLY` / `_YEARLY` | Plan price IDs (`personal` = Personal, `solo` = Pro, `pro` = Team) |\n\n> Fastmail and other IMAP providers connect via app password and need no OAuth credentials.\n\n## Database & migrations\n\nSchema and Row‑Level Security policies live in [`supabase/migrations/`](supabase/migrations/). Core tables: `workspaces`, `workspace_members`, `inboxes` (encrypted credentials, soft‑deleted), `api_keys` (hashed, scoped, inbox‑restricted), `oauth_clients`, `scheduled_sends`, `workspace_invites`, and a month‑partitioned `activity_log`.\n\n```bash\n# Apply migrations to the linked project\nnpx supabase db push\n\n# Generate TypeScript types from the live schema\nnpx supabase gen types typescript --linked > apps/web/src/types/database.ts\n```\n\n> The Supabase CLI is the source of truth for DB changes in this project.\n\n## Deployment\n\n**Web app → Vercel** (project `mcp-emails-web`):\n\n```bash\nvercel --prod --yes\n```\n\nSecurity headers and function timeouts are defined in `vercel.json`. The marketing routes are served with a CDN‑cacheable `Cache-Control` (set in `proxy.ts`) so crawlers and repeat visitors hit the edge cache; the dashboard, auth, and API routes stay `no-store`.\n\n**MCP server → Supabase edge function:**\n\n```bash\nnpx supabase functions deploy mcp-server --project-ref <your-project-ref> --no-verify-jwt\n```\n\n## Self-hosting\n\nDon't want to trust the hosted service with your mail? Run the **same MCP server** on your own\nmachine. [`self-host/`](self-host/) ships a containerized stack (Postgres + PostgREST + the Deno\nserver, no Supabase/Stripe/dashboard), so your credentials are encrypted with a key only you hold\nand decrypted only inside your own container.\n\n```bash\ncd self-host\nmake setup      # generate secrets (.env)\nmake up         # build + start the stack\nexport IMAP_PASSWORD='your-app-password'\nmake provision EMAIL=you@example.com IMAP_HOST=imap.fastmail.com SMTP_HOST=smtp.fastmail.com SERVICE=fastmail\nmake key NAME=\"my agent\"   # mint an mcpe_ key, then point your client at http://localhost:8787\n```\n\nIt is IMAP/SMTP-first (Fastmail, iCloud, Yahoo, Zoho, Yandex, generic) via app password; Gmail/Outlook\nOAuth and the web dashboard remain hosted-only. The container runs `supabase/functions/mcp-server/`\nunmodified; see [`self-host/README.md`](self-host/README.md) for the full guide.\n\n## Internationalization\n\nBuilt with **next‑intl** (`localePrefix: 'as-needed'`, `localeDetection: false` for stable canonical URLs). English is served at `/`; other locales carry a prefix (`/nb`, `/es`, `/fr`, `/zh`). Translations live under [`apps/web/messages/`](apps/web/messages/).\n\nSupported locales: **English, Norwegian Bokmål, Spanish, French, Chinese (Simplified)**.\n\n## Security model\n\n- **Credentials encrypted at rest** with AES‑256‑GCM; decrypted only inside the edge function at call time.\n- **No message storage** — email bodies and attachments are fetched live and never persisted. Attachment text extraction runs transiently in the request and returns no raw attachment bytes.\n- **API keys are hashed** (only a prefix is stored for display) and scoped per permission and per inbox, with optional expiry.\n- **OAuth 2.0 + PKCE** for client authorization; **Dynamic Client Registration** (RFC 7591) for MCP clients.\n- **Row‑Level Security** isolates every workspace's data at the database layer.\n- **Strict CSP**, HSTS, `X-Frame-Options: DENY`, and related headers on every response.\n\n## License\n\nMCP Emails is open source under the [GNU Affero General Public License v3.0](LICENSE) (AGPL‑3.0). The hosted service at [mcpemails.com](https://mcpemails.com) runs the same server you can [self-host](self-host/), so you can read the code, verify it, and run it yourself. See [`/security`](https://mcpemails.com/security) for the trust model.\n\n---\n\n<sub>Send and receive email from any agent. © MCPEmails, AGPL‑3.0.</sub>\n",
  "bytes": 20715,
  "sha": "1817b0fc98961ad592ac211c531bd7ff80edf096e41277de7bc987ebd0081da6",
  "repo_slug": "albretsen/mcpemails",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_mcpemails_emails_bb035825/readme"
}