Run this on Windows and get Outlook Desktop as an MCP server. No Graph API, no Entra app registration — just your local Outlook.
Project description
outlook-desktop-mcp
Run this on Windows and get Outlook Desktop as an MCP server. No Microsoft Graph API, no Entra app registration, no OAuth tokens — just your local Outlook.
Uses COM automation to talk directly to your running Outlook Desktop (Classic) instance, inheriting whatever authentication you already have.
MCP Client (Claude Code, etc.)
|
| stdio (JSON-RPC)
v
outlook-desktop-mcp (Python)
|
| COM automation (MSOUTL.OLB)
v
Outlook Desktop (Classic) — OUTLOOK.EXE
|
| Your existing auth session
v
Exchange Online / Microsoft 365
Requirements
- Windows (COM automation is Windows-only)
- Outlook Desktop (Classic) —
OUTLOOK.EXE, not the newolk.exe - Python 3.12+
- Outlook must be running when the MCP server starts
Install
pip install outlook-desktop-mcp
Or from source:
git clone https://github.com/aaanerud/outlook-desktop-mcp.git
cd outlook-desktop-mcp
python -m venv .venv
.venv\Scripts\activate
pip install pywin32 "mcp[cli]" -e .
python .venv\Scripts\pywin32_postinstall.py -install
Register with Claude Code
claude mcp add outlook-desktop -- outlook-desktop-mcp
Or if installed from source:
claude mcp add outlook-desktop -- powershell.exe -Command "& 'C:\path\to\outlook-desktop-mcp.cmd' mcp"
Then in any Claude Code session, the 9 email tools are available automatically.
Available Tools
| Tool | What it does |
|---|---|
send_email |
Send email via your default Outlook profile |
list_emails |
List recent emails from any folder |
read_email |
Read full email by ID or subject search |
mark_as_read |
Mark an email as read |
mark_as_unread |
Mark an email as unread |
move_email |
Move email to archive or any folder |
reply_email |
Reply or reply-all, preserving thread |
list_folders |
List folder hierarchy with item counts |
search_emails |
Full-text search on subject and body |
How it works
The server runs a dedicated COM thread (STA apartment) that holds the Outlook.Application object. The async MCP event loop dispatches tool calls to this thread via a queue, so COM threading rules are respected and the MCP protocol never blocks.
All tool descriptions are written for LLM consumption — when Claude Code discovers the tools, it knows exactly how to use each one (what arguments to pass, what formats to expect, edge cases to watch for).
Extending
The architecture supports adding more Outlook modules. Planned:
- Calendar — events, meetings, scheduling
- Contacts — address book lookups
- Tasks — to-do items
Add new @mcp.tool() functions in server.py using the same bridge.call() pattern.
Why not Microsoft Graph?
Graph API requires an Entra (Azure AD) app registration, admin consent for mail permissions, OAuth token management, and tenant configuration. For a local developer tool that just wants to send and read email, that's massive overhead.
COM automation requires: Outlook is open. That's it.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file outlook_desktop_mcp-0.1.0.tar.gz.
File metadata
- Download URL: outlook_desktop_mcp-0.1.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a05ca998884b68124d662714a31d7ceaa72caea21ddbf2622fcda266bae233eb
|
|
| MD5 |
381989c8fb1cf9c5713868cea4e2eab0
|
|
| BLAKE2b-256 |
bfb6666a799db1861b0a326a41c94a0a2bb8797f8b83c96bf2d505d850685f5a
|
File details
Details for the file outlook_desktop_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: outlook_desktop_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6a70748ea17adc9287ebe81aeccda5d55a6bbb2e5d627b51bf3ba432fbf96cd
|
|
| MD5 |
de33d9d0c4c433752d85e6e506b6a4cb
|
|
| BLAKE2b-256 |
a57073637cdfa5014e956f06d99f230abdd24c3f41a72a8f22903d90a2efb26f
|