SkillAgentSearch skills...

outlook-ews-mcp

Secure MCP server for on-prem Microsoft Exchange (EWS) with tools for email, calendar, contacts, folders, attachments, and free/busy availability.

Install / Use

claude mcp add viartemev -- npx -y github:viartemev/outlook-ews-mcp

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

84/100

Category

Automation

Supported Platforms

Claude Code
Claude Desktop

Our assessment of outlook-ews-mcp

outlook-ews-mcp scores 84/100 on our quality scale, 2110th of 2,881 Automation skills we index.

Its MCP Server is 22 KB long, well organised into 22 sections with 8 code examples: a thorough specification that gives an agent plenty to work with.

It has 10 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
4/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 11 days ago, so outlook-ews-mcp is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 97/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

outlook-ews-mcp compared with similar skills

All 4 of these similar skills score higher than outlook-ews-mcp; compare them before choosing.

SkillScoreStarsUpdatedFormat
outlook-ews-mcp (this skill)by viartemev841011d agoMCP Server
Agent-Reachby Panniantong10097.0k5d agoCLAUDE.md
headroomby headroomlabs-ai10075.2ktodayCLAUDE.md
CowAgentby zhayujie10047.4ktodayCLAUDE.md
Scraplingby D4Vinci10087.3ktodayMCP Server

Frequently asked questions

How do I install outlook-ews-mcp?
Run claude mcp add viartemev -- npx -y github:viartemev/outlook-ews-mcp. The install tabs above show the steps for each supported agent.
Which AI agents does outlook-ews-mcp work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is outlook-ews-mcp safe to use?
It is MIT-licensed and scores 97/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is outlook-ews-mcp still maintained?
The repository was last updated 11 days ago, so outlook-ews-mcp is actively maintained.

outlook-ews-mcp

<p align="right"><b>English</b> · <a href="README.ru.md">Русский</a></p>

Python MCP Exchange Status License

outlook-ews-mcp is an MCP server for on-prem Microsoft Exchange via EWS (exchangelib). It gives MCP-compatible clients (Claude Desktop, Claude Code, and any other MCP client) access to email, calendar, contacts, folders, attachments, and availability data through a single, testable Python service — no direct mailbox scripting required.

Renamed from outlook-mcp. That name was already taken on PyPI by an unrelated project, so the distribution and CLI name are now outlook-ews-mcp. The Python import path is unchanged. Until the first tagged PyPI release, install from this repository as shown below.

Contents

Highlights

  • Email — list, search (substring or Advanced Query Syntax), read, send, reply, forward, move, copy, delete, mark, categorize, bulk actions, raw MIME export, attachment add/delete
  • System — Inbox Rules, Out-of-Office (automatic replies), read-only delegate listing
  • Calendar — list, create, update, delete, respond to invites, find free slots, view a shared/delegate mailbox's calendar, Room Finder, bulk actions
  • Contacts — search, read, create, update, delete
  • Folders & attachments — folder CRUD and attachment download
  • Auth — NTLM and Basic against on-prem Exchange
  • Transport — stdio and SSE
  • Architecture — centralized error mapping through a single ExchangeClient abstraction (see Project notes)
  • Safety — a privacy-safer smoke check by default (see Smoke check)
  • Ops — Docker image plus GitHub and GitLab CI/CD pipelines included

Tool catalog

Every tool below is registered in tool_specs.py, the single source of truth for its name, description, and schema. Read-only marks tools that never modify the mailbox — they get more concurrency (see Request queue) and are safe to call speculatively.

System

| Tool | Description | Read-only | | --- | --- | --- | | ping_exchange | Check connectivity to Exchange | ✅ | | get_mailbox_info | Get mailbox metadata | ✅ | | list_delegates | List mailbox delegates and their folder permission levels — read-only because exchangelib has no delegate write support | ✅ | | list_inbox_rules | List server-side inbox rules | ✅ | | create_inbox_rule | Create a server-side inbox rule, e.g. "from this sender → move to folder" | | | update_inbox_rule | Enable/disable a rule or change its priority (other fields aren't updatable here) | | | delete_inbox_rule | Delete a server-side inbox rule by id | | | get_out_of_office | Get the out-of-office (automatic reply) settings | ✅ | | set_out_of_office | Turn automatic replies off, on, or schedule a start/end window | |

⚠️ create_inbox_rule / update_inbox_rule / delete_inbox_rule manage rules over EWS, which removes the client-side rule blob desktop Outlook keeps — this can wipe rules a user created in Outlook itself. This is documented EWS behavior, not a bug here.

Email

| Tool | Description | Read-only | | --- | --- | --- | | list_emails | List emails in a folder | ✅ | | get_email | Get a full email by id | ✅ | | get_email_mime | Export a message's raw RFC 822 MIME content, base64-encoded | ✅ | | get_thread | Get every message of a conversation in order, bodies included | ✅ | | search_emails | Search by substring (subject/body/sender) or server-side Advanced Query Syntax | ✅ | | send_email | Send a new email | | | reply_email | Reply to an email | | | forward_email | Forward an email | | | move_email | Move an email to another folder | | | copy_email | Copy an email to another folder | | | move_emails | Bulk move, with per-item results — one bad id doesn't fail the rest | | | copy_emails | Bulk copy, with per-item results | | | delete_emails | Bulk delete, with per-item results (soft-deletes unless hard_delete) | | | delete_email | Delete an email | | | mark_email | Update read state, importance, or the follow-up flag | | | categorize_email | Set, add, or remove Outlook categories (the coloured labels) | | | mark_emails | Bulk version of mark_email, with per-item results | | | categorize_emails | Bulk version of categorize_email, with per-item results | | | list_categories | List categories in use with counts, sampled from recent messages (not the mailbox master category list) | ✅ | | list_folders | List mailbox folders | ✅ | | create_folder | Create a mailbox folder | | | rename_folder | Rename a folder — refuses built-in folders (Inbox, Sent Items, Calendar, ...) | | | delete_folder | Delete a folder and everything in it — refuses built-in folders | | | create_draft | Create an email draft | | | create_reply_draft | Create a reply-all draft in the original conversation, with additional recipients, mentions and attachments; does not send | | | update_draft | Update a draft; omitted fields are left unchanged, attachments (if given) replaces the whole set | | | send_draft | Submit a draft and confirm its copy in Sent Items | | | add_attachment | Attach a local file to a message, typically a draft — the file must live under EXCHANGE_ATTACHMENT_ROOT | | | delete_attachment | Remove one attachment from a message by id | | | get_attachment | Save an attachment to disk | ✅ |

Calendar

| Tool | Description | Read-only | | --- | --- | --- | | list_events | List calendar events in a time range; pass mailbox for a colleague's default calendar (needs delegate/impersonation access, not combinable with calendar_id) | ✅ | | get_event | Get a calendar event by id; pass mailbox for a colleague's calendar | ✅ | | create_event | Create a calendar event | | | update_event | Update a calendar event | | | delete_event | Delete a calendar event | | | respond_to_invite | Accept, decline, or tentatively respond to an invite | | | find_free_slots | Find open meeting time slots | ✅ | | delete_events | Bulk delete events, with per-item results | | | respond_to_invites | Bulk respond to invites, with per-item results | | | get_my_availability | Get free/busy slots; pass mailbox for a colleague's calendar | ✅ | | list_calendars | List calendars | ✅ | | list_room_lists | List Room Finder room lists (groups of meeting rooms) | ✅ | | list_rooms | List the meeting rooms in a Room Finder room list | ✅ |

Contacts

| Tool | Description | Read-only | | --- | --- | --- | | search_contacts | Search contacts | ✅ | | get_contact | Get a contact by id | ✅ | | create_contact | Create a personal contact | | | update_contact | Update a personal contact | | | delete_contact | Delete a personal 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 Global Address List
  • Expose Exchange operations through a controlled MCP boundary instead of direct mailbox scripting

Security notes

What the current code does:

| | | | --- | --- | | Scoped connectivity | Connects only to the Exchange/EWS endpoint configured in EXCHANGE_SERVER | | No telemetry | Contains no telemetry, analytics, or third-party data export logic | | Secrets stay local | Keeps secrets in environment variables / .env, ignored by .gitignore (.env, .env.*, while keeping .env.example) | | Clean error payloads | Structured MCP error responses never include raw Exchange exception text, message bodies, attachment contents, or passwords; successful tools return only the mailbox data they were asked for | | Clean logs | LOG_LEVEL only controls the app's own outlook_mcp.* loggers; exchangelib's SOAP XML loggers — which would otherwise dump full request/response XML, even at ERROR level on transport errors — are always force-silenced | | Clean Docker builds | .dockerignore excludes .env, tests, caches, and VCS metadata from the build context |

What you should still be careful with:

  • EXCHANGE_VERIFY_SSL=false disables TLS certificate verification — trusted internal/self-signed environments only.
  • EXCHANGE_AUTH_TYPE=Basic sends credentials in the clear, so the server refuses to start against an http:// EXCHANGE_SERVER; only override with EXCHANGE_ALLOW_INSECURE_BASIC_AUTH=true for a local/test server you control.
  • get_attachment writes files to disk, and send_email/reply_email/forward_email/ create_draft read local files (via attachments) and attach their contents to outgoing mail. Combined with untrusted email content, this is a plausible path for prompt-injected exfiltration of any file readable by the process. Local file access is refused by default and only works once EXCHANGE_ATTACHMENT_ROOT is set to an absolute directory, which then confines both attachments paths and get_attachment's save_path to that directory tree (an unset save_path still falls back to the system temp directory).
  • outlook-ews-mcp-smoke is privacy-safe by default and prints only masked mailbox info plus counts; set OUTLOOK_MCP_SMOKE_INCLUDE_DATA=true only 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-ews-mcp

By default the server runs in stdio mode. Set MCP_TRANSPORT=sse to start an HTTP server instead.

Configuration

Minimal .env to get started — everything else below has a working default:

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

A fully commented copy of every variable lives in .env.example.

| Variable | Default | Description | | --- | --- | --- | | EXCHANGE_SERVER | (required) | EWS endpoint URL, e.g. https://mail.company.com/EWS/Exchange.asmx | | EXCHANGE_USERNAME | (required) | DOMAIN\username or a UPN. Exactly one backslash — dotenv does not process escape sequences | | EXCHANGE_PASSWORD | (required) | Account password | | EXCHANGE_EMAIL_ADDRESS | unset | SMTP address; set when EXCHANGE_USERNAME isn't one | | EXCHANGE_AUTH_TYPE | NTLM | NTLM or Basic | | EXCHANGE_ALLOW_INSECURE_BASIC_AUTH | false | Allow Basic auth over http:// — local/test servers only | | EXCHANGE_VERIFY_SSL | true | Verify the server's TLS certificate; false only for trusted internal/self-signed setups | | EXCHANGE_VERSION | unset (auto-detected) | Exchange server version, e.g. EXCHANGE_2016 | | EXCHANGE_TIMEZONE_FALLBACK | Europe/Moscow | Used only when Exch

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10
CategoryAutomation
Updated11d ago
Forks4

Languages

Python

Trust signals

97/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

1 info