Doramagic 项目包 · 项目说明书
ms-365-admin-mcp-server 项目
生成时间:2026-05-13 14:28:40 UTC
项目介绍
ms-365-admin-mcp-server 是一个基于 Microsoft Model Context Protocol (MCP) 的服务器项目,专门为 Microsoft 365 管理任务提供标准化的工具接口。该项目将 Microsoft Graph API 中的管理员操作封装为离散的、类型安全的工具(tools),使 AI 代理能够以受控和安全的方式执行 Micr...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
项目概述
ms-365-admin-mcp-server 是一个基于 Microsoft Model Context Protocol (MCP) 的服务器项目,专门为 Microsoft 365 管理任务提供标准化的工具接口。该项目将 Microsoft Graph API 中的管理员操作封装为离散的、类型安全的工具(tools),使 AI 代理能够以受控和安全的方式执行 Microsoft 365 租户管理操作。 资料来源:README.md
项目支持发布到 npm 作为 @okapi-ca/ms-365-admin-mcp-server,同时容器镜像发布到 GHCR (ghcr.io/okapi-ca/ms-365-admin-mcp-server)。 资料来源:CHANGELOG.md
核心架构
技术栈
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 运行时 | Node.js / TypeScript | 严格模式,ESLint + Prettier 规范 |
| API 层 | Microsoft Graph API | OpenAPI 规范自动生成客户端 |
| 认证 | MSAL (Microsoft Authentication Library) | 客户端凭据流 |
| 类型安全 | Zod | Graph 响应的运行时验证 |
| 构建 | npm | 包管理和脚本执行 |
模块结构
src/
auth.ts # MSAL 客户端凭据流实现
auth-bootstrap.ts # RFC 8628 设备代码引导认证
cli.ts # Commander 参数解析
cloud-config.ts # 全球版与中国世纪互联版端点配置
endpoints.json # 工具定义的权威数据源
generated/ # 自动生成的 Zod 客户端代码
tool-categories.ts # 工具分类正则模式
risk-level.ts # 风险等级计算模块
user-token-authorization.ts # 用户令牌授权验证
untrusted-envelope.ts # 不受信任响应包装器
资料来源:CONTRIBUTING.md
核心功能
工具生态
项目当前包含 444 个管理员工具,覆盖以下主要类别:
| 类别 | 功能范围 | 参考文档 |
|---|---|---|
identity | 用户、组、角色、设备、PIM、来宾、外部身份 | usecase-identity.md |
exchange | 消息追踪、邮箱管理 | usecase-exchange.md |
intune | 设备、合规、配置、Autopilot、应用、RBAC | usecase-intune.md |
governance | 访问评审、权利管理、生命周期工作流、条款使用 | usecase-governance.md |
compliance | 许可证、安全评分、身份保护、风险检测、CA策略 | usecase-compliance.md |
response | 事件响应写入(禁用、撤销、确认、忽略) | usecase-response.md |
ediscovery | 电子发现案例(Microsoft Purview) | usecase-ediscovery.md |
cloudpc | 云 PC / Windows 365 | usecase-cloudpc.md |
callrecords | Teams 通话记录 | usecase-callrecords.md |
print | 通用打印 | usecase-print.md |
infoprotection | BitLocker、威胁评估、敏感度标签 | usecase-infoprotection.md |
sharepointadmin | SharePoint 租户管理 | usecase-sharepointadmin.md |
retention | 记录管理 | usecase-retention.md |
资料来源:tools-catalog.md
工具分类模式
工具类别通过正则表达式自动匹配工具名称:
export const TOOL_CATEGORIES: Record<string, ToolCategory> = {
identity: {
name: 'identity',
pattern: /user|group|role|device|administrative|directory/i,
description: '用户、组、角色、设备、PIM...',
},
response: {
name: 'response',
pattern:
/disable-user|revoke|block|reset|isolate|update-security|.../i,
description: '事件响应操作...',
},
// ...
};
安全模型
项目实现了多层安全防护机制。
风险等级体系
所有非 GET 操作必须标注风险等级,作为 MCP 工具注册的依据:
| 风险等级 | 判定标准 | 示例工具 |
|---|---|---|
low | 只读或微小影响 | run-hunting-query, add-security-alert-comment |
medium | 单个实体的可逆变更 | update-user, add-group-member, create-invitation |
high | 广泛影响、凭据变更或破坏性操作 | revoke-user-sessions, update-conditional-access-policy |
critical | 不可逆或租户范围影响 | delete-user, wipe-managed-device, delete-conditional-access-policy |
资料来源:CONTRIBUTING.md
安全机制
| 机制 | 描述 |
|---|---|
--max-risk-level | CLI 参数限制注册工具的最大风险等级 |
--allow-writes | 显式授权写入操作 |
| 响应包装器 | Graph 响应使用 nonce 包装防提示注入 |
| 最小权限 | 仅请求必需的 Graph API 权限 |
项目包含 51 个单元测试覆盖所有五个安全关键模块。 资料来源:CHANGELOG.md
认证机制
客户端凭据流
graph TD
A[启动服务器] --> B[读取 .env 配置]
B --> C{环境变量检查}
C -->|缺失 MSAL 配置| D[触发设备代码引导]
C -->|有 MSAL 配置| E[初始化 MSAL 客户端]
D --> F[RFC 8628 设备代码流程]
F --> G[获取访问令牌]
E --> G
G --> H[缓存令牌到 mcp-remote]
H --> I[服务器就绪]云配置
项目支持 Microsoft 365 全球版和中国世纪互联版(21Vianet)的不同端点,通过 cloud-config.ts 模块统一管理。 资料来源:src/auth.ts
开发工作流
环境配置
git clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git
cd ms-365-admin-mcp-server
npm install
npm run generate # 下载 Graph OpenAPI 规范并生成客户端
npm run build
npm test
本地 .env 文件配置:
MS365_ADMIN_MCP_CLIENT_ID=...
MS365_ADMIN_MCP_CLIENT_SECRET=...
MS365_ADMIN_MCP_TENANT_ID=...
资料来源:CONTRIBUTING.md
添加工具流程
graph LR
A[编辑 endpoints.json] --> B[添加工具定义]
B --> C[npm run generate]
C --> D[生成 Zod 客户端代码]
D --> E[node dist/index.js --list-tools]
E --> F[验证工具注册]
F --> G[添加单元测试]
G --> H[更新 README.md 工具表]资料来源:CONTRIBUTING.md
工具定义规范
endpoints.json 中每个工具定义包含:
{
"toolName": {
"method": "GET|POST|PATCH|DELETE",
"appPermissions": ["Permission.Read.All"],
"llmTip": "可选的 LLM 提示信息",
"riskLevel": "low|medium|high|critical"
}
}
版本历史
| 版本 | 工具数 | 主要变更 |
|---|---|---|
| 当前 | 444 | 安全修复、BitLocker 恢复密钥等敏感读取标注 |
| 之前 | 369 | 新增云 PC、Teams 通话记录、通用打印等5个类别 |
| 更早 | 306 | 107 个高价值管理员端点 |
| 更早 | 199 | 安全修复、权限范围缩减 |
资料来源:CHANGELOG.md
使用场景
管理员操作自动化
项目主要用于以下场景:
- 身份管理:用户生命周期管理、组分配、角色权限
- 设备管理:Intune 设备合规性监控、丢失设备远程操作
- 安全响应:风险用户确认、 compromised 用户隔离
- 合规审计:电子发现、访问评审、审计日志查询
- 租户配置:SharePoint、Teams、Exchange 设置管理
MCP 客户端集成
项目作为 MCP 服务器运行,Claude Desktop/Code 等客户端可通过 MCP Inspector 进行交互式调试:
npm run inspector
资料来源:CONTRIBUTING.md
质量保证
| 检查项 | 命令 |
|---|---|
| 代码格式检查 | npm run format:check |
| ESLint 检查 | npm run lint |
| 完整验证 | npm run verify |
| 列出所有工具 | node dist/index.js --list-tools |
| 列出所有权限 | node dist/index.js --list-permissions |
许可证
本项目采用 MIT 许可证。 资料来源:CHANGELOG.md
资料来源:[CONTRIBUTING.md]()
核心功能特性
ms-365-admin-mcp-server 是一个基于 Model Context Protocol (MCP) 的 Microsoft 365 管理服务器,通过 Microsoft Graph API 为 AI 助手提供对 Microsoft 365 管理功能的标准化访问接口。该项目从 175 个工具起步,经过多次迭代已扩展至 515 个管理工具,覆盖安全、审计、合规...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
ms-365-admin-mcp-server 是一个基于 Model Context Protocol (MCP) 的 Microsoft 365 管理服务器,通过 Microsoft Graph API 为 AI 助手提供对 Microsoft 365 管理功能的标准化访问接口。该项目从 175 个工具起步,经过多次迭代已扩展至 515 个管理工具,覆盖安全、审计、合规、设备管理、身份治理等核心领域。
1. 系统架构概览
1.1 整体架构
ms-365-admin-mcp-server 采用分层架构设计,核心层负责与 Microsoft Graph API 交互,认证层处理 Azure AD 应用注册凭证,配置层支持全球版和中国区(21Vianet)两种部署模式。
graph TD
subgraph 客户端层
A[MCP 客户端 / Claude Code]
B[MCP Inspector]
end
subgraph 服务端核心
C[CLI 解析层<br/>src/cli.ts]
D[工具注册表<br/>src/endpoints.json]
E[风险评估引擎<br/>src/risk-level.ts]
end
subgraph 认证与配置
F[MSAL 认证<br/>src/auth.ts]
G[云配置<br/>src/cloud-config.ts]
end
subgraph Microsoft Graph API
H[全球版<br/>graph.microsoft.com]
I[中国版<br/>graph.microsoft.cn]
end
A --> C
B --> C
C --> D
C --> E
C --> F
F --> G
G --> H
G --> I
D --> H
D --> I1.2 目录结构
| 目录/文件 | 功能说明 |
|---|---|
bin/ | 代码生成脚本(OpenAPI 规范转换为 Zod 客户端) |
src/ | 核心源代码 |
src/auth.ts | MSAL 客户端凭证流认证 |
src/cli.ts | Commander 参数解析 |
src/cloud-config.ts | 全球版与中国区端点配置 |
src/endpoints.json | 工具定义的事实来源 |
src/generated/ | 自动生成的 Zod 验证代码 |
src/risk-level.ts | 风险等级计算与权限校验 |
src/tool-categories.ts | 工具分类与预设定义 |
docs/ | 使用文档、风险模型、剧本 |
2. 工具分类与预设体系
2.1 预设分类总览
该服务器将 515 个工具组织为 17 个功能预设(Preset),每个预设对应特定的管理场景。预设通过正则表达式匹配工具名称实现自动归类。
| 预设名称 | 功能描述 | 对应用例文件 |
|---|---|---|
security | 安全警报、事件、攻击模拟、威胁情报 | usecase-security.md |
audit | 目录审计、登录日志、预配记录、已删除项 | usecase-audit.md |
health | 服务运行状况、消息中心公告 | usecase-health.md |
reports | 使用报告(Teams、邮件、SharePoint、OneDrive) | usecase-reports.md |
identity | 用户、组、角色、设备、PIM、来宾用户、外部身份 | usecase-identity.md |
exchange | 邮件跟踪、邮箱管理 | usecase-exchange.md |
intune | 设备、合规、配置、Autopilot、应用、RBAC | usecase-intune.md |
governance | 访问评审、权利管理生命周期、条款使用 | usecase-governance.md |
compliance | 许可证、安全分数、身份保护、风险检测、CA 策略 | usecase-compliance.md |
response | 事件响应写入操作(禁用、吊销、确认、驳回) | usecase-response.md |
ediscovery | 电子发现案例(Purview) | usecase-ediscovery.md |
cloudpc | 云 PC / Windows 365 | usecase-cloudpc.md |
callrecords | Teams 通话记录 | usecase-callrecords.md |
print | 通用打印 | usecase-print.md |
infoprotection | BitLocker、威胁评估、敏感度标签 | usecase-infoprotection.md |
sharepointadmin | SharePoint 租户管理 | usecase-sharepointadmin.md |
retention | 记录管理 | usecase-retention.md |
2.2 工具分类定义实现
预设分类在 src/tool-categories.ts 中通过 TypeScript 接口和正则表达式定义:
export interface ToolCategory {
name: string;
pattern: RegExp;
description: string;
}
export const TOOL_CATEGORIES: Record<string, ToolCategory> = {
security: {
name: 'security',
pattern: /security|alert|incident|attack-simulation|threat-intel/i,
description: 'Security alerts, incidents, attack simulations...',
},
identity: {
name: 'identity',
pattern: /user|group|role|conditional|directory|domain|auth-method|.../i,
description: 'Identity and access management...',
},
// ... 其他预设
};
资料来源:src/tool-categories.ts:1-20
2.3 工具发现与验证
服务器提供命令行工具用于验证工具分类和权限配置:
# 列出所有工具
node dist/index.js --list-tools
# 按预设列出工具
node dist/index.js --preset security --list-tools
# 列出所需权限
node dist/index.js --list-permissions
# 验证特定预设
node dist/index.js --preset identity --list-tools | grep list-users
3. 风险等级管理体系
3.1 风险等级定义
服务器对所有非 GET 操作工具进行风险分类,确保高风险操作需要明确授权:
| 风险等级 | 判断标准 | 影响范围 | 操作示例 |
|---|---|---|---|
low | 只读效果或最小影响 | 有限 | 添加安全警报评论、重新处理用户许可证 |
medium | 可逆变更影响单个实体 | 单个实体 | 更新用户、创建组、添加工具成员 |
high | 重大影响、凭证变更或破坏性操作 | 多个实体 | 吊销用户会话、更新条件访问策略 |
critical | 不可逆或租户级影响 | 整个租户 | 删除用户、擦除托管设备、删除条件访问策略 |
3.2 风险等级计算逻辑
风险等级的计算遵循以下优先级:
- 已配置风险等级优先:如果
endpoints.json中明确指定了riskLevel,则使用该值 - GET 请求默认低风险:GET 请求默认为
low(只读操作) - 未标注写入操作默认为 critical:对于没有明确标注风险等级的写入操作,默认设置为
critical(故障安全原则)
export function effectiveRiskLevel(
configuredRiskLevel: RiskLevel | undefined,
method: string
): RiskLevel {
if (configuredRiskLevel) return configuredRiskLevel;
return method.toUpperCase() === 'GET' ? 'low' : 'critical';
}
3.3 权限校验机制
工具执行前会校验其风险等级是否在允许范围内:
export function isToolAllowed(
configuredRiskLevel: RiskLevel | undefined,
method: string,
maxRiskLevel: RiskLevel
): boolean {
return rank(effectiveRiskLevel(configuredRiskLevel, method)) <= rank(maxRiskLevel);
}
写入操作的默认行为需要显式启用:
# 允许中等风险操作
node dist/index.js --allow-writes medium
# 允许高风险操作(需二次确认)
node dist/index.js --allow-writes high
3.4 高危工具分类
#### Critical 级别(需带外审批)
以下操作被视为不可逆或具有租户范围影响:
delete-user— 删除用户账户delete-group— 删除安全组delete-conditional-access-policy— 删除条件访问策略wipe-managed-device— 远程擦除托管设备delete-managed-device— 删除设备注册delete-ediscovery-case— 删除电子发现案例
#### High 级别(需显式确认 + 预演)
以下操作需要操作员确认并可能需要干运行:
revoke-user-sessions— 吊销用户会话confirm-compromised-users— 确认受损用户change-user-password— 更改用户密码update-device— 更新设备配置create-attack-simulation— 创建攻击模拟(钓鱼测试)
4. 认证与安全机制
4.1 MSAL 客户端凭证流
服务器使用 Microsoft Authentication Library (MSAL) 的客户端凭证流进行认证,适用于服务级(无用户交互)的管理操作:
sequenceDiagram
participant MCP as MCP Server
participant MSAL as MSAL 库
participant AAD as Azure AD
MCP->>AAD: 请求访问令牌<br/>(client_id, client_secret, tenant_id)
AAD-->>MSAL: 返回 access_token
MSAL-->>MCP: access_token
MCP->>Graph: Graph API 请求<br/>(Bearer token)
Graph-->>MCP: API 响应4.2 环境变量配置
需要在 .env 文件中配置以下凭证:
MS365_ADMIN_MCP_CLIENT_ID=... # Azure AD 应用注册的应用 ID
MS365_ADMIN_MCP_CLIENT_SECRET=... # 应用密钥
MS365_ADMIN_MCP_TENANT_ID=... # 租户 ID
4.3 查询字符串与错误信息防护
服务器对以下内容进行脱敏处理以防止凭证泄露:
- 查询字符串参数
testLogin错误消息中的敏感信息
sec: sanitize query strings and testLogin error leaks — CHANGELOG.md
5. 云配置与多租户支持
5.1 全球版与中国区切换
服务器支持两种 Microsoft Graph 端点配置,适用于不同的主权云环境:
graph LR
A[请求] --> B{cloud-config}
B -->|全球版| C[graph.microsoft.com]
B -->|中国版| D[graph.microsoft.cn<br/>21Vianet]
style C fill:#4CAF50
style D fill:#FF9800| 云类型 | Graph 端点 | 适用场景 |
|---|---|---|
| Global | graph.microsoft.com | 全球 Microsoft 365 商业版 |
| China | graph.microsoft.cn | 世纪互联运营的 Azure 中国区 |
配置详情见 src/cloud-config.ts。
6. 工具定义与代码生成
6.1 端点定义格式
工具定义以 JSON 格式存储在 endpoints.json 中,作为所有工具定义的事实来源:
{
"toolName": "list-users",
"endpoint": "/v1.0/users",
"method": "GET",
"appPermissions": ["User.Read.All"],
"llmTip": "列出租户中的所有用户",
"riskLevel": "low"
}
6.2 代码生成流程
服务器采用 OpenAPI 规范驱动的工作流:
graph LR
A[Graph OpenAPI 规范] --> B[bin/ 脚本]
B --> C[生成 Zod 验证代码]
B --> D[更新 endpoints.json]
C --> E[src/generated/]
D --> F[src/endpoints.json]
style A fill:#2196F3,color:#fff
style E fill:#E3F2FD
style F fill:#E3F2FD生成命令:
npm run generate # 下载 Graph OpenAPI 规范并生成客户端
重要提示:src/generated/ 目录下的文件由代码生成脚本自动维护,请勿手动编辑。如需修改工具定义,应编辑 endpoints.json 后重新生成。
7. 命令行接口
7.1 可用命令
服务器通过 src/cli.ts 提供以下命令行选项:
| 命令 | 功能 |
|---|---|
--list-tools | 列出所有可用工具 |
--list-permissions | 列出所需 Graph API 权限 |
--list-tools --preset <name> | 按预设筛选工具 |
--list-tools --category <name> | 按类别筛选工具 |
--allow-writes <level> | 允许指定风险等级的写入操作 |
--preset <name> --list-tools | 验证预设分类 |
--inspector | 启动 MCP Inspector |
7.2 交互式调试
使用 MCP Inspector 进行本地调试:
npm run inspector
8. 开发与贡献指南
8.1 开发环境搭建
git clone https://github.com/okapi-ca/ms-365-admin-mcp-server.git
cd ms-365-admin-mcp-server
npm install
npm run generate # 生成客户端代码
npm run build # 编译 TypeScript
npm test # 运行测试
npm run verify # 完整验证(lint + 测试)
8.2 添加新工具的工作流
添加新工具的标准流程:
- 编辑端点定义:在
endpoints.json中添加工具定义
- 重新生成客户端:
``bash npm run generate ``
- 验证工具注册:
- 添加测试:为非平凡参数处理或 skipEncoding 规则添加测试
- 更新 README.md:更新工具计数和类别表格
8.3 提交规范
| 前缀 | 使用场景 |
|---|---|
feat: | 新工具、预设或功能 |
fix: | 错误修复 |
sec: | 安全修复 |
docs: | 仅文档更改 |
chore: | 工具、依赖、非功能性变更 |
refactor: | 无行为变更的重构 |
test: | 仅测试 |
build(deps): | 依赖升级 |
9. 权限模型
9.1 最小权限原则
所有新工具必须声明最小必需的 Graph API 权限:
| 操作类型 | 推荐权限 | 避免 |
|---|---|---|
| 只读 | *.Read.All | *.ReadWrite.All |
| 写入 | *.ReadWrite.All | 仅在必要时使用 |
9.2 应用权限 vs 委托权限
服务器使用 应用权限(application permissions),因为它是无用户交互的服务级操作:
// endpoints.json 中的权限声明
{
"appPermissions": ["User.Read.All", "Group.Read.All"]
}
10. 快速参考表
10.1 关键文件速查
| 文件路径 | 用途 |
|---|---|
src/endpoints.json | 工具定义的源文件 |
src/tool-categories.ts | 预设分类配置 |
src/risk-level.ts | 风险计算逻辑 |
src/auth.ts | MSAL 认证 |
src/cloud-config.ts | 云端点配置 |
src/cli.ts | 命令行接口 |
docs/RISK_MODEL.md | 风险模型文档 |
docs/USE_CASES.md | 用例文档 |
10.2 风险等级快速对照
权限等级: low < medium < high < critical
允许写入: --allow-writes medium 允许 low + medium
10.3 版本历史要点
| 版本 | 工具数量 | 关键变更 |
|---|---|---|
| 当前 | 515 | 71 个管理写入端点 |
| v1.0 | 444 | 75 个管理写入操作 |
| - | 369 | Cloud PC、Teams 通话记录、通用打印、信息保护 |
| - | 306 | eDiscovery、Intune、身份治理 |
| - | 199 | 权限范围缩减至最小权限 |
| 早期 | 175 | 基础安全、设备、PIM、风险检测 |
资料来源:CHANGELOG.md:1-50
资料来源:[src/tool-categories.ts:1-20]()
系统架构
ms-365-admin-mcp-server 是一个基于 Model Context Protocol (MCP) 的 Microsoft 365 管理服务器,通过 Microsoft Graph API 为 AI 代理提供 515+ 管理工具的访问能力。服务器采用 TypeScript 开发,运行于 Node.js 环境,支持标准输入输出(STDIO)和 HTTP 两种...
继续阅读本节完整说明和来源证据。
概述
ms-365-admin-mcp-server 是一个基于 Model Context Protocol (MCP) 的 Microsoft 365 管理服务器,通过 Microsoft Graph API 为 AI 代理提供 515+ 管理工具的访问能力。服务器采用 TypeScript 开发,运行于 Node.js 环境,支持标准输入输出(STDIO)和 HTTP 两种传输模式,可部署在 Azure Container Apps 等云环境中。
核心设计原则:
- 安全优先:所有写操作必须按风险等级分类,需要显式授权方可执行
- 最小权限:仅请求必要的 Graph API 权限
- 零破坏变更:工具名称、参数结构预设分类不可随意变更
- 代码生成:工具定义基于 OpenAPI 规范自动生成,确保与 Graph API 同步
资料来源:CONTRIBUTING.md
资料来源:[CONTRIBUTING.md](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/CONTRIBUTING.md)
通信传输层
本文档详细介绍 ms-365-admin-mcp-server 项目中的通信传输层架构,涵盖客户端认证、HTTP 服务器部署、令牌管理以及远程调用的完整流程。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
ms-365-admin-mcp-server 的通信传输层是连接 MCP 客户端(如 Claude Desktop/Code)与 Microsoft Graph API 的核心组件。该层负责处理 OAuth 2.0 身份认证、HTTP 服务器托管、MCP 协议通信以及令牌缓存等关键功能。
项目的通信架构支持两种主要运行模式:
| 运行模式 | 描述 | 适用场景 |
|---|---|---|
| 本地模式 | 直接在本地运行 MCP 服务器,通过标准输入/输出与客户端通信 | 开发调试、本地使用 |
| 远程 HTTP 模式 | 通过 HTTP 服务器托管,支持远程客户端访问 | 生产部署、多用户环境 |
架构组件
核心模块职责
┌─────────────────────────────────────────────────────────────────┐
│ MCP 客户端 (Claude) │
└─────────────────────────────┬───────────────────────────────────┘
│ HTTP / stdio
┌─────────────────────────────▼───────────────────────────────────┐
│ 通信传输层 │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ http-server │ │ auth-bootstrap│ │ auth (MSAL) │ │
│ └─────────────┘ └──────────────┘ └─────────────────────────┘ │
└─────────────────────────────┬───────────────────────────────────┘
│ HTTPS
┌─────────────────────────────▼───────────────────────────────────┐
│ Microsoft Graph API │
└─────────────────────────────────────────────────────────────────┘
| 模块 | 文件 | 主要职责 |
|---|---|---|
| HTTP 服务器 | src/http-server.ts | 托管 MCP 端点、处理请求路由 |
| 认证引导 | src/auth-bootstrap.ts | RFC 8628 device_code 流程初始化 |
| MSAL 认证 | src/auth.ts | Microsoft 身份平台客户端凭证流 |
| CLI 入口 | src/cli.ts | 命令行参数解析、模式切换 |
| 错误处理 | src/upstream-error.ts | 上游 API 错误规范化 |
资料来源:src/http-server.ts、src/auth-bootstrap.ts:45-60
HTTP 服务器部署
部署方式
项目支持多种 HTTP 服务器部署配置,主要通过环境变量和命令行参数进行控制。
#### 环境变量配置
| 环境变量 | 描述 | 默认值 |
|---|---|---|
MS365_ADMIN_MCP_CLIENT_ID | Azure AD 应用注册客户端 ID | 必需 |
MS365_ADMIN_MCP_CLIENT_SECRET | Azure AD 应用注册客户端密钥 | 必需 |
MS365_ADMIN_MCP_TENANT_ID | Azure AD 租户 ID | 必需 |
MCP_REMOTE_CONFIG_DIR | 远程配置目录路径 | ~/.mcp-auth/mcp-remote-<version>/ |
CI | 是否在 CI 环境运行 | false |
#### 命令行参数
node dist/index.js --preset <preset-name> --list-tools
node dist/index.js --preset <preset-name> --list-permissions
npm run inspector
| 参数 | 描述 |
|---|---|
--preset <name> | 指定工具预设类别 |
--list-tools | 列出所有可用工具 |
--list-permissions | 列出所需 Graph API 权限 |
--inspector | 使用 MCP Inspector 交互式运行 |
资料来源:src/cli.ts
MCP Inspector 交互模式
开发调试阶段可以使用 MCP Inspector 进行交互式测试:
npm run inspector
该命令启动交互式调试服务器,便于验证工具注册、权限配置以及请求路由是否正常工作。
资料来源:CONTRIBUTING.md:43
认证机制
MSAL 客户端凭证流
src/auth.ts 模块实现了 Microsoft 身份库 (MSAL) 的客户端凭证流,用于服务器到服务器的认证场景。
// 核心认证流程伪代码
const clientCredentialFlow = new ClientCredentialFlow({
clientId: process.env.MS365_ADMIN_MCP_CLIENT_ID,
clientSecret: process.env.MS365_ADMIN_MCP_CLIENT_SECRET,
tenantId: process.env.MS365_ADMIN_MCP_TENANT_ID,
});
此认证方式适用于后台服务场景,不需要用户交互即可获取访问令牌。
资料来源:src/auth.ts
RFC 8628 Device Code 引导流程
src/auth-bootstrap.ts 实现了 RFC 8628 定义的 device_code 认证流程,专门用于为远程 MCP 客户端预先填充令牌缓存。
#### 核心流程
┌──────────────┐ ┌───────────────┐ ┌──────────────────┐
│ CLI 工具 │────▶│ OAuth 服务器 │────▶│ 用户设备/浏览器 │
│ (auth-bootstrap)│ │ (/authorize) │ │ (验证页面) │
└──────┬───────┘ └───────────────┘ └──────────────────┘
│ │
│ 轮询 /token │
│◀──────────────────────────────────────────┤
│ │
▼ │
┌──────────────┐ │
│ 缓存令牌 │ │
│ _tokens.json│ │
│ _client_info│ │
└──────────────┘ │
#### 功能特性
- 缓存键计算:
md5(serverUrl),与mcp-remote的getServerUrlHash完全匹配,确保缓存正确关联 - 缓存路径:
~/.mcp-auth/mcp-remote-<version>/ - 文件权限:0600(仅所有者读写),保护敏感凭证
- 剪贴板支持:自动复制设备代码到剪贴板(
pbcopy/clip/wl-copy/xclip),CI 或非 TTY 环境自动禁用
资料来源:src/auth-bootstrap.ts:60-75
#### 命令行用法
ms-365-admin-mcp-auth -s <MCP服务器URL> [--scope <范围>] [--cache-dir <路径>]
| 选项 | 描述 |
|---|---|
-s, --server <url> | MCP 服务器 URL(必需),支持带或不带 /mcp 后缀 |
--scope <scope> | 覆盖默认 OAuth 范围(默认使用服务器元数据) |
--cache-dir <path> | 覆盖缓存目录路径 |
#### 退出码
| 退出码 | 含义 |
|---|---|
| 0 | 认证成功 |
| 1 | 用法错误 |
| 2 | 网络错误 |
| 3 | 认证被拒绝 |
| 4 | 超时 |
资料来源:src/auth-bootstrap.ts:20-35
令牌缓存机制
认证引导工具生成的缓存文件包含两个关键文件:
| 文件 | 用途 |
|---|---|
<hash>_client_info.json | OAuth 客户端信息 |
<hash>_tokens.json | 访问令牌和刷新令牌 |
缓存键采用 MD5 哈希算法,直接对应服务器 URL,确保多服务器部署场景下缓存隔离。
资料来源:src/auth-bootstrap.ts:68-70
远程 HTTP 服务器架构
请求处理流程
┌─────────────────────────────────┐
│ HTTP 请求入口 │
│ (Azure Container Apps / VPS) │
└───────────────┬─────────────────┘
│
┌───────────────▼─────────────────┐
│ 请求路由与中间件 │
│ - 认证验证 │
│ - 协议解析 │
└───────────────┬─────────────────┘
│
┌─────────────────────────┼─────────────────────────┐
│ │ │
┌─────────▼─────────┐ ┌──────────▼──────────┐ ┌────────▼────────┐
│ MCP 协议处理器 │ │ 工具注册表 │ │ Graph API │
│ (method routing) │──▶│ (endpoints.json) │──▶│ 客户端 │
└───────────────────┘ └─────────────────────┘ └─────────────────┘
云端部署注意事项
根据 docs/TROUBLESHOOTING.md 文档,远程 HTTP 部署需要考虑以下因素:
| 注意事项 | 说明 |
|---|---|
| 平台 SSO | Azure AD 条件访问可能触发平台 SSO,导致 device_code 流程复杂化 |
| 条件访问策略 | 需要确保部署的 MCP 服务器被条件访问策略允许 |
| Docker 挂载 | 使用 --cache-dir 和 MCP_REMOTE_CONFIG_DIR 环境变量支持 Docker 卷挂载 |
| 多用户场景 | 不同用户需配置独立的缓存目录 |
认证流程对比
#### 本地模式(标准输入/输出)
Claude Desktop ──▶ stdio ──▶ MCP Server ──▶ Graph API
- 直接进程间通信
- 无需网络配置
- 适用于单用户场景
#### 远程模式(HTTP 服务器)
Claude Desktop/Code ──▶ HTTPS ──▶ MCP Remote Proxy ──▶ MCP Server ──▶ Graph API
│
device_code 认证
(预填充令牌缓存)
- 基于 HTTP 的远程调用
- 支持分布式部署
- 需要令牌缓存配置
错误处理
上游错误规范化
src/upstream-error.ts 模块负责解析和规范化来自 Microsoft Graph API 的错误响应。
#### 错误代码提取
// 从 OAuth 错误响应中提取 error_codes
if (parsed.error_codes && Array.isArray(parsed.error_codes)) {
const codes = parsed.error_codes
.filter((c) => typeof c === 'number')
.slice(0, 5);
if (codes.length > 0) {
parts.push(`error_codes=[${codes.join(',')}]`);
}
}
#### 错误格式化
| 场景 | 输出格式 |
|---|---|
| 可解析的错误 | error=X error_description=Y error_codes=[...] |
| 不可解析响应 | <unparseable N bytes> |
| 无可识别字段 | <no recognise oauth error fields> |
资料来源:src/upstream-error.ts:10-25
认证错误分类
| 错误类型 | 处理方式 |
|---|---|
| 网络错误 | 退出码 2,可重试 |
| 认证拒绝 | 退出码 3,检查权限配置 |
| 超时 | 退出码 4,增加超时配置 |
安全性考虑
令牌存储安全
| 安全措施 | 实现 |
|---|---|
| 文件权限 | 0600,仅进程所有者可访问 |
| 缓存隔离 | MD5 URL 哈希确保不同服务器缓存分离 |
| 环境变量 | 敏感信息通过环境变量注入,避免硬编码 |
最小权限原则
新增工具必须声明最小 Graph API 权限,禁止请求 .ReadWrite.All 当 .Read.All 即可满足需求。
配置示例
本地开发配置
# .env 文件
MS365_ADMIN_MCP_CLIENT_ID=your-client-id
MS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret
MS365_ADMIN_MCP_TENANT_ID=your-tenant-id
Docker 部署配置
docker run -e MS365_ADMIN_MCP_CLIENT_ID=xxx \
-e MS365_ADMIN_MCP_CLIENT_SECRET=xxx \
-e MS365_ADMIN_MCP_TENANT_ID=xxx \
-e MCP_REMOTE_CONFIG_DIR=/data/mcp-cache \
-v /path/to/cache:/data/mcp-cache \
ghcr.io/okapi-ca/ms-365-admin-mcp-server
Device Code 认证
ms-365-admin-mcp-auth -s https://your-host.azurecontainerapps.io/mcp \
--cache-dir /data/mcp-cache
故障排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
Server disconnected | 网络连接问题或服务器未运行 | 检查服务器状态和网络连通性 |
| 设备代码流程超时 | 用户未在规定时间内完成认证 | 使用较长的超时时间或重新发起流程 |
| 条件访问阻止 | 平台 SSO 或 CA 策略限制 | 检查并配置条件访问策略 |
| 缓存权限错误 | Docker 卷挂载权限问题 | 确保挂载目录权限正确 |
相关文档
| 文档 | 位置 | 内容 |
|---|---|---|
| HTTP 部署指南 | docs/HTTP_DEPLOYMENT.md | 远程服务器部署详细说明 |
| 故障排查指南 | docs/TROUBLESHOOTING.md | 常见问题与解决方案 |
| 贡献指南 | CONTRIBUTING.md | 开发设置与代码规范 |
| 安全模型 | docs/RISK_MODEL.md | 风险分级与安全要求 |
资料来源:[CONTRIBUTING.md:35-45]()
认证系统
ms-365-admin-mcp-server 的认证系统负责保护 MCP 服务器的访问安全,支持两种主要的认证模式:
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
ms-365-admin-mcp-server 的认证系统负责保护 MCP 服务器的访问安全,支持两种主要的认证模式:
- 服务令牌模式(Service Token Mode):使用客户端 ID 和客户端密钥进行身份验证,适用于服务到服务的通信
- OAuth 2.0 代理模式(OAuth Mode):通过 Microsoft Entra ID 实现用户身份验证,支持 Claude Desktop、Claude Code 和 Claude.ai Web 等客户端的 OAuth 授权流程
该认证系统的核心目标是确保只有经过授权的用户和服务才能调用 Microsoft Graph API 执行租户管理操作。
架构概览
graph TD
subgraph "客户端层"
A[Claude Desktop]
B[Claude Code]
C[Claude.ai Web]
D[第三方 MCP 客户端]
end
subgraph "认证层"
E[MCP 认证中间件]
F[OAuth 代理]
G[令牌验证器]
H[JWKS 缓存]
end
subgraph "Microsoft Entra ID"
I[令牌颁发]
J[JWKS 端点]
end
subgraph "资源层"
K[Graph API]
L[MCP 工具]
end
A --> E
B --> E
C --> F
D --> E
D --> F
E --> G
F --> I
G --> H
H --> J
E --> L
G --> K
F --> K核心组件
1. 认证模块(src/auth.ts)
认证模块实现了 MSAL(Microsoft Authentication Library)的客户端凭据流,用于获取访问 Microsoft Graph API 的应用程序级令牌。
| 功能 | 说明 |
|---|---|
| 客户端凭据流 | 使用应用 ID 和证书/密钥获取应用级访问令牌 |
| 云配置支持 | 支持全球云和世纪互联(21Vianet)中国区云端点 |
| 令牌缓存 | 内置令牌缓存机制,避免频繁请求新令牌 |
2. OAuth 代理(src/oauth-proxy.ts)
OAuth 代理实现了完整的 OAuth 2.0 + PKCE 授权代码流程,使 Claude 客户端能够通过 Microsoft Entra ID 进行身份验证。
sequenceDiagram
participant Client as Claude 客户端
participant Proxy as OAuth 代理
participant Entra as Microsoft Entra ID
participant Graph as Graph API
Client->>Proxy: GET /.well-known/oauth-authorization-server
Proxy->>Client: 返回元数据
Client->>Proxy: GET /authorize?response_type=code&...
Proxy->>Entra: 重定向到 Entra 授权端点
Entra->>User: 显示登录页面
User->>Entra: 完成身份验证
Entra->>Proxy: 重定向回 /callback?code=xxx
Client->>Proxy: POST /token (authorization_code)
Proxy->>Entra: 使用 code 兑换令牌
Entra->>Proxy: 返回 access_token, refresh_token
Proxy->>Client: 返回令牌
Client->>Proxy: GET /mcp (Bearer token)
Proxy->>Graph: 使用 access_token 调用 API
Graph->>Proxy: 返回数据
Proxy->>Client: 返回结果#### OAuth 代理端点
| 端点 | 方法 | 功能 |
|---|---|---|
/.well-known/oauth-authorization-server | GET | 返回 OAuth 2.0 服务器元数据 |
/.well-known/oauth-protected-resource | GET | 返回受保护资源元数据(用于客户端发现) |
/authorize | GET | 授权端点,启动 PKCE 流程 |
/callback | GET | 授权回调处理 |
/token | POST | 令牌颁发端点 |
/client/register | POST | 动态客户端注册(DCR) |
3. 令牌验证器(src/token-validator.ts)
令牌验证器负责验证 HTTP 传输模式下传入的 Bearer 令牌,确保令牌的有效性和合法性。
| 验证项目 | 说明 |
|---|---|
| JWT 签名验证 | 使用 JWKS 端点获取公钥验证 JWT 签名 |
| 颁发者验证 | 确认令牌由预期的 Entra 租户颁发 |
| 受众验证 | 确认令牌适用于此应用(aud 声明) |
| 租户验证 | 确认令牌来自授权的租户(tid 声明) |
| 用户范围验证 | 确认令牌包含必需的 scp 声明(默认 access_as_user) |
验证失败时的日志记录包括违规的 aud、tid 和 upn 信息,便于排查问题。
4. JWKS 缓存(src/jwks-stale-cache.ts)
为了提高性能和减少网络请求,令牌验证器使用 JWKS 缓存来存储和重用公钥信息。
| 特性 | 说明 |
|---|---|
| 内存缓存 | 将 JWKS 数据缓存在内存中 |
| 过期策略 | 支持配置缓存过期时间 |
| 后台刷新 | 令牌验证前自动刷新过期缓存 |
| 错误处理 | 缓存过期时优雅降级 |
5. 密钥管理(src/secrets.ts)
密钥管理模块负责从多种来源获取敏感配置信息:
| 来源 | 优先级 | 说明 |
|---|---|---|
| 环境变量 | 最高 | 直接从 process.env 读取 |
| Azure Key Vault | 次高 | 从 Key Vault 获取存储的密钥 |
| 默认值 | 最低 | 使用编译时默认值 |
支持的密钥类型:
AZURE_CLIENT_ID:应用(客户端)IDAZURE_CLIENT_SECRET:客户端密钥AZURE_TENANT_ID:租户 ID
6. HTTP 服务器认证中间件(src/http-server.ts)
HTTP 服务器实现了 /mcp 端点的 Bearer 令牌验证中间件,遵循 RFC 6750 标准。
flowchart LR
A[收到 /mcp 请求] --> B{Authorization Header}
B -->|无或非 Bearer| C[返回 401<br/>WWW-Authenticate Header]
B -->|有 Bearer| D[提取令牌]
D --> E{令牌类型}
E -->|用户令牌| F[用户令牌验证器]
E -->|服务令牌| G[服务令牌验证器]
F -->|通过| H[允许访问]
F -->|失败| I{原因}
I -->|无授权用户| J[返回 403]
I -->|其他| K[返回 401]
G -->|通过| H
G -->|失败| L[返回 403]
H --> M[处理 MCP 请求]#### WWW-Authenticate 响应头
| 场景 | 状态码 | WWW-Authenticate Header |
|---|---|---|
| 缺少令牌 | 401 | Bearer resource_metadata="..." |
| 令牌验证失败 | 403 | Bearer resource_metadata="...", error="invalid_token" |
7. 认证引导工具(src/auth-bootstrap.ts)
认证引导工具实现了 RFC 8628 设备代码流,用于在 CLI 环境中自动化 OAuth 认证过程。
| 功能 | 说明 |
|---|---|
| 设备代码获取 | 从服务器获取设备代码和用户验证码 |
| PKCE 支持 | 自动生成 code_verifier 和 code_challenge |
| 令牌缓存 | 将客户端信息和令牌保存到本地文件 |
| 缓存目录 | 默认 $MCP_REMOTE_CONFIG_DIR/mcp-remote-<version> |
认证流程
服务令牌模式
graph LR
A[客户端] -->|携带 Bearer Token| B[MCP 中间件]
B --> C[令牌验证器]
C -->|验证 JWT 签名| D[JWKS 缓存]
D -->|返回公钥| C
C -->|验证声明| E{验证结果}
E -->|通过| F[Graph API 调用]
E -->|失败| G[返回 401/403]OAuth 模式
graph TD
A[Claude Desktop 启动] -->|无缓存令牌| B[发起设备代码流]
B --> C[auth-bootstrap 获取设备代码]
C --> D[用户完成浏览器认证]
D --> E[缓存令牌到本地]
E --> F[MCP 连接携带缓存令牌]
F --> G[OAuth 代理验证令牌]
G -->|有效| H[允许 Graph API 调用]
G -->|无效/过期| I[使用 refresh_token 刷新]
I -->|刷新成功| H
I -->|刷新失败| J[提示重新认证]安全配置
启动参数
| 参数 | 说明 | 默认值 | 安全性 |
|---|---|---|---|
--allowed-clients | 允许的服务客户端 ID 列表 | 必需(无默认) | P1 |
--oauth-mode | 启用 OAuth 2.0 代理模式 | false | P1 |
--authorized-users | OAuth 模式下允许的用户 OID 列表 | 必需(无默认值) | P1 |
--allow-any-tenant-user | 允许任意租户用户(需明确启用) | false | P1 |
--public-url | OAuth 模式的公共 URL | 必需(behind proxy 时) | P1 |
--required-user-scopes | 用户令牌必需的 scope | access_as_user | P1 |
--client-secret | 服务客户端密钥 | 从环境变量获取 | P2 |
--trusted-ip-headers | 信任的 IP 来源头 | 无 | P2 |
安全修复记录
| 标识 | 描述 | 版本 | 严重性 |
|---|---|---|---|
| SEC-F01 | OAuth 模式在空用户白名单时失败关闭 | 0.2.0 | P1 |
| SEC-F02 | --public-url 对 OAuth 模式为必需项 | 0.2.0 | P1 |
| SEC-F03 | 新增 --required-user-scopes 强制验证 scope 声明 | 0.2.3 | P1 |
| SEC-F04 | /token 端点速率限制:10 req/min/IP | 0.2.3 | P1 |
| SEC-F05 | PKCE 桥接内存化,降低多副本部署风险 | 0.2.3 | P1 |
部署注意事项
OAuth 模式部署
OAuth 模式部署需要满足以下条件:
- Entra 应用注册配置:
- 公开暴露
access_as_user委托 scope(api://<client-id>/access_as_user) - 配置
requestedAccessTokenVersion: 2 - 授予管理员同意
- 网络配置:
- 必须设置
--public-url(反向代理后必需) - 配置
trust proxy设置(如适用)
- 多副本部署:
- 由于 PKCE 桥接内存化特性,默认单副本部署
- 多副本部署需显式设置
maxReplicas并考虑外部化 PKCE 桥接
从旧版本迁移
| 场景 | 操作 |
|---|---|
| 使用 OAuth 模式且依赖"任意认证用户"行为 | 添加 --allow-any-tenant-user |
| OAuth 模式部署在反向代理后 | 添加 --public-url https://<fqdn> |
Entra 应用未暴露 access_as_user scope | 添加 --required-user-scopes "" |
Bicep 部署依赖默认 maxReplicas = 3 | 显式设置 maxReplicas |
相关文件
| 文件 | 职责 |
|---|---|
src/auth.ts | MSAL 客户端凭据流实现 |
src/oauth-proxy.ts | OAuth 2.0 授权代码流代理 |
src/token-validator.ts | JWT 令牌验证 |
src/jwks-stale-cache.ts | JWKS 密钥缓存管理 |
src/secrets.ts | 密钥和环境变量管理 |
src/http-server.ts | HTTP 传输和认证中间件 |
src/auth-bootstrap.ts | RFC 8628 设备代码引导 |
infra/main.bicep | Azure Container Apps 部署配置 |
来源:https://github.com/okapi-ca/ms-365-admin-mcp-server / 项目说明书
授权机制
ms-365-admin-mcp-server 的授权机制采用分层设计,支持两种主要的认证模式:OAuth 2.0 代理模式和服务令牌模式。系统通过用户令牌授权模块验证调用者身份,并结合速率限制和范围检查确保安全性。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
ms-365-admin-mcp-server 的授权机制采用分层设计,支持两种主要的认证模式:OAuth 2.0 代理模式和服务令牌模式。系统通过用户令牌授权模块验证调用者身份,并结合速率限制和范围检查确保安全性。
授权机制的核心职责包括:
- 验证用户令牌的签名、颁发者和范围
- 实施基于允许列表的访问控制
- 提供细粒度的范围(scope)验证
- 支持 Entra ID(Azure AD)集成的 OAuth 2.0 流程
架构总览
graph TD
A[HTTP 请求] --> B[/mcp 认证中间件]
B --> C{OAuth 模式启用?}
C -->|是| D[用户令牌验证]
C -->|否| E{允许客户端模式?}
E -->|是| F[服务令牌验证]
E -->|否| G[返回 403]
D --> H{令牌有效?}
D --> I{在授权用户列表?}
D --> J{范围满足?}
H -->|否| K[返回 invalid_token / 401]
I -->|否| L[返回 unauthorized / 403]
J -->|否| M[返回 insufficient_scope / 403]
H -->|是| I
I -->|是| J
J -->|是| N[提取 claims<br/>oid, upn, name, appid]
F --> O[验证服务令牌签名]
O -->|成功| P[允许访问]
N --> P用户令牌授权
核心验证流程
用户令牌授权模块(src/user-token-authorization.ts)负责验证通过 OAuth 2.0 流程获取的用户令牌。验证过程遵循以下步骤:
- 签名验证 — 验证 JWT 签名来自可信的 JWKS 端点
- 声明验证 — 检查
aud(受众)、tid(租户 ID)等关键声明 - 用户白名单检查 — 验证
upn是否在授权用户列表中 - 范围验证 — 确认令牌包含所需的 OAuth 范围
关键函数
export function authorizeUserClaims(
payload: UserTokenPayload,
options: UserTokenValidatorOptions
): UserTokenAuthorizationResult
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
payload | UserTokenPayload | 解码后的 JWT 载荷 |
options.requiredScopes | string[] | 必需的 OAuth 范围列表 |
options.authorizedUsers | string[] | 授权用户 UPN 列表 |
options.requiredAudiences | string[] | 必需的受众声明 |
options.requiredTenantId | string | 必需的租户 ID |
返回值:
| 字段 | 说明 |
|---|---|
ok: true | 授权成功,返回包含 claims 的对象 |
ok: false | 授权失败,reason 指示失败原因 |
失败原因与 HTTP 状态码
| 失败原因 | HTTP 状态 | 说明 |
|---|---|---|
invalid_token | 401 | 令牌格式错误或签名验证失败 |
insufficient_scope | 403 | 令牌缺少必需的范围 |
unauthorized_user | 403 | 用户不在授权列表中 |
// 资料来源:src/user-token-authorization.ts:46-52
if (missing.length > 0) {
logger.warn(
`User token missing required scope(s): ${missing.join(', ')}; token scp=${payload.scp ?? '<none>'}`
);
return { ok: false, reason: 'insufficient_scope' };
}
范围解析逻辑
系统通过 parseTokenScopes 函数解析令牌中的 scp 声明,并与必需范围进行比对:
graph LR
A[scp 声明] --> B{解析范围列表}
B --> C[requiredScopes]
C --> D[过滤出不匹配项]
D --> E{missing.length > 0?}
E -->|是| F[返回 insufficient_scope]
E -->|否| G[授权通过]OAuth 2.0 代理模式
概述
当服务器以 --oauth-mode 运行时,启用 OAuth 2.0 代理功能。用户通过 Entra ID 进行身份验证后,服务器代理令牌交换和验证流程。
端点列表
| 端点 | 方法 | 说明 |
|---|---|---|
/.well-known/oauth-authorization-server | GET | OAuth 发现文档 |
/.well-known/oauth-protected-resource | GET | 受保护资源元数据 |
/authorize | GET | 授权请求入口 |
/token | POST | 令牌交换 |
/devicecode | POST | 设备代码流 |
授权流程
sequenceDiagram
participant U as 用户
participant S as MCP Server
participant E as Entra ID
U->>S: 访问 MCP 端点 (无令牌)
S->>U: 返回 401 + WWW-Authenticate
U->>S: GET /authorize
S->>E: 重定向到 Entra ID<br/>client_id, redirect_uri, scope
E->>U: 登录页面
U->>E: 完成身份验证 + MFA
E->>S: redirect_uri + auth_code
S->>E: POST /token<br/>client_id, client_secret, code
E->>S: access_token, refresh_token
S->>U: 返回令牌给客户端客户端认证
OAuth 代理在 /token 端点强制要求客户端凭证:
// 资料来源:src/oauth-proxy.ts:85-100
const { clientId: reqClientId, clientSecret: reqClientSecret } = extractClientCredentials(req);
if (!reqClientId || !reqClientSecret) {
res.status(401).json({
error: 'invalid_client',
error_description: 'Missing client_id or client_secret',
});
return;
}
| 字段 | 说明 |
|---|---|
client_id | 注册的 OAuth 应用客户端 ID |
client_secret | 对应的客户端密钥 |
设备代码引导
对于无浏览器环境,服务器提供 RFC 8628 设备代码流程:
ms-365-admin-mcp-auth -s https://your-host.azurecontainerapps.io/mcp
工作流程:
- 客户端向
/devicecode请求设备代码 - 服务器返回
device_code和user_code - 用户在另一设备访问
verification_uri并输入user_code - 轮询
/token直到授权完成
// 资料来源:src/auth-bootstrap.ts:60-80
const { verification_uri, user_code, device_code, interval, expires_in } = await getDeviceCode(
serverUrl,
clientId,
scope
);
服务令牌模式
概述
当部署使用 --allowed-clients 参数时,系统接受预注册的服务令牌(如 MCP Remote 客户端令牌)。
认证中间件顺序
graph TD
A[请求到达 /mcp] --> B{oauth-mode 启用?}
B -->|是| C[尝试用户令牌验证]
B -->|否| D{allowed-clients 启用?}
C --> E{用户令牌验证成功?}
E -->|是| F[允许访问]
E -->|否| G{allowed-clients 启用?}
D -->|是| H[尝试服务令牌验证]
D -->|否| I[返回 403]
H --> J{服务令牌验证成功?}
J -->|是| F
J -->|否| I
G -->|是| H
G -->|否| I令牌缓存
用户令牌和客户端信息缓存到本地目录:
$MCP_REMOTE_CONFIG_DIR/mcp-remote-<version>/
├── client-info.json
└── tokens.json
缓存文件权限设置为 0700(目录)和 0600(文件),确保令牌安全存储。
速率限制
限制器配置
系统通过 src/oauth-rate-limiters.ts 为 OAuth 端点配置多层速率限制:
| 端点 | 限制器 | 窗口 | 最大请求 |
|---|---|---|---|
/token (device_code) | tokenDevicePollLimiter | 1 分钟 | 10 次 |
/token (其他) | tokenTightLimiter | 1 分钟 | 5 次 |
/register | tokenTightLimiter | 1 分钟 | 5 次 |
/devicecode | tokenTightLimiter | 1 分钟 | 5 次 |
设备代码轮询限制
设备代码轮询(polling)有特殊的速率限制,防止客户端过度请求:
// 资料来源:src/oauth-rate-limiters.ts:25-35
const tokenDevicePollLimiter = rateLimit({
windowMs: 60 * 1000,
max: 10,
standardHeaders: true,
legacyHeaders: false,
message: {
error: 'invalid_request',
error_description: 'Too many device_code poll requests',
},
});
CLI 配置选项
通过 src/cli.ts 暴露的启动参数控制授权行为:
| 参数 | 说明 | 默认值 |
|---|---|---|
--oauth-mode | 启用 OAuth 2.0 代理模式 | false |
--allowed-clients | 允许的服务客户端 ID 列表(逗号分隔) | 无 |
--public-url | OAuth 模式下的公共 URL | 必需(OAuth 模式下) |
--required-user-scopes | 必需的 OAuth 用户范围 | 必需(OAuth 模式下) |
--allow-any-tenant-user | 允许任何已验证租户的用户 | false |
必需参数组合
graph TD
A[启动参数检查] --> B{OAuth 模式?}
B -->|是| C{提供 --public-url?}
C -->|否| D[错误:需要 public-url]
C -->|是| E{提供 --required-user-scopes?}
E -->|否| F[使用默认值]
E -->|是| G[使用指定范围]
B -->|否| H{提供 --allowed-clients?}
H -->|否| I[错误:需要 allowed-clients 或 oauth-mode]
H -->|是| J[启动成功]示例启动命令
# OAuth 模式(Claude Desktop 集成)
ms-365-admin-mcp-server --transport streamable-http \
--oauth-mode \
--public-url https://mcp.contoso.com \
--required-user-scopes "access_as_user"
# 服务客户端模式
ms-365-admin-mcp-server --transport streamable-http \
--allowed-clients "client-id-1,client-id-2"
# 混合模式
ms-365-admin-mcp-server --transport streamable-http \
--oauth-mode \
--allowed-clients "legacy-client-id" \
--public-url https://mcp.contoso.com
安全考量
令牌验证原则
- 签名验证优先 — 所有 JWT 必须通过 JWKS 验证签名
- 范围最小化 — 仅接受明确声明的范围
- 租户隔离 — 除非明确允许,否则仅接受同一租户的用户
- 客户端认证 — OAuth 端点强制要求客户端凭证
日志记录
授权失败时,系统记录详细诊断信息:
// 资料来源:src/user-token-authorization.ts:40-45
logger.warn(
`User (${upnForLog}) not in authorized-users allowlist`
);
return { ok: false, reason: 'invalid_token' };
日志包含的信息:
- 用户主体名称(UPN)
- 缺失的范围列表
- 令牌受众(aud)和租户 ID(tid)
速率限制保护
- 防止设备代码轮询滥用
- 限制令牌注册请求频率
- 防止暴力破解客户端凭证
迁移指南
从旧版本升级
| 版本 | 变更 |
|---|---|
| 0.2.0+ | 新增 --oauth-mode 支持 |
| 0.2.4+ | 允许客户端参数变为可选(需要 --oauth-mode 或 --allowed-clients) |
常见配置错误
| 错误 | 解决方案 |
|---|---|
ERR_MISSING_PUBLIC_URL | 添加 --public-url 参数 |
ERR_MISSING_REQUIRED_SCOPES | 添加 --required-user-scopes 参数 |
ERR_RATE_LIMIT_EXCEEDED | 减少设备代码轮询频率 |
参考资料
- 授权核心实现:src/user-token-authorization.ts
- OAuth 代理:src/oauth-proxy.ts
- 设备代码引导:src/auth-bootstrap.ts
- 速率限制:src/oauth-rate-limiters.ts
- CLI 配置:src/cli.ts
- 安全审查文档:docs/SECURITY_REVIEW_2026-04-20.md
来源:https://github.com/okapi-ca/ms-365-admin-mcp-server / 项目说明书
工具分类系统
工具分类系统(Tool Categories System)是 ms-365-admin-mcp-server 项目中用于组织和管理 515 个 Microsoft Graph API 工具的核心组件。该系统通过正则表达式模式匹配将工具自动归类到不同的功能域,使管理员和 AI 代理能够根据业务场景快速定位所需工具。 资料来源:[agent-skills/ms365-admi...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
工具分类系统(Tool Categories System)是 ms-365-admin-mcp-server 项目中用于组织和管理 515 个 Microsoft Graph API 工具的核心组件。该系统通过正则表达式模式匹配将工具自动归类到不同的功能域,使管理员和 AI 代理能够根据业务场景快速定位所需工具。 资料来源:agent-skills/ms365-admin-mcp/references/tools-catalog.md:1
核心设计目标
| 目标 | 说明 |
|---|---|
| 按领域组织 | 将 515 个工具按功能域(安全、身份、合规等)分组 |
| 模式匹配 | 使用正则表达式自动识别工具所属分类 |
| 预设管理 | 支持通过 --preset 参数动态加载相关工具集 |
| 风险分层 | 每个分类关联特定的风险级别,便于权限管控 |
架构设计
系统架构图
graph TD
A[endpoints.json] --> B[工具注册表]
B --> C{工具分类器}
C --> D[TOOL_CATEGORIES]
C --> E[CLI preset 参数]
D --> F[security<br/>audit<br/>health<br/>reports]
D --> G[identity<br/>governance<br/>response]
D --> H[exchange<br/>intune<br/>ediscovery]
D --> I[cloudpc<br/>callrecords<br/>print<br/>infoprotection<br/>sharepointadmin<br/>retention]
E --> J[list-tools<br/>filter by pattern]
F --> K[MCP Inspector<br/>动态加载]
G --> K
H --> K
I --> K核心接口定义
工具分类系统定义了一个简洁的接口,包含三个必需属性: 资料来源:src/tool-categories.ts:1-5
export interface ToolCategory {
name: string; // 分类唯一标识符
pattern: RegExp; // 匹配工具名称的正则表达式
description: string; // 人类可读的分类描述
}
分类清单
完整分类对照表
| 分类名称 | 模式关键词 | 描述 | 文档参考 |
|---|---|---|---|
security | security, alert, incident, attack-simulation, threat-intel | Microsoft 365 Defender 安全告警、事件、攻击模拟和威胁情报 | usecase-security.md |
audit | audit, sign-in, provisioning, directory, deleted-user, deleted-group | 审计日志、目录审计、登录记录和已删除项目 | usecase-audit.md |
health | service, health, issue, message | 服务健康状态和消息中心公告 | usecase-health.md |
reports | report, activity, usage | Teams、邮箱、SharePoint、OneDrive、M365 应用使用报告 | usecase-reports.md |
identity | user, group, role, conditional, directory, domain, auth-method, credential, application, service-principal, sp-password, sp-key, sp-token, sp-owner, oauth2, organization, named-location, device, administrative-unit, cross-tenant, pim, app-role, invitation, identity-provider, b2x, api-connector, custom-auth | Entra ID 用户、组、角色、设备、PIM、来宾用户、外部身份的身份和访问管理 | usecase-identity.md |
governance | role-resource-namespace | 访问评审、权利管理、生命周期工作流、角色/组 PIM、使用条款、应用同意的身份治理 | usecase-governance.md |
response | disable-user, revoke, block, reset, isolate, update-security, delete-user-auth, delete-user-phone, update-device, update-user-auth, confirm-compromised, dismiss-risky, confirm-safe, hunting-query, wipe-managed, retire-managed, remote-lock, locate-managed, bypass-activation, apply-hold, remove-hold | 事件响应操作(禁用用户、撤销会话、确认泄露/安全、 dismissal 风险、威胁狩猎查询) | usecase-response.md |
ediscovery | ediscovery | Microsoft Purview 电子发现案例 | usecase-ediscovery.md |
cloudpc | cloud-pc, provisioning-polic | Cloud PC / Windows 365(云电脑、配置策略、设备镜像) | usecase-cloudpc.md |
callrecords | call-record, call-session, pstn-call, direct-routing | Teams 通话记录(会话、分段、参与方、PSTN 通话、直接路由) | usecase-callrecords.md |
print | 通用打印(打印机、共享、连接器、服务、任务定义) | usecase-print.md | |
infoprotection | sensitivity, bitlocker, threat-assessment, mip | BitLocker、威胁评估、敏感度标签 | usecase-infoprotection.md |
sharepointadmin | spo, sharepoint | SharePoint 租户管理 | usecase-sharepointadmin.md |
retention | retention, records | 记录管理 | usecase-retention.md |
exchange | exchange, mailbox, message-trace | 消息追踪、邮箱管理 | usecase-exchange.md |
intune | intune, mdm, mam, compliance, autopilot | 设备管理、合规配置、Autopilot、应用保护策略 | usecase-intune.md |
teamsadmin | teams, channel, meeting | Teams 团队、频道、会议、应用设置 | usecase-teamsadmin.md |
资料来源:src/tool-categories.ts:7-85
使用方式
命令行预设加载
通过 --preset 参数加载特定分类的工具集:
# 列出所有安全相关工具
node dist/index.js --preset security --list-tools
# 列出所有身份管理工具
node dist/index.js --preset identity --list-tools
# 列出所有合规相关工具
node dist/index.js --preset compliance --list-tools
验证工具分类
检查特定工具是否被正确分类:
node dist/index.js --preset mypreset --list-tools
扩展机制
添加新分类
在 src/tool-categories.ts 文件中扩展 TOOL_CATEGORIES 对象:
export const TOOL_CATEGORIES: Record<string, ToolCategory> = {
// ... 现有分类 ...
mypreset: {
name: 'mypreset',
pattern: /pattern-matching-tool-names/i,
description: 'Short human-readable description',
},
};
分类匹配规则
正则表达式必须能够匹配 endpoints.json 中定义的 toolName。验证方法:
node dist/index.js --preset mypreset --list-tools | grep list-something
与风险级别系统的集成
工具分类系统与风险级别系统(risk-level.ts)协同工作,为每个操作提供安全保障:
export function effectiveRiskLevel(
configuredRiskLevel: RiskLevel | undefined,
method: string
): RiskLevel {
if (configuredRiskLevel) return configuredRiskLevel;
// GET 请求默认为 low,危险操作默认为 critical
return method.toUpperCase() === 'GET' ? 'low' : 'critical';
}
风险级别分类
| 级别 | 描述 | 包含的操作类型 |
|---|---|---|
low | 仅读取或无害操作 | GET 请求、报表生成 |
medium | 可逆的单实体变更 | update-user, add-group-member |
high | 影响范围大或凭证变更 | revoke-user-sessions, update-conditional-access-policy |
critical | 不可逆或租户级影响 | delete-user, wipe-managed-device, delete-conditional-access-policy |
技术实现细节
模式匹配优先级
当一个工具名称同时匹配多个分类的正则表达式时,系统按以下原则处理:
- 最长匹配优先 — 选择模式最具体的分类
- 精确分类优先 — 明确命名的分类(如
ediscovery)优先于宽泛匹配 - 配置覆盖 —
endpoints.json中的显式分类配置优先于自动匹配
分类与文档映射
工具目录(tools-catalog.md)建立了分类与用例文档的完整映射:
graph LR
A[security preset] --> B[usecase-security.md]
A --> C[usecase-threatintel.md]
D[identity preset] --> E[usecase-identity.md]
F[compliance preset] --> G[usecase-compliance.md]
F --> H[usecase-response.md]每个用例文档包含:
- 工具清单表格(操作、用途、风险级别)
- 常见操作模式(Pattern)
- 安全护栏(Guardrails)
资料来源:agent-skills/ms365-admin-mcp/references/tools-catalog.md:1-50
开发工作流
添加新工具到现有分类
- 在
src/endpoints.json中添加工具定义 - 运行
npm run generate重新生成客户端代码 - 验证工具是否被正确分类:
node dist/index.js --list-tools | grep <tool-name> - 检查所需 Graph API 权限:
node dist/index.js --list-permissions | grep <permission>
创建新分类
- 编辑
src/tool-categories.ts添加新的ToolCategory条目 - 编写对应的
usecase-<category>.md参考文档 - 在
agent-skills/ms365-admin-mcp/references/tools-catalog.md中添加索引 - 运行测试验证:
npm run verify
总结
工具分类系统是 ms-365-admin-mcp-server 的核心组织机制,通过 16 个预设分类覆盖了 Microsoft 365 管理的全部功能域。系统利用正则表达式模式实现自动化分类,结合风险级别系统提供了完整的安全保障。该设计遵循了最小权限原则,所有新工具必须声明最小必需的 Graph API 权限,且非 GET 操作必须明确标注风险级别。
资料来源:[src/tool-categories.ts:7-85]()
风险模型
风险模型是 ms-365-admin-mcp-server 安全架构的核心组件,为所有管理工具提供风险级别的分类和访问控制机制。该模型确保高风险操作得到适当的审查和确认,防止意外或恶意的租户级别更改。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
风险模型是 ms-365-admin-mcp-server 安全架构的核心组件,为所有管理工具提供风险级别的分类和访问控制机制。该模型确保高风险操作得到适当的审查和确认,防止意外或恶意的租户级别更改。
风险模型的主要职责包括:
- 为每个管理工具分配明确的风险等级(
low、medium、high、critical) - 提供运行时风险级别检查机制
- 支持通过 CLI 参数
--max-risk-level限制可执行的最高风险级别 - 默认为安全策略:未明确标注的写操作自动归类为
critical
风险等级定义
四级风险体系
| 风险等级 | 判定标准 | 示例工具 |
|---|---|---|
low | 只读效果(POST 查询、报告)或trivial注解 | run-hunting-query、add-security-alert-comment、Intune 报告 |
medium | 可逆的单一实体变更 | update-user、add-group-member、create-invitation |
high | 重大影响:范围广、凭证变更或破坏性操作 | revoke-user-sessions、update-conditional-access-policy |
critical | 不可逆或租户级别影响 | delete-user、wipe-managed-device、delete-conditional-access-policy |
判定规则
风险等级判定遵循以下原则:
- 已配置风险优先:如果工具显式配置了
configuredRiskLevel,直接使用该值 - 方法默认策略:未配置的工具,GET 请求默认为
low,写操作默认为critical(fail-safe 机制) - 高风险优先原则:难以判断时,选择更高的风险等级
export function effectiveRiskLevel(
configuredRiskLevel: RiskLevel | undefined,
method: string
): RiskLevel {
if (configuredRiskLevel) return configuredRiskLevel;
return method.toUpperCase() === 'GET' ? 'low' : 'critical';
}
风险级别函数
函数列表
// 计算有效风险级别
export function effectiveRiskLevel(
configuredRiskLevel: RiskLevel | undefined,
method: string
): RiskLevel
// 检查工具是否在允许范围内
export function isToolAllowed(
configuredRiskLevel: RiskLevel | undefined,
method: string,
maxRiskLevel: RiskLevel
): boolean
级别排序
风险级别按严重程度排序为:low < medium < high < critical
function rank(level: RiskLevel): number {
const ranking: Record<RiskLevel, number> = {
low: 0,
medium: 1,
high: 2,
critical: 3,
};
return ranking[level];
}
允许检查逻辑
工具是否允许执行取决于其有效风险级别是否不超过配置的最大风险级别:
graph TD
A[工具调用请求] --> B{获取有效风险级别}
B --> C{获取最大风险级别 cap}
C --> D{rank有效级别 <= rank最大级别?}
D -->|是| E[允许执行]
D -->|否| F[拒绝执行 + 提示]CLI 风险控制
命令行参数
| 参数 | 说明 | 隐含效果 |
|---|---|---|
--allow-writes | 允许执行写操作 | 启用写入工具注册 |
--max-risk-level <level> | 设置最高可执行风险级别 | 隐含 --allow-writes,隐藏更高级别工具 |
风险限制示例
# 只允许只读操作
ms-365-admin-mcp-server --max-risk-level low
# 允许低和中风险操作
ms-365-admin-mcp-server --max-risk-level medium
# 允许所有操作(含高风险)
ms-365-admin-mcp-server --max-risk-level high
# 允许所有操作(含关键风险)
ms-365-admin-mcp-server --max-risk-level critical
资料来源:CHANGELOG.md:1-20
关键工具风险映射
Critical 级别工具(需带外审批)
以下工具具有不可逆或租户级别影响,执行前必须获得正式变更请求审批:
| 工具名称 | 影响描述 |
|---|---|
delete-user | 永久删除用户账户 |
delete-group | 永久删除安全组/Microsoft 365 组 |
delete-application | 删除应用注册 |
delete-service-principal | 删除服务主体 |
delete-conditional-access-policy | 删除条件访问策略 |
delete-exchange-mailbox | 删除 Exchange 邮箱 |
delete-ediscovery-case | 删除 eDiscovery 案例 |
delete-team | 删除 Teams 团队 |
delete-managed-device | 删除托管设备记录 |
wipe-managed-device | 完全擦除设备数据 |
clean-windows-device | 清理 Windows 设备 |
add-directory-role-member | 添加特权目录角色成员 |
create-pim-role-assignment-request | 特权角色的 PIM 分配请求 |
create-pim-role-eligibility-request | 特权角色资格请求 |
disable-user-account | 禁用特权或紧急访问账户 |
资料来源:agent-skills/ms365-admin-mcp/references/tools-catalog.md:30-45
High 级别工具(需明确确认 + 预演)
| 工具名称 | 风险描述 |
|---|---|
revoke-user-sessions | 撤销用户所有会话,影响用户当前工作 |
confirm-compromised-users | 确认用户账户已被泄露 |
confirm-safe-users | 将用户标记为安全(误报处理) |
dismiss-risky-users | 忽略风险用户 |
confirm-compromised-service-principals | 确认服务主体泄露 |
dismiss-risky-service-principals | 忽略风险服务主体 |
delete-user-phone-auth-method | 删除用户手机认证方法 |
change-user-password | 更改用户密码 |
update-device | 更新设备配置 |
create-conditional-access-policy | 创建条件访问策略 |
update-conditional-access-policy | 更新条件访问策略 |
资料来源:agent-skills/ms365-admin-mcp/references/tools-catalog.md:50-60
敏感读取工具
某些 GET 操作因暴露敏感信息也被标注风险级别:
| 风险等级 | 工具类型 | 示例 |
|---|---|---|
high | 密钥/恢复信息 | BitLocker 恢复密钥、LAPS 密码 |
medium | 认证信息 | 认证方法、登录记录、风险检测 |
high | 合规数据 | eDiscovery 案例、保管人、搜索、主题权限请求 |
资料来源:CHANGELOG.md:1-20
高危操作安全模式
必须遵循的操作流程
对于 high 和 critical 级别的工具,必须执行以下序列:
graph TD
A[识别目标对象] --> B[预演 Dry-Run]
B --> C[读取目标对象详情]
C --> D[列出预期影响]
D --> E[请求明确确认]
E --> F{确认?}
F -->|是| G[执行操作]
F -->|否| H[取消操作]
G --> I[记录审计日志]标准确认话术
执行高风险操作前,必须向操作员说明:
"即将调用<工具名称>对<目标>执行<影响描述>。此操作<可逆性/不可逆>。是否确认执行?"
资料来源:agent-skills/ms365-admin-mcp/SKILL.md:50-70
工具目录中的风险索引
工具目录按预设(preset)和风险级别双重索引,便于快速查找:
graph LR
A[工具目录] --> B[按预设索引]
A --> C[按风险级别索引]
B --> B1[security<br/>audit<br/>health<br/>reports<br/>identity<br/>exchange<br/>intune<br/>governance<br/>compliance<br/>response<br/>ediscovery<br/>cloudpc<br/>callrecords<br/>print<br/>infoprotection<br/>sharepointadmin<br/>retention]
C --> C1[Critical<br/>需带外审批]
C --> C2[High<br/>确认+预演]
C --> C3[Medium<br/>明确确认]
C --> C4[Low<br/>常规操作]资料来源:agent-skills/ms365-admin-mcp/references/tools-catalog.md:1-30
安全集成
与其他安全机制的关系
| 安全组件 | 集成点 | 说明 |
|---|---|---|
| SEC-G01 | --max-risk-level | 风险级别 cap 作为安全门控 |
| SEC-G02 | 响应包装器 | Graph 响应被nonce信封包装,防止提示注入 |
| SEC-G03 | 敏感读取标注 | 22个敏感GET工具已标注风险级别 |
最小权限原则
新工具必须:
- 声明最小必需的 Graph API 权限(
appPermissions) - 避免请求
.ReadWrite.All当.Read.All足够时 - 所有写操作必须附带风险级别标注
最佳实践
开发新工具时的风险标注
在 endpoints.json 中添加新工具时,必须包含风险级别:
{
"toolName": "create-something",
"method": "POST",
"appPermissions": ["Something.ReadWrite.All"],
"riskLevel": "medium"
}
风险升级场景
以下情况应提升风险等级:
- 操作影响多个实体
- 操作修改凭证或访问权限
- 操作产生不可逆的数据变更
- 操作具有租户范围的影响
降低风险的方法
如需降低操作风险,可考虑:
- 添加预演/确认步骤
- 限制操作范围(单用户而非批量)
- 添加延迟执行或审批工作流
- 提供回滚机制
总结
风险模型是 ms-365-admin-mcp-server 安全架构的基础,通过四级风险体系(low、medium、high、critical)对所有515个管理工具进行分类。该模型配合 CLI 风险上限参数 --max-risk-level 和强制性的确认流程,确保管理员在执行敏感操作时经过充分审查,防止租户级别的意外或恶意更改。
资料来源:[src/risk-level.ts:1-30](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/risk-level.ts)
部署指南
本文档提供 ms-365-admin-mcp-server 的完整部署指南,涵盖从 Azure AD 应用注册到容器化部署的全流程。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 部署概述
1.1 部署模式
ms-365-admin-mcp-server 支持两种主要部署模式:
| 部署模式 | 说明 | 适用场景 |
|---|---|---|
| STDIO 模式 | 标准输入输出通信,适合本地开发和 Claude Code 集成 | 本地开发、单用户 |
| HTTP 服务器模式 | REST API 服务,支持远程访问和 Docker 部署 | 生产环境、多租户 |
1.2 核心部署架构
graph TD
A[客户端 MCP Client] -->|HTTP/gRPC| B[ms-365-admin-mcp-server]
B --> C[Azure AD 应用注册]
B --> D[Microsoft Graph API]
D --> E[Microsoft 365 管理 API]
F[Docker 容器] --> B
G[Azure Container Instances] --> F
H[Azure App Service] --> B1.3 部署前提条件
- Node.js 18+ (STDIO 模式)
- Docker 20.10+ (容器模式)
- Azure 订阅
- Microsoft 365 租户管理员权限
2. Azure AD 应用注册
2.1 创建应用注册
在 Azure Portal 中创建应用注册,配置以下设置:
| 设置项 | 推荐值 | 说明 |
|---|---|---|
| 支持的账户类型 | 仅此组织目录中的账户 | 单租户部署 |
| 重定向 URI | http://localhost:7000 | 本地开发 |
| 重定向 URI (生产) | https://<your-domain>/mcp | HTTP 服务器模式 |
2.2 配置应用程序权限
ms-365-admin-mcp-server 使用应用程序权限(application permissions),需要以下 Graph API 权限:
{
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "<permission-id>",
"type": "Role"
}
]
}
]
}
资料来源:docs/APP_REGISTRATION.md:1-50
2.3 获取凭据
部署需要以下环境变量:
| 环境变量 | 说明 |
|---|---|
MS365_ADMIN_MCP_CLIENT_ID | Azure AD 应用程序客户端 ID |
MS365_ADMIN_MCP_CLIENT_SECRET | 应用程序客户端密钥 |
MS365_ADMIN_MCP_TENANT_ID | Azure AD 租户 ID |
3. Docker 部署
3.1 拉取镜像
# 从 GitHub Container Registry 拉取
docker pull ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest
# 验证镜像
docker run -d \
--name mcp-server \
-p 7000:7000 \
-e MS365_ADMIN_MCP_CLIENT_ID="<your-client-id>" \
-e MS365_ADMIN_MCP_CLIENT_SECRET="<your-client-secret>" \
-e MS365_ADMIN_MCP_TENANT_ID="<your-tenant-id>" \
-e MS365_ADMIN_MCP_ALLOWED_CLIENTS="*" \
ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest
3.2 Docker 容器安全配置
Docker 镜像使用非 root 用户运行,确保容器安全性:
# 基础镜像配置
FROM node:18-alpine
# 创建非 root 用户
RUN addgroup -g 1001 -S mcpuser && \
adduser -S mcpuser -u 1001
# 切换到非 root 用户
USER mcpuser
# 设置工作目录
WORKDIR /app
资料来源:Dockerfile:1-30
3.3 卷挂载配置
生产环境建议挂载日志目录:
docker run -d \
--name mcp-server \
-p 7000:7000 \
-v /path/to/config:/app/config:ro \
-v /path/to/logs:/var/log/mcp-server \
-e MS365_ADMIN_MCP_LOG_DIR="/var/log/mcp-server" \
ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest
4. Azure 基础设施部署
4.1 Bicep 部署架构
graph TD
A[main.bicep] --> B[Azure Container Instance]
A --> C[用户托管身份 UAMI]
A --> D[Azure Key Vault]
A --> E[虚拟网络]
B --> C
B --> D
C --> D
F[Private Container Registry] --> B4.2 必需参数
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
allowedClients | string | 是 | 允许访问的客户端 CIDR 列表 |
acrLoginServer | string | 否 | 私有容器注册表服务器 |
tags | object | 否 | 资源标签 |
location | string | 否 | 部署区域 |
4.3 部署命令
# 使用 Azure CLI 部署
az deployment sub create \
--location eastus \
--template-file infra/main.bicep \
--parameters allowedClients="['10.0.0.0/8']" \
--parameters acrLoginServer="myregistry.azurecr.io"
# 验证部署
az container show --resource-group <rg-name> --name <container-name>
4.4 用户托管身份配置
Bicep 模板自动配置用户托管身份(UAMI)用于:
- 从 Azure Key Vault 检索客户端密钥
- 访问 Azure 资源
- 容器注册表拉取镜像
resource uami 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: 'mcp-server-identity'
location: location
}
5. HTTP 服务器模式配置
5.1 启动参数
| 参数 | 默认值 | 说明 |
|---|---|---|
--port | 7000 | HTTP 服务器监听端口 |
--host | 0.0.0.0 | 绑定地址 |
--allowed-clients | - | 允许的客户端 IP/CIDR |
--log-dir | - | 日志目录 |
--allow-writes | false | 允许写操作 |
--max-risk-level | medium | 最大风险级别 |
--preset | - | 预置工具类别 |
--enabled-tools | - | 启用工具正则表达式 |
5.2 安全配置
| 安全功能 | 默认状态 | 说明 |
|---|---|---|
| 安全头 | 启用 | X-Content-Type-Options, X-Frame-Options, CSP |
| Body 大小限制 | 100KB | 防止大文件攻击 |
| 路径参数验证 | 启用 | 防止路径遍历 |
| ReDoS 保护 | 启用 | 正则表达式长度限制 500 字符 |
| 敏感数据脱敏 | 启用 | 日志中不泄露密钥 |
资料来源:docs/AZURE_DEPLOYMENT_SECURITY.md:1-50
5.3 设备代码认证流程
HTTP 服务器支持设备代码认证(device_code flow),适用于无法使用客户端密钥的场景:
# 启动服务器并触发设备代码认证
node dist/index.js --http --device-code
# 输出示例
# To sign in, use a web browser to open the page https://microsoft.com/devicelogin
# and enter the code ABC12345 to authenticate.
认证流程:
sequenceDiagram
participant C as 客户端
participant S as MCP 服务器
participant A as Azure AD
C->>S: 请求 /token (device_code)
S->>A: POST /devicecode
A-->>S: device_code, user_code
S-->>C: 显示 user_code
C->>S: 轮询 /token
Note over C: 用户在浏览器输入 code
C->>A: 用户在 microsoft.com/devicelogin 认证
A-->>S: 返回 tokens
S-->>C: 返回 access_token6. 环境变量配置
6.1 完整环境变量列表
| 环境变量 | 必需 | 默认值 | 说明 |
|---|---|---|---|
MS365_ADMIN_MCP_CLIENT_ID | 是 | - | Azure AD 客户端 ID |
MS365_ADMIN_MCP_CLIENT_SECRET | 是* | - | 客户端密钥 |
MS365_ADMIN_MCP_TENANT_ID | 是 | - | 租户 ID |
MS365_ADMIN_MCP_LOG_DIR | 否 | - | 日志目录 |
MS365_ADMIN_MCP_PORT | 否 | 7000 | HTTP 端口 |
MS365_ADMIN_MCP_HOST | 否 | 0.0.0.0 | 绑定主机 |
MS365_ADMIN_MCP_ALLOWED_CLIENTS | 否 | - | 允许的客户端 |
MS365_ADMIN_MCP_ALLOW_WRITES | 否 | false | 允许写操作 |
MS365_ADMIN_MCP_MAX_RISK_LEVEL | 否 | medium | 最大风险级别 |
MCP_REMOTE_CONFIG_DIR | 否 | ~/.mcp-auth | OAuth 缓存目录 |
*设备代码模式下不需要
6.2 日志配置
Winston 日志默认使用以下路径:
# 容器环境默认日志路径
MS365_ADMIN_MCP_LOG_DIR=/tmp/.ms365-admin-mcp/logs
注意:在 Bicep 模板中已配置为 /tmp/...,避免 rootless 用户在 /nonexistent/.ms365-admin-mcp/logs 出现权限错误。
7. 生产环境检查清单
7.1 部署前检查
- [ ] Azure AD 应用注册已完成
- [ ] 所需 Graph API 权限已获批准
- [ ] 客户端 ID 和租户 ID 已获取
- [ ] 客户端密钥已生成并安全存储
- [ ] 网络策略已配置(允许来自 MCP 客户端的访问)
- [ ] 日志存储已配置
7.2 安全检查清单
- [ ] 使用 HTTPS(生产环境)
- [ ] 配置
allowedClients限制访问 - [ ]
ALLOW_WRITES默认关闭 - [ ] 监控日志中的敏感信息泄露
- [ ] 定期轮换客户端密钥
- [ ] 配置 Key Vault 存储密钥
资料来源:docs/AZURE_DEPLOYMENT_SECURITY.md:50-100
7.3 高可用性配置
# 使用 Azure Container Apps 实现高可用
az containerapp create \
--name mcp-server \
--resource-group <rg-name> \
--environment <env-name> \
--image ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest \
--min-replicas 2 \
--max-replicas 10
8. 故障排除
8.1 常见部署错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
EACCES 日志写入失败 | 权限问题 | 设置 MS365_ADMIN_MCP_LOG_DIR=/tmp/... |
tenant_rejected | 使用了 common 端点 | 改用单租户 organizations 端点 |
Server disconnected | 设备代码认证超时 | 重新启动认证流程 |
| 401 Unauthorized | 客户端密钥过期 | 更新密钥或使用设备代码流 |
8.2 容器日志查看
# 查看容器日志
docker logs mcp-server
# 实时跟踪日志
docker logs -f mcp-server
# 进入容器调试
docker exec -it mcp-server sh
8.3 网络连通性测试
# 测试 Graph API 连通性
curl -v https://graph.microsoft.com/v1.0/$select
# 测试 Token 端点
curl -v -X POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
9. 相关文档
资料来源:[docs/APP_REGISTRATION.md:1-50]()
配置参考
本页面详细说明 ms-365-admin-mcp-server 的所有配置选项,包括环境变量、云端配置、认证方式、预设分组以及风险级别策略。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 环境变量配置
服务器通过环境变量读取 Azure AD 应用注册凭据。支持两种模式:标准环境和 Azure 中国区(21Vianet)。
1.1 必需的环境变量
| 环境变量 | 描述 | 示例 |
|---|---|---|
MS365_ADMIN_MCP_CLIENT_ID | Azure AD 应用程序(客户端)ID | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
MS365_ADMIN_MCP_CLIENT_SECRET | 客户端密钥 | ~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
MS365_ADMIN_MCP_TENANT_ID | Azure AD 租户 ID | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
1.2 云端环境配置
| 环境变量 | 默认值 | 描述 |
|---|---|---|
MS365_ADMIN_MCP_CLOUD | global | 云环境:global(全球版)或 cn(中国区 21Vianet) |
1.3 服务器运行配置
| 环境变量 | 默认值 | 描述 |
|---|---|---|
MS365_ADMIN_MCP_PORT | 3000 | HTTP 服务器监听端口 |
MS365_ADMIN_MCP_HOST | 0.0.0.0 | HTTP 服务器绑定地址 |
MS365_ADMIN_MCP_ALLOW_WRITES | false | 允许执行写入操作 |
MS365_ADMIN_MCP_MAX_RISK_LEVEL | medium | 最大允许风险级别 |
MS365_ADMIN_MCP_PRESET | all | 初始工具预设分组 |
1.4 认证缓存配置
| 环境变量 | 默认值 | 描述 |
|---|---|---|
MCP_REMOTE_CONFIG_DIR | ~/.mcp-auth/mcp-remote-<version>/ | 设备码认证缓存目录 |
AZURE_CLIENT_SECRET | - | Key Vault 密钥保管库模式下的客户端密钥 |
资料来源:src/secrets.ts
2. 云端配置详解
2.1 云环境端点
服务器支持两种 Microsoft 365 云环境:
graph TD
A[启动服务器] --> B{MS365_ADMIN_MCP_CLOUD?}
B -->|global| C[全球版端点]
B -->|cn| D[中国区端点 21Vianet]
C --> E[login.microsoftonline.com]
D --> F[login.partner.microsoftonline.cn]全球版端点:
| 用途 | 端点 URL |
|---|---|
| Microsoft Graph | https://graph.microsoft.com |
| Azure AD 令牌 | https://login.microsoftonline.com |
| Azure Key Vault | https://vault.azure.net |
中国区(21Vianet)端点:
| 用途 | 端点 URL |
|---|---|
| Microsoft Graph | https://microsoftgraph.chinacloudapi.cn |
| Azure AD 令牌 | https://login.partner.microsoftonline.cn |
| Azure Key Vault | https://vault.azure.cn |
资料来源:src/cloud-config.ts:10-45
3. 认证配置
3.1 认证流程
服务器使用 MSAL(Microsoft Authentication Library)的客户端凭据流(Client Credentials Flow)进行身份验证:
sequenceDiagram
participant Client
participant Server
participant Azure AD
Client->>Server: 请求调用工具
Server->>Azure AD: 获取访问令牌 (client_credentials)
Azure AD-->>Server: access_token
Server->>Microsoft Graph: API 请求 + access_token
Microsoft Graph-->>Server: 响应数据
Server-->>Client: 工具执行结果3.2 认证模式
| 模式 | 配置方式 | 说明 |
|---|---|---|
| 环境变量 | MS365_ADMIN_MCP_CLIENT_SECRET | 最简方式,直接明文存储密钥 |
| Key Vault | AZURE_CLIENT_SECRET + Key Vault URI | 生产环境推荐,密钥由 Azure Key Vault 管理 |
资料来源:src/auth.ts
3.3 设备码认证(远程 HTTP 服务器)
对于远程 HTTP 服务器部署,服务器支持 RFC 8628 设备码流:
# 预填充认证缓存
ms-365-admin-mcp-auth --server https://your-host.azurecontainerapps.io/mcp
# 退出码说明
# 0 - 成功
# 1 - 用法错误
# 2 - 网络错误
# 3 - 认证被拒绝
# 4 - 超时
认证缓存位置:~/.mcp-auth/mcp-remote-<version>/,包含:
缓存密钥使用 md5(serverUrl) 计算,与 mcp-remote 的 getServerUrlHash 完全匹配。
4. 工具预设分组
工具预设(Presets)用于按功能域分组暴露管理工具,减少 MCP 客户端需要处理的工具数量。
4.1 可用预设列表
| 预设名称 | 说明 | 包含工具类型 |
|---|---|---|
security | 安全警报、事件、攻击模拟、威胁情报 | Microsoft 365 Defender 相关 |
audit | 审计日志、登录日志、已删除项目 | 目录审计、登录、预配 |
health | 服务健康状况、消息中心公告 | 服务状态、问题、消息 |
reports | 使用报告 | Teams、邮件、SharePoint、OneDrive、M365 应用 |
identity | 身份和访问管理 | 用户、组、角色、设备、PIM、访客用户、外部身份 |
exchange | Exchange 管理 | 邮件追踪、邮箱、收件人 |
intune | Intune 设备管理 | 设备、合规、配置、Autopilot、应用、RBAC |
governance | 标识治理 | 访问评审、权利管理、生命周期工作流、TOU、应用同意 |
compliance | 合规性管理 | 许可证、安全分数、身份保护、风险检测、条件访问 |
response | 事件响应操作 | 禁用用户、撤销会话、确认泄露、 dismissing 风险 |
ediscovery | 电子发现案例 | Microsoft Purview |
cloudpc | Cloud PC / Windows 365 | 云电脑、预配策略、设备镜像 |
callrecords | Teams 通话记录 | 会话、段、参与者、PSTN 通话、Direct Routing |
print | 通用打印 | 打印机、共享、连接器、服务 |
infoprotection | 信息保护 | BitLocker、威胁评估、敏感度标签 |
sharepointadmin | SharePoint 管理 | SharePoint 租户管理 |
retention | 记录管理 | 保留策略、处置工作流 |
teamsadmin | Teams 管理 | 团队、频道、成员、应用、策略 |
all | 所有可用工具 | 全部 515 个工具 |
资料来源:src/tool-categories.ts:1-80
4.2 预设模式匹配规则
每个预设通过正则表达式模式匹配工具名称:
// 示例:identity 预设的匹配模式
/role|directory|domain|auth-method|credential|application|service-principal|sp-password|sp-key|sp-token|sp-owner|oauth2|organization|named-location|device|administrative-unit|cross-tenant|pim|app-role|invitation|identity-provider|b2x|api-connector|custom-auth/i
4.3 组合预设
支持同时启用多个预设:
import { getCombinedPresetPattern } from './tool-categories';
const combined = getCombinedPresetPattern(['security', 'audit']);
// 返回组合后的正则表达式
5. 风险级别策略
5.1 风险级别定义
| 级别 | 含义 | 示例工具 |
|---|---|---|
low | 只读操作,查询类操作 | list-users、get-team |
medium | 有限影响,局部修改 | create-team、update-user |
high | 重大影响,范围广泛或凭证变更 | revoke-user-sessions、update-conditional-access-policy |
critical | 不可逆或租户范围影响 | delete-user、wipe-managed-device、delete-conditional-access-policy |
资料来源:src/risk-level.ts
5.2 风险级别判定逻辑
graph TD
A[工具执行请求] --> B{配置了 riskLevel?}
B -->|是| C[使用配置的 riskLevel]
B -->|否| D{HTTP 方法是 GET?}
D -->|是| E[默认为 low]
D -->|否| F[默认为 critical]
C --> G[与 maxRiskLevel 比较]
E --> G
F --> G
G --> H{rank ≤ maxRiskLevel?}
H -->|是| I[允许执行]
H -->|否| J[拒绝执行]风险等级排序(从小到大):low < medium < high < critical
5.3 关键工具列表
Critical 级别(需要带外审批):
| 工具 | 风险 |
|---|---|
delete-user | critical |
delete-group | critical |
delete-application | critical |
delete-service-principal | critical |
delete-conditional-access-policy | critical |
delete-exchange-mailbox | critical |
delete-ediscovery-case | critical |
delete-team | critical |
delete-managed-device | critical |
wipe-managed-device | critical |
clean-windows-device | critical |
add-directory-role-member | critical |
create-pim-role-assignment-request | critical |
disable-user-account | critical |
High 级别(需要明确确认):
| 工具 | 风险 |
|---|---|
revoke-user-sessions | high |
confirm-compromised-users | high |
dismiss-risky-users | high |
change-user-password | high |
create-conditional-access-policy | high |
delete-named-location | high |
create-auth-strength-policy | high |
6. 端点配置
6.1 端点定义格式
endpoints.json 是工具定义的信任源,每个端点包含:
{
"toolName": "list-users",
"pathPattern": "/users",
"method": "GET",
"appPermissions": ["User.Read.All"],
"llmTip": "可选的提示信息,显示在工具描述中"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
toolName | string | 是 | 工具唯一标识符 |
pathPattern | string | 是 | Microsoft Graph API 路径 |
method | string | 是 | HTTP 方法(GET/POST/PATCH/DELETE) |
appPermissions | string[] | 是 | 所需的应用权限 |
llmTip | string | 否 | 展示给 LLM 的提示信息 |
riskLevel | string | 否 | 风险级别(仅非 GET 方法需要) |
6.2 必需权限示例
7. CLI 命令行参数
7.1 本地模式(Stdio)
ms-365-admin-mcp-server [options]
选项:
--preset <name> 工具预设分组
--allow-writes 允许写入操作
--max-risk-level <level> 最大风险级别 (low/medium/high/critical)
--list-tools 列出指定预设的工具
--list-permissions 列出所需 Graph 权限
--version, -v 显示版本
--help, -h 显示帮助
7.2 HTTP 服务器模式
ms-365-admin-mcp-server --http [options]
HTTP 专用选项:
--port <number> 监听端口 (默认: 3000)
--host <address> 绑定地址 (默认: 0.0.0.0)
7.3 认证引导
ms-365-admin-mcp-auth --server <url> [options]
选项:
-s, --server <url> MCP 服务器 URL(必需)
--scope <scope> 覆盖 OAuth scope
--cache-dir <path> 缓存目录覆盖
8. 本地开发配置
8.1 本地 .env 文件格式
# Azure AD 应用注册
MS365_ADMIN_MCP_CLIENT_ID=your-client-id
MS365_ADMIN_MCP_CLIENT_SECRET=your-client-secret
MS365_ADMIN_MCP_TENANT_ID=your-tenant-id
# 可选:云环境 (默认 global)
MS365_ADMIN_MCP_CLOUD=global
8.2 开发验证命令
# 验证工具列表
node dist/index.js --preset security --list-tools
# 验证所需权限
node dist/index.js --preset identity --list-permissions
# 运行 MCP 检查器
npm run inspector
9. Docker 部署配置
9.1 环境变量配置
docker run -e MS365_ADMIN_MCP_CLIENT_ID=xxx \
-e MS365_ADMIN_MCP_CLIENT_SECRET=xxx \
-e MS365_ADMIN_MCP_TENANT_ID=xxx \
-e MS365_ADMIN_MCP_PORT=3000 \
ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest
9.2 Docker Compose 示例
services:
mcp-server:
image: ghcr.io/okapi-ca/ms-365-admin-mcp-server:latest
environment:
MS365_ADMIN_MCP_CLIENT_ID: "${CLIENT_ID}"
MS365_ADMIN_MCP_CLIENT_SECRET: "${CLIENT_SECRET}"
MS365_ADMIN_MCP_TENANT_ID: "${TENANT_ID}"
MS365_ADMIN_MCP_CLOUD: "global"
MS365_ADMIN_MCP_PORT: "3000"
ports:
- "3000:3000"
10. Azure Container Apps 部署
通过 Bicep 模板部署时,可在 infra/main.bicep 中配置:
// 环境变量通过 Key Vault 引用
MS365_ADMIN_MCP_CLIENT_ID: keyVaultSecret('client-id')
MS365_ADMIN_MCP_CLIENT_SECRET: keyVaultSecret('client-secret')
MS365_ADMIN_MCP_TENANT_ID: keyVaultSecret('tenant-id')
MS365_ADMIN_MCP_CLOUD: 'global'
11. 故障排除配置
11.1 常见配置问题
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 认证失败 | 客户端密钥过期 | 续订 Azure AD 应用密钥 |
| 权限不足 | 缺少 Graph API 权限 | 在 Azure AD 中添加所需权限 |
| 工具不可用 | 预设配置错误 | 使用 --list-tools 验证工具列表 |
| 写入被拒绝 | --allow-writes 未启用 | 添加 --allow-writes 参数 |
11.2 调试日志
服务器使用 Winston 日志记录器,通过设置日志级别环境变量可获取详细调试信息:
# 启用调试日志
DEBUG=ms-365-admin-mcp-server:* ms-365-admin-mcp-server
12. 配置验证清单
部署前请确认以下配置项:
- [ ] Azure AD 应用已注册且
CLIENT_ID、CLIENT_SECRET、TENANT_ID已获取 - [ ] 应用已授权所需 Graph API 权限(使用最小权限原则)
- [ ] 根据部署区域选择正确的
MS365_ADMIN_MCP_CLOUD值 - [ ] 生产环境建议使用 Azure Key Vault 管理密钥
- [ ]
max-risk-level已根据组织安全策略配置 - [ ] 对于远程 HTTP 部署,已运行设备码引导流程
- [ ] 已通过
--list-permissions验证所需权限
资料来源:[src/cloud-config.ts:1-50](https://github.com/okapi-ca/ms-365-admin-mcp-server/blob/main/src/cloud-config.ts)
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
下游已经要求复核,不能在页面中弱化。
用户安装前需要知道权限边界和敏感操作。
Pitfall Log / 踩坑日志
项目:okapi-ca/ms-365-admin-mcp-server
摘要:发现 8 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:能力坑 - 能力判断依赖假设。
1. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 建议检查:将假设转成下游验证清单。
- 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
- 证据:capability.assumptions | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | README/documentation is current enough for a first validation pass.
2. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
- 证据:evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | last_activity_observed missing
3. 安全/权限坑 · 下游验证发现风险项
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:下游已经要求复核,不能在页面中弱化。
- 建议检查:进入安全/权限治理复核队列。
- 防护动作:下游风险存在时必须保持 review/recommendation 降级。
- 证据:downstream_validation.risk_items | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium
4. 安全/权限坑 · 存在安全注意事项
- 严重度:medium
- 证据强度:source_linked
- 发现:No sandbox install has been executed yet; downstream must verify before user use.
- 对用户的影响:用户安装前需要知道权限边界和敏感操作。
- 建议检查:转成明确权限清单和安全审查提示。
- 防护动作:安全注意事项必须面向用户前置展示。
- 证据:risks.safety_notes | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | No sandbox install has been executed yet; downstream must verify before user use.
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 建议检查:把风险写入边界卡,并确认是否需要人工复核。
- 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
- 证据:risks.scoring_risks | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | no_demo; severity=medium
6. 安全/权限坑 · 来源证据:SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)
- 严重度:medium
- 证据强度:source_linked
- 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:SEC-004: UPN persisted in logs without redaction option (PII / GDPR exposure)
- 对用户的影响:可能影响授权、密钥配置或安全边界。
- 建议检查:来源显示可能已有修复、规避或版本变化,说明书中必须标注适用版本。
- 防护动作:不得脱离来源链接放大为确定性结论;需要标注适用版本和复核状态。
- 证据:community_evidence:github | cevd_6ede43fd3f7247e0981524934656dbeb | https://github.com/okapi-ca/ms-365-admin-mcp-server/issues/71 | 来源类型 github_issue 暴露的待验证使用条件。
7. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
- 防护动作:issue/PR 响应未知时,必须提示维护风险。
- 证据:evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | issue_or_pr_quality=unknown
8. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
- 证据:evidence.maintainer_signals | github_repo:1210842314 | https://github.com/okapi-ca/ms-365-admin-mcp-server | release_recency=unknown
来源:Doramagic 发现、验证与编译记录