npm package: @hamzashahbaz/outlook-mcp
Description: Outlook email MCP server for Claude — 19 tools for reading, sending, and managing email via Microsoft Graph API
Author: Hamza Shahbaz
Latest version: 0.1.0

# outlook-mcp

MCP server for Claude that provides full Outlook email management via Microsoft Graph API. Read, send, organize, draft, and bulk-manage emails — all from Claude Code or Claude Desktop.

## Quick Install

```bash
claude mcp add outlook -e OUTLOOK_CLIENT_ID=your_client_id -- npx -y @hamzashahbaz/outlook-mcp
```

## Features

19 tools for complete email management:

### Reading
| Tool | Description |
|------|-------------|
| `outlook_list_messages` | List emails in a folder with pagination and OData filters |
| `outlook_get_message` | Get full email details by message ID |
| `outlook_search_messages` | Search emails using KQL queries |
| `outlook_list_folders` | List all mail folders with unread counts |

### Sending
| Tool | Description |
|------|-------------|
| `outlook_send_email` | Send a new email to one or more recipients |
| `outlook_reply` | Reply to an email (reply or reply-all) |
| `outlook_forward` | Forward an email to new recipients |

### Drafts
| Tool | Description |
|------|-------------|
| `outlook_create_draft` | Create a draft email (saved, not sent) |
| `outlook_update_draft` | Update an existing draft |
| `outlook_send_draft` | Send a previously created draft |
| `outlook_delete_draft` | Delete a draft |

### Organization
| Tool | Description |
|------|-------------|
| `outlook_move_message` | Move a message to a different folder |
| `outlook_delete_message` | Delete a message (moves to Deleted Items) |
| `outlook_update_message` | Mark as read/unread, flag/unflag |
| `outlook_mark_all_read` | Mark all messages in a folder as read |
| `outlook_create_folder` | Create a new mail folder |
| `outlook_empty_folder` | Permanently delete all messages in a folder |

### Bulk Operations
| Tool | Description |
|------|-------------|
| `outlook_bulk_move_by_sender` | Move all emails from a sender domain to a folder |
| `outlook_bulk_move_by_search` | Move emails matching a KQL search query to a folder |

## Prerequisites

- **Node.js** 18+
- **Azure App Registration** with device code flow enabled

## Setup

### Azure App Registration

1. Go to [Azure Portal](https://portal.azure.com) > **App Registrations** > **New Registration**
2. Name: `Outlook MCP` (or anything you like)
3. Supported account types: **Personal Microsoft accounts only** (or include organizational if needed)
4. Redirect URI: Leave blank (device code flow doesn't need one)
5. Under **Authentication** > Advanced settings:
   - Enable **Allow public client flows** (required for device code)
6. Under **API Permissions**, add Microsoft Graph delegated permissions:
   - `Mail.ReadWrite`
   - `Mail.Send`
   - `User.Read`
7. Copy the **Application (client) ID** — this is your `OUTLOOK_CLIENT_ID`

## Authentication

On first run, the server initiates an **OAuth 2.0 device code flow**:

1. A URL and code are displayed in stderr output
2. Open the URL in your browser and enter the code
3. Sign in with your Microsoft account and grant permissions
4. Tokens are saved automatically for future use

Tokens auto-refresh using the refresh token. If a refresh fails (e.g., token revoked), delete the token file and restart — the device code flow will trigger again.

## Configuration

### Claude Code

Add via CLI (recommended):

```bash
claude mcp add outlook -e OUTLOOK_CLIENT_ID=your_client_id -- npx -y @hamzashahbaz/outlook-mcp
```

Or add manually to `.mcp.json`:

```json
{
  "mcpServers": {
    "outlook": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@hamzashahbaz/outlook-mcp"],
      "env": {
        "OUTLOOK_CLIENT_ID": "your_client_id"
      }
    }
  }
}
```

### Claude Desktop

Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "outlook": {
      "command": "npx",
      "args": ["-y", "@hamzashahbaz/outlook-mcp"],
      "env": {
        "OUTLOOK_CLIENT_ID": "your_client_id"
      }
    }
  }
}
```

## Token Storage

Tokens are stored at `~/.outlook-mcp/.tokens.json` with `600` permissions (owner read/write only). This location persists across npx invocations.

The file contains:
- **Access token** — short-lived, auto-refreshed
- **Refresh token** — long-lived, used to obtain new access tokens

To re-authenticate, delete the token file:

```bash
rm ~/.outlook-mcp/.tokens.json
```

## Folder Names

Standard Outlook folder names: `Inbox`, `SentItems`, `Drafts`, `DeletedItems`, `Archive`, `JunkEmail`

Custom folders use the display name as created.

## Troubleshooting

### "OUTLOOK_CLIENT_ID environment variable is required"
Set `OUTLOOK_CLIENT_ID` in your MCP configuration's `env` block.

### Authentication expired
Delete the token file and restart:
```bash
rm ~/.outlook-mcp/.tokens.json
```
The device code flow will trigger again on next use.

### "Insufficient privileges"
Check your Azure App Registration > **API Permissions**. Ensure `Mail.ReadWrite` and `Mail.Send` are granted. For organizational accounts, admin consent may be required.

### Rate limited
Microsoft Graph enforces rate limits. The server reports the `Retry-After` header value. Wait and retry.

## Known Limitations

- **Cannot delete mail folders** — Microsoft Graph API does not support folder deletion for personal accounts
- **Search pagination** — KQL search results are limited to 25 per request (the server handles pagination internally)
- **Bulk operations** — Process up to 200-500 messages per call to avoid timeouts

## How It Works

- **API**: Microsoft Graph API v1.0
- **Auth**: OAuth 2.0 device code flow
- **Protocol**: Model Context Protocol (MCP) over stdio
- **Validation**: Zod schemas for all tool inputs
- **Built for**: Claude Code and Claude Desktop

## License

MIT