{
  "markdown": "<!-- mcp-name: io.github.salahawad/outlook-personal-mcp -->\n# outlook-personal-mcp\n\nAn MCP server that gives Claude Code and Codex full control of a personal Outlook.com mailbox and calendar via the Microsoft Graph API. Written in Python, speaks the MCP stdio transport, and uses per-user device-code OAuth so your credentials never leave your machine. MIT licensed.\n\n---\n\n## Features\n\n- **Mail** — list, search, read, send, reply, forward, move, copy, flag, mark read/unread, delete (soft or hard)\n- **Drafts** — create, update, attach local files, send\n- **Folders** — list, create, rename, delete\n- **Calendar** — list calendars, list/search/get/create/update/delete events, respond to invites (accept/decline/tentative), check free/busy availability\n- **Per-user OAuth** — you register your own free Azure app; the server authenticates with your Microsoft account and caches the token locally\n- **Local stdio** — runs as a child process of the MCP host; your mailbox data never transits a third party\n\n---\n\n## Prerequisites\n\n- Python 3.10 or later\n- [`uv`](https://docs.astral.sh/uv/) (fast Python package and tool runner) — **required at runtime**: the server is launched via `uvx`, and it is not bundled by your MCP host (including Claude Desktop). Install it with `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS/Linux) or `powershell -c \"irm https://astral.sh/uv/install.ps1 | iex\"` (Windows).\n- A personal Microsoft account (Outlook.com, Hotmail, Live, etc.)\n- A free Azure app registration (see below — takes about three minutes)\n\n---\n\n## Azure App Registration\n\n1. Go to [https://portal.azure.com](https://portal.azure.com) → **Microsoft Entra ID** → **App registrations** → **New registration**.\n2. Name it anything you like (e.g. `outlook-personal-mcp`). Under **Supported account types** choose **Personal Microsoft accounts only**. No redirect URI is needed. Click **Register**.\n3. Open the app → **Authentication** → **Advanced settings** → **Allow public client flows** → set to **Yes** → **Save**. (This is required for the device-code login flow used by this server.)\n4. Go to **API permissions** → **Add a permission** → **Microsoft Graph** → **Delegated permissions**, then add:\n   - `Mail.ReadWrite`\n   - `Mail.Send`\n   - `Calendars.ReadWrite`\n\n   (`User.Read` is included by default; `offline_access` is requested automatically at runtime — you do not need to add it.)\n5. Copy the **Application (client) ID** from the **Overview** page. This is your `OUTLOOK_MCP_CLIENT_ID`.\n\n### Alternatively: create the app with the Azure CLI\n\nIf you have the [`az` CLI](https://learn.microsoft.com/cli/azure/install-azure-cli), the whole registration is one command:\n\n```bash\naz login --use-device-code --allow-no-subscriptions   # sign in with your personal account\n\naz ad app create \\\n  --display-name \"outlook-personal-mcp\" \\\n  --sign-in-audience PersonalMicrosoftAccount \\\n  --is-fallback-public-client true \\\n  --required-resource-accesses '[{\"resourceAppId\":\"00000003-0000-0000-c000-000000000000\",\"resourceAccess\":[{\"id\":\"024d486e-b451-40bb-833d-3e66d98c5c73\",\"type\":\"Scope\"},{\"id\":\"e383f46e-2787-4529-855e-0e479a3ffac0\",\"type\":\"Scope\"},{\"id\":\"1ec239c2-d7c9-4623-a91a-a9775856bb36\",\"type\":\"Scope\"}]}]' \\\n  --query appId -o tsv\n```\n\nThe printed `appId` is your `OUTLOOK_MCP_CLIENT_ID`. (The GUIDs are the Microsoft Graph delegated scopes `Mail.ReadWrite`, `Mail.Send`, and `Calendars.ReadWrite`.) **Note:** a brand-new app registration takes a few minutes to propagate to Microsoft's consumer login endpoint — if your first login fails with `AADSTS700016` (\"application … not found\"), wait a few minutes and retry.\n\n---\n\n## Install & First-Time Login\n\nRun the one-time interactive login. It prints a short URL and a code; open the URL in any browser, enter the code, approve the permissions, and you are done. The token is cached at `~/.config/outlook-personal-mcp/token_cache.bin` (mode 600) and refreshed automatically on subsequent runs — you will not be prompted again unless the refresh token expires or is revoked.\n\n```bash\nOUTLOOK_MCP_CLIENT_ID=<your-app-client-id> uvx mcp-outlook-personal login\n```\n\n> To run the latest unreleased code from source instead of the PyPI release, swap `mcp-outlook-personal` for `--from git+https://github.com/salahawad/outlook-personal-mcp mcp-outlook-personal`.\n\n---\n\n## Configure Claude Code\n\nAdd the server to your project's `.mcp.json` (or `~/.claude/.mcp.json` for all projects):\n\n```json\n{\n  \"mcpServers\": {\n    \"outlook\": {\n      \"command\": \"uvx\",\n      \"args\": [\"mcp-outlook-personal\"],\n      \"env\": { \"OUTLOOK_MCP_CLIENT_ID\": \"<your-app-client-id>\" }\n    }\n  }\n}\n```\n\nAlternatively, use the CLI: `claude mcp add`.\n\n---\n\n## Configure Codex\n\nAdd the server to `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.outlook]\ncommand = \"uvx\"\nargs = [\"mcp-outlook-personal\"]\nenv = { OUTLOOK_MCP_CLIENT_ID = \"<your-app-client-id>\" }\n```\n\n---\n\n## Install as a Claude Desktop extension (.mcpb)\n\nThis server is also packaged as a [Claude Desktop extension](https://www.anthropic.com/engineering/desktop-extensions) (`.mcpb`). Build the bundle from a checkout:\n\n```bash\nnpx @anthropic-ai/mcpb pack . dist/mcp-outlook-personal.mcpb\n```\n\nThen in Claude Desktop open **Settings → Extensions**, install the `dist/mcp-outlook-personal.mcpb` file, and enter your **Azure App Client ID** (plus any optional settings) when prompted.\n\n> **Requirement:** the extension launches the server with `uvx mcp-outlook-personal`, so [`uv`](https://docs.astral.sh/uv/) must be installed and on your `PATH` — Claude Desktop does not bundle it (see [Prerequisites](#prerequisites)). Codex and other stdio hosts use the config above instead of the `.mcpb`.\n\n---\n\n## Configuration (Environment Variables)\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `OUTLOOK_MCP_CLIENT_ID` | **Yes** | — | Azure app's Application (client) ID |\n| `OUTLOOK_MCP_AUTHORITY` | No | `https://login.microsoftonline.com/consumers` | MSAL authority URL (change only if you move to a work/school tenant) |\n| `OUTLOOK_MCP_TOKEN_CACHE` | No | `~/.config/outlook-personal-mcp/token_cache.bin` | Path to the MSAL token cache file |\n| `OUTLOOK_MCP_FILE_ROOT` | No | `~/.local/share/outlook-personal-mcp/files` | Only files under this directory can be read by `add_attachment` or written by `download_attachment` |\n| `OUTLOOK_MCP_MAX_FILE_BYTES` | No | `3145728` | Maximum bytes allowed for local attachment reads and attachment downloads |\n| `OUTLOOK_MCP_ALLOW_PERMANENT_DELETE` | No | `false` | Set to `true` to enable the `permanent_delete` tool (irreversible — see below) |\n| `OUTLOOK_MCP_DEBUG` | No | `false` | Set to `true` to log each Graph request's method, URL, and HTTP status code to stderr. Never logs tokens or message content. |\n\n---\n\n## Tools\n\n### Account\n\n| Tool | Description |\n|---|---|\n| `whoami` | Return the signed-in user's Microsoft account profile |\n\n### Mail\n\n| Tool | Description |\n|---|---|\n| `list_messages` | List messages (newest first); optionally filter by folder or unread-only |\n| `search_messages` | Full-text search across the entire mailbox (Graph `$search`) |\n| `get_message` | Get a single message; optionally include the full body |\n| `list_attachments` | List a message's attachments (id, name, size, content type) |\n| `download_attachment` | Download an attachment to a path under `OUTLOOK_MCP_FILE_ROOT` (refuses to overwrite an existing file) |\n| `send_mail` | Send an email |\n| `reply` | Reply to a message (`reply_all` to reply to everyone) |\n| `forward` | Forward a message to recipients with an optional comment |\n| `move_message` | Move a message to another folder |\n| `copy_message` | Copy a message to another folder |\n| `mark_read` | Mark a message read or unread |\n| `flag_message` | Flag or unflag a message |\n| `delete_message` | Delete a message (moves it to Deleted Items; reversible) |\n| `permanent_delete` | **Permanently** delete a message (irreversible). Only available when `OUTLOOK_MCP_ALLOW_PERMANENT_DELETE=true` |\n\n### Folders\n\n| Tool | Description |\n|---|---|\n| `list_folders` | List mail folders with unread and total message counts |\n| `create_folder` | Create a mail folder, optionally nested under a parent |\n| `rename_folder` | Rename a mail folder |\n| `delete_folder` | Delete a mail folder (moves it to Deleted Items) |\n\n### Drafts\n\n| Tool | Description |\n|---|---|\n| `create_draft` | Create a draft message (not sent) |\n| `update_draft` | Update a draft's subject and/or body |\n| `add_attachment` | Attach a local file (a regular, non-symlink file under `OUTLOOK_MCP_FILE_ROOT`) to a draft |\n| `send_draft` | Send an existing draft |\n\n### Calendar\n\n| Tool | Description |\n|---|---|\n| `list_calendars` | List the user's calendars |\n| `list_events` | List events; if `start`/`end` (ISO 8601) are given, returns that time window |\n| `search_events` | Search events by free text |\n| `get_event` | Get one event including body, attendees, and online meeting link |\n| `create_event` | Create a calendar event with optional attendees and online meeting |\n| `update_event` | Update fields on an existing event (only provided fields change) |\n| `delete_event` | Delete/cancel a calendar event |\n| `respond_event` | Respond to a meeting invite: `accept`, `decline`, or `tentative` |\n| `find_availability` | Get free/busy availability for a list of people over a time window |\n\n---\n\n## Permanent Delete\n\nThe `permanent_delete` tool bypasses the Deleted Items folder and removes a message irreversibly. It is **disabled by default** — when `OUTLOOK_MCP_ALLOW_PERMANENT_DELETE` is not set (or is `false`), the tool is not registered with the MCP server at all and will not appear in the tool list.\n\nTo enable it, set `OUTLOOK_MCP_ALLOW_PERMANENT_DELETE=true` in the server's environment block in your `.mcp.json` / `config.toml`. Only do this if you understand the consequences: there is no undo and no Recoverable Items path for personal accounts.\n\n---\n\n## Security\n\n- **Token cache is a credential.** The file at `~/.config/outlook-personal-mcp/token_cache.bin` contains a long-lived refresh token. It is written with mode `600`, but treat it like a password — never commit it, never share it, and store it on an encrypted volume.\n- **Data stays local.** The server runs as a child process of Claude Code / Codex over stdio. Your mailbox content is passed directly between the MCP host and the Microsoft Graph API; no third-party relay is involved.\n- **Revocation.** To revoke access, delete the token cache file and/or navigate to [https://account.microsoft.com/permissions](https://account.microsoft.com/permissions) to remove the Azure app's consent. You can also delete the Azure app registration entirely from the portal.\n- **File paths.** `download_attachment` writes only under `OUTLOOK_MCP_FILE_ROOT` and refuses to overwrite existing files. `add_attachment` reads only regular, non-symlink files under `OUTLOOK_MCP_FILE_ROOT`. Relative paths are resolved under that root; absolute paths outside it (and any path traversing a symlink) are rejected. Both tools enforce `OUTLOOK_MCP_MAX_FILE_BYTES`. Review these paths before confirming any tool call that touches the filesystem.\n\n---\n\n## Development\n\n```bash\ngit clone https://github.com/salahawad/outlook-personal-mcp\ncd outlook-personal-mcp\nuv venv && uv pip install -e \".[dev]\"\nuv run pytest\nuv run ruff check .\n```\n\n---\n\n## Privacy Policy\n\nThis server runs entirely on your machine and sends data only between your machine and Microsoft's Graph API — no third-party relay, no telemetry, and the maintainer receives nothing. OAuth tokens are cached locally at `~/.config/outlook-personal-mcp/token_cache.bin` (mode 600). See [PRIVACY.md](PRIVACY.md) for the full privacy policy.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 11774,
  "sha": "a1244543fceed4d1d0543c928662d682e446c3721e6a326548c7db08fae0f97b",
  "repo_slug": "salahawad/outlook-personal-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_salahawad_outlook_personal_mcp_061ac138/readme"
}