Doramagic 项目包 · 项目说明书
ms-365-admin-mcp-server 项目
通过 Microsoft Graph API 应用权限执行 Microsoft 365 管理操作的 MCP 服务器,支持安全、审计、报表和服务运行状况等功能。
Project Overview & Core Features
ms-365-admin-mcp-server 是一个面向 LLM 客户端的 Model Context Protocol (MCP) 服务器,把 Microsoft 365 管理员日常所需的 Microsoft Graph API 操作封装为 500+ 个可调用的工具,租户范围覆盖安全、身份、合规、Intune、Exchange、Teams、eDiscovery 等关键管...
继续阅读本节完整说明和来源证据。
项目定位与目标场景
ms-365-admin-mcp-server 是一个面向 LLM 客户端的 Model Context Protocol (MCP) 服务器,把 Microsoft 365 管理员日常所需的 Microsoft Graph API 操作封装为 500+ 个可调用的工具,租户范围覆盖安全、身份、合规、Intune、Exchange、Teams、eDiscovery 等关键管理域。服务器通过 @modelcontextprotocol/sdk 暴露 JSON-RPC 接口,并使用 @azure/msal-node 处理 OAuth/Entra 身份认证,资料来源:package.json:25-32。
主要使用场景包括:
- 安全运维与事件响应:暴露 Microsoft Defender 告警/事件/狩猎查询、用户确认失陷/安全等高敏操作。
- 身份与治理:Entra ID 用户/组/角色/条件访问/PIM/访问审阅/权利管理全栈。
- Intune 设备管理:托管设备、合规策略、Autopilot、远程锁定/擦除/重启等响应类操作。
- 代理/合规检索:审计日志、消息跟踪、eDiscovery、通用打印、Copilot 管理。
社区在 v0.6.3 发布说明 中也确认了"以 LLM 客户端为操作员"这一定位,并配套发布了 ms365-admin-mcp Agent Skill 作为技能层。
核心架构与组件划分
服务器由以下几个关键模块组成:
| 模块 | 文件 | 职责 |
|---|---|---|
| 端点元数据 | src/generated/endpoint-types.ts | 描述 Graph 端点的 HTTP 方法、路径、参数、Zod schema(HTTP 方法仅 get/post/put/delete/patch 五种) |
| 工具注册 | src/graph-tools.ts | 把 endpoints.json 中的每个端点注册为 MCP 工具,注入风险等级文案、readOnlyHint/destructiveHint 等注解 |
| 风险等级 | src/risk-level.ts | 集中实现 low/medium/high/critical 四级分类与门控 |
| 工具分类 | src/tool-categories.ts | 基于正则匹配的 13+ 个分类(security/audit/identity/intune/...)驱动 --preset 与文档分组 |
| 鉴权代理 | src/oauth-proxy.ts | 实现 RFC 7591 DCR、/authorize、/token、RFC 8628 设备码等端点 |
| 用户令牌校验 | src/user-token-validator.ts / src/user-token-authorization.ts | JWKS 拉取、签名校验、声明授权、UPN 日志脱敏 |
| 云环境 | src/cloud-config.ts | 区分 global(商业云)与 china(世纪互联) |
| 启动 CLI | src/cli.ts / src/index.ts | 解析 commander 选项、装配服务器、暴露 --list-tools/--verify-login 等维护子命令 |
src/generated/hack.ts 是为适配旧版 Zodios 元数据而存在的"垫片"层——它会剥离参数名中的 $/_ 前缀,并把路径中 :foo 形式的占位符显式补为 Path 类型参数,确保 schema 在运行时能正确装配。
安全模型:风险等级与 App Role 双闸门
服务器对写操作采用纵深防御策略,避免一个工具调用就在租户内造成不可逆变更,资料来源:src/risk-level.ts:1-25。
1. 风险等级标注
每个工具在 endpoints.json 中都带有显式 riskLevel 字段(low/medium/high/critical)。effectiveRiskLevel() 决定兜底值:GET 端点默认 low,但任何缺失显式等级的写操作会被视为 critical——这是"失败安全"设计,避免未来新增端点因忘记标注而被错误地以 medium 暴露,资料来源:src/risk-level.ts:50-65。
2. 顶层封顶:--max-risk-level
CLI 启动时可指定 --max-risk-level medium 这类封顶值,服务器只会注册低于等于该等级的工具。isToolAllowed() 用 rank() 函数按位比较,这层控制对 stdio 传输也生效。
3. 调用者身份门控:Entra App Roles
在 HTTP 传输且已认证的场景下,服务器把 Entra 应用角色映射为允许的写等级集合,资料来源:src/risk-level.ts:75-90:
| 角色 | 允许的写等级 |
|---|---|
Tools.Write.LowMedium | low + medium |
Tools.Write.High | high |
Tools.Write.Critical | critical |
三个角色互相独立、可叠加,没有隐式层级。如果调用者未携带任何 Tools.Write.* 角色但带了合法的 bearer 令牌,注册阶段会以空集合跳过所有非 GET 工具。社区 issue #126 关注的是当前 OAuth 代理把客户端与受保护资源共用同一个 App 注册导致 Entra 拒绝 refresh_token(AADSTS65005),这是把 scp 强制执行重新打开的必经改造。
部署、传输与扩展能力
服务器通过 --transport stdio|http 切换传输模式,HTTP 模式默认监听 127.0.0.1:8080 并支持 --allowed-clients <ids> 限制服务对服务调用的 Entra App ID 白名单,资料来源:src/cli.ts:25-55。开启 --oauth-mode 后会激活完整 OAuth 代理栈,发布 /.well-known/oauth-authorization-server 与 /.well-known/oauth-protected-resource 元数据,grant types 包含 authorization_code、refresh_token 与 RFC 8628 设备码,资料来源:src/oauth-proxy.ts:10-30。
对于无浏览器的容器/CI 场景,ms-365-admin-mcp-auth 子命令提供 RFC 8628 设备码引导,把 access token 预置到 mcp-remote 缓存目录,让 Claude Desktop/Code 跳过浏览器跳转,资料来源:src/auth-bootstrap.ts:1-25。多云支持方面,parseCloudType() 在 china(21Vianet,门户 portal.azure.cn)和 global 之间切换 Graph 端点根,资料来源:src/cloud-config.ts:1-25。
Agent Skills 配套:agent-skills/ms365-admin-mcp 是一个 LLM 可加载的技能层,强制"dry-run → confirm → audit"安全模式并按用例路由到服务器子集,把 docs/USE_CASES.md、docs/RISK_MODEL.md 与剧本目录的官方内容索引起来,资料来源:agent-skills/README.md:1-20。
See Also
- Tools & Risk Model —
risk-level.ts与tool-categories.ts详解 - Authentication & OAuth Proxy — DCR、设备码、JWKS 校验
- Deployment & Transports — stdio/http/云环境/cli 启动参数
- Agent Skills Integration — 客户端技能与安全模式
来源:https://github.com/okapi-ca/ms-365-admin-mcp-server / 项目说明书
Tool Catalog, Presets & Risk Classification
通过 Microsoft Graph API 应用权限执行 Microsoft 365 管理操作的 MCP 服务器,支持安全、审计、报表和服务运行状况等功能。
继续阅读本节完整说明和来源证据。
Tool Catalog, Presets & Risk Classification
通过 Microsoft Graph API 应用权限执行 Microsoft 365 管理操作的 MCP 服务器,支持安全、审计、报表和服务运行状况等功能。
来源:https://github.com/okapi-ca/ms-365-admin-mcp-server / 项目说明书
System Architecture & Code Generation Pipeline
ms-365-admin-mcp-server 是一个将 Microsoft Graph API 暴露为 MCP(Model Context Protocol)工具的服务端项目,其核心运行机制建立在「代码生成 + 运行时注册」的双层流水线之上。package.json 中的脚本定义了这套流水线的入口:generate 触发 generate-graph-client.mjs...
继续阅读本节完整说明和来源证据。
概览
ms-365-admin-mcp-server 是一个将 Microsoft Graph API 暴露为 MCP(Model Context Protocol)工具的服务端项目,其核心运行机制建立在「代码生成 + 运行时注册」的双层流水线之上。package.json 中的脚本定义了这套流水线的入口:generate 触发 generate-graph-client.mjs 重新生成端点元数据与 TypeScript 类型;verify 则串行执行 generate → lint → format:check → build → test 形成一条端到端的发布前校验链 资料来源:package.json:scripts。
整体架构可拆为四层:
| 层级 | 主要产物 | 运行时职责 |
|---|---|---|
| 源码层 | src/*.ts | 业务逻辑、CLI 解析、风险分级 |
| 生成层 | src/generated/* + endpoints.json | 端点类型与 Zod schema 的预生成 |
| 构建层 | tsup 打包 | 产出可执行二进制 |
| 运行层 | MCP Server(stdio / http) | 工具注册、请求路由、风险门控 |
代码生成流水线
生成层是整个系统的「数据源」。项目在构建前会调用 generate-graph-client.mjs,其输出同时落到两个位置:
endpoints.json—— 一份包含toolName、method、pathPattern、appPermissions、riskLevel字段的端点清单。该文件在src/index.ts与src/graph-tools.ts中被readFileSync加载,作为工具注册的事实数据源 资料来源:src/index.ts、src/graph-tools.ts。src/generated/endpoint-types.ts与src/generated/hack.ts—— 预生成的 TypeScript 类型定义与 Zodios 兼容层。hack.ts模拟了 Zodios 的核心能力:扫描:param占位符、补全缺失的路径参数、并对参数名做[$_]+规范化 资料来源:src/generated/hack.ts:makeApi。
flowchart LR
A[Graph API Spec] --> B[generate-graph-client.mjs]
B --> C[endpoints.json]
B --> D[src/generated/*.ts]
C --> E[运行时工具注册]
D --> E
E --> F[MCP Tools: 515+]生成层是「不可手工编辑」的——agent-skills/README.md 明确要求新工具的参考必须先在 src/endpoints.json 中存在,这从侧面印证了生成产物即权威源的原则 资料来源:agent-skills/README.md:Contributing。
风险等级与工具分类模型
生成出的端点元数据进入运行时后,会经过两道分类门控:
- 风险等级(SEC-G01):
risk-level.ts引入有序的'low' | 'medium' | 'high' | 'critical'四档分级,rank()将其映射为可比较的数值。effectiveRiskLevel()在缺省值时按 HTTP 方法兜底:GET 默认为low,写方法默认为critical(fail-safe)资料来源:src/risk-level.ts:effectiveRiskLevel。 - 工具分类:
tool-categories.ts用正则模式将端点划入security、audit、health、reports、identity、compliance、exchange、intune、governance、response、ediscovery、cloudpc、callrecords、print等类别,便于通过--preset或--enabled-tools正则做白名单筛选 资料来源:src/tool-categories.ts:TOOL_CATEGORIES。
这两套模型在 src/graph-tools.ts:registerGraphTools 中合流:先按 --read-only 过滤非 GET 端点,再按 isToolAllowed() 做风险上限裁剪,最后按 enabledToolsRegex 进一步收敛;返回的注册数与被跳过的原因会写入结构化日志 资料来源:src/graph-tools.ts:registerGraphTools。
工具注册与执行
注册阶段会为每个端点生成一段 server.tool() 调用,并在描述中显式标注 RISK LEVEL 字符串,以便 LLM 客户端在调用前做出风险判断。当端点配置中包含 APP_ONLY_PERMISSIONS(如 BitlockerKey.Read.All、Exchange.ManageAsApp 等)时,注册器自动切换到 app-only Graph 客户端,因为这些权限在 Microsoft Graph 中没有委托型等价物 资料来源:src/graph-tools.ts:APP_ONLY_PERMISSIONS。
执行阶段(executeGraphTool)会在请求体中调用 coerceJsonStringBody(),对形如 JSON 对象/数组的字符串做预处理;返回结果通过 wrapUntrustedContent()(SEC-G02)加一层不可信内容信封后再交给 LLM 上下文,避免直接回写导致提示注入放大 资料来源:src/graph-tools.ts:coerceJsonStringBody。
CLI 层由 src/cli.ts 中的 commander 定义 --max-risk-level、--preset、--list-tools 等开关,运行时通过 args 解构后传入注册函数 资料来源:src/cli.ts:option。
社区反馈与版本演进
代码生成管线与运行时风险模型是过去多个版本的核心改动面:
- v0.6.3 引入了基于 Entra App Roles 的「每调用方写操作分级」(
Tools.Write.LowMedium/High/Critical),risk-level.ts末尾的Map Entra App Role注释正是该 PR 的产物 资料来源:src/risk-level.ts:Map Entra。 - 社区 issue #126 反映了当 OAuth 代理应用同时充当 client 与 resource 时,Entra 会拒绝
refresh_token的自引用授权(AADSTS 错误),提示该流水线需要在安全层面继续解耦注册对象 资料来源:issue #126。 - 持续发布的 v0.7.0 → v0.14.0 主要在端点生成、风险门控与依赖更新上迭代,
verify脚本确保每次改动都经过生成层与运行时的一致性校验 资料来源:package.json:verify。
See Also
来源:https://github.com/okapi-ca/ms-365-admin-mcp-server / 项目说明书
Authentication, Security Model & Deployment
ms-365-admin-mcp-server 将 500 多个 Microsoft Graph 管理端点暴露为 Model Context Protocol (MCP) 工具。鉴于其中多数属于高权限写操作(禁用用户、撤销会话、隔离设备、修改条件访问策略等),系统采用了多层安全防护:传输层 OAuth 2.0、令牌层 JWT/JWKS 验证、工具层风险等级分类,以及按调用者...
继续阅读本节完整说明和来源证据。
身份验证、安全模型与部署
概述
ms-365-admin-mcp-server 将 500 多个 Microsoft Graph 管理端点暴露为 Model Context Protocol (MCP) 工具。鉴于其中多数属于高权限写操作(禁用用户、撤销会话、隔离设备、修改条件访问策略等),系统采用了多层安全防护:传输层 OAuth 2.0、令牌层 JWT/JWKS 验证、工具层风险等级分类,以及按调用者的 Entra 应用角色授权。资料来源:src/oauth-proxy.ts:1-30、资料来源:src/risk-level.ts:1-15、资料来源:src/http-server.ts:1-30。
服务器支持两种传输模式:
- stdio:本地进程管道(Claude Desktop 本地启动),使用托管身份(client credentials)或环境注入的令牌
- HTTP + OAuth:面向远程 LLM 客户端,使用 Microsoft Entra ID(v2.0 端点)作为身份提供商
两种模式最终汇聚到统一的 Graph 客户端与工具注册管线,但授权模型不同——stdio 模式依赖 CLI 标志(--allow-writes、--max-risk-level),HTTP 模式额外叠加按调用者的 Tools.Write.* 应用角色检查。资料来源:src/server.ts:1-30。
OAuth 代理与令牌流程
src/oauth-proxy.ts 实现了一个完整的 RFC 7591 动态客户端注册 + RFC 6749 授权服务器,外加 RFC 8628 设备授权流程,以适配无浏览器容器与 CI 运行器场景。代理暴露以下端点:
GET /.well-known/oauth-authorization-server— 颁发授权服务器元数据GET /.well-known/oauth-protected-resource— 描述受保护资源(/mcp)的元数据POST /register— 动态注册机密客户端并下发 client_secretPOST /token— 支持authorization_code、refresh_token、urn:ietf:params:oauth:grant-type:device_code三种 grantPOST /devicecode— 设备授权请求入口,需要与/token相同的客户端凭据(SEC-F04b)
所有客户端必须为机密客户端(client_secret_post 或 client_secret_basic),且授权码流程强制使用 PKCE 的 S256 方法。资料来源:src/oauth-proxy.ts:1-50。
sequenceDiagram
participant C as MCP 客户端
participant P as OAuth 代理
participant E as Entra ID
participant M as /mcp 端点
C->>P: POST /register (redirect_ris)
P-->>C: client_id + client_secret
C->>P: POST /devicecode (或 /authorize)
P->>E: 转发授权/设备码请求
E-->>P: access_token + refresh_token
P-->>C: 返回令牌
C->>M: Bearer access_token
M->>M: JWT 验证 + 角色检查
M-->>C: 工具调用结果JWT 验证通过 jsonwebtoken + jwks-rsa 完成。src/token-validator.ts 与 src/user-token-validator.ts 分别为服务令牌(SP)和用户令牌建立 JWKS 客户端,并维护 24 小时内存缓存。当 Entra 发生密钥轮换时,引入陈旧密钥回退(SEC-F08)以容忍超出 24 小时的 JWKS 中断。资料来源:src/token-validator.ts:1-60、资料来源:src/user-token-validator.ts:1-30。
src/http-server.ts 中的中间件严格遵循 RFC 6750 §3.1:缺少 Bearer 头返回 401 并附带 WWW-Authenticate: Bearer resource_metadata="..." 挑战头;签名/受众/签发方/过期失败映射到 invalid_token (401),作用域不足映射到 insufficient_scope (403)。资料来源:src/http-server.ts:1-50。
风险等级与按调用者授权
src/risk-level.ts 定义了一个有序的风险模型:low < medium < high < critical。所有写端点都标注了显式的 riskLevel,CLI 标志 --max-risk-level 决定工具注册时暴露的最高等级。缺省规则采用"安全失败":GET 端点默认 low,但任何缺少显式标注的写端点默认 critical,确保未来新增端点不会被静默泄漏到 medium 阈值之下。资料来源:src/risk-level.ts:1-70。
按调用者的细粒度授权通过三个独立、可叠加的 Entra 应用角色实现(v0.6.3,PR #104):
Tools.Write.LowMedium→ 授予low+mediumTools.Write.High→ 授予highTools.Write.Critical→ 授予critical
writeRiskTiers 在 src/server.ts 中根据调用者声明的 roles 计算授权集合,传入 registerGraphTools 与 --max-risk-level 形成 AND 组合。stdio 模式下调用者身份不可用(roles === undefined),此时跳过角色检查仅依赖 CLI 控制;HTTP 模式下若已认证但未分配任何 Tools.Write.* 角色,则得到一个空集合,意味着所有写工具被静默拒绝。资料来源:src/server.ts:1-30、资料来源:src/risk-level.ts:60-100。
部署模式与安全加固
stdio 部署:直接由 Claude Desktop/Code 派生子进程。src/auth-bootstrap.ts 提供一个独立的 ms-365-admin-mcp-auth CLI,使用 RFC 8628 设备码预填充 mcp-remote 令牌缓存,避免每次启动都启动浏览器。资料来源:src/auth-bootstrap.ts:1-40。
HTTP 部署:将服务器发布为 Azure Container Apps 之类的远程端点,通过 docs/HTTP_DEPLOYMENT.md 与 docs/AZURE_DEPLOYMENT_SECURITY.md 中的网络隔离、托管身份、CORS 与速率限制配置强化。OAuth 代理与 /mcp 端点部署在同一进程,但 /mcp 强制 Bearer 鉴权。
src/upstream-error.ts 实现了 SEC-F07:上游 Entra 错误响应仅透出 RFC 6749 §5.2 规定的 error、error_description 与 Microsoft 扩展的 error_codes,并把描述裁剪至 200 字符,避免关联 ID、堆栈片段泄漏到日志。UPN 在日志中通过 SHA-256 前 16 字符做脱敏(SEC-F08)。资料来源:src/upstream-error.ts:1-30、资料来源:src/user-token-authorization.ts:1-30。
已知问题与安全审计
社区报告的开放问题 #126 指出:当 OAuth 代理应用注册(86f46c1e)同时充当 OAuth 客户端(代理将其 client_id+client_secret 转发到上游)与受保护资源(api://{clientId}/access_as_user)时,Entra 拒绝自引用的 refresh_token grant 并返回 AADSTS... 错误,导致 SEC-F03 scp 强制执行被旁路。建议的缓解措施是将客户端应用与资源应用分离为两个独立的应用注册。资料来源:issue #126。
定期安全审计产物(docs/SECURITY_REVIEW_2026-04-20.md 与 docs/SECURITY_REVIEW_2026-04-25.md)记录了 SEC-G01(工具风险等级)、SEC-F04b(机密客户端强制)、SEC-F07(日志安全)、SEC-F08(密钥回退)等已落实控制项的复核结果。
See Also
- 风险模型详解:docs/RISK_MODEL.md
- 应用注册清单:docs/APP_REGISTRATION.md
- 应用角色配置:docs/APP_ROLES.md
- HTTP 部署指南:docs/HTTP_DEPLOYMENT.md
- Azure 部署安全:docs/AZURE_DEPLOYMENT_SECURITY.md
- LLM 代理技能:agent-skills/README.md
- 工具分类参考:src/tool-categories.ts
来源:https://github.com/okapi-ca/ms-365-admin-mcp-server / 项目说明书
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
风险会影响是否适合普通用户安装。
Pitfall Log / 踩坑日志
项目:okapi-ca/ms-365-admin-mcp-server
摘要:发现 8 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:配置坑 - 可能修改宿主 AI 配置。
1. 配置坑 · 可能修改宿主 AI 配置
- 严重度:medium
- 证据强度:source_linked
- 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
- 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
- 证据:capability.host_targets | https://github.com/okapi-ca/ms-365-admin-mcp-server | host_targets=mcp_host, claude_code, claude
2. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 证据:capability.assumptions | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass.
3. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 证据:evidence.maintainer_signals | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 证据:downstream_validation.risk_items | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 证据:risks.scoring_risks | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium
6. 安全/权限坑 · 来源证据:Separate OAuth client app from resource app to re-enable SEC-F03 scp enforcement
- 严重度:medium
- 证据强度:source_linked
- 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:Separate OAuth client app from resource app to re-enable SEC-F03 scp enforcement
- 对用户的影响:可能影响授权、密钥配置或安全边界。
- 证据:community_evidence:github | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/126 | 来源类型 github_issue 暴露的待验证使用条件。
7. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 证据:evidence.maintainer_signals | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown
8. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 证据:evidence.maintainer_signals | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown
来源:Doramagic 发现、验证与编译记录