mcpField
E
entraadm MCP

entraadm MCP

本地服务
github.com/shigechika安全03 天前更新

关于 entraadm MCP

entraadm MCP 面向 Microsoft Entra ID 管理与无人值守分诊,汇总登录和审计日志,并提供 Azure VM 备份及 Microsoft 365 服务状态查询。工具默认只读;会话撤销需显式启用。

主要功能

  1. 01翻译登录失败代码并聚合失败统计
  2. 02识别密码喷洒及可疑账户迹象
  3. 03查询目录审计和用户 MFA 方法
  4. 04查看 Azure VM 备份、策略及活动
  5. 05检查 Microsoft 365 服务健康状况
  6. 06可选撤销单个账户的登录会话

适用场景

  1. 01调查账户登录失败与密码喷洒
  2. 02排查可能遭入侵的账户和来源 IP
  3. 03巡查目录变更与 MFA 注册情况
  4. 04汇总 VM 备份及 Microsoft 365 事件

MCP 相关

该 MCP 服务向客户端提供固定的 Entra ID、Azure Resource Manager 和 Microsoft 365 查询工具。工具默认只读;仅在设置 ENTRAADM_ENABLE_REVOKE_SESSIONS=1 后,才注册撤销登录会话的写入工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"shigechika-entraadm": {
"command": "uvx",
"args": [
"entraadm-mcp"
]
}
}
}
启动命令uvx entraadm-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypientraadm-mcp1.8.1

工具

9

收录的工具列表 · 更新于 2 天前

此工具无需参数。

详细介绍

entraadm-mcp

English | 日本語

用于 Microsoft Entra ID 登录和审核日志分类处理的 MCP 服务,还能用同一凭据回答早间巡查时会问的两个 Azure 相关问题:我们的 Azure VM 是否已备份?Microsoft 365 当前是否出现故障?服务仅提供只读操作,只有一个可选工具例外,它可以将遭到入侵的帐户从所有位置注销。

为什么不选择 Microsoft 官方的 Microsoft MCP Server for Enterprise

Microsoft 为 Entra ID 数据提供了官方 MCP Server for Enterprise。 它适合坐在键盘前进行交互式管理的管理员,却不适合无人值守的分类处理机器人:

  • 仅支持委托式身份验证。 官方服务不支持仅应用身份验证(客户端凭据),因此无法在服务帐户后以无头模式运行。entraadm-mcp 专为这种场景构建:生产环境使用仅应用身份验证,本地开发时可回退到委托式身份验证(az login)。
  • 通用 Graph 查询工具,而非固定工具集。 官方服务提供一个工具,允许模型针对 Microsoft Graph 构造任意 GET/架构发现调用。这对人工使用很灵活,但难以为自动分类处理配置文件设置允许列表。entraadm-mcp 则提供十五个固定的只读工具(另有一个可选写入工具,见下文)。
  • 不翻译 AADSTS 错误。 登录失败会以原始错误代码返回;分类处理仍需查阅对照表。entraadm-mcp 会为每次登录失败标注代码的实际含义。
  • 不支持跨请求聚合。 Microsoft Graph 本身无法在服务器端按 status/errorCode 筛选登录记录,也没有内置的密码喷洒攻击视图。signin_failure_stats 会在客户端进行聚合,并标记针对多个不同用户发生登录失败的 IP —— 这是 Entra 的按帐户智能锁定机制本身无法检测到的模式。

工具

工具回答的问题
health_checkGraph 是否可访问?此凭据能否读取登录日志?
get_user此账户是否已启用、是否从本地环境同步,以及它有哪些许可证?
signin_logs此用户登录失败(或成功)的原因是什么?AADSTS 代码已翻译。
signin_failure_stats租户范围内的失败汇总:错误代码、用户、应用、源 IP 排名,以及密码喷洒攻击嫌疑对象
signin_success_stats按源 IP 汇总租户范围内的成功登录:多个账户共用的 IP、通过旧式身份验证(SMTP/IMAP)登录成功的情况——可用于发现安全漏洞的视图
compromise_suspects哪些账户可能已被接管:向多个账户发起密码喷洒攻击并成功登录部分账户的外部 IP(spray_breaches);来自用户所在国家以外的成功登录(foreign_successes,通过旧式协议登录时风险较高);以及租户拥有 Entra ID P2 时,Microsoft 标记的风险用户
signin_by_ip来自某个源 IP 的所有登录:谁从该 IP 登录成功、尝试登录过哪些账户,以及登录时间
directory_audits谁在何时更改了目录中的哪些内容(阻止/解除阻止、属性编辑)?
get_user_auth_methods此账户是否实际注册了 MFA?
list_subscriptions此凭据可以查看哪些 Azure 订阅?(ARM)
vm_backup_status哪些 Azure VM 由 Azure Backup 备份?最近一次备份是否成功?是否有过期的恢复点?(ARM)
vm_backup_policiesAzure VM 备份策略的计划和保留设置是什么?(ARM)
vm_activity是有人重启了此 Azure VM,还是 Azure 导致了重启(主机故障、维护)?查看指定时间范围内的活动日志和资源运行状况(ARM)
m365_service_healthMicrosoft 365 服务是否降级?有哪些未解决的事件和公告?
daily_brief一次调用即可汇总 m365_service_health、signin_failure_stats、directory_audits 和 compromise_suspects(计数及排名前 5 项)

以上所有工具均为只读。另有一个会更改状态的工具,默认关闭:

工具功能
revoke_sign_in_sessions在所有位置将一个账户注销(Graph revokeSignInSessions:刷新令牌和会话 Cookie 均会失效)。用于确认账户已遭入侵的情况。仅当 ENTRAADM_ENABLE_REVOKE_SESSIONS=1 时才会注册

此工具会先按精确的 userPrincipalName 查找账户,并拒绝处理来宾账户。 每个结果都包含相同的键,包括 revoked 和 not_covered:它不会禁用账户、重置密码或移除 MFA 方法;已颁发的访问令牌会继续有效,直到过期(通常约一小时)。当 Graph 确认已撤销时,revoked 为 true;未执行任何操作时(拒绝处理、请求发送前超时、Graph 返回 4xx),为 false;结果不确定时(网络错误导致响应丢失、重试后仍收到 5xx、请求发送后超时、成功响应无法读取),为 null。此时再次调用是安全的,因为撤销操作具有幂等性。对于未经过独立审批流程的部署(例如共享网关),请勿设置此开关——这样该工具就不会出现在 tools/list 中。解除账户阻止和重置密码不在此工具的范围内。

这四个 Azure Resource Manager 工具特意放在一个以 Entra 命名的服务中:它们使用相同的应用注册和 azure-identity 凭据对象(第二个令牌范围 https://management.azure.com/.default),在同一部署中运行,并由同一个 health_check 检查。为这些工具单独设置一个服务会增加一倍的运维负担。它们用于治理查询,而非资源管理;对于凭据没有 Reader 角色的订阅,list_subscriptions 不会显示该订阅。

身份验证模式

根据设置的环境变量选择两种身份验证模式:

模式条件环境变量
仅应用三个变量均已设置ENTRAADM_TENANT_ID、ENTRAADM_CLIENT_ID、ENTRAADM_CLIENT_SECRET
azure-cli均未设置(使用当前的 az login 会话)

仅设置三个仅应用变量中的一个或两个属于配置错误,服务会拒绝启动,而不会悄然回退到非预期的其他身份验证模式。

必需的 Graph 权限
工具权限备注
get_user(基本字段)User.Read.All
signin_logs、signin_failure_stats、signin_success_stats、compromise_suspects、signin_by_ip、directory_audits、get_user 的 sign_in_activity 字段AuditLog.Read.All(仅应用)或 Reports Reader 目录角色(委托)
get_user_auth_methodsUserAuthenticationMethod.Read.All仅应用;在典型的租户角色分配中,委托(az login)身份验证不可用
m365_service_health、daily_brief 的 service_health 部分ServiceHealth.Read.All使用委托身份验证时,已登录用户还需要一个可读取服务运行状况的 Entra 角色(例如 Service Support Administrator 或 Global Reader)
compromise_suspects 的 microsoft_risky_users、identity_protection 探测(health_check、daily_brief)IdentityRiskyUser.Read.All可选。Identity Protection 需要 Entra ID P2:如果未获得该许可证,Graph 会返回 403「未获许可」,探测结果会报告 not_licensed;其他内容不受影响
revoke_sign_in_sessions(选择启用)User.RevokeSessions.All(仅应用)或 User Administrator / Helpdesk Administrator 目录角色(委托;对于管理员帐户,需 Privileged Authentication Administrator)仅在 ENTRAADM_ENABLE_REVOKE_SESSIONS=1 时启用。这是一项写入权限:仅向需要此工具的部署授予该权限。执行前的帐户查询需要 User.Read.All。如果没有该权限,工具会针对当前使用的身份验证模式返回 missing_permission,且不会进行任何更改
所需的 Azure RBAC
工具角色备注
list_subscriptions无列出凭据可见的所有订阅;空列表表示尚未在任何位置授予角色
vm_backup_status、vm_backup_policies、vm_activity每个订阅都需要 ReaderReader 是 */read,涵盖所有用到的终结点。仅有 Backup Reader 不够(它没有 Microsoft.Compute/virtualMachines/read)。授予服务主体(仅应用模式)或已登录用户(azure-cli)

Azure RBAC 是可选的:health_check 会将 ARM 可达性和可见订阅数量作为信息性的 arm 探测结果报告,但不会改变 status,因此仅用于 Entra 问题排查的部署仍会保持 healthy。

缺少权限不会导致工具崩溃。相应工具(或单个字段)会降级为 {"error": "...", "missing_permission": "..."},并提供所需角色或权限的人类可读说明,因此即使尚未授予完整权限,health_check 和所有其他工具仍可使用。

Identity Protection(Entra ID P2)。 如果租户已开通此功能,compromise_suspects 会添加 Microsoft 自己的风险判定:通过轻量级的 riskyUsers?$top=1 探测来对每个租户进行分类,结果可能是 licensed、not_licensed(403“未获许可”:没有 Entra ID P2)、no_permission(其他 403:没有 IdentityRiskyUser.Read.All)或 error;licensed 和 not_licensed 会缓存一小时(如果请求返回 200,但行中的 riskLevel: hidden,也表示没有 P2)。此处会探测终结点本身:/subscribedSkus 可能被拒绝访问,而且即使能获取 SKU 列表,仍需将其映射到 P2。health_check 会按租户报告此状态,但不会改变 status;daily_brief 也会在每个租户的摘要中报告此状态,因此会注意到 P2 开通的那一天。已获许可时:microsoft_risky_users 会列出未解决的高风险用户(atRisk / confirmedCompromised),并单独列出中风险用户,同时标记那些也出现在 spray_breaches / foreign_successes 中的用户。此时,counts 统计所有发现中的不同账户,之后才会截断列表:high 包含此处或 Microsoft 高风险列表中的任何高风险账户;medium 包含此处或 Microsoft 中风险列表中的任何中风险账户,但不包括高风险账户(counts.microsoft_high / microsoft_medium 表示 Microsoft 列表中的数量)。否则,该部分会显示为 {available: false, reason},其他内容不变——切勿将其解读为“没有高风险用户”。

设置

uv tool install entraadm-mcp
# or
pip install entraadm-mcp

配置

生产环境或无人值守使用时,请设置以下三个仅应用模式变量:

export ENTRAADM_TENANT_ID=00000000-0000-0000-0000-000000000000
export ENTRAADM_CLIENT_ID=00000000-0000-0000-0000-000000000000
export ENTRAADM_CLIENT_SECRET=your-client-secret

或者将这三个变量全部留空,并在本地开发时先运行 az login。

可选项:

# Default page cap for the log-scanning tools (1-50, default 50).
export ENTRAADM_MAX_PAGES_DEFAULT=50
# Wall-clock budget per tool call in seconds (default 45; 0 disables). A hosted MCP
# client cuts a call off at about 60 s, so a scan stops at the budget and returns
# what it has with capped=true.
export ENTRAADM_DEADLINE=45
# Your own address ranges (NAT egress, offices, labs). Spray suspects inside them are
# listed separately as internal_spray_suspects, labelled with the site.
export ENTRAADM_SITES_INI=/path/to/sites.ini
# The countries your users sign in from (assigned ISO 3166-1 alpha-2 codes). compromise_suspects
# reports successes from elsewhere; unset or with an invalid code, that list is skipped.
export ENTRAADM_HOME_COUNTRIES=JP
# Register revoke_sign_in_sessions, the one state-changing tool (exactly "1"; anything
# else leaves it off). Also needs the User.RevokeSessions.All permission.
export ENTRAADM_ENABLE_REVOKE_SESSIONS=1
# Serve several tenants from one process (see "Several tenants" below).
export ENTRAADM_CONFIG=/path/to/tenants.ini

ENTRAADM_SITES_INI 的格式与 keycloak-mcp 的 KEYCLOAK_SITES_INI 相同,因此一个文件即可供两者使用(参见 sites.ini.example)。查找时采用最长前缀匹配。若已设置该文件但无法读取,health_check 会报告 degraded,此时每个 IP 都会被视为外部 IP。无效 CIDR 也会以相同方式报告,但仍会使用有效范围。

多个租户

单个进程可以服务多个 Entra 租户,就像 gwsadm-mcp 可以服务多个 Workspace 域一样。将 ENTRAADM_CONFIG 指向一个 INI 文件,并为每个租户设置一个 [tenant.<name>] 部分:

[tenant.staff]
tenant_id = 00000000-0000-0000-0000-000000000001
domains = example.edu
default = true

[tenant.students]
tenant_id = 00000000-0000-0000-0000-000000000002
domains = students.example.edu
; optional: an app registration of its own instead of the shared one
; client_id = 00000000-0000-0000-0000-000000000003
; client_secret_env = ENTRAADM_STUDENTS_CLIENT_SECRET
键必填含义
tenant_id是租户 ID(GUID)或其域名(包含句点,例如 contoso.onmicrosoft.com);不接受 common、organizations 和 consumers
domains是以逗号分隔的 UPN 域名列表,将其路由到此租户(精确匹配,不区分大小写)
default多个部分时,需在其中一个部分设置未指定租户的调用所使用的租户;如果只有一个部分,则该部分默认即为默认租户
client_id + client_secret_env否;两者要么都设置,要么都不设置使用专属应用;client_secret_env 指定存放其密钥的环境变量。切勿将密钥放入文件中
未设置 client_id 的区段会复用环境应用(ENTRAADM_CLIENT_ID /
ENTRAADM_CLIENT_SECRET),并从该区段对应的租户请求令牌;如果没有环境应用,则会在该租户中使用 az login。设置 ENTRAADM_CONFIG 时不会使用 ENTRAADM_TENANT_ID。取消设置 ENTRAADM_CONFIG 后,单租户配置会保持不变。

要在多个租户间共用一个应用,请将应用注册设为多租户(支持的帐户类型:任何组织目录中的帐户),添加相同的 Graph 应用程序权限,然后让其他每个租户的管理员授予管理员同意:

https://login.microsoftonline.com/<tenant-id>/adminconsent?client_id=<app-id>

如果文件不可读、包含非 [tenant.*] 区段或未知键、缺少 tenant_id 或 domains、tenant_id 既不是 GUID 也不是点分域名、将同一个域名分配给两个租户,或者多个租户中没有默认租户(或有两个默认租户),服务将拒绝启动,且 --check 会失败。--check 会探测每个租户。

路由:

  • 接受 UPN 的工具(get_user、get_user_auth_methods、signin_logs、 revoke_sign_in_sessions,以及指定了 user 时的 directory_audits)会在其 domains 包含该 UPN 域名的租户中运行(精确匹配)。如果没有租户认领该域名,则会拒绝请求,而非引发异常:tenant_configured: false、found: null(未运行查找)以及 configured_domains。对于 revoke_sign_in_sessions:revoked: false、found: null,不会发送任何内容。如果经常查找此类 UPN,请将 <tenant>.onmicrosoft.com 列入 domains。
  • get_user、get_user_auth_methods 和 signin_logs 也接受 tenant,它优先于 UPN 的域名:适用于 *.onmicrosoft.com 或 #EXT# UPN,或登录记录保存在主机租户中的 B2B 来宾。 revoke_sign_in_sessions 有意不提供此类覆盖:写入操作只会针对拥有该 UPN 域名的租户。
  • 面向整个租户的工具(signin_failure_stats、signin_success_stats、compromise_suspects、signin_by_ip、directory_audits、m365_service_health)接受可选的 tenant;默认使用默认租户。如果 directory_audits 同时指定了 tenant 和一个域名被其他租户认领的 user,请求会被拒绝(这会在错误的日志中搜索,且一无所获);如果 user 的域名未被任何租户认领(外部或合作伙伴管理员、来宾),则会在指定租户或默认租户中搜索,并在结果中显示 user_domain_claimed: false。
  • tenant 可以是区段名称、其域名或租户 ID。没有租户文件时,它可以是 default 或环境中的租户 ID;其他值都会被拒绝(tenant_configured: false)。
  • health_check 和 daily_brief 会涵盖每个租户。其顶层键仍与之前一样,属于默认租户;tenant 指明该租户,tenants 包含各租户的结果。调用预算(ENTRAADM_DEADLINE)会在租户间平均分配(先处理默认租户,每个租户使用剩余预算的一份),因此响应缓慢的租户不会拖住其他租户;未能响应的租户会在其对应条目中标记为 error,并使 health_check 的 status 最高只能为 degraded。设置 ENTRAADM_DEADLINE=0 时没有预算限制:会依次完整扫描每个租户,这可能超过客户端约 60 秒的超时限制。
  • Azure Resource Manager 工具(list_subscriptions、vm_backup_status、 vm_backup_policies、vm_activity)仅服务默认租户。
  • 使用租户文件时,每个结果都会注明其 tenant(ARM 工具为默认租户;未选定租户的拒绝结果为 null)。仅使用环境变量时,结果保持不变,但 revoke_sign_in_sessions 始终会包含 tenant、tenant_configured 和 configured_domains(其键始终固定)。

使用方法

Claude Code(插件)
/plugin marketplace add shigechika/entraadm-mcp
/plugin install entraadm-mcp@entraadm-mcp
Claude Code(手动配置)

添加到 .mcp.json:

{
  "mcpServers": {
    "entraadm-mcp": {
      "type": "stdio",
      "command": "uvx",
      "args": ["entraadm-mcp"],
      "env": {
        "ENTRAADM_TENANT_ID": "${ENTRAADM_TENANT_ID:-}",
        "ENTRAADM_CLIENT_ID": "${ENTRAADM_CLIENT_ID:-}",
        "ENTRAADM_CLIENT_SECRET": "${ENTRAADM_CLIENT_SECRET:-}"
      }
    }
  }
}
Codex
codex mcp add entraadm-mcp \
  --env ENTRAADM_TENANT_ID=your-tenant-id \
  --env ENTRAADM_CLIENT_ID=your-client-id \
  --env ENTRAADM_CLIENT_SECRET=your-client-secret \
  -- uvx entraadm-mcp

任何其他能启动 stdio 服务的 MCP 客户端也可采用相同方式:将 uvx entraadm-mcp 设为命令,并在其环境中设置配置中的 ENTRAADM_* 变量。

直接执行
entraadm-mcp
CLI 选项
选项效果
--version打印版本并退出
--check解析身份验证、探测 Graph 可达性和登录日志访问权限,打印报告(以及一行信息性 ARM 内容),退出码为 0(配置错误时为 1)

注意事项

  • 覆盖范围约定。 遍历分页 Graph 集合的每个结果,若未完整扫描其窗口,则会带有一个 capped 布尔值——部分扫描绝不会被报告为穷尽扫描。
  • found: false 不是错误。 对于不存在的账户,get_user 和 get_user_auth_methods 会返回 {"found": false, ...},而不是 error 键——userPrincipalName 中的拼写错误不应让人误以为此服务已损坏。
  • 保留期限。 Entra ID P1 会将登录和目录审核日志保留 30 天。超出此期限的时间窗口会返回空结果,而不是错误。

开发

uv sync --dev
uv run pytest -v
uv run ruff check .
uv run ruff format --check .
实时冒烟测试
uv run python scripts/smoke_test.py

只读(即使启用,也会按名称跳过 revoke_sign_in_sessions),不打印任何负载(仅显示工具名称、状态和行数),且范围有限(明确指定较小的时间窗口和分页上限)——此处不会对租户进行写入,也不会扫描超过一天的日志。

发布

此仓库使用由 Conventional Commits 驱动的 release-please。将 feat:/fix: PR 合并到 main 后,release-please 会创建或更新发布 PR;合并该 PR 后会为版本打标签,并触发发布流水线(PyPI、MCP Registry)。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。