Auth Inbox is an open-source, self-hosted email verification code platform built on Cloudflare's free serverless services. It automatically processes incoming emails, filters out promotional mail before hitting the AI, extracts verification codes or links, classifies each mail, and stores everything in a database. A modern React dashboard with account login lets an admin manage everything, while regular users only see the mails an admin has granted them. AI agents can read the inbox too, through a built-in remote MCP server.
Don't want ads and spam in your main inbox? Need a bunch of alternative addresses for signups? Want your AI agent to complete sign-up flows by reading OTPs on its own? Try this secure, serverless, lightweight service!
flowchart LR
A([Your Inboxes]) --> B[Email Worker]
B --> C{Promotional?}
C -->|Yes| D[Save raw only]
C -->|No| E[AI Extraction + Category]
E --> F[(D1 Database)]
F --> G[React Dashboard]
F --> H([Bark iOS Push])
F --> I[Remote MCP Server]
I --> J([AI Agents])
- Features
- Technologies Used
- Installation
- Multi-User & Access Grants
- MCP Server (for AI Agents)
- Upgrading from v1
- License
- Screenshots
- Promotional Filter: Detects and skips bulk/marketing emails via headers (
List-Unsubscribe,Precedence: bulk, etc.) before calling the AI — saves tokens. - AI Code Extraction & Classification: Any OpenAI-compatible or Anthropic provider extracts verification codes, links, and organization names, and tags each mail with a category (
login_code,registration,password_reset,account_security,payment,other). - Multi-User Access Control: Admin creates users and grants them access per address pattern and per category. Sensitive categories (password resets, account security alerts) are denied to regular users by default and raw email bodies are admin-only — enforced at the SQL query layer, for REST and MCP alike.
- Remote MCP Server: Connect claude.ai as a remote connector via built-in OAuth (dynamic client registration + PKCE), or self-issue API keys for header-based clients (Claude Code, Cursor, …) over Streamable HTTP. Includes a
wait_for_codetool that blocks until a fresh OTP arrives — perfect for automated sign-up flows. - Modern Dashboard: React 18 + shadcn/ui interface with account login, mail list with category badges, detail panel, API key management, and an admin page for users and grants.
- Safe HTML Preview: Email HTML is sanitized with DOMPurify and rendered in a sandboxed iframe (admin only).
- One-click Copy: Verification codes and links have copy buttons with toast confirmation.
- Real-Time Notifications: Optionally sends Bark push notifications when new codes arrive.
- Database: Stores all raw emails and AI-extracted results in Cloudflare D1, with schema managed by migrations.
- Cloudflare Workers — Serverless runtime for email handling and API.
- Hono — Web framework for routing, middleware, and JWT sessions.
- Cloudflare D1 — SQLite-compatible serverless database.
- Cloudflare Email Routing — Routes incoming emails to the Worker.
- React 18 + Vite + Tailwind CSS + shadcn/ui — Frontend dashboard.
- Any OpenAI-compatible / Anthropic AI provider — Configurable via env vars; Gemini, OpenAI, DeepSeek, Groq, Anthropic, and more.
- Model Context Protocol (MCP) —
@modelcontextprotocol/sdk+@hono/mcpfor the remote agent interface. - Bark API — Optional iOS push notifications.
- TypeScript — End-to-end type safety.
- An API key from any supported AI provider (e.g. Google AI Studio, OpenAI, Anthropic, DeepSeek, Groq)
- A domain bound to your Cloudflare account
- Cloudflare Account ID and API Token from here
- (Optional) Bark App for iOS push notifications
-
Create D1 Database
Go to Cloudflare Dashboard →
Workers & Pages→D1 SQL Database→Create. Name itinbox-d1.Copy the
database_idfor the next step. Tables are managed by themigrations/directory in this repo — the deploy workflow applies D1 migrations automatically before deploying.(Optional — only if you want to connect claude.ai as a remote MCP connector) also go to
Storage & Databases→KV→Create a namespace, name itOAUTH_KV, and copy its namespace ID. Without it, OAuth is disabled and the MCP server works with API keys only. -
Fork & Deploy
In your forked repository, go to
Settings→Secrets and variables→Actionsand add:CLOUDFLARE_ACCOUNT_IDCLOUDFLARE_API_TOKENTOML— use the comment-free template, fill in your D1database_idand AI config (plus theOAUTH_KVnamespace id if you created one), to avoid parse errors.
Then go to
Actions→Deploy Auth Inbox to Cloudflare Workers→Run workflow.After success, go to your Worker's
Settings→Variables and Secretsand add a secret namedJWT_SECRET(a long random string). Then open your Worker URL — since the users table is empty, the login page will prompt you to create the first admin account.Delete the workflow logs afterwards to avoid leaking your config.
-
Jump to Set Email Forwarding.
-
Clone and install
git clone https://github.com/TooonyChen/AuthInbox.git cd AuthInbox pnpm install -
Create D1 database
pnpm wrangler d1 create inbox-d1
Copy the
database_idfrom the output.(Optional — only for claude.ai remote connectors) also create the OAuth KV namespace:
pnpm wrangler kv namespace create OAUTH_KV
Without it, OAuth is disabled and the MCP server works with API keys only.
-
Configure
cp wrangler.toml.example wrangler.toml
Edit
wrangler.tomland fill in at least:[vars] UseBark = "false" # AI provider AI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai" AI_API_KEY = "your-api-key" AI_API_FORMAT = "openai" AI_MODEL = "gemini-2.0-flash" [[d1_databases]] binding = "DB" database_name = "inbox-d1" database_id = "<your-database-id>" # Optional — only for claude.ai remote connectors (OAuth): # [[kv_namespaces]] # binding = "OAUTH_KV" # must be named OAUTH_KV # id = "<your-kv-namespace-id>"
AI_API_FORMATis one of:Value Request path Providers openai/v1/chat/completionsOpenAI, Gemini (OpenAI-compat), DeepSeek, Groq, Mistral, … responses/v1/responsesOpenAI Responses API anthropic/v1/messagesAnthropic Claude direct Common
AI_BASE_URLvalues:OpenAI: https://api.openai.com Gemini (OpenAI-compat): https://generativelanguage.googleapis.com/v1beta/openai Anthropic: https://api.anthropic.com DeepSeek: https://api.deepseek.com Groq: https://api.groq.com/openaiFallback provider (optional), used after the primary fails 3 retries:
# AI_FALLBACK_BASE_URL = "https://api.openai.com" # AI_FALLBACK_API_KEY = "fallback-api-key" # AI_FALLBACK_API_FORMAT = "openai" # AI_FALLBACK_MODEL = "gpt-4o-mini"
Optional Bark config:
barkTokens,barkUrl.Set the JWT secret (do not put it in
wrangler.tomlfor production):pnpm exec wrangler secret put JWT_SECRET -
Build and deploy
pnpm run deploy
This builds the frontend, applies remote D1 migrations, and deploys the Worker.
Output:
https://auth-inbox.<your-subdomain>.workers.dev
Go to Cloudflare Dashboard → Websites → <your-domain> → Email → Email Routing → Routing Rules.
Catch-all address (forward all mail to the Worker):

Custom addresses (forward specific addresses):

Open your Worker URL. On first visit (empty users table) the login page turns into a "create admin account" form — create the first admin and you're in.
Two roles: admin and user.
- Admin sees everything: all mails, raw bodies, rendered HTML, user management, grant management.
- User only sees mails matched by grants an admin created for them, and never sees raw email bodies — only the AI-extracted results.
A grant = (user, address pattern, allowed categories, allow-sensitive flag):
- Address patterns use SQLite GLOB:
netflix@mail.example.comfor exact match,*@mail.example.comfor a whole domain. - Every mail is classified at ingest time:
login_code/registration/password_reset/account_security/payment/other. password_resetandaccount_securityare sensitive: even if listed in a grant, they are stripped unless the grant explicitly setsallow_sensitive. Fail-safe by design — a misclassified mail means a user sees one less mail, never one more.- Mails ingested before v2 are categorized
legacyand are always admin-only.
So a user can be allowed to read the Netflix login code sent to a shared address, while the Netflix password reset mail on the same address stays admin-only. Everything is enforced in a single SQL-level query function shared by the web API and the MCP server.
Manage users and grants in the dashboard's Users & Access page (admin only).
Auth Inbox exposes a remote MCP server at https://<your-worker-domain>/mcp (Streamable HTTP). Two ways to authenticate:
Option A — OAuth (claude.ai remote connectors, and any OAuth-capable MCP client)
Requires the optional OAUTH_KV binding (see installation). Go to claude.ai → Settings → Connectors → Add custom connector and enter https://your.domain/mcp. Claude discovers the OAuth server automatically (dynamic client registration + PKCE), sends you to the Auth Inbox login/consent page, and connects as your account. Tokens inherit your role and grants; revoking a user in the dashboard kills their OAuth access immediately.
Option B — API key (Claude Code, Cursor, scripts, …)
-
Log in to the dashboard → API Keys → create a key (
aik_…, shown only once). Keys inherit your role and grants. -
Connect from Claude Code:
claude mcp add --transport http authinbox https://your.domain/mcp \ --header "Authorization: Bearer aik_xxx"
Available tools:
| Tool | Purpose |
|---|---|
list_addresses |
List inbox addresses the key's user may read |
list_codes |
List recent codes/links, filterable by address or service |
get_latest_code |
Get the single most recent code for an address/service |
wait_for_code |
Block (up to 55s) until a new code arrives — for automated sign-up/login flows |
All tools go through the same permission filter as the web API, so an agent holding a user's key or OAuth token can never read sensitive or raw content.
v2 is a breaking change:
- Basic Auth is gone.
FrontEndAdminID/FrontEndAdminPasswordinwrangler.tomlare no longer used — remove them. Accounts live in the D1userstable. - Set a
JWT_SECRETsecret:pnpm exec wrangler secret put JWT_SECRET. - Run migrations:
pnpm run db:migrate:remote(also runs automatically inpnpm run deployand the GitHub Actions workflow). Existing data is preserved; old mails are marked categorylegacy(admin-only). - Create the first admin on the login page after deploying (or
POST /api/auth/setup— only works while the users table is empty).
- Cloudflare Workers for the powerful serverless platform.
- Hono and the Model Context Protocol teams.
- shadcn/ui for the component library.
- Bark for real-time push notifications.
- The open-source community for inspiration and support.
- GitHub Actions auto-deploy
- Fallback AI provider support
- React dashboard (shadcn/ui)
- Promotional filter (before any AI call)
- Raw email view + sandboxed HTML preview
- Multi-user support (admin/user roles + per-address, per-category grants)
- Remote MCP server for AI agents
- OAuth on
/mcp(for claude.ai remote connectors) - Regex extraction (no-AI option)
- More notification channels (Slack, webhook, …)
- Email sending


