
Security News
Open VSX Unblocks Extension IDs Used in Malware Campaign
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.
mcp-outlook-personal
Advanced tools
MCP server for a personal Outlook.com mailbox and calendar via Microsoft Graph
An 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.
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).Go to https://portal.azure.com → Microsoft Entra ID → App registrations → New registration.
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.
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.)
Go to API permissions → Add a permission → Microsoft Graph → Delegated permissions, then add:
Mail.ReadWriteMail.SendCalendars.ReadWrite(User.Read is included by default; offline_access is requested automatically at runtime — you do not need to add it.)
Copy the Application (client) ID from the Overview page. This is your OUTLOOK_MCP_CLIENT_ID.
If you have the az CLI, the whole registration is one command:
az login --use-device-code --allow-no-subscriptions # sign in with your personal account
az ad app create \
--display-name "outlook-personal-mcp" \
--sign-in-audience PersonalMicrosoftAccount \
--is-fallback-public-client true \
--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"}]}]' \
--query appId -o tsv
The 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.
Run 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.
OUTLOOK_MCP_CLIENT_ID=<your-app-client-id> uvx mcp-outlook-personal login
To run the latest unreleased code from source instead of the PyPI release, swap
mcp-outlook-personalfor--from git+https://github.com/salahawad/outlook-personal-mcp mcp-outlook-personal.
Add the server to your project's .mcp.json (or ~/.claude/.mcp.json for all projects):
{
"mcpServers": {
"outlook": {
"command": "uvx",
"args": ["mcp-outlook-personal"],
"env": { "OUTLOOK_MCP_CLIENT_ID": "<your-app-client-id>" }
}
}
}
Alternatively, use the CLI: claude mcp add.
Add the server to ~/.codex/config.toml:
[mcp_servers.outlook]
command = "uvx"
args = ["mcp-outlook-personal"]
env = { OUTLOOK_MCP_CLIENT_ID = "<your-app-client-id>" }
This server is also packaged as a Claude Desktop extension (.mcpb). Build the bundle from a checkout:
npx @anthropic-ai/mcpb pack . dist/mcp-outlook-personal.mcpb
Then 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.
Requirement: the extension launches the server with
uvx mcp-outlook-personal, souvmust be installed and on yourPATH— Claude Desktop does not bundle it (see Prerequisites). Codex and other stdio hosts use the config above instead of the.mcpb.
| Variable | Required | Default | Description |
|---|---|---|---|
OUTLOOK_MCP_CLIENT_ID | Yes | — | Azure app's Application (client) ID |
OUTLOOK_MCP_AUTHORITY | No | https://login.microsoftonline.com/consumers | MSAL authority URL (change only if you move to a work/school tenant) |
OUTLOOK_MCP_TOKEN_CACHE | No | ~/.config/outlook-personal-mcp/token_cache.bin | Path to the MSAL token cache file |
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 |
OUTLOOK_MCP_MAX_FILE_BYTES | No | 3145728 | Maximum bytes allowed for local attachment reads and attachment downloads |
OUTLOOK_MCP_ALLOW_PERMANENT_DELETE | No | false | Set to true to enable the permanent_delete tool (irreversible — see below) |
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. |
| Tool | Description |
|---|---|
whoami | Return the signed-in user's Microsoft account profile |
| Tool | Description |
|---|---|
list_messages | List messages (newest first); optionally filter by folder or unread-only |
search_messages | Full-text search across the entire mailbox (Graph $search) |
get_message | Get a single message; optionally include the full body |
list_attachments | List a message's attachments (id, name, size, content type) |
download_attachment | Download an attachment to a path under OUTLOOK_MCP_FILE_ROOT (refuses to overwrite an existing file) |
send_mail | Send an email |
reply | Reply to a message (reply_all to reply to everyone) |
forward | Forward a message to recipients with an optional comment |
move_message | Move a message to another folder |
copy_message | Copy a message to another folder |
mark_read | Mark a message read or unread |
flag_message | Flag or unflag a message |
delete_message | Delete a message (moves it to Deleted Items; reversible) |
permanent_delete | Permanently delete a message (irreversible). Only available when OUTLOOK_MCP_ALLOW_PERMANENT_DELETE=true |
| Tool | Description |
|---|---|
list_folders | List mail folders with unread and total message counts |
create_folder | Create a mail folder, optionally nested under a parent |
rename_folder | Rename a mail folder |
delete_folder | Delete a mail folder (moves it to Deleted Items) |
| Tool | Description |
|---|---|
create_draft | Create a draft message (not sent) |
update_draft | Update a draft's subject and/or body |
add_attachment | Attach a local file (a regular, non-symlink file under OUTLOOK_MCP_FILE_ROOT) to a draft |
send_draft | Send an existing draft |
| Tool | Description |
|---|---|
list_calendars | List the user's calendars |
list_events | List events; if start/end (ISO 8601) are given, returns that time window |
search_events | Search events by free text |
get_event | Get one event including body, attendees, and online meeting link |
create_event | Create a calendar event with optional attendees and online meeting |
update_event | Update fields on an existing event (only provided fields change) |
delete_event | Delete/cancel a calendar event |
respond_event | Respond to a meeting invite: accept, decline, or tentative |
find_availability | Get free/busy availability for a list of people over a time window |
The 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.
To 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.
~/.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.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.git clone https://github.com/salahawad/outlook-personal-mcp
cd outlook-personal-mcp
uv venv && uv pip install -e ".[dev]"
uv run pytest
uv run ruff check .
This 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 for the full privacy policy.
MIT — see LICENSE.
FAQs
MCP server for a personal Outlook.com mailbox and calendar via Microsoft Graph
We found that mcp-outlook-personal demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Open VSX has removed three extension IDs from its malicious-extension list as the legitimate publishers they impersonated move to claim the names for themselves.

Product
Socket’s PHP and Composer support is now in Beta for all customers, with PHP reachability analysis generally available.

Product
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.