Outlook MCP: Connecting to Outlook without 3rd-party auth
Unofficial local MCP server that drives Outlook the same way Outlook Web itself does — the first-party device-code flow plus Outlook Web's internal JSON API. No Microsoft Graph, no Azure app registration, no admin consent, no browser cookies, no desktop COM. Run it locally, connect any MCP client, and your agent can read, search, index and draft mail — sending only happens with a human-issued one-time approval for the exact content.
Warning
https://outlook.cloud.microsoft/owa/service.svcis not a public, supported Microsoft API. It can change or be blocked by tenant policy at any time. For production integrations prefer Microsoft Graph. This server is stdio-only.
What it does
| Area | Tools |
|---|---|
| Read & search | search_emails (live), search_index (local full-text, 2–3 ms), get_email, get_email_html (links + text), list_mail_folders, list_calendar_events |
| Local index | index_sync (all mail folders), index_bodies (full body text on disk), index_attachment_text (PDF/Office → text, file stays on the server), index_status, index_verify |
| Drafts | create_draft, create_reply_draft (HTML body so mobile clients fold quotes), send_draft (nonce-gated), track_status (sent / replied / bounced, never "read") |
| Trust & health | outlook_auth_status, pixels_sync, outlook-web-mcp doctor (six local checks, no network, no secrets) |
17 tools, stdio-only. Sending requires a one-time nonce issued by the human in a
terminal (outlook-web-mcp approve <draftId>); the digest binds the exact HTML
body, recipients, Bcc and attachments, and expires in 30 minutes.
Why no third-party auth
Microsoft Graph and most Outlook integrations require an Azure app registration and tenant admin consent — a wall if you are on a managed account. This fork instead signs in through Outlook Web's own first-party client ID with the device-code flow, then speaks the same private JSON dialect the web app speaks. Nothing asks an admin for anything.
Quickstart
# clone, then:
uv sync --locked
uv run outlook-web-mcp doctor # local health check, no network, no secrets
uv run outlook-web-mcp login # device-code sign-in with Outlook's own client id
Register in your MCP client (e.g. claude mcp add / settings.json):
{
"mcpServers": {
"outlook-web": {
"command": "/absolute/path/to/onezion-outlook-web-mcp/.venv/bin/outlook-web-mcp-server",
"env": { "OUTLOOK_WEB_TIME_ZONE_ID": "China Standard Time" }
}
}
}
The send gate
- Agent calls
create_draft/create_reply_draft— saved to Drafts, never sent. - You review it in Outlook, then run
outlook-web-mcp approve <draftId>in a terminal. It prints exactly what you are approving and writes a one-time nonce. - Agent calls
send_draft— it sends only if the nonce matches the exact content (digest covers HTML body, To/Cc/Bcc, attachment name:size) and is within 30 minutes. Editing anything invalidates the approval; the nonce is consumed on send. Never runapprovefor an agent, and never paste a nonce into a chat.
Security posture
- CA bundle pinned to
certifi;trust_env=Falseso environment proxies cannot hijack token-bearing requests (explicit proxy opt-in only). - Upstream error text is never echoed to tool results; opt-in logs are 0600.
- Response size cap enforced mid-stream; every response must come from the pinned OWA host.
- Stored credentials are refused if the client id changes; verification URLs must be a Microsoft sign-in host.
- Full findings ledger:
docs/audit/2026-11-06-security-audit.md(P2 7/7 closed).
Docs
PITFALLS.md— 23 hard-won pitfalls of this private dialect (flat recipient entries, SendItem 500, ItemClass vs MessageClass, …). Read before hacking.docs/specs/docs/plans/docs/acceptance-*.md— dated design/acceptance trail.docs/audit/2026-11-06-security-audit.md— third-party-style audit + closure ledger.skills/use-outlook-web-mcp/— an agent-facing skill (MCP copy; runbook for JS-rendered mail is screenshot + OCR outside the MCP).docs/internal-api.md— upstream's dialect notes.
Credits & license
Fork of ma-nakaya/outlook-web-mcp-server
(see NOTICE, upstream pin aa41b13). Upstream code stays MIT; all fork
modifications are licensed under AGPL-3.0 — any hosted modification of this
server must publish its source. See LICENSE for the exact boundary.
Maintainer: onezion12344. Not affiliated with Microsoft or the upstream author.
Status
Tested against one real Exchange Online tenant (HKU) with ~12k messages indexed.
CI matrix configured (ubuntu/macOS/Windows); the collector under
collector/pixel-worker/ is deployable but not deployed, and read-tracking
pixels are therefore off unless you deploy it yourself.