{
  "markdown": "# outlook-classic-mcp\n\n![outlook-classic-mcp banner](src/public/outlook-classic-mcp-banner.png)\n\nA local **MCP (Model Context Protocol) server** that exposes the **classic\nOutlook desktop client** — mail, folders, calendar, contacts, tasks, color\ncategories, mail rules, and Out-of-Office status — to any MCP-aware\nagent: Claude Code, Claude Desktop, Cowork, GitHub Copilot / VS Code\nagent mode, Cursor, Cline, Continue, Windsurf, and anything else that\nspeaks MCP.\n\nIt talks to Outlook's COM API on Windows via `pywin32`, the same path\nmacros and Office add-ins use. Authentication piggybacks on whatever\naccount Outlook is already signed into — **no Azure / Entra app\nregistration, no Microsoft Graph API, no OAuth tokens.**\n\n---\n\n## Requirements\n\n- Windows 10 or 11\n- **Outlook desktop (Classic)** — the `OUTLOOK.EXE` shipped with\n  Microsoft 365 / Office. The \"new Outlook\" (`olk.exe`) is **not**\n  supported (no COM surface).\n- Python 3.10+ (the installer fetches Python 3.11 via `uv` if you\n  don't already have one).\n\nYou do **not** need to open Outlook before starting the server — the\nserver auto-launches Outlook on its first COM call.\n\n---\n\n## Install\n\nThree paths, simplest first.\n\n### Option 1 — Agent plugin (recommended)\n\nThe repo doubles as a **plugin marketplace**. Installing the plugin registers the MCP server *and* loads the bundled [`outlook` skill](#agent-skill) (an operational reference that teaches the agent how to drive these tools) in one step. The MCP server itself is fetched on demand by `uvx` directly from PyPI — no `git clone`, no `pip install`, no `.venv` to maintain.\n\nThe plugin format started in Claude Code and is now supported by other agents too (Cowork, Copilot, Cursor, and others that adopted the plugin/skill format) — point your agent's plugin install flow at this repo. The commands below are for Claude Code:\n\nInstall [`uv`](https://docs.astral.sh/uv/) once if you don't have it:\n\n```powershell\npowershell -ExecutionPolicy ByPass -c \"irm https://astral.sh/uv/install.ps1 | iex\"\n```\n\nOpen a fresh terminal so PATH refreshes, then in any Claude Code session:\n\n```text\n/plugin marketplace add anasahmed07/Outlook-Classic-MCP\n/plugin install outlook@outlook-classic-mcp\n```\n\nRestart Claude Code (`/quit`, reopen). First call has a one-time 5–15 s pause while `uvx` resolves the package; subsequent calls are instant. Confirm with `outlook_whoami`.\n\nTo update later: `/plugin marketplace update outlook-classic-mcp` then `/plugin update outlook@outlook-classic-mcp`. To pull a fresh PyPI release of the server itself: `uv cache clean outlook-classic-mcp`.\n\n### Option 2 — From PyPI with uv (any MCP client)\n\nWorks for any MCP client. The smart client installer auto-registers the server with Claude Desktop, Claude Code, Cursor, Cline, Continue, and Windsurf; for other clients (e.g. VS Code / Copilot agent mode), add the server to their MCP config manually — see below.\n\n```bat\nuv pip install --system outlook-classic-mcp\npython -m outlook_mcp.scripts.install_to_clients\n```\n\n(`uv` is Astral's Python installer — see Option 1 above for the one-line install. `--system` writes to your system Python so `python -m outlook_mcp` resolves anywhere; drop the flag if you'd rather install into an active venv.)\n\nPackage: <https://pypi.org/project/outlook-classic-mcp/>.\n\n---\n\n## Smart client installer\n\n`scripts/install_to_clients.py` detects which MCP clients are\ninstalled on your machine and shows a checkbox menu:\n\n```\nSelect which clients to register outlook-mcp with:\n  [ ] 1. Claude Desktop      C:\\Users\\you\\AppData\\Roaming\\Claude\\claude_desktop_config.json\n  [ ] 2. Claude Code         (via `claude` CLI)\n  [ ] 3. Cursor              C:\\Users\\you\\.cursor\\mcp.json\n\nType a number to toggle, 'a' to select all, 'n' for none,\n'enter' to confirm, 'q' to quit without changes.\n```\n\nFor each toggled client it deep-merges\n`mcpServers.outlook = {\"command\": \".venv/Scripts/python.exe\", \"args\": [\"-m\", \"outlook_mcp\"]}`\ninto the right config (or runs `claude mcp add` for Claude Code).\nExisting files are snapshotted to `<file>.bak` first. Re-running is\nidempotent — it updates the entry instead of duplicating it.\n\nSupported clients: **Claude Desktop, Claude Code, Cursor, Cline,\nContinue, Windsurf.**\n\n### Manual config (any other MCP client)\n\nAny client not covered by the installer just needs the standard stdio\nserver entry in its MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"outlook\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"outlook-classic-mcp\", \"outlook-mcp\"]\n    }\n  }\n}\n```\n\n(VS Code / Copilot agent mode names the top-level key `servers` in\n`mcp.json` instead of `mcpServers`; the entry itself is the same.)\n\n---\n\n## Tools\n\n31 tools across 9 categories, all prefixed `outlook_*`.\n\n| Category       | Tools |\n| -------------- | ----- |\n| Mail           | `list_mails`, `search_mails`, `get_mail`, `send_mail`, `reply_mail`, `forward_mail`, `move_mail`, `delete_mail`, `mark_mail`, `save_attachments` |\n| Folders        | `list_folders`, `create_folder` |\n| Calendar       | `list_events`, `get_event`, `create_event`, `update_event`, `delete_event`, `respond_event` |\n| Contacts       | `list_contacts`, `search_contacts` (saved contacts + org directory), `get_contact`, `resolve_name` |\n| Tasks          | `list_tasks`, `create_task`, `complete_task` |\n| Categories     | `list_categories`, `set_category` |\n| Rules          | `list_rules`, `toggle_rule` |\n| Out-of-Office  | `get_out_of_office` |\n| Account        | `whoami` — sanity check; shows the bound mailbox |\n\n---\n\n## MCP Apps — interactive UI in the chat\n\nSince v0.3.0 the server implements the [MCP Apps extension](https://modelcontextprotocol.io/extensions/apps/overview)\n(SEP-1865): read tools ship a self-contained HTML view that supporting\nhosts (Claude, Claude Desktop, VS Code Copilot, Goose, Postman, …)\nrender in a sandboxed iframe right inside the conversation — instead of\na wall of text you get a real inbox, agenda, or contact list. Hosts\nwithout MCP Apps support are unaffected and keep getting the usual\nmarkdown.\n\n![mail list MCP App](src/public/mcp-app-mail-list.png)\n\n| View | Rendered by | What you can do in it |\n| ---- | ----------- | --------------------- |\n| Mail list | `list_mails`, `search_mails` | open mails in a reading pane, mark read/unread, flag, delete, filter unread, refresh |\n| Mail reader | `get_mail` | full body + attachment list, mark, flag, delete |\n| Calendar agenda | `list_events` | day-grouped agenda, expand an event for attendees + body, refresh |\n| Contacts | `list_contacts`, `search_contacts` | live search (incl. org directory), copy addresses |\n| Tasks | `list_tasks` | complete tasks, quick-add new ones, show completed, refresh |\n\n![calendar MCP App](src/public/mcp-app-calendar.png)\n\nThe views are plain inline HTML/CSS/JS (no build step, no external\nCDNs — the sandbox CSP blocks those anyway), follow the host's\nlight/dark theme, and talk back over the standard `postMessage`\nJSON-RPC dialect: buttons in the UI call the same `outlook_*` tools the\nmodel uses, and in-app actions (delete, complete, …) are reported back\ninto the model's context so the conversation stays in sync.\n\nTechnically: each UI tool carries `_meta.ui.resourceUri` pointing at a\n`ui://outlook/*.html` resource (mime `text/html;profile=mcp-app`) and\nreturns markdown for the model **plus** `structuredContent` for the\napp. To preview the views without an MCP host:\n`python scripts/preview_ui.py`, then open\n`.ui-preview/harness.html?view=mail-list` (any view name, optional\n`&theme=dark`) in a browser.\n\n---\n\n## Agent skill\n\nThe repo also ships an agent **skill** at `skills/outlook/` (standard Agent Skills format — works in Claude Code, Cowork, Copilot, Cursor, and other agents that load skills) — a self-contained operational reference that teaches the agent how to drive the `outlook_*` tools correctly: folder reference syntax, the `EntryID` handle pattern, ISO-8601 date conventions, the `Recurrence` object, which calls have side effects to confirm before, and 19 worked recipes for common workflows (triage, drafting replies, weekly digests, scheduling meetings, recurring events, attachment handling, multi-mailbox setups).\n\nLayout:\n\n```\nskills/outlook/\n├── SKILL.md                  # always-loaded operational core\n└── references/               # loaded on demand\n    ├── tools.md              # full per-tool parameter / return-shape reference\n    ├── recipes.md            # worked multi-step workflows\n    ├── gotchas.md            # quirks + failure modes (Programmatic Access prompt, EX:/O= addresses, live rule toggling, sandboxed paths, etc.)\n    └── setup.md              # install instructions an agent can walk a user through when the tools aren't connected yet\n```\n\nInstalling the [plugin](#option-1--agent-plugin-recommended) auto-loads this skill alongside the MCP server. For an agent that supports skills but not plugins, copy the `skills/outlook/` directory into wherever it loads skills from.\n\n---\n\n## Conventions\n\n**Folder references** can be:\n\n- A well-known name: `inbox`, `sent`, `drafts`, `deleted`, `outbox`,\n  `junk`, `calendar`, `contacts`, `tasks`, `notes`\n- A slash path: `Inbox/Projects/Acme`\n- A path qualified by store name: `Mailbox - you@example.com/Inbox/Projects/Acme`\n\nUse `outlook_list_folders` to discover paths.\n\n**Dates / times** are ISO-8601 strings. Inputs without a timezone are\ntreated as local time (what Outlook stores); returned timestamps carry\nthe user's local UTC offset explicitly (`2026-06-10T16:33:22+05:00`).\n\n**Item IDs** are Outlook `EntryID` strings. Read tools return them\non every item; pass them back to detail / edit / delete tools.\n\n**Response format** — most read tools accept `response_format`:\n- `markdown` (default) — pretty rendered output\n- `json` — full structured data\n\n**Errors** are raised, so the MCP host marks the response\n`isError: true`. Error messages try to suggest a corrective next step.\n\n**Filesystem paths** for `attachments=` and `output_dir=` must be\nabsolute and under the user profile (default sandbox). Set\n`OUTLOOK_MCP_ALLOW_ANY_PATH=1` to disable the sandbox if you legitimately\nneed to read or write outside `%USERPROFILE%`.\n\n---\n\n## Architecture\n\n```\n                  +-------------------+\n   stdio  <--->   |  FastMCP server   |   <-- one per process\n                  +---------+---------+\n                            |\n                  await bridge.call(...)\n                            |\n                            v\n                  +-------------------+\n                  | OutlookBridge     |   persistent STA thread\n                  | - one Dispatch    |   single Outlook.Application\n                  | - work queue      |   handle, reused by every call\n                  +---------+---------+\n                            |\n                  Outlook COM (auto-launches OUTLOOK.EXE if needed)\n```\n\nThe MCP event loop never blocks on COM, and COM only ever sees the\none STA thread it needs. This is faster than per-call dispatch and\nthe Outlook process stays warm across calls.\n\n---\n\n## Development\n\n```bat\n.venv\\Scripts\\activate\npip install -e .[dev]\npytest\n```\n\nSmoke test the running server with the MCP inspector:\n\n```bat\nnpx @modelcontextprotocol/inspector .venv\\Scripts\\python.exe -m outlook_mcp\n```\n\n> The inspector mangles backslashes on Windows — use forward-slash\n> paths if you hit \"ENOENT\" errors.\n\nPublish to PyPI:\n\n```bat\npublish.bat\n```\n\n(`TWINE_USERNAME=__token__`, `TWINE_PASSWORD=<pypi-token>`.)\n\n---\n\n## Notes & caveats\n\n- The first call after a cold start takes a few seconds — Outlook's\n  COM surface boots up. After that, calls are fast (one Dispatch\n  handle is reused).\n- Closing Outlook while the server is running is fine: the next tool\n  call detects the dead COM connection, relaunches OUTLOOK.EXE,\n  reconnects, and retries automatically (expect that one call to take\n  15–30 s).\n- Outlook auto-launch relies on standard COM behavior. On\n  tightly-locked-down machines (UAC, group policy blocking COM\n  activation), open Outlook manually and try again.\n- Send / reply / forward / delete may trigger Outlook's \"Programmatic\n  Access\" security prompts on some corporate machines. If your IT\n  policy blocks programmatic send entirely, write tools will fail —\n  read tools still work.\n- Some properties (e.g. `SenderEmailAddress` for Exchange addresses)\n  come back as `EX:/O=...` distinguished names rather than SMTP. Use\n  `from_address` substring matching instead of exact equality — or\n  `search_mails(scope='from')`, which also matches the real SMTP\n  address.\n- Toggling mail rules modifies live rules immediately — there is no\n  staging buffer. Confirm the rule name with `outlook_list_rules`\n  before calling `outlook_toggle_rule`.\n- This server is **local-only**. Do not expose it over a network.\n\n---\n\n## Troubleshooting\n\n**\"Outlook COM thread did not become ready\"** — Outlook didn't\nauto-launch. Open it manually, sign in, then restart the MCP client\nso it re-spawns the server.\n\n**Inspector shows ENOENT for the python path** — known Windows\nquirk; use forward slashes (`C:/Users/you/...`) instead of\nbackslashes.\n\n**Send / reply gets blocked silently** — Outlook → File → Options →\nTrust Center → Programmatic Access. The setting that works while\nyou're using the server is \"Never warn me about suspicious activity\n(not recommended)\" — or have IT add the Python interpreter as a\ntrusted publisher.\n\n---\n\n## License\n\nMIT\n\n",
  "bytes": 13426,
  "sha": "e3ad47c2bf21dd25bc474ba3601ec4479dd8a060ad49b733a41df9e09a9ba97c",
  "repo_slug": "anasahmed07/outlook-classic-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_anasahmed07_outlook_classic_mcp_outlook_3a9a0e71/readme"
}