【免费下载链接】ms-365-mcp-server
A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Microsoft Office services through the Graph API
ms-365-mcp-server是一个让 AI 代理通过 Microsoft Graph API 操作 Microsoft 365 的 MCP(Model Context Protocol)服务器,可驱动邮件、日历、OneDrive、Teams、SharePoint 等 300+ 工具。本文面向新手与运维,讲解如何在无头环境(服务器、容器、CI)中用 OBO(On-Behalf-Of)委托认证,让 AI 代理代表你安全地读写 Office 数据,且服务器不保存任何用户令牌。
太长不看
| 目标 | 方案 | 关键命令 / 配置 |
|---|---|---|
| 无头环境代表用户办公 | --obo+--http | npx @softeria/ms-365-mcp-server --http 3000 --org-mode --obo |
| 必须项 | 机密客户端密钥 | 环境变量MS365_MCP_CLIENT_SECRET |
| 多用户共享 | 无状态,每请求独立身份 | 用户 Bearer Token 随请求携带 |
| 权限收紧 | 管理员同意 + 工具过滤 | --read-only、--allowed-scopes、--preset |
💡 一句话理解 OBO:用户在浏览器登录一次,AI 代理之后每次调用都“代表你”用你的身份去访问 Microsoft 365,服务器本身不留存令牌。
无头环境为什么需要 OBO 委托认证
标准登录(设备码 / 浏览器授权)都假设“有人盯着屏幕”。但在一台服务器或容器里:
- 没有浏览器,无法弹出登录窗口;
- 无法交互式输入设备码;
- 你希望服务 7×24 运行,而不是一小时后就因令牌过期而失效。
OBO(On-Behalf-Of,代表用户)正是为这种场景设计的委托模式。它的价值在于无状态:服务器不为每个用户保存令牌,而是“即来即换、用完即弃”——这正是 docs/deployment.md 中“Production Deployment”强调的核心架构:stateless, no token store。
对比一下,无头环境下有三种身份方案,OBO 是多用户部署的首选:
| 方案 | 适用场景 | 服务器是否存令牌 |
|---|---|---|
| OBO 委托认证(推荐) | 多用户、长期运行的 AI 代理 | ❌ 否(每请求现换) |
BYOT(自带令牌MS365_MCP_OAUTH_TOKEN) | 外部系统已管理令牌 | ❌ 否 |
| 本地 MSAL 登录 + 缓存命令 | 单账号固定身份 | ✅ 是(可接外部存储) |
OBO 委托认证工作原理:一次登录,代理长期工作
整个委托链条分为三步,身份始终“属于用户”,服务器只是中间人。
MCP 客户端(Claude Desktop / claude.ai / Open WebUI) │ ① OAuth 授权码 + PKCE(用户在浏览器登录一次) ▼ ms-365-mcp-server --http --obo (无状态,不存令牌) │ ② 收到 /mcp 请求,携带 Bearer Token ▼ OBO 令牌交换 acquireTokenOnBehalfOf │ ③ 换取 Graph 令牌(graph.microsoft.com/.default) ▼ Microsoft Graph API(以用户身份读写邮件/日历/文件)拆开看这三步在源码里的落点:
- 授权只请求“访问本应用”。OBO 模式下
/authorize只请求<clientId>/access_as_user(外加User.Read、offline_access与--extra-scopes),因此工具派生的 Graph 权限根本不会出现在授权同意页,见 src/server.ts#L858-L886。 - 令牌交换。收到
/mcp请求后,服务器调用 MSAL 的acquireTokenOnBehalfOf,把用户令牌换成本应用的 Graph 令牌,核心实现在 src/obo-client.ts#L31-L48;请求级注入发生在 src/server.ts#L1083-L1089。 - 以用户身份访问 Graph。换得的令牌通过
AsyncLocalStorage注入每个请求上下文(src/request-context.ts),代理的每次工具调用都继承“你的身份、你的权限、你的数据边界”。
🔑 关键点:最终能干什么,取决于租户已为你授予的管理员同意权限,而不是代理“想要”什么——这是 OBO 天然的安全边界。
无头环境 OBO 部署三步走
第一步:创建 Azure AD 应用注册(机密客户端)
OBO 必须使用机密客户端(confidential client),因此一定要创建客户端密钥:
新建应用注册,支持账户类型选“仅限本组织目录中的账户”(单租户)。
重定向 URI(平台类型 Web):填 MCP 客户端的回调地址,例如 Claude 的
https://claude.ai/api/mcp/auth_callback。⚠️ 常见坑:填错会报AADSTS50011(redirect URI mismatch),详见 docs/deployment.md。API 权限:添加 Microsoft Graph 委托权限,用下面的命令打印你当前配置需要的精确清单:
npx @softeria/ms-365-mcp-server --org-mode --list-permissions授予管理员同意,跳过每个用户的重复授权:
az ad app permission admin-consent --id your-app-client-id在“证书和机密”中创建客户端密钥,并记下
clientId、tenantId、clientSecret。
第二步:配置环境变量并启动服务
把凭据交给服务器(生产环境建议改用 Azure Key Vault,见下节)。最小启动命令:
MS365_MCP_CLIENT_ID=your-client-id \ MS365_MCP_TENANT_ID=your-tenant-id \ MS365_MCP_CLIENT_SECRET=your-secret \ npx @softeria/ms-365-mcp-server --http 3000 --org-mode --obo用 Docker 运行(官方镜像,非 root 用户):
docker run -p 3000:3000 \ -e MS365_MCP_CLIENT_ID=your-client-id \ -e MS365_MCP_TENANT_ID=your-tenant-id \ -e MS365_MCP_CLIENT_SECRET=your-secret \ ghcr.io/softeria/ms-365-mcp-server:latest \ --http 3000 --org-mode --obo⚠️ 启动自检:
--obo若缺少--http或缺少MS365_MCP_CLIENT_SECRET会直接报错退出(--obo requires --http、--obo requires MS365_MCP_CLIENT_SECRET),校验逻辑见 src/server.ts#L422-L438。这些“快速失败”能帮你少踩坑。
第三步:连接 MCP 客户端
客户端指向你的 HTTP 端点,首次使用时自动发现 OAuth 端点并打开浏览器完成登录:
{ "mcpServers": { "ms365": { "type": "streamable-http", "url": "https://mcp.example.com/mcp" } } }Claude Code 则可用:
claude mcp add ms365 --transport http https://mcp.example.com/mcp若服务器位于反向代理之后,务必设置--public-url https://mcp.example.com,确保返回给浏览器的授权 URL 可从外部访问。
关键启动参数与权限配置
| 参数 / 环境变量 | 作用 | 何时使用 |
|---|---|---|
--obo | 启用 OBO 令牌交换 | 无头、多用户部署必配 |
MS365_MCP_CLIENT_SECRET | 机密客户端密钥 | OBO 强制要求 |
--extra-scopes <scopes> | 向令牌请求追加 Graph 权限 | 默认工具不覆盖、又确需的能力 |
--allowed-scopes <scopes> | 收窄暴露的工具面(不改变 OBO) | 企业按权限边界做工具裁剪 |
--read-only | 禁用全部写操作 | 只读审计、降低风险 |
--preset mail/--preset teams | 按应用精简工具 | 减少上下文与令牌消耗 |
几个新手容易混淆的点:
--extra-scopes才是“加权限”的正道。OBO 下用户只同意本应用自身作用域,因此想额外让代理读邮件,就在授权时加上,例如--extra-scopes 'Mail.Read',让用户在登录时同意(见 test/obo-authorize-extra-scopes.test.ts)。--allowed-scopes不会“覆盖”OBO,它只收窄工具面,OAuth 元数据与登录流程仍按 OBO 规则运行,说明见 README.md。- 个人微软账户(consumers)需要显式作用域才能兑换令牌,服务器已自动在
/token携带<clientId>/access_as_user offline_access以规避AADSTS70011,实现见 src/lib/microsoft-auth.ts#L343-L350。
生产环境安全最佳实践
针对无头、多租户部署,建议叠加以下护栏(均见 docs/deployment.md 的“Security Considerations”):
- 密钥进 Key Vault:
MS365_MCP_KEYVAULT_URL=https://your-keyvault.vault.azure.net,配合托管身份读取,避免密钥出现在环境变量。完整的一键部署模板见 examples/azure-container-apps/。 - 无状态优先:OBO 路径不写入任何 MSAL 令牌缓存,天然规避令牌泄露风险。
- 只读 + 工具过滤:
--read-only叠加--enabled-tools或--preset,把代理能做的事缩到最小。 - 审计日志:默认开启结构化审计,记录“谁在何时访问了什么”,满足合规留痕需求。
- 重定向 URI 白名单:共享/生产部署建议用
MS365_MCP_ALLOWED_REDIRECT_URIS显式收敛,防止开放重定向。
常见问题快速排查
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 启动即报错退出 | --obo缺--http或缺MS365_MCP_CLIENT_SECRET | 补齐 HTTP 模式与机密客户端密钥 |
401 on /mcp | clientId/tenantId配置错误 | 核对应用注册 ID 与租户 ID |
redirect_uri mismatch | 重定向 URI 与应用注册不一致 | 在应用注册中登记客户端回调地址 |
Graph 返回403 | 缺作用域 / 未授予管理员同意 | 重跑--list-permissions并补授同意 |
AADSTS70011 | 个人账户兑换缺scope | 服务器已自动携带作用域,确认租户为预期值 |
提示:OBO 令牌交换失败时,日志会打印
OBO token exchange failed(来自 src/obo-client.ts),这是定位“换令牌”这一步的最直接线索。
小结
无头环境让 AI 代理长期为你工作的关键,就是选对身份模式:用--obo的 OBO 委托认证,服务器无状态、令牌即来即换,代理永远以“你”的身份和“你的权限”访问 Microsoft 365。掌握“应用注册 → 启动--http --obo→ 连接客户端”三步,再按需叠加只读、工具过滤与 Key Vault,就能安全地把 ms-365-mcp-server 部署成 7×24 的办公代理。
延伸阅读:docs/deployment.md(生产部署全景)、src/obo-client.ts(OBO 客户端)、examples/azure-container-apps/(一键部署示例)。
【免费下载链接】ms-365-mcp-server
A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Microsoft Office services through the Graph API
相关推荐
Apereo CAS 集成 HiOrg Server 委托认证(OAuth2/OpenID Connect)完整指南
Apereo CAS 集成 HiOrg Server 委托认证(OAuth2/OpenID Connect)完整指南 本文聚焦于 Apereo CAS 如何作为
后端认证鉴权单点登录身份认证Browser-Use MCP Server 完整指南:实现浏览器环境下的无缝编程协作
Browser Use MCP Server 完整指南:实现浏览器环境下的无缝编程协作 快速问答:什么是Browser Use MCP Server? Q:它能
Gemini MCP Server离线工作模式:无网络环境下的AI协作方案
Gemini MCP Server离线工作模式:无网络环境下的AI协作方案 你是否曾在网络中断时被迫中断AI开发工作?是否需要在涉密环境中使用AI工具却受限于网
后端AI 应用大模型LLM 网关MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考