m365-mcp

m365-mcp

A Model Context Protocol server that gives Claude Code (or any MCP client) controlled access to Microsoft 365 through the Microsoft Graph API: mail, calendar, contacts, files, notes, tasks, Teams, SharePoint, and the full tenant-admin surface.

Category
访问服务器

README

m365-mcp

A Model Context Protocol server that gives Claude Code (or any MCP client) controlled access to Microsoft 365 through the Microsoft Graph API: mail, calendar, contacts, files, notes, tasks, Teams, SharePoint, and the full tenant-admin surface.

It runs locally as a stdio subprocess. There is no hosted component, no client secret, and no inbound network exposure. Authentication is a local public-client browser flow, and every token stays on your machine.

Status: 441 tools, multi-account (personal and work identities mixed in one server), public-client auth with per-account token caches. License: MIT.

┌──────────────────────────────────────────────────────────────────┐
│  441 tools total                                                   │
│                                                                    │
│  173  available to PERSONAL  Microsoft accounts (167 + 6 mgmt)     │
│  441  available to WORK / school accounts (everything)             │
│                                                                    │
│  Same tool names for both. Work-only tools are blocked, with a     │
│  clear error, when called against a personal account.              │
└──────────────────────────────────────────────────────────────────┘

The capability story has three tiers, and the rest of this document follows that order: what a personal account gets, what a business (work/school) account adds, and what a tenant administrator unlocks on top.


Tier 1: Personal Microsoft accounts

If you sign in with a consumer Microsoft account (@outlook.com, @hotmail.com, @live.com, @msn.com), you get the complete personal productivity surface: 173 tools (167 Graph tools plus 6 account-management tools). Everything in this tier works against a personal mailbox with no tenant, no admin, and no license beyond a normal Microsoft account.

Family Tools What it covers
Mail 50 Read, search (full-text + paginated), draft, reply, reply-all, forward, send, move, copy, flag, categorize, delete, folders, rules, inbox-tip checks, MIME export, Focused-Inbox overrides, attachments (incl. >3 MB upload sessions), auto-reply
Calendar 25 List/create/update/delete events, respond to invites, calendars + groups, recurring-event expansion, find_meeting_times, free/busy, reminders, event attachments
Contacts 15 Search, CRUD, contact folders, per-contact photos, delta sync
Microsoft To Do 14 Task lists, tasks, checklist steps, linked resources, delta sync
OneDrive 24 Browse, upload, download, copy/move, share links, invitations, permissions, versions, search, recent, thumbnails, Office-Online previews, delta sync
OneNote 14 Notebooks, sections, section groups, pages, HTML content read/write, previews
Profile + Mailbox settings 13 Profile, photo, working hours, time zone, language, supported-locale lists
Subscriptions / webhooks 5 Change-notification subscriptions (needs a public HTTPS callback)
Refinements 7 Master categories, unified search, reference + item attachments
Account management 6 add_account, list_accounts, get_account_info, set_default_account, remove_account, list_known_scopes

Primary use case

Screen an inbox, draft replies for your approval, triage junk, route newsletters with rules, manage your calendar, and organize OneDrive, all by asking Claude in natural language.

Known personal-account limits

A handful of Graph families are work-only at the platform level and simply do not exist for consumer accounts (Teams chat, SharePoint sites, org directory, Planner, admin reports, and so on). The server tags those tools so they fail fast with a readable message instead of a raw Graph 403. The durable list lives in PERSONAL_ACCOUNT_LIMITS.md. Notable nuances:

  • OneNote works on personal accounts but can return transient errors for a minute or two right after first consent. Retry rather than concluding it is unsupported.
  • Subscriptions require a publicly reachable HTTPS notificationUrl, so they need an ngrok-style tunnel to be useful from a purely local server. Personal accounts support subscriptions on mail, calendar, drive root, and To Do tasks, but not on contacts.
  • Workbook / Excel API is de-scoped on personal accounts in favor of the separate excel-mcp-server.

Tier 2: Business (work / school) accounts

Sign in with a Microsoft Entra (Azure AD) work or school account and you keep all 173 personal tools, then add 157 collaboration tools that only exist inside an organization. These target Teams, SharePoint, Microsoft 365 Groups, Planner, the org directory, shared mailboxes, Bookings, and the Excel Workbook API.

Family Tools What it covers
Teams chat 17 List/create chats, send/edit/delete/restore messages, reactions, members, pins, tenant-wide message search
Teams channels 16 Channels (standard/private/shared), messages + threaded replies, reactions, members, files folder
Teams (teams themselves) 10 List/get/update teams, archive/unarchive, clone, members, promote owners
Online meetings 9 Create/update/delete Teams meetings, attendance reports, recordings, transcripts (WebVTT)
SharePoint sites 7 Root site, site search, subsites, modern pages, permission entries
SharePoint document libraries 14 Browse/upload/download/copy/move, share links, invitations, search across libraries
SharePoint lists + items 11 Lists, items, fields, columns (the row-oriented data primitive: trackers, registers, lookups)
Microsoft 365 Groups 15 Groups, members, owners, group mailbox conversations + threads, the backing team
Planner 15 Plans, buckets, tasks, task details, assignments (etag-aware)
Directory + people 14 User search, manager/reports hierarchy, member-of, free/busy, People API, org contacts
Shared mailboxes 10 Read/search/draft/send on a shared mailbox you have delegate access to
Bookings 9 Booking businesses, appointments, services, staff, publish
Workbook / Excel 10 Worksheets, ranges, tables, named ranges, persistent sessions

What this enables

A work account turns the server into a full collaboration assistant: post to a Teams channel, search every chat you are in, manage a SharePoint document library or list, run a Planner board, look up a colleague's manager or free/busy, or draft from a shared support mailbox.

Delegated, not impersonating. Every action runs as you, with your permissions. Shared-mailbox tools require that you already hold Exchange Online FullAccess or folder rights on that mailbox; the Graph scopes alone do not grant the underlying data access.


Tier 3: Tenant administrators

If your work account holds admin roles, the server exposes 111 additional governance, security, and device-management tools. These read and write tenant-wide configuration, so several are flagged as sensitive and should only be invoked with explicit intent.

Family Tools What it covers
Admin queries 10 Service health + incidents, Message Center posts, directory audit log, sign-in logs, provisioning logs
Reports 15 Usage reports across Office 365, email, Teams, OneDrive, SharePoint, Outlook, apps, Yammer (rolling D7/D30/D90/D180 windows)
Identity governance 12 Access reviews + decisions, entitlement-management access packages, Terms of Use, lifecycle workflows
Conditional Access + roles 17 CA policies (create/update/delete ⚠), named locations, auth-strength, authorization policy, directory role assignments, PIM activate
Directory objects 20 Devices, applications, service principals, administrative units, deleted-item recycle bin (restore ⚠ / purge ⚠)
eDiscovery + sensitivity labels 13 eDiscovery cases, custodians (legal hold ⚠), KQL searches, review sets, sensitivity labels
Security 9 Alerts, incidents, Secure Score history + controls, threat indicators
Intune 10 Managed devices (wipe ⚠ / retire ⚠ / sync), configuration + compliance policies, app policies, mobile apps
Universal Print 5 Printers, printer jobs, your jobs, print shares

⚠ sensitive operations. Tools that change tenant-wide security policy, place data on legal hold, or wipe a device are marked with a warning in CLAUDE.md. Confirm intent before invoking. Note that Graph exposes device writes only to app-only auth, so update_device / delete_device cannot run through this delegated public-client flow (device read works fine; Intune wipe/retire use a different, supported path).

The full, per-tool inventory for every tier lives in CLAUDE.md; architecture and design notes are in As_Built_Specification.md.


Setup overview

Setup is three moving parts, done once per identity:

  1. Register an Azure app and grant it Graph permissions (this section).
  2. Point the server at the app via .env.
  3. Generate a token with the add_account tool (the Authentication section).

You register one app per Microsoft identity:

Path You have Apps to register
A A personal account only 1 app in the consumer (Microsoft-account) directory
B A work account only 1 single-tenant app in that work tenant
C Both, or several work tenants 1 app per identity; they coexist in one server

Microsoft only allows one personal account per person, so the personal app uses the un-suffixed .env keys. Each work tenant adds its own suffixed pair.

Prerequisites

  • Node.js 18+ (uses native fetch).
  • A Microsoft account (personal, or work/school in any Entra tenant).
  • For work apps: tenant-admin consent, either yours or your admin's.
  • macOS, Windows, or Linux. The first sign-in opens your default browser briefly.

Account setup and permission changes (Azure portal)

Do this in the Microsoft Entra admin center, entra.microsoft.com. Sign in as the identity you want to connect. For a work account, confirm the tenant shown in the top-right is the correct one before you start.

Step 1: Register the app

Applications → App registrations → + New registration.

Field Personal-account app Work-account app
Name m365-mcp-personal m365-mcp-<tenant>
Supported account types "Personal Microsoft accounts only" "Accounts in this organizational directory only (single tenant)"
Redirect URI Platform = Public client/native (mobile & desktop), URI = http://localhost:3333/auth/callback same

Click Register.

Use single-tenant for work apps. Register a separate app per work tenant rather than one multitenant app, unless you specifically need cross-tenant sign-in.

Step 2: Copy the identifiers

On the app's Overview page, copy:

Field Goes into .env as Notes
Application (client) ID AZURE_CLIENT_ID (or AZURE_CLIENT_ID_<TENANT>) A GUID
Directory (tenant) ID AZURE_TENANT_ID (or AZURE_TENANT_ID_<TENANT>) The tenant GUID for work apps. For personal apps, use the literal string consumers

Step 3: Add API permissions

API permissions → + Add a permission → Microsoft Graph → Delegated permissions. These are the 14 base (Tier 1) scopes every account needs:

Scope Enables
User.Read, User.ReadWrite Profile, photo, sign-in discovery
Mail.Read, Mail.ReadWrite, Mail.Send All mail tools
MailboxSettings.Read, MailboxSettings.ReadWrite Auto-reply, working hours, time zone, inbox rules
Calendars.Read, Calendars.ReadWrite All calendar tools
Contacts.Read, Contacts.ReadWrite All contact tools
Tasks.ReadWrite Microsoft To Do
Notes.ReadWrite OneNote
Files.ReadWrite OneDrive

Work and admin accounts add the work-only scope set on top (roughly 90 scopes spanning Teams, SharePoint, Groups, Planner, directory, reports, identity governance, Conditional Access, security, Intune, Print, and Bookings). Rather than transcribe all of them here:

  • Run the list_known_scopes tool to print the exact base + work-only list the add_account flow will request, or
  • Read the authoritative source: DEFAULT_SCOPES and WORK_ONLY_SCOPES in src/auth/multi-account-auth.ts.

Add every scope your tier needs, then click Add permissions.

Step 4: Grant admin consent (work accounts only)

On the API permissions page, click "Grant admin consent for <tenant>". The admin-only .All scopes require this. If you are not an admin, send your tenant admin this URL (substitute your client and tenant IDs):

https://login.microsoftonline.com/<tenant-id>/adminconsent?client_id=<client-id>&redirect_uri=http://localhost:3333/auth/callback

After a one-time approval, users in the tenant sign in without per-user consent prompts on the .All scopes. Personal accounts skip this step; you consent in-browser during add_account.

Step 5: Confirm authentication settings

Authentication:

  • Platform configurations = "Mobile and desktop applications" with redirect URI http://localhost:3333/auth/callback.
  • Advanced settings → Allow public client flows = Yes. If it is No, switch it and Save.

There is no client secret. This is a public-client / loopback-redirect app by design; adding a secret is unnecessary and unsupported by the flow.


Install and configure

git clone https://github.com/Corvalon/mcp-m365.git
cd mcp-m365
npm install
cp .env.example .env
npm run build

Edit .env. The server auto-loads it from the repo root on startup. Always single-quote every value (Node's env parser treats an unquoted # as a mid-line comment and will silently truncate a value).

# --- Personal account (Path A) ---
AZURE_CLIENT_ID='<personal-app-client-id>'
AZURE_TENANT_ID='consumers'

# --- Work account(s) (Path B/C), one suffixed pair per tenant ---
# The suffix is a short name you choose; it must match the `tenant`
# argument you pass to add_account.
AZURE_CLIENT_ID_CONTOSO='<contoso-app-client-id>'
AZURE_TENANT_ID_CONTOSO='<contoso-tenant-guid>'

A personal pair and any number of work pairs can all live in the same .env.


Wire into Claude Code

Add the server to your MCP config (~/.claude.json, or via the Claude Code IDE settings):

{
  "mcpServers": {
    "m365": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-m365/dist/index.js"]
    }
  }
}

Restart Claude Code. The server logs a startup line confirming 441 tools registered, and the tools become available as mcp__m365__*. The .env is read from the repo root automatically, so no extra env wiring is needed.


Authentication / token generation

Tokens are generated at runtime through the MCP tools, not by a separate script. The first time you connect an identity you run add_account, which opens a browser for OAuth consent and caches the result locally.

Generate your first token

Ask Claude to run add_account, or call it directly:

Personal account:

// mcp__m365__add_account
{ "alias": "personal", "accountType": "personal" }

Work account (the tenant value must match your .env suffix, lowercase):

// mcp__m365__add_account
{ "alias": "contoso", "accountType": "work", "tenant": "contoso" }

What happens:

  1. The tool reads the matching client/tenant IDs from .env and builds the consent URL (base scopes for personal, base + work-only for work).
  2. Your default browser opens. Sign in and approve. The call blocks for up to 2 minutes waiting for you to finish.
  3. A local listener on http://localhost:3333/auth/callback catches the redirect and exchanges the code for tokens.
  4. An audience guard verifies you signed in with the expected identity. If you accidentally pick the wrong account in the browser, the account is rejected and not persisted; just re-run add_account.
  5. The access + refresh tokens are written to a per-alias cache under .token-cache/, and the account metadata to accounts.json. The first account you add becomes the default.

After this, MSAL refreshes tokens silently. You only return to the browser when a refresh fails or you widen scopes. On failure the server raises a structured REAUTH_REQUIRED <alias> error naming exactly which account to re-add.

Routing calls to an account

Every Graph tool accepts an optional account alias. Omit it to use the default.

{ "account": "contoso", "top": 10 }   // read_inbox against the work account
{ "top": 10 }                          // read_inbox against the default account

Manage accounts

Tool Purpose
list_accounts Show every registered account and which is default
get_account_info Full record for one alias (client/tenant/authority, scopes, timestamps)
set_default_account Choose the alias used when a call omits account
remove_account Remove an account and delete its token cache
list_known_scopes Preview the scopes add_account will request

Re-authenticate or widen scopes

  • Re-auth one account: remove_account <alias> then add_account again.
  • Widen scopes: add the broader scope in the Azure portal, then re-run add_account with the same alias and a wider scopes array (MSAL merges the consent).
  • Fully revoke: remove_account deletes the local cache but does not revoke the Microsoft-side grant. To revoke server-side, remove the app at account.microsoft.com/consent/manage (personal) or via the tenant admin (work).

Security model

  • No client secret. Public-client, loopback-redirect, delegated auth only.
  • Local-only tokens. .env, accounts.json, and .token-cache/ are all gitignored and never leave your machine.
  • Delegated permissions. Every action runs as the signed-in user with that user's rights. The server cannot exceed what the account can already do.
  • Tier enforcement. Work-only tools carry a compatibility="work" flag and are rejected before the handler runs when targeted at a personal account (and vice versa), for both explicit-alias and default-account calls.
  • Redaction. homeAccountId is truncated to its first 8 characters in surfaces an operator might log (list_accounts, get_account_info).

Troubleshooting

Symptom Likely cause Fix
AADSTS50194 / multitenant error signing in with a work account App audience wrong, or .env has AZURE_TENANT_ID=consumers for a work app Use the tenant GUID for work; consumers only for personal
AADSTS65001: not consented Missing admin consent for a .All scope Grant admin consent on the API permissions page, or send the admin-consent URL
Audience mismatch from add_account You picked the wrong identity in the browser popup Re-run add_account and choose the correct account
Browser opens but the callback hangs Something else is on port 3333 Free the port (lsof -i :3333); the redirect port is fixed at 3333
REAUTH_REQUIRED <alias> Refresh token expired or scopes changed Run add_account again for that alias
403 on Teams/SharePoint/Groups/admin tools Called against a personal account Those are work-only; see PERSONAL_ACCOUNT_LIMITS.md
OneNote returns Transient error ... {0} right after consent Known OneNote warm-up flakiness Retry; it is not a real failure

Development

npm run build          # tsc -> dist/
npm run dev            # tsx src/index.ts (no build step)
npm test               # Vitest unit suite
npm run test:coverage  # with coverage

Tools are grouped into per-family src/tools/*.register.ts modules and wired up in src/index.ts. Auth lives in src/auth/ (multi-account-auth.ts holds the scope catalog and MSAL layer; graph-client.ts loads .env and exposes the default client). All Graph calls funnel through one account-aware choke point, so tools stay account-agnostic.


Reference docs

File Purpose
CLAUDE.md Full per-tool inventory + project conventions
As_Built_Specification.md Architecture, modules, auth model, scope catalog
RUNBOOK.md Operational procedures (re-auth, build, scope changes)
PERSONAL_ACCOUNT_LIMITS.md Graph families that do not work on personal accounts

License

MIT. See LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选
mcp-server-qdrant

mcp-server-qdrant

这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。

官方
精选
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选