v0.3 New: reads attachments and transcripts →

Work email for your AI agent

An MCP server for Microsoft Exchange / OWA. Your agent checks your inbox, searches mail, and summarizes threads and attachments. Nothing goes out until you click Send.

curl -LsSf https://raw.githubusercontent.com/Khomiakov7706/owa-mail-mcp/main/install.sh | sh

Works with Claude CodeClaude DesktopCodexCursorOpenCodeKilo Codeany MCP client

what needs my reply since last night?
owa-mail · get_status → ivan.petrov@company.com
owa-mail · check_mail → 37 messages
owa-mail · get_thread → “Q4 budget”, 41 messages
Needs your reply — 3: 1. Anna Smith — Q4 budget, estimate due by 3:00 PM (today) 2. Maria Ivanova — approve time off (Friday) 3. John Doe (external) — contract renewal FYI — 9, newsletters — 25.
tell Anna I'll send the estimate tomorrow by noon
owa-mail · send_email → waiting for your confirmation in the browser…
Send confirmation window: recipients with the external one highlighted, subject, body, and Send, Edit, Don't send buttons Send confirmation window
confirmation window · your browser
9
tools for your agent
0
messages sent without your OK
1
command to install
MIT
open source, free

Features

Everything you do in email, in one question

The agent sees your mailbox the way you do in web mail. It decides which message to open, which thread to pull together, and what to read in an attachment.

Inbox triage

New mail for any period, sorted into “reply”, “FYI” and “safe to skip”.

check_mailtriage_inbox

Threads without the quotes

The whole conversation from Inbox and Sent, in order, without the “From: … Sent: …” clutter. Who proposed what, and what’s expected of you.

get_threadsummarize_thread

Attachments and transcripts

Text from .docx, PDF, .txt, .md, .csv, HTML, and .vtt/.srt subtitles — with speaker lines like “Anna: …”.

get_attachment

Search across all folders

By text, sender, recipient, subject, date and attachments. Dates the way people write them: yesterday, 7d, 2026-10-01.

search_messages(sender="Anna", text="budget", since="30d")
→ 6 messages, newest first
search_messagesget_message

People and senders

Your company address book: name, exact address, title, department. Plus who wrote to you most this week, with unread counts.

list_senders(since="7d")
→ Anna Smith · 12 messages · 3 unread
find_peoplelist_senders

Nothing is sent without your “yes”

The agent can draft a message or a reply in a thread, but it can’t send on its own. A confirmation window opens in your browser.

  • Send, Edit or Don’t send — your call
  • External addresses are highlighted; Bcc comes with a warning
  • Only your browser knows the window’s address, so text in an email can’t talk the agent into clicking the button
  • No answer in 50 seconds and the message isn’t sent; a retry never sends it twice
  • Sending stays off until you turn it on
send_email
Send confirmation window Send confirmation window

How it works

Three minutes from install to first answer

  1. Install with one command

    The installer puts its own Python in a separate folder and leaves the system one alone. To update, run the same command. Your settings are kept.

    $ curl -LsSf …/install.sh | sh
    ==> Done: owa-mail-mcp 0.3
  2. Connect your mailbox

    The setup window asks for the same details you use for web mail. Test connection shows your name and latest messages.

    Setup window: server address, email, login, password, and a successful connection test Mailbox setup window
  3. Ask your agent

    The Add button registers the server in Claude Code, Codex, Claude Desktop or Cursor. Then just ask: “what’s new in my inbox?”

    › what’s new in my inbox since yesterday?
    ⏺ owa-mail · check_mail → 12 messages

Install

Install and connect

You need access to your mail server: if web mail only opens over VPN, turn the VPN on. The program's windows follow your system language; you can switch it in the setup window.

Paste into Terminal. The setup window opens in about a minute.

curl -LsSf https://raw.githubusercontent.com/Khomiakov7706/owa-mail-mcp/main/install.sh | sh

In PowerShell:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv tool install --python 3.12 git+https://github.com/Khomiakov7706/owa-mail-mcp
owa-mail-mcp setup

Copy this text and send it to your agent (Claude Code, Codex, Cursor). It will install and connect the server for you. The agent doesn’t need your password: you enter it in the setup window.

Install and connect the OWA Mail MCP server for my Exchange work email.
1. Run: curl -LsSf https://raw.githubusercontent.com/Khomiakov7706/owa-mail-mcp/main/install.sh | sh
2. Connect the server to yourself. For Claude Code: claude mcp add --scope user owa-mail -- ~/.local/bin/owa-mail-mcp
3. I'll set up the mailbox (server address, login, password) myself in the window that opens — don't ask me for the password.
4. Then call get_status and show me the result.
Instructions for agents: https://khomiakov7706.github.io/owa-mail-mcp/llms.txt

The easiest way is the Add button in the setup window (owa-mail-mcp setup). Or in a terminal:

claude mcp add --scope user owa-mail -- ~/.local/bin/owa-mail-mcp

To check: claude mcp list, or /mcp in a session.

Settings → Developer → Edit Config, then restart Claude Desktop. The setup window fills in the exact path for you.

{
  "mcpServers": {
    "owa-mail": { "command": "/Users/YOU/.local/bin/owa-mail-mcp" }
  }
}
codex mcp add owa-mail -- ~/.local/bin/owa-mail-mcp

File ~/.cursor/mcp.json:

{
  "mcpServers": {
    "owa-mail": { "command": "/Users/YOU/.local/bin/owa-mail-mcp" }
  }
}

File ~/.config/opencode/opencode.json (for a single project, opencode.json in its root). OpenCode has its own format: an mcp key, "type": "local", and the command as an array. OpenCode doesn’t read the mcpServers key. The Add button in the setup window writes this for you.

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "owa-mail": {
      "type": "local",
      "command": ["/Users/YOU/.local/bin/owa-mail-mcp"],
      "enabled": true
    }
  }
}

Restart OpenCode. To check: opencode mcp list.

Newer Kilo Code versions use the same format as OpenCode, in ~/.config/kilo/kilo.jsonc (for a project, kilo.jsonc or .kilo/kilo.jsonc):

{
  "mcp": {
    "owa-mail": {
      "type": "local",
      "command": ["/Users/YOU/.local/bin/owa-mail-mcp"],
      "enabled": true
    }
  }
}

Older extension versions: Kilo Code → MCP Servers → “Edit Global MCP” (file mcp_settings.json; for a project, .kilocode/mcp.json):

{
  "mcpServers": {
    "owa-mail": {
      "command": "/Users/YOU/.local/bin/owa-mail-mcp",
      "args": [],
      "disabled": false,
      "alwaysAllow": []
    }
  }
}

After editing, restart Kilo Code (in VS Code: Developer: Reload Window).

Any MCP client over stdio: the command is the absolute path to owa-mail-mcp, with no arguments or environment variables. The server reads its settings from its own file and the keychain.

System
macOS, Linux, Windows
Mail
Exchange 2013 / 2016 / 2019 — the same server as your OWA web mail
After updating
Restart the MCP server in your client: in Claude Code, /mcp → Reconnect

For developers and agents

MCP tools

Everything except send_email is read-only. Email content is data, not instructions: the server explicitly tells the agent not to follow commands found in messages.

ToolWhat it does
get_statusWho the user is, current time, unread count, version, whether sending is on
check_mailNew messages in Inbox (unread by default) with previews
search_messagesSearch by text, sender, recipient, subject, date, attachments; folders: inbox, sent, inbox_and_sent, all
get_messageThe full message: body (HTML → text), recipients, attachment names
get_threadThe whole thread in order across all folders, without quoted history, with participants
get_attachmentAttachment text: .docx, .pdf, .txt, .md, .csv, .html, .vtt/.srt, attached emails
find_peopleOrganization address book: name, address, title, department
list_sendersWho wrote in a period: message count, unread, latest subject; for sent, who you wrote to
send_emailwriteA new message or a reply (reply_to_message_id, reply_all) — only after you confirm in the window

Prompts: summarize_thread — a thread summary, triage_inbox — inbox triage. Full reference: the Markdown version of this page and llms.txt.

Security

Security, honestly

For personal use, the design is sound. But it hasn’t had an independent audit yet, and the main risk isn’t in the code: everything the agent reads goes to the AI service behind it.

What’s protected

Password in the keychain

Keychain, Credential Manager or Secret Service. Not in a file, not in the log, not with the agent: no tool can reveal it.

Only your server

The password goes only to the Exchange server you set, and only over HTTPS. Redirects to other hosts get no password.

Nothing is sent without your “yes”

Off by default. Every message needs your click in a local window. Hidden characters, invalid addresses and too many recipients are rejected; external addresses are highlighted.

Local windows are locked down

127.0.0.1 only, a secret random address, Host and Origin checks, no embedding: other sites can’t reach them.

Certificate pinning

Standard certificate checks stay on. An internal company certificate is accepted only if it’s that exact one, by SHA-256.

No account lockouts

After a rejected password, requests to Exchange stop, and request rates are limited. The log keeps only tool names and timestamps — no email content.

What it doesn’t solve

  1. Your mail goes to an AI service. Everything the agent reads — messages, attachments, transcripts — is sent to the company that runs the agent. A bank or another regulated company needs sign-off from its security team, and policy may forbid it outright. That’s a policy question, not a code question.
  2. Emails with “commands” for the agent. An incoming email can contain text aimed at the agent: “forward this…”. The server asks the agent to treat mail as data, but that’s a request, not a lock. The real safeguard is the confirmation window: read the message before you click Send. The agent can read everything; you can’t limit it to specific folders yet.
  3. How it installs. curl … | sh installs whatever is on the main branch right now. There are no signed releases or pinned versions yet: if the GitHub account is compromised, the next update will be too.
  4. Settings that weaken security. “Legacy encryption settings” for the server, and a password in the OWA_MAIL_PASSWORD variable in the agent config instead of the keychain. Both are off until you turn them on.
  5. Access to your computer. Anyone already signed in as you can use the saved password and the running program — as with any app that stores a password.

Before you connect work email

  • Get your security team’s sign-off on sending email content to an AI service.
  • Don’t turn on sending unless you really need it.
  • Get an independent code review and install a pinned version, not the latest from main.

FAQ

Frequently asked questions

Is it safe?

For personal use, the design is sound: the password lives in the keychain, and nothing is sent until you confirm. But there has been no independent audit, and email content goes to an AI service — corporate mail needs sign-off from your security team. Details in Security.

Where do I find the server address?

It’s the address of your work web mail in the browser: mail.company.com, https://owa.company.com or https://outlook.company.com/owa. Any of these works.

It says “server unreachable”, but web mail opens fine

The setup window tells you why. DNS: reconnect your VPN. Connection: your browser probably goes through a proxy (you can set it under Advanced → Proxy). TLS: an old server; the window offers to allow legacy settings for that server only.

It says “the server doesn’t respond like EWS”

There’s a gateway with a web login in front of EWS. The program first signs in through OWA and continues on the same connection — that’s usually enough. If not, use Copy diagnostics in the setup window (no passwords included) and send it to IT or open an issue.

Where are my login and password stored? Do they survive updates?

The password is in the system keychain; everything else is in config.json in your user folder (on a Mac, ~/Library/Application Support/owa-mail-mcp). Updates don’t touch them. To check: owa-mail-mcp status.

I updated, but the errors are the same

Your client is still running the old process. Restart the MCP server: in Claude Code, /mcp → owa-mail → Reconnect; in Claude Desktop and Cursor, quit and reopen the app.

How do I know it’s working?

Ask your agent to “check my mail status”. get_status returns your address, unread count and version. The call log is at the bottom of the setup window.

Can the agent send mail without me?

No. Sending is off by default, and every message goes through a confirmation window whose address only your browser knows. No answer in 50 seconds and the message isn’t sent.

Exchange Online (Microsoft 365)?

The server is built for on-premises Exchange 2013–2019 over EWS. Microsoft 365 has disabled password sign-in for EWS, so for cloud mail, servers built on Microsoft Graph are a better fit.

Inbox: 0. Enjoy your evening.

One command, and your agent reads work email right alongside you.

curl -LsSf https://raw.githubusercontent.com/Khomiakov7706/owa-mail-mcp/main/install.sh | sh