outlook-mcp
Secure MCP server for on-prem Microsoft Exchange (EWS) with tools for email, calendar, contacts, folders, attachments, and free/busy availability.
README
outlook-mcp
outlook-mcp is an MCP server for on-prem Microsoft Exchange via EWS (exchangelib).
It gives MCP-compatible clients access to email, calendar, contacts, folders, attachments, and availability data through a single, testable Python service.
Short description
Secure MCP server for on-prem Microsoft Exchange (EWS) with tools for email, calendar, contacts, folders, attachments, and free/busy availability.
Suggested repository topics / tags
mcp, model-context-protocol, exchange, microsoft-exchange, ews, outlook, email, calendar, contacts, python, automation, exchangelib
Highlights
- email operations: list, search, read, send, reply, forward, move, copy, delete, mark
- calendar operations: list, create, update, delete, respond to invites, find free slots
- contacts operations: search, read, create, update, delete
- folder operations and attachment download
- Exchange auth via
NTLMandBasic - MCP transport via
stdioandSSE - centralized error mapping and a single
ExchangeClientabstraction - privacy-safer smoke check output by default
- Docker support and GitLab CI/CD pipeline included
Tool catalog
System
ping_exchangeget_mailbox_info
list_emailsget_emailsearch_emailssend_emailreply_emailforward_emailmove_emailcopy_emaildelete_emailmark_emaillist_folderscreate_foldercreate_draftsend_draftget_attachment
Calendar
list_eventsget_eventcreate_eventupdate_eventdelete_eventrespond_to_invitefind_free_slotsget_my_availabilitylist_calendars
Contacts
search_contactsget_contactcreate_contactupdate_contactdelete_contact
Typical use cases
- connect Claude Desktop or another MCP client to on-prem Exchange
- search inbox messages and fetch full email content
- send or draft emails from AI workflows
- inspect calendars and create meetings
- check free/busy windows for scheduling
- search personal contacts or the GAL
- expose Exchange operations through a controlled MCP boundary instead of direct mailbox scripting
Security notes
What the current code does:
- connects only to the Exchange/EWS endpoint configured in
EXCHANGE_SERVER - does not contain telemetry, analytics, or third-party data export logic
- keeps secrets in environment variables /
.env - ignores local secret files via
.gitignore(.env,.env.*, while keeping.env.example) - logs only tool name, status, duration, and error code; it does not log message bodies, attachment contents, or passwords
- excludes
.env, tests, caches, and VCS metadata from Docker build context via.dockerignore
What you should still be careful with:
EXCHANGE_VERIFY_SSL=falsedisables TLS certificate verification and should be used only for trusted internal/self-signed environmentsget_attachmentwrites files to disk, so choose a safe destination directoryoutlook-mcp-smokeis privacy-safe by default and prints only masked mailbox info plus counts; setOUTLOOK_MCP_SMOKE_INCLUDE_DATA=trueonly if you explicitly want real inbox/event data in stdout- if you enable file logging with
LOG_FILE, protect that file with OS permissions - if you publish Docker images from CI, protect GitLab/GitHub project access and registry permissions
Quick start
uv venv
source .venv/bin/activate
uv pip install -e .[dev]
cp .env.example .env
outlook-mcp
By default the server runs in stdio mode. Set MCP_TRANSPORT=sse to start an HTTP server.
Configuration
Example .env:
EXCHANGE_SERVER=https://mail.company.com/EWS/Exchange.asmx
EXCHANGE_USERNAME=DOMAIN\\username
EXCHANGE_PASSWORD=secret
EXCHANGE_EMAIL_ADDRESS=user@company.com
EXCHANGE_VERIFY_SSL=true
EXCHANGE_AUTH_TYPE=NTLM
EXCHANGE_VERSION=EXCHANGE_2016
EXCHANGE_TIMEOUT=30
EXCHANGE_MAX_RETRIES=3
EXCHANGE_TIMEZONE=Europe/Moscow
EXCHANGE_IMPERSONATE_AS=
ATTACHMENT_MAX_SIZE_MB=10
MCP_TRANSPORT=stdio
MCP_SSE_HOST=127.0.0.1
MCP_SSE_PORT=8080
LOG_LEVEL=INFO
LOG_FILE=
Notes:
- set
EXCHANGE_EMAIL_ADDRESSwhenEXCHANGE_USERNAMEis not an SMTP address OAuth2is reserved in config, but this build currently supports live auth withNTLMorBasicEXCHANGE_IMPERSONATE_ASenables mailbox impersonation when Exchange permissions are configured accordinglyATTACHMENT_MAX_SIZE_MBis enforced before sending/replying/forwarding/drafting with local attachments
Claude Desktop example
{
"mcpServers": {
"outlook": {
"command": "outlook-mcp",
"env": {
"EXCHANGE_SERVER": "https://mail.company.com/EWS/Exchange.asmx",
"EXCHANGE_USERNAME": "DOMAIN\\username",
"EXCHANGE_PASSWORD": "secret",
"EXCHANGE_EMAIL_ADDRESS": "user@company.com",
"EXCHANGE_AUTH_TYPE": "NTLM"
}
}
}
}
Smoke check
After filling .env, run:
outlook-mcp-smoke
Default output is sanitized for safer verification. If you intentionally want sample mailbox/event data in the output:
OUTLOOK_MCP_SMOKE_INCLUDE_DATA=true outlook-mcp-smoke
Docker
docker build -t outlook-mcp .
docker run --rm --env-file .env outlook-mcp
GitLab CI/CD
The repository includes .gitlab-ci.yml with these stages:
lint— runsrufftest— runspytestbuild— builds Python package artifacts intodist/release— builds and pushes a Docker image to the GitLab Container Registry on the default branch and on tags
Default image tagging behavior:
- default branch: pushes
:$CI_COMMIT_SHORT_SHAand:latest - git tag: pushes
:$CI_COMMIT_TAG
GitLab built-in registry variables are used:
CI_REGISTRYCI_REGISTRY_USERCI_REGISTRY_PASSWORDCI_REGISTRY_IMAGE
Development
uv run --python 3.12 --with '.[dev]' ruff check .
uv run --python 3.12 --with '.[dev]' pytest -q
Project notes
- The implementation is centered around a single
ExchangeClientabstraction so auth, transport, retries, and error mapping stay centralized. - Errors are returned in a structured JSON form suitable for MCP
isError=truehandling. RTK.mdis not present in this repository, so the implementation followsPLAN.md.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.