@joshluedeman/m365-mcp
v0.1.0
Published
Microsoft 365 MCP server — Mail, Calendar, Tasks, Contacts via Microsoft Graph
Downloads
236
Maintainers
Readme
📬 m365-mcp
Microsoft 365 tools for any MCP-compatible AI client — Mail, Calendar, Tasks, and Contacts via the Microsoft Graph API.
m365-mcp is a Model Context Protocol server that connects your Microsoft 365 account to any MCP-compatible AI client. It exposes 22 tools across Mail, Calendar, Tasks (Microsoft To Do), and Contacts — all authenticated via a single device code sign-in with no Azure portal setup required. It runs over stdio and works with Claude Desktop, Claude Code, Cursor, Zed, Windsurf, and any other MCP-compatible client.
✨ Features
- 📧 Mail — search, read, send, flag, and organize email across folders
- 📅 Calendar — search events, create/update meetings, find free/busy availability
- ✅ Tasks — full Microsoft To Do integration: task lists, tasks, create/complete/delete
- 👤 Contacts — search, read, create, and update personal contacts
- 🔐 Zero Azure setup — ships with a pre-registered multi-tenant app; no portal configuration required
- 📦 npx distribution — run with
npx @joshluedeman/m365-mcp, no global install needed - 🖥 Any MCP client — Claude Desktop, Claude Code, Cursor, Zed, Windsurf, and more
🏗 How it works
graph LR
User["User"] --> Client["MCP Client"]
Client -->|"MCP stdio"| Server["m365-mcp"]
Server -->|"HTTPS"| Graph["Microsoft Graph API"]
Graph --> Mail["Mail"]
Graph --> Calendar["Calendar"]
Graph --> Tasks["Tasks"]
Graph --> Contacts["Contacts"]🚀 Quick Start
1. (Optional) Install globally
npm install -g @joshluedeman/m365-mcpOr skip this and use npx directly — it works either way.
2. Run setup
npx @joshluedeman/m365-mcp setupThis opens a browser for device code sign-in. Sign in with your Microsoft 365 account and the token is cached to ~/.config/m365-mcp/token-cache.json. You will not be prompted again unless the refresh token expires (~90 days).
3. Add to your MCP client
Most MCP clients accept a JSON server definition in this form:
{
"mcpServers": {
"m365": {
"command": "npx",
"args": ["m365-mcp"]
}
}
}Claude Desktop — edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows).
Claude Code — add via CLI:
claude mcp add m365 -- npx @joshluedeman/m365-mcpCursor — add to .cursor/mcp.json in your project or ~/.cursor/mcp.json globally.
Zed — add to your Zed settings under "context_servers".
Other clients — consult your client's MCP server configuration docs; the command is npx @joshluedeman/m365-mcp.
🔐 Authentication
Authentication uses the MSAL device code flow. No Azure CLI, no service principal, no secrets to manage.
sequenceDiagram
participant U as User
participant S as m365-mcp setup
participant A as Azure AD
U->>S: npx @joshluedeman/m365-mcp setup
S->>A: Request device code
A-->>S: Device code + verification URL
S-->>U: Display URL and code
U->>A: Open browser, enter code, sign in
A-->>S: Access token + refresh token
S->>S: Cache tokens to ~/.config/m365-mcp/token-cache.json
S-->>U: Done — setup completeOn subsequent runs the server loads the cached token silently. The refresh token is valid for approximately 90 days; re-run npx @joshluedeman/m365-mcp setup if it expires.
🛠 Available Tools
| Tool | Description |
|------|-------------|
| search_emails | Search emails by keyword, sender, date range, or folder |
| read_email | Read the full content of an email by ID |
| send_email | Send a new email |
| flag_email | Flag or unflag an email for follow-up |
| list_mail_folders | List all mail folders in the mailbox |
| move_email | Move an email to a different folder |
Calendar
| Tool | Description |
|------|-------------|
| search_events | Search calendar events by keyword or time range |
| get_event | Get full details of a calendar event by ID |
| create_event | Create a new calendar event |
| update_event | Update an existing calendar event |
| find_availability | Find free/busy availability across attendees |
Tasks (Microsoft To Do)
| Tool | Description |
|------|-------------|
| list_task_lists | List all task lists |
| list_tasks | List tasks in a task list |
| get_task | Get details of a specific task |
| create_task | Create a new task in a task list |
| update_task | Update an existing task |
| complete_task | Mark a task as completed |
| delete_task | Delete a task |
Contacts
| Tool | Description |
|------|-------------|
| search_contacts | Search personal contacts by name or email |
| get_contact | Get full details of a contact by ID |
| create_contact | Create a new personal contact |
| update_contact | Update an existing contact |
⚙️ Enterprise / Advanced Configuration
Environment variables
| Variable | Description |
|----------|-------------|
| M365_MCP_CLIENT_ID | Override the built-in app registration with your own Azure AD client ID |
| M365_MCP_TENANT_ID | Restrict authentication to a specific tenant (defaults to common) |
Config file override
Create ~/.config/m365-mcp/config.json to set options persistently:
{
"clientId": "your-azure-ad-app-client-id",
"tenantId": "your-tenant-id"
}Environment variables take precedence over the config file.
Enterprise consent
The built-in app registration is multi-tenant and supports personal Microsoft accounts. First-time sign-in for work/school accounts will show an "unverified publisher" consent screen — this is expected for community-distributed apps. An Azure AD admin can pre-consent on behalf of the organization to suppress this prompt for all users. If your organization requires a verified app registration, use the M365_MCP_CLIENT_ID override with your own registered application.
🤝 Contributing
Contributions are welcome. See CONTRIBUTING.md for development setup, branching conventions, and the pull request process.
📄 License
MIT — see LICENSE.
