288 lines
8.1 KiB
Markdown
288 lines
8.1 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
# 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`):
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"exchange": {
|
|
"command": "uvx",
|
|
"args": [
|
|
"exchange-mcp-server",
|
|
"--owa-url", "https://owa.example.com"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Cursor** (`.cursor/mcp.json`):
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"exchange": {
|
|
"command": "uvx",
|
|
"args": [
|
|
"exchange-mcp-server",
|
|
"--owa-url", "https://owa.example.com"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Claude Code** (`.mcp.json`):
|
|
|
|
```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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
pip install -e ".[http]" # adds uvicorn + sse-starlette
|
|
```
|
|
|
|
### Start the server
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```json
|
|
{
|
|
"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`:
|
|
|
|
```bash
|
|
echo -n 'my-secret-token' | sha256sum
|
|
# → 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
|
|
```
|
|
|
|
### Security notes
|
|
|
|
- Always use a strong random token.
|
|
- Bind to `127.0.0.1` unless you have a reverse proxy / firewall.
|
|
- For `streamable-http` the client must send `Accept: text/event-stream`.
|
|
- The `--token-hash` is required whenever `--transport` is not `stdio`.
|
|
|
|
## Login
|
|
|
|
The `login` MCP tool accepts session cookies that you copy from your browser.
|
|
|
|
1. Log into OWA in your browser.
|
|
2. Open DevTools (F12) → Application → Cookies → select your OWA domain.
|
|
3. Copy all cookies as `name=value` pairs (one per line).
|
|
4. Call the `login` tool 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
|
|
```
|