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.
- 📧 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
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"]
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 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 complete
On 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.
| 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 |
| 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 |
| 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 |
| 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 |
| 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) |
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.
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.
Contributions are welcome. See CONTRIBUTING.md for development setup, branching conventions, and the pull request process.
MIT — see LICENSE.