# M365 MCP
Powerful MCP server for Microsoft Graph API - a complete AI assistant toolkit for Outlook, Calendar, OneDrive, and Contacts.
## Features
- **Email Management**: Read, send, reply, manage attachments, organize folders
- **Calendar Intelligence**: Create, update, check availability, respond to invitations
- **OneDrive Files**: Upload, download, browse with pagination
- **Contacts**: Search and list contacts from your address book
- **Multi-Account**: Support for multiple Microsoft accounts (personal, work, school)
- **Unified Search**: Search across emails, files, events, and people
## Quick Start
**📚 See [QUICKSTART.md](QUICKSTART.md) for complete installation and setup guide.**
### TL;DR
```bash
# 1. Install
git clone https://github.com/robin-collins/m365-mcp.git
cd m365-mcp && uv sync
# 2. Configure (use .env.example template)
cp .env.example .env
# Edit .env with your M365_MCP_CLIENT_ID
# 3. Authenticate
uv run authenticate.py
# 4. Run
uv run m365-mcp
```
### Claude Desktop
```bash
# Add M365 MCP server (replace with your Azure app ID)
claude mcp add m365-mcp -e M365_MCP_CLIENT_ID=your-app-id-here -- uvx --from git+https://github.com/robin-collins/m365-mcp.git m365-mcp
# Start Claude Desktop
claude
```
### Usage Examples
```bash
# Email examples
> read my latest emails with full content
> reply to the email from John saying "I'll review this today"
> send an email with attachment to alice@example.com
# Calendar examples
> show my calendar for next week
> check if I'm free tomorrow at 2pm
> create a meeting with Bob next Monday at 10am
# File examples
> list files in my OneDrive
> upload this report to OneDrive
> search for "project proposal" across all my files
# Multi-account
> list all my Microsoft accounts
> send email from my work account
```
## Available Tools
### Email Tools
- **`list_emails`** - List emails with optional body content
- **`get_email`** - Get specific email with attachments
- **`create_email_draft`** - Create email draft with attachments support
- **`send_email`** - Send email immediately with CC/BCC and attachments
- **`reply_to_email`** - Reply maintaining thread context
- **`reply_all_email`** - Reply to all recipients in thread
- **`update_email`** - Mark emails as read/unread
- **`move_email`** - Move emails between folders
- **`delete_email`** - Delete emails
- **`get_attachment`** - Get email attachment content
- **`search_emails`** - Search emails by query
### Calendar Tools
- **`list_events`** - List calendar events with details
- **`get_event`** - Get specific event details
- **`create_event`** - Create events with location and attendees
- **`update_event`** - Reschedule or modify events
- **`delete_event`** - Cancel events
- **`respond_event`** - Accept/decline/tentative response to invitations
- **`check_availability`** - Check free/busy times for scheduling
- **`search_events`** - Search calendar events
### Contact Tools
- **`list_contacts`** - List all contacts
- **`get_contact`** - Get specific contact details
- **`create_contact`** - Create new contact
- **`update_contact`** - Update contact information
- **`delete_contact`** - Delete contact
- **`search_contacts`** - Search contacts by query
### File Tools
- **`list_files`** - Browse OneDrive files and folders
- **`get_file`** - Download file content
- **`create_file`** - Upload files to OneDrive
- **`update_file`** - Update existing file content
- **`delete_file`** - Delete files or folders
- **`search_files`** - Search files in OneDrive
### Utility Tools
- **`unified_search`** - Search across emails, events, and files
- **`list_accounts`** - Show authenticated Microsoft accounts
- **`authenticate_account`** - Start authentication for a new Microsoft account
- **`complete_authentication`** - Complete the authentication process after entering device code
## Manual Setup
### 1. Azure App Registration
1. Go to [Azure Portal](https://portal.azure.com) → Microsoft Entra ID → App registrations
2. New registration → Name: `m365-mcp`
3. Supported account types: Personal + Work/School
4. Authentication → Allow public client flows: Yes
5. API permissions → Add these delegated permissions:
- Mail.ReadWrite
- Calendars.ReadWrite
- Files.ReadWrite
- Contacts.Read
- People.Read
- User.Read
6. Copy Application ID
### 2. Installation
```bash
git clone https://github.com/robin-collins/m365-mcp.git
cd m365-mcp
uv sync
```
### 3. Authentication
```bash
# Set your Azure app ID
export M365_MCP_CLIENT_ID="your-app-id-here"
# Run authentication script
uv run authenticate.py
# Follow the prompts to authenticate your Microsoft accounts
```
### 4. Claude Desktop Configuration
Add to your Claude Desktop configuration:
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"microsoft": {
"command": "uvx",
"args": ["--from", "git+https://github.com/robin-collins/m365-mcp.git", "m365-mcp"],
"env": {
"M365_MCP_CLIENT_ID": "your-app-id-here"
}
}
}
}
```
Or for local development:
```json
{
"mcpServers": {
"microsoft": {
"command": "uv",
"args": ["--directory", "/path/to/m365-mcp", "run", "m365-mcp"],
"env": {
"M365_MCP_CLIENT_ID": "your-app-id-here"
}
}
}
}
```
## Transport Modes
M365 MCP supports two transport modes for different use cases:
### stdio (Default) - For Desktop Apps
**Use for:** Claude Desktop, local MCP clients
**Security:** Inherently secure through process isolation (no authentication required)
```bash
# Default mode - no configuration needed
export M365_MCP_CLIENT_ID="your-app-id"
uv run m365-mcp
```
### Streamable HTTP - For Web/API Access
**Use for:** Web applications, remote access, multi-client scenarios
**Security:** ⚠️ **Requires authentication** (bearer token or OAuth)
**Protocol:** Uses MCP Streamable HTTP (spec 2025-03-26+)
```bash
# Generate secure token
export MCP_AUTH_TOKEN=$(openssl rand -hex 32)
# Configure Streamable HTTP with bearer authentication
export M365_MCP_CLIENT_ID="your-app-id"
export MCP_TRANSPORT="http"
export MCP_AUTH_METHOD="bearer"
export MCP_HOST="127.0.0.1"
export MCP_PORT="8000"
# Start server
uv run m365-mcp
```
**Client connection:**
```python
from mcp.client.http import http_client
async with http_client(
"http://localhost:8000/mcp",
headers={"Authorization": f"Bearer {your_token}"}
) as (read, write):
# Use the session...
```
**📚 See [SECURITY.md](SECURITY.md) for complete security guide and authentication options**
## Multi-Account Support
All tools require an `account_id` parameter as the first argument:
```python
# List accounts to get IDs
accounts = list_accounts()
account_id = accounts[0]["account_id"]
# Use account for operations
send_email(account_id, "user@example.com", "Subject", "Body")
list_emails(account_id, limit=10, include_body=True)
create_event(account_id, "Meeting", "2024-01-15T10:00:00Z", "2024-01-15T11:00:00Z")
```
## Development
```bash
# Run tests
uv run pytest tests/ -v
# Type checking
uv run pyright
# Format code
uvx ruff format .
# Lint
uvx ruff check --fix --unsafe-fixes .
```
## Example: AI Assistant Scenarios
### Smart Email Management
```python
# Get account ID first
accounts = list_accounts()
account_id = accounts[0]["account_id"]
# List latest emails with full content
emails = list_emails(account_id, limit=10, include_body=True)
# Reply maintaining thread
reply_to_email(account_id, email_id, "Thanks for your message. I'll review and get back to you.")
# Forward with attachments
email = get_email(email_id, account_id)
attachments = [get_attachment(email_id, att["id"], account_id) for att in email["attachments"]]
send_email(account_id, "boss@company.com", f"FW: {email['subject']}", email["body"]["content"], attachments=attachments)
```
### Intelligent Scheduling
```python
# Get account ID first
accounts = list_accounts()
account_id = accounts[0]["account_id"]
# Check availability before scheduling
availability = check_availability(account_id, "2024-01-15T10:00:00Z", "2024-01-15T18:00:00Z", ["colleague@company.com"])
# Create meeting with details
create_event(
account_id,
"Project Review",
"2024-01-15T14:00:00Z",
"2024-01-15T15:00:00Z",
location="Conference Room A",
body="Quarterly review of project progress",
attendees=["colleague@company.com", "manager@company.com"]
)
```
## Security Notes
- Tokens are cached locally in `~/.m365_mcp_token_cache.json`
- Use app-specific passwords if you have 2FA enabled
- Only request permissions your app actually needs
- Consider using a dedicated app registration for production
## Troubleshooting
- **Authentication fails**: Check your CLIENT_ID is correct
- **"Need admin approval"**: Use `M365_MCP_TENANT_ID=consumers` for personal accounts
- **Missing permissions**: Ensure all required API permissions are granted in Azure
- **Token errors**: Delete `~/.m365_mcp_token_cache.json` and re-authenticate
## License
MIT
Raw data
{
"_id": null,
"home_page": null,
"name": "m365-mcp",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "ai, calendar, mcp, microsoft-365, microsoft-graph, onedrive, outlook",
"author": null,
"author_email": "robin-collins <robin.f.collins@outlook.com>, elyx <elio@pascarelli.com>",
"download_url": "https://files.pythonhosted.org/packages/5e/c9/ea042f9c2c763957b23644e9106766e95fb6bc54157578875097149fc6f8/m365_mcp-0.1.2.tar.gz",
"platform": null,
"description": "# M365 MCP\n\nPowerful MCP server for Microsoft Graph API - a complete AI assistant toolkit for Outlook, Calendar, OneDrive, and Contacts.\n\n## Features\n\n- **Email Management**: Read, send, reply, manage attachments, organize folders\n- **Calendar Intelligence**: Create, update, check availability, respond to invitations\n- **OneDrive Files**: Upload, download, browse with pagination\n- **Contacts**: Search and list contacts from your address book\n- **Multi-Account**: Support for multiple Microsoft accounts (personal, work, school)\n- **Unified Search**: Search across emails, files, events, and people\n\n## Quick Start\n\n**\ud83d\udcda See [QUICKSTART.md](QUICKSTART.md) for complete installation and setup guide.**\n\n### TL;DR\n\n```bash\n# 1. Install\ngit clone https://github.com/robin-collins/m365-mcp.git\ncd m365-mcp && uv sync\n\n# 2. Configure (use .env.example template)\ncp .env.example .env\n# Edit .env with your M365_MCP_CLIENT_ID\n\n# 3. Authenticate\nuv run authenticate.py\n\n# 4. Run\nuv run m365-mcp\n```\n\n### Claude Desktop\n\n```bash\n# Add M365 MCP server (replace with your Azure app ID)\nclaude mcp add m365-mcp -e M365_MCP_CLIENT_ID=your-app-id-here -- uvx --from git+https://github.com/robin-collins/m365-mcp.git m365-mcp\n\n# Start Claude Desktop\nclaude\n```\n\n### Usage Examples\n\n```bash\n# Email examples\n> read my latest emails with full content\n> reply to the email from John saying \"I'll review this today\"\n> send an email with attachment to alice@example.com\n\n# Calendar examples \n> show my calendar for next week\n> check if I'm free tomorrow at 2pm\n> create a meeting with Bob next Monday at 10am\n\n# File examples\n> list files in my OneDrive\n> upload this report to OneDrive\n> search for \"project proposal\" across all my files\n\n# Multi-account\n> list all my Microsoft accounts\n> send email from my work account\n```\n\n## Available Tools\n\n### Email Tools\n- **`list_emails`** - List emails with optional body content\n- **`get_email`** - Get specific email with attachments\n- **`create_email_draft`** - Create email draft with attachments support\n- **`send_email`** - Send email immediately with CC/BCC and attachments\n- **`reply_to_email`** - Reply maintaining thread context\n- **`reply_all_email`** - Reply to all recipients in thread\n- **`update_email`** - Mark emails as read/unread\n- **`move_email`** - Move emails between folders\n- **`delete_email`** - Delete emails\n- **`get_attachment`** - Get email attachment content\n- **`search_emails`** - Search emails by query\n\n### Calendar Tools\n- **`list_events`** - List calendar events with details\n- **`get_event`** - Get specific event details\n- **`create_event`** - Create events with location and attendees\n- **`update_event`** - Reschedule or modify events\n- **`delete_event`** - Cancel events\n- **`respond_event`** - Accept/decline/tentative response to invitations\n- **`check_availability`** - Check free/busy times for scheduling\n- **`search_events`** - Search calendar events\n\n### Contact Tools\n- **`list_contacts`** - List all contacts\n- **`get_contact`** - Get specific contact details\n- **`create_contact`** - Create new contact\n- **`update_contact`** - Update contact information\n- **`delete_contact`** - Delete contact\n- **`search_contacts`** - Search contacts by query\n\n### File Tools\n- **`list_files`** - Browse OneDrive files and folders\n- **`get_file`** - Download file content\n- **`create_file`** - Upload files to OneDrive\n- **`update_file`** - Update existing file content\n- **`delete_file`** - Delete files or folders\n- **`search_files`** - Search files in OneDrive\n\n### Utility Tools\n- **`unified_search`** - Search across emails, events, and files\n- **`list_accounts`** - Show authenticated Microsoft accounts\n- **`authenticate_account`** - Start authentication for a new Microsoft account\n- **`complete_authentication`** - Complete the authentication process after entering device code\n\n## Manual Setup\n\n### 1. Azure App Registration\n\n1. Go to [Azure Portal](https://portal.azure.com) \u2192 Microsoft Entra ID \u2192 App registrations\n2. New registration \u2192 Name: `m365-mcp`\n3. Supported account types: Personal + Work/School\n4. Authentication \u2192 Allow public client flows: Yes\n5. API permissions \u2192 Add these delegated permissions:\n - Mail.ReadWrite\n - Calendars.ReadWrite\n - Files.ReadWrite\n - Contacts.Read\n - People.Read\n - User.Read\n6. Copy Application ID\n\n### 2. Installation\n\n```bash\ngit clone https://github.com/robin-collins/m365-mcp.git\ncd m365-mcp\nuv sync\n```\n\n### 3. Authentication\n\n```bash\n# Set your Azure app ID\nexport M365_MCP_CLIENT_ID=\"your-app-id-here\"\n\n# Run authentication script\nuv run authenticate.py\n\n# Follow the prompts to authenticate your Microsoft accounts\n```\n\n### 4. Claude Desktop Configuration\n\nAdd to your Claude Desktop configuration:\n\n**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` \n**Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n \"mcpServers\": {\n \"microsoft\": {\n \"command\": \"uvx\",\n \"args\": [\"--from\", \"git+https://github.com/robin-collins/m365-mcp.git\", \"m365-mcp\"],\n \"env\": {\n \"M365_MCP_CLIENT_ID\": \"your-app-id-here\"\n }\n }\n }\n}\n```\n\nOr for local development:\n\n```json\n{\n \"mcpServers\": {\n \"microsoft\": {\n \"command\": \"uv\",\n \"args\": [\"--directory\", \"/path/to/m365-mcp\", \"run\", \"m365-mcp\"],\n \"env\": {\n \"M365_MCP_CLIENT_ID\": \"your-app-id-here\"\n }\n }\n }\n}\n```\n\n## Transport Modes\n\nM365 MCP supports two transport modes for different use cases:\n\n### stdio (Default) - For Desktop Apps\n\n**Use for:** Claude Desktop, local MCP clients\n\n**Security:** Inherently secure through process isolation (no authentication required)\n\n```bash\n# Default mode - no configuration needed\nexport M365_MCP_CLIENT_ID=\"your-app-id\"\nuv run m365-mcp\n```\n\n### Streamable HTTP - For Web/API Access\n\n**Use for:** Web applications, remote access, multi-client scenarios\n\n**Security:** \u26a0\ufe0f **Requires authentication** (bearer token or OAuth)\n\n**Protocol:** Uses MCP Streamable HTTP (spec 2025-03-26+)\n\n```bash\n# Generate secure token\nexport MCP_AUTH_TOKEN=$(openssl rand -hex 32)\n\n# Configure Streamable HTTP with bearer authentication\nexport M365_MCP_CLIENT_ID=\"your-app-id\"\nexport MCP_TRANSPORT=\"http\"\nexport MCP_AUTH_METHOD=\"bearer\"\nexport MCP_HOST=\"127.0.0.1\"\nexport MCP_PORT=\"8000\"\n\n# Start server\nuv run m365-mcp\n```\n\n**Client connection:**\n```python\nfrom mcp.client.http import http_client\n\nasync with http_client(\n \"http://localhost:8000/mcp\",\n headers={\"Authorization\": f\"Bearer {your_token}\"}\n) as (read, write):\n # Use the session...\n```\n\n**\ud83d\udcda See [SECURITY.md](SECURITY.md) for complete security guide and authentication options**\n\n## Multi-Account Support\n\nAll tools require an `account_id` parameter as the first argument:\n\n```python\n# List accounts to get IDs\naccounts = list_accounts()\naccount_id = accounts[0][\"account_id\"]\n\n# Use account for operations\nsend_email(account_id, \"user@example.com\", \"Subject\", \"Body\")\nlist_emails(account_id, limit=10, include_body=True)\ncreate_event(account_id, \"Meeting\", \"2024-01-15T10:00:00Z\", \"2024-01-15T11:00:00Z\")\n```\n\n## Development\n\n```bash\n# Run tests\nuv run pytest tests/ -v\n\n# Type checking\nuv run pyright\n\n# Format code\nuvx ruff format .\n\n# Lint\nuvx ruff check --fix --unsafe-fixes .\n```\n\n## Example: AI Assistant Scenarios\n\n### Smart Email Management\n```python\n# Get account ID first\naccounts = list_accounts()\naccount_id = accounts[0][\"account_id\"]\n\n# List latest emails with full content\nemails = list_emails(account_id, limit=10, include_body=True)\n\n# Reply maintaining thread\nreply_to_email(account_id, email_id, \"Thanks for your message. I'll review and get back to you.\")\n\n# Forward with attachments\nemail = get_email(email_id, account_id)\nattachments = [get_attachment(email_id, att[\"id\"], account_id) for att in email[\"attachments\"]]\nsend_email(account_id, \"boss@company.com\", f\"FW: {email['subject']}\", email[\"body\"][\"content\"], attachments=attachments)\n```\n\n### Intelligent Scheduling\n```python\n# Get account ID first\naccounts = list_accounts()\naccount_id = accounts[0][\"account_id\"]\n\n# Check availability before scheduling\navailability = check_availability(account_id, \"2024-01-15T10:00:00Z\", \"2024-01-15T18:00:00Z\", [\"colleague@company.com\"])\n\n# Create meeting with details\ncreate_event(\n account_id,\n \"Project Review\",\n \"2024-01-15T14:00:00Z\", \n \"2024-01-15T15:00:00Z\",\n location=\"Conference Room A\",\n body=\"Quarterly review of project progress\",\n attendees=[\"colleague@company.com\", \"manager@company.com\"]\n)\n```\n\n## Security Notes\n\n- Tokens are cached locally in `~/.m365_mcp_token_cache.json`\n- Use app-specific passwords if you have 2FA enabled\n- Only request permissions your app actually needs\n- Consider using a dedicated app registration for production\n\n## Troubleshooting\n\n- **Authentication fails**: Check your CLIENT_ID is correct\n- **\"Need admin approval\"**: Use `M365_MCP_TENANT_ID=consumers` for personal accounts\n- **Missing permissions**: Ensure all required API permissions are granted in Azure\n- **Token errors**: Delete `~/.m365_mcp_token_cache.json` and re-authenticate\n\n## License\n\nMIT",
"bugtrack_url": null,
"license": "MIT",
"summary": "Microsoft 365 MCP server for Outlook, Calendar, and OneDrive with multi-account support",
"version": "0.1.2",
"project_urls": {
"Documentation": "https://github.com/robin-collins/m365-mcp#readme",
"Homepage": "https://github.com/robin-collins/m365-mcp",
"Issues": "https://github.com/robin-collins/m365-mcp/issues",
"Repository": "https://github.com/robin-collins/m365-mcp"
},
"split_keywords": [
"ai",
" calendar",
" mcp",
" microsoft-365",
" microsoft-graph",
" onedrive",
" outlook"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "71009329c1a5a31414fe760e485ee4077b131120221d9a26a2948ddd3415635f",
"md5": "95cbb88a18cd9ad0c1f9ca4fb78050f0",
"sha256": "5e90514b73e37c24b3bdc0218e447fc7ca9fc7564ee9dd9bf52d283525564180"
},
"downloads": -1,
"filename": "m365_mcp-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "95cbb88a18cd9ad0c1f9ca4fb78050f0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 56861,
"upload_time": "2025-10-13T13:30:19",
"upload_time_iso_8601": "2025-10-13T13:30:19.105740Z",
"url": "https://files.pythonhosted.org/packages/71/00/9329c1a5a31414fe760e485ee4077b131120221d9a26a2948ddd3415635f/m365_mcp-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5ec9ea042f9c2c763957b23644e9106766e95fb6bc54157578875097149fc6f8",
"md5": "e1b973ec324cfda1b9090ec287895384",
"sha256": "17d4545f678190a2c2c2826fa435dad4db009ad8510d60e51e6f8bbce4d8d6aa"
},
"downloads": -1,
"filename": "m365_mcp-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "e1b973ec324cfda1b9090ec287895384",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 248541,
"upload_time": "2025-10-13T13:30:21",
"upload_time_iso_8601": "2025-10-13T13:30:21.891116Z",
"url": "https://files.pythonhosted.org/packages/5e/c9/ea042f9c2c763957b23644e9106766e95fb6bc54157578875097149fc6f8/m365_mcp-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-13 13:30:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "robin-collins",
"github_project": "m365-mcp#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "m365-mcp"
}