OWA MCP Server
MCP (Model Context Protocol) server for any Microsoft Exchange / OWA (Outlook Web Access) deployment. Gives LLM agents access to email, calendar, directory search, folders, availability, and meeting analytics via 30 tools.
Works with any on-premise or hosted Exchange server that exposes OWA.
Quick Start
# Install
pip install -e .
# Add to your MCP client config with --owa-url
# Then use the login tool to paste your session cookies
Install
Add to your MCP client config. Replace https://owa.example.com with your OWA URL.
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"exchange": {
"command": "uvx",
"args": [
"exchange-mcp-server",
"--owa-url", "https://owa.example.com"
]
}
}
}
Cursor (.cursor/mcp.json):
{
"mcpServers": {
"exchange": {
"command": "uvx",
"args": [
"exchange-mcp-server",
"--owa-url", "https://owa.example.com"
]
}
}
}
Claude Code (.mcp.json):
{
"mcpServers": {
"exchange": {
"command": "uvx",
"args": [
"exchange-mcp-server",
"--owa-url", "https://owa.example.com"
]
}
}
}
CLI Arguments
| Argument | Default | Required | Description |
|---|---|---|---|
--owa-url |
— | Yes | Base URL of the OWA instance (e.g. https://owa.example.com) |
--cookie-file |
session-cookies.txt |
No | Path to session cookies file |
--transport |
stdio |
— | stdio, sse, or streamable-http |
--token-hash |
— | For HTTP | SHA-256 hash of the bearer token |
--port |
8000 |
— | HTTP/SSE listener port |
--host |
127.0.0.1 |
— | HTTP/SSE listener host |
--enabled-tools |
— | No | Comma-separated whitelist of tool names |
--disabled-tools |
— | No | Comma-separated blacklist of tool names |
Tool filtering examples
# Hide only the most dangerous tools
exchange-mcp-server --owa-url https://owa.example.com \
--disabled-tools "send_email,delete_email,cancel_meeting"
# Allow only email and calendar tools
exchange-mcp-server --owa-url https://owa.example.com \
--enabled-tools "get_emails,get_email,send_email,get_calendar_events,create_meeting"
# Whitelist a set, then remove one from it
exchange-mcp-server --owa-url https://owa.example.com \
--enabled-tools "get_emails,get_email,send_email,delete_email" \
--disabled-tools "delete_email"
# → only get_emails, get_email, send_email remain
HTTP Transport
Run the server over HTTP (streamable-http or SSE) instead of stdio. This is useful when the MCP client cannot spawn a local process, or when you want to expose the server on a network.
Installation
pip install -e ".[http]" # adds uvicorn + sse-starlette
Start the server
# Compute the token hash once (store only the hash, never the plaintext token)
TOKEN_HASH=$(echo -n 'my-secret-token' | sha256sum | cut -d' ' -f1)
# stdio (default, for local MCP clients)
exchange-mcp-server --owa-url https://owa.example.com
# streamable-http (recommended for HTTP)
exchange-mcp-server \
--owa-url https://owa.example.com \
--transport streamable-http \
--token-hash "$TOKEN_HASH" \
--port 8000 \
--host 127.0.0.1
# SSE
exchange-mcp-server \
--owa-url https://owa.example.com \
--transport sse \
--token-hash "$TOKEN_HASH" \
--port 8000
CLI arguments
| Argument | Default | Required | Description |
|---|---|---|---|
--owa-url |
— | Yes | Base URL of the OWA instance (e.g. https://owa.example.com) |
--cookie-file |
session-cookies.txt |
No | Path to session cookies file |
--transport |
stdio |
— | stdio, sse, or streamable-http |
--token-hash |
— | For HTTP | SHA-256 hash of the bearer token |
--port |
8000 |
— | HTTP/SSE listener port |
--host |
127.0.0.1 |
— | HTTP/SSE listener host |
--enabled-tools |
— | No | Comma-separated whitelist of tool names |
--disabled-tools |
— | No | Comma-separated blacklist of tool names |
Client configuration (HTTP)
{
"mcpServers": {
"exchange": {
"url": "http://127.0.0.1:8000/mcp",
"headers": {
"Authorization": "Bearer my-secret-token"
}
}
}
}
Authentication
The server stores only the SHA-256 hash of your token — the plaintext token never touches the filesystem. Every HTTP request must include:
Authorization: Bearer <plaintext-token>
The server hashes the incoming token and compares it with the stored hash.
Pass the hash via --token-hash:
echo -n 'my-secret-token' | sha256sum
# → 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
Security notes
- Always use a strong random token.
- Bind to
127.0.0.1unless you have a reverse proxy / firewall. - For
streamable-httpthe client must sendAccept: text/event-stream. - The
--token-hashis required whenever--transportis notstdio.
Login
The login MCP tool accepts session cookies that you copy from your browser.
- Log into OWA in your browser.
- Open DevTools (F12) → Application → Cookies → select your OWA domain.
- Copy all cookies as
name=valuepairs (one per line). - Call the
logintool with the cookies string.
Example cookies string:
X-OWA-CANARY=abc123
CookieAuth1=def456
...
login(cookies="X-OWA-CANARY=abc123\nCookieAuth1=def456\n...")
On success, cookies are saved to session-cookies.txt and all tools become usable. When the session expires, repeat the steps.
Tools (30)
Email (10)
| Tool | Description |
|---|---|
get_emails |
List emails from a folder with filtering |
get_email |
Get full email content by ID |
send_email |
Send a new email |
reply_email |
Reply to an email |
forward_email |
Forward an email |
delete_email |
Delete an email |
move_email |
Move email to another folder |
mark_email_read |
Mark email as read/unread |
download_attachments |
Download file attachments from an email |
get_email_links |
Extract hyperlinks from an email body |
Calendar (7)
| Tool | Description |
|---|---|
get_calendar_events |
Get events in a date range (supports recurring expansion) |
create_meeting |
Create a meeting with attendees |
update_meeting |
Update an existing meeting |
cancel_meeting |
Cancel a meeting and notify attendees |
respond_to_meeting |
Accept, decline, or tentatively accept |
download_event_attachments |
Download file attachments from a calendar event |
get_event_links |
Extract hyperlinks from the event description |
Directory (1)
| Tool | Description |
|---|---|
find_person |
Search people in Active Directory |
Folders (7)
| Tool | Description |
|---|---|
get_folders |
List mail folders with unread counts |
create_folder |
Create a new mail folder |
rename_folder |
Rename an existing folder |
empty_folder |
Empty all items from a folder |
delete_folder |
Delete a mail folder |
move_folder |
Move a folder to a different parent |
check_session |
Check if the OWA session is authenticated |
Availability (2)
| Tool | Description |
|---|---|
find_free_time |
Find free slots in your calendar |
find_meeting_time |
Find common free slots for multiple people |
Analytics (2)
| Tool | Description |
|---|---|
get_meeting_stats |
Meeting count statistics for multiple people |
get_meeting_contacts |
Connection matrix — who you meet with most |
Auth (1)
| Tool | Description |
|---|---|
login |
Authenticate to OWA using browser session cookies |
Files
exchange_mcp/
server.py # FastMCP server entry point
owa_client.py # OWA HTTP client
tools/
email.py # Email tools
calendar.py # Calendar tools
people.py # Directory search
folders.py # Folder management & session check
availability.py # Free time / meeting time
analytics.py # Meeting stats & contacts
auth.py # Login tool
pyproject.toml # Package config