Overview

Angelos

A self-hosted email MCP server I built so my assistant can work through my existing inbox. Reading, drafts, replies, attachments, and reviewed sending, with scoped access and durable send receipts.

GoMCPRedis
EmailOAuthPasskeys
Angelos

I mostly built Angelos so my assistant could email people for me. If I’m already talking to ChatGPT or Claude, I want to be able to say “find that conversation, reply to them, and clean up the rest” without opening another app and doing the actual work myself. I couldn’t find a connector that did that reliably enough for the way I wanted to use it.

I’d already worked through much of the mail side in iCloud CLI: IMAP, message threads, replies, CC and BCC, attachments, and the awkward state around sending. That was a local tool an agent could drive from a shell. Angelos takes the same problem to a different place: a self-hosted MCP server that connects my existing mailbox to assistants in a browser or on my phone, without keeping my computer running.

One mailbox is the whole deployment

The tempting version of this was a shared service where anybody signs up and connects their email. I deliberately didn’t build that. Each person forks the project and deploys their own instance on Vercel, with their own Redis store and one configured mailbox. Multiple assistants can connect to that mailbox, but there isn’t a multi-user mail platform underneath it.

That choice removes a lot of product and operational machinery I didn’t need. The mail provider remains the authority for messages and folders; Angelos doesn’t become a replacement inbox database. Apple Mail or any other ordinary client can stay connected, and changes made through either surface are changes to the same mailbox. The Go service handles the assistant-facing tools, authentication, provider differences, and send state.

The provider boundary supports TLS IMAP/SMTP, eligible Gmail OAuth setups, and delegated Microsoft Graph for supported Outlook and Microsoft 365 mailboxes. Those aren’t interchangeable promises. Provider and organization policies still decide which setup is available, so the connection guide makes those differences explicit.

An inbox designed to be read by an agent

I designed the tools from the assistant’s side of the conversation. Searching an inbox shouldn’t mean dumping every matching email body into context. Discovery returns bounded summaries; the assistant reads the messages and attachments it actually needs. Reading uses provider operations that leave the message’s read status alone. A tool inspecting my inbox shouldn’t quietly reorganize it just by looking.

The same restraint applies to what the results claim. An unread flag isn’t proof that something is urgent. A set of related message headers isn’t proof that every part of a conversation has been found. Moving mail can make an old reference stale, and an empty page can still have a continuation cursor. Those details matter when the reader is a model that will otherwise confidently turn a partial result into a complete answer.

Sending needs a receipt, especially when something times out

Reading is the easy half. Sending is where a retry can turn one intended email into two real emails.

Angelos separates preparing a message from dispatching it. Preparation fixes the recipients, envelope, MIME bytes, and attachments, with a digest binding that exact payload. A durable atomic claim permits one dispatch attempt for that preparation, and a receipt records what happened. The assistant can inspect that receipt before deciding what to do next.

The boundary is deliberately honest: SMTP acceptance doesn’t prove delivery, and a connection can fail after the provider accepted a message but before the server received the response. That outcome is uncertain, not permission to send again. The sending safeguards preserve that distinction instead of promising exactly-once email.

Approval is a separate responsibility. OAuth scopes and server gates constrain access, but the trusted assistant client still has to obtain the person’s approval when an action needs it. A model echoing the right digest proves that the payload matches; it doesn’t prove a human reviewed it.

Self-hosting that can stay current

Passkey sign-in and OAuth give compatible assistants access to the personal deployment. Setup can be done with an agent handling the ordinary deployment work while the owner supplies credentials and approves access. After that, the mailbox stays reachable without a laptop in the loop. Release updates can be opted into through GitHub Actions, so keeping a personal fork current doesn’t have to become another recurring chore.

That’s the product I wanted: I can text my assistant from wherever I am, have it find, organize, draft, or reply in the mailbox I already use, and still be able to tell what it actually did.

Use ← and → to navigate