关于 graph-atlas-mcp
graph-atlas-mcp 跟踪 Microsoft Graph 中已公布及未公布的架构变更,涵盖 Entra 等身份领域的历史记录。开发者和管理员可搜索变更、查看权限与角色关联,并通过交互式 MCP Apps 可视化工具探索关系。
主要功能
- 01按关键词或语义搜索架构变更
- 02按日期和对象筛选变更
- 03查看对象变更历史
- 04关联 Graph 对象、权限与角色
- 05探索可视化架构图
适用场景
- 01检查 Graph API 端点的近期变更
- 02查看 API 对象关联的权限
- 03探索 Entra 角色可访问的内容
MCP 相关
提供 MCP 工具,用于查询 Microsoft Graph 架构变更、快照、权限和角色。MCP Apps 可视化工具可在兼容的 MCP 客户端中展示并探索架构图。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Microsoft Graph Atlas MCP
一个 MCP 服务,用于跟踪 Microsoft Graph API 的架构变更——包括 Microsoft 文档中记录的变更,以及未记录的变更。覆盖完整的 Entra ID、Entra ID Governance、Identity & Access Management、Entra Agent ID 和 Information Protection 范围,发布时已预置一年的历史记录。内置交互式架构可视化工具,通过 MCP Apps 在 MCP 客户端中呈现。

原因
Microsoft Graph 持续在 v1.0 和 beta 版本中演进。官方更新日志经过编辑整理,内容并不完整——未记录的架构变更(新增属性、移除关系、新枚举值)会先于公告进入生产环境。此 MCP 服务每天对实际的 $metadata CSDL 进行差异比较,以弥补这一缺口,并从公共社区跟踪器和官方更新日志中回填一年的历史记录。
数据来源
| 来源 | 内容 | 粒度 |
|---|---|---|
seed-entra-ms | 一次性导入 changes.entra.ms 的历史 CSDL 差异 | 属性级 |
backfill-graph-changelog | 一次性抓取 Microsoft 官方“What's New”历史记录,并归类到 8 个 IAM 对象系列 | 功能级 |
self | 每日获取并比较 $metadata,从首次采集起持续进行 | 属性级 |
另外两个表为每项变更补充实际的权限/角色背景:permissions(从 Merill 的 Graph Permissions Explorer 抓取的 1,036 个范围)和 roles(来自 Microsoft Learn 权限参考的 135 个 Entra 内置角色及其 microsoft.directory/* 操作),并通过 role_permission_map 进行交叉引用。
快速开始(npx)
需要 Node.js 22+(使用内置的 node:sqlite)。将其添加到 MCP 客户端中,例如
Claude Desktop 的 claude_desktop_config.json:
{
"mcpServers": {
"graph-atlas": {
"command": "npx",
"args": ["-y", "graph-atlas-mcp"]
}
}
}
设置就这么简单:首次启动时,服务会自动从此仓库的 GitHub Releases 下载最新发布的
数据库(变更历史、权限、角色、嵌入向量),存入 ~/.graph-atlas-mcp/,
并按照每日发布节奏保持更新。
从源代码开发
git clone https://github.com/darrenjrobinson/graph-atlas-mcp.git
cd graph-atlas-mcp
npm install
npm run build
填充数据库(首次运行)
npm run seed # one-off: import changes.entra.ms's ~1,600 historical records
npm run backfill # re-runnable: scrape the official changelog for the 8 IAM families
npm run collect # fetch v1.0 + beta $metadata, establish today's baseline snapshot
npm run collect-permissions # re-runnable, ~9 min: scrape ~1,036 Graph permission pages
npm run collect-roles # re-runnable, ~1 min: scrape 135 Entra built-in roles + actions
npm run build-role-map # re-runnable: cross-reference roles <-> permissions (see limitations)
这会在项目根目录生成 graph-atlas.db。npm run seed 使用一个被 git 忽略的、
一次性本地脚本(scripts/seed-from-entra-ms.js)——它不属于已提交的仓库。
数据库使用 WAL 日志模式,因此这些采集脚本可以与已打开该文件的 MCP 客户端(例如 Claude Desktop)并发运行,而不会发生锁争用。
可选:语义搜索
如果设置了 OPENAI_API_KEY,search_changes 会自动以混合模式(关键词 + 语义)运行;
否则会退化为仅关键词搜索:
export OPENAI_API_KEY=sk-...
npm run embed # generates embeddings for any change records that don't have one yet
在运行 collect 后重新运行 npm run embed,只会为新记录生成嵌入向量——这是增量操作,而非重新生成全部嵌入向量。
将源代码检出版本连接到 MCP 客户端
开发时,将客户端指向你的构建版本和本地数据库,而非 npm 包:
{
"mcpServers": {
"graph-atlas": {
"command": "node",
"args": ["--experimental-sqlite", "/absolute/path/to/graph-atlas-mcp/dist/index.js"],
"env": {
"GRAPH_ATLAS_DB": "/absolute/path/to/graph-atlas-mcp/graph-atlas.db"
}
}
}
}
GRAPH_ATLAS_DB 将服务指向一个指定的数据库文件。如果未设置,服务会先查找
~/.graph-atlas-mcp/graph-atlas.db(从最新的 GitHub Release 自动下载),然后
回退到当前工作目录中的 ./graph-atlas.db。
工具
| 工具 | 用途 |
|---|---|
search_changes | 使用自然语言或关键词搜索所有来源。配置 OpenAI 密钥后,会通过 Reciprocal Rank Fusion 结合关键词与语义搜索;否则仅进行关键词搜索。 |
get_recent_changes | 结构化查询——按日期、终结点、对象类型/名称、变更类型和来源进行筛选。 |
get_object_history | 查看单个对象(例如 group、accessPackage)的完整变更历史,按时间从早到晚排列。跨来源匹配时不区分大小写。 |
get_change_detail | 查看单条变更记录的完整详情,以及同一天、同一对象的相关变更。 |
get_snapshot_summary | 统计每个快照中的实体、属性和枚举数量——回答“Graph API 现在有多大?” |
get_server_info | 查看服务本身的信息——运行版本、变更日志条目、数据新鲜度,以及两种发布渠道(按日历标记的数据库每日发布与采用 semver 的 npm 服务发布)。 |
get_permission_context | 查看哪些权限会影响某个 Graph 对象、各权限解锁的功能、谁可以授予这些权限(基于启发式判断——参见限制)以及该对象的近期变更。 |
schema_change_report | 提供架构/权限/角色关系图的结构化 JSON(无 UI),包含节点、边和变更活动计数,供推理使用。 |
visualize_schema_graph | 在 MCP 客户端内打开交互式 Graph Atlas 可视化工具(通过 MCP Apps)——这是一个采用 D3 力导向布局的关系图,支持搜索、展开和查看节点详情。详见下文。 |
expand_schema_node | 展开已打开的可视化工具中的一个节点(或向模型提供单节点邻域增量)——为应用的双击/展开交互提供支持。 |
search_schema_objects | 跨实体类型、权限和角色进行名称搜索——将模糊名称解析为规范节点 ID;为应用的搜索框提供支持。 |
get_node_timeline | 仅供应用使用:为可视化工具的详情面板提供简洁的变更时间线(模型改用 get_object_history)。 |
查询示例
- “Agent ID Graph API 最近有哪些变更?”
- “群组 API 是否有关于嵌套的变更?”
- “accessPackageSuggestion 资源的历史记录是什么?”
- “过去 7 天 beta 终结点有哪些变更?”
- “显示敏感度标签或 DLP 策略变更”
架构可视化工具
visualize_schema_graph 会打开 Graph Atlas 可视化工具——这是一个 d3 力导向 SVG 图,借助 MCP Apps 直接在 MCP 客户端中渲染(Claude Desktop、ChatGPT、VS Code 及其他兼容的宿主)。其架构和外观移植自 EntraPulse Polyarchy:
- 深色主题界面(浅色主题会跟随宿主):胶囊式视图标签、玻璃质感面板,以及显示实时节点/边/工具调用计数的底部状态栏。
- 累加式画布 + 会话缓存——探索时,图会不断累加。双击任意节点(或点击面板中的 设为焦点 按钮)即可将上下文切换到该节点:跳数会重新锚定,画布会平滑移动至中心,并展开该节点的邻域。本次会话中已获取的数据会从缓存中即时重新展开,不会重复调用工具。重置 会清空画布,但保留缓存。
- 搜索——工具栏搜索框(由
search_schema_objects提供支持)可按名称匹配实体类型、权限和角色,并将焦点切换到所选项。 - 详情面板——按类型显示字段(实体的属性/导航/更改,权限的应用/委派同意及说明,角色的影响范围/已发布操作/模板 ID),并在面板内显示更改历史时间线(由
get_node_timeline提供支持)。 - 可重新排列的布局——拖动节点后,它会固定在放置位置,因此你可以拉开集群,以便查看密集的邻域;新的展开内容会从其来源节点向外延伸。
- 颜色语义——实体类型根据与焦点的距离使用不同深浅的蓝色;权限和角色使用其关系颜色(绿色表示 涉及/琥珀色表示 授予),并随距离增加而淡化。红色专用于提示:实心红环标记特权角色和管理员同意权限,琥珀色/红色活动点标记近期有更改的实体。图例(左下角)兼作可见性筛选器——取消勾选某种关系或对象类型后,其显示效果会变暗。
- 模型感知——每次切换焦点/展开后,应用都会推送
updateModelContext,让助手无需额外调用工具即可了解屏幕上的内容。
可通过 view(或应用内标签)选择三个切入维度,让你从问题的起点开始——角色、权限或实体/API:
entity——图实体类型;边表示导航属性和继承关系。focus_object= 类似group的实体。在 Permission 标签页中展开实体会显示涉及该实体的权限;在 Role 标签页中则会展开两跳——这些权限 以及授予这些权限的角色(因此,展开user会显示用户管理员、帮助台管理员等角色)。permission——权限范围、它涉及的实体,以及授予它的角色。focus_object= 类似User.Invite.All的权限。role——Entra 角色、它授予的权限,以及这些权限涉及的实体(两跳)。focus_object= 类似User Administrator的角色。这是回答“此角色实际上能做什么”/最小权限比较问题的视图。
运行 npm run build 进行构建(服务端 tsc、app-ui 类型检查,然后由 esbuild 将 app-ui/atlas-app/ 打包为单个自包含文件 dist/app-ui/atlas-app.html——MCP App 资源必须是一个不依赖外部网络的整体;资源 URI 为 ui://graph-atlas/atlas-app.html)。服务端会在启动时读取一次构建后的 HTML,因此重新构建后请重启 MCP 客户端(或服务器连接)。
使用 MCP Jam 进行测试
# published package
npx @mcpjam/inspector@latest npx -y graph-atlas-mcp
# or a source checkout
GRAPH_ATLAS_DB=/absolute/path/to/graph-atlas.db \
npx @mcpjam/inspector@latest node --experimental-sqlite /absolute/path/to/dist/index.js
对于源代码检出,所有路径都必须是绝对路径——MCP Jam 会从自身的工作目录启动服务。需要了解 MCP Jam(v2.34)的两个特性:小组件只会在 MCP Jam 主机配置文件下渲染(“Claude”主机模拟配置文件会导致小组件 iframe 一直停留在“loading”状态);小组件的 Sandbox 选项卡和 debug/widget-visibility 跟踪事件是诊断空白小组件最快的方法。
注意:实体节点 ID 在所有地方都使用小写(accessreview),显示标签则保留 CSDL 的大小写(accessReview)——实体名称在 CSDL 和权限源数据中的大小写并不统一,规范 ID 能确保同一实体在所有视图中始终对应同一个节点。
构建期间发现并修复的实际问题:
- CSDL 中的简写
graph.命名空间别名没有被移除(会悄无声息地产生零条边)。 - Merill 的页面中,
permissions.resources的实体名称大小写并不统一(会悄无声息地将一个实体拆分成两个看起来重复的节点,并在两者之间留下悬空边)。 - MCP Apps 默认启用的
autoResize会根据应用自身文档的内容高度设置 iframe 大小——这对全高弹性布局应用毫无用处。现在应用会禁用此功能并主动申请空间(支持时使用全屏,否则使用较高的内嵌框架)。 - 最初的 force-graph(canvas)实现会在调用
graphData()后同步调用zoomToFit——此时经过防抖的布局尚未分配节点位置,因此会产生 NaN 缩放变换,并导致每次重新渲染时画布永久空白(首次渲染除外)。d3/SVG 移植版消除了这类问题:模拟过程是同步的,居中操作也会跳过尚未定位的节点。 - UI 发送了变更窗口选择器的值(
"30"),而服务端会按字典序比较 ISO 日期,导致所有变更计数都被悄无声息地清零。现在since同时接受这两种格式(天数会在服务端规范化),UI 也会直接转换为 ISO 日期。 - 浏览器会在隐藏的 iframe 中冻结
requestAnimationFrame,因此如果主机隐藏小组件时初始化了图谱,d3 的模拟就无法完成布局——所有节点都会堆叠在原点。现在,新节点会在其展开来源旁获得明确的初始位置;每次结构性渲染都会同步执行一次布局迭代;画布重新可见时,IntersectionObserver会重新加热模拟。 - 即使关闭了
autoResize,某些主机(Claude Desktop 的应用界面)仍会根据应用报告的高度设置 iframe 大小。现在应用会在显示模式协商后始终报告大小,优先使用主机提供的containerDimensions,并在主机上下文发生变化时重新报告。
工作原理
- 每日收集(
.github/workflows/collect.yml,UTC 时间 02:00)会获取两个端点的$metadata——两者都可公开访问,无需注册 Entra 应用。 scripts/parse-csdl.js会将 CSDL XML 解析为结构化 JSON(实体/复杂/枚举类型、属性、导航属性、实体集、单例、函数/操作)。scripts/diff-snapshots.js会将今天的解析结果与snapshots/v1.0/和snapshots/beta/中最新存储的快照进行比较(快照会提交到代码库,作为审计记录)。- 检测到的变更会以
source = 'self'写入graph-atlas.db;如果发现了任何变更,scripts/create-release.js就会发布更新后的 GitHub Release。 - MCP 客户端启动时,如果有比本地缓存更新的最新版本发布,就会自动下载。
已知限制
- 关键词搜索使用基于
LIKE的匹配,并非真正的 BM25——Node 内置的node:sqlite未附带 FTS5 扩展。排序采用简单的词项覆盖率/频率启发式算法。 - 语义搜索需要
OPENAI_API_KEY;向量存储使用 sqlite-vec(内置,无需外部向量数据库)。 $metadata差异比较仅涵盖架构级变更,不包括 CSDL 本身未体现的行为、权限或端点级变更。- 回填的变更日志记录采用功能级描述(“添加了 X 资源类型”),而非种子数据和自行收集的数据中采用的属性级描述——官方变更日志不包含 CSDL 片段。
get_permission_context会限制响应大小。 像user这样的常见对象会匹配 190 多项权限,而像Directory.ReadWrite.All这样的宽泛权限会列出 300 多个端点——测试中,不设上限的响应达到了 417 KB,并导致 MCP 传输连接实际中断。对象名称查询最多返回 25 项权限(按资源数量从少到多排列,limit参数最高为 50),并通过total_matching_count告知是否还有更多结果;每项权限的graph_endpoints最多返回 10 个,并通过graph_endpoints_total_count/graph_endpoints_truncated标明总数和是否截断。筛选特定的permission_name,即可获取某项权限完整且未截断的详情。grantable_by(角色与权限的映射)是启发式关联,并非权威映射。 Microsoft 未发布 Entra RBAC 操作(microsoft.directory/*)与 OAuth 权限范围(User.Read.All等)之间的官方对应关系——它们是两个独立的授权系统,只是恰好管理着部分重叠的资源类型。scripts/build-role-permission-map.js会将某项权限的主要资源(从权限名称推导,例如AdministrativeUnit.Read.All->administrativeUnit)与角色针对同一资源的操作进行匹配。在将grantable_by结果视为权威信息之前,请先进行验证。匹配依据是操作类别(读取/创建/更新/删除/还原/启用/禁用/邀请/许可证/会话/全部),而不是粗略的读取与写入二分法——早期的二分版本曾产生已确认的误报(“Directory Writers”对users有创建/更新/启用/禁用操作,但没有删除/还原操作,却仅因两者都属于“写入级”,就被标记为可授予User.DeleteRestore.All)。Graph 自身的细粒度权限名称(DeleteRestore、EnableDisableAccount、Invite、ReadUpdate等)在设计上与具体操作相对应,因此permissionRequiredCategories()会将每个动词部分映射到满足条件的具体操作类别——已根据 Microsoft 内置角色参考文档,对完整的访客生命周期操作集进行了验证(邀请/创建/更新/启用-禁用/删除-还原 × Guest Inviter/Directory Writers/User Administrator,共 15 种组合,全部精确匹配)。无法识别的/长尾动词(ReadWrite、Write、Manage、FullControl以及约 75 种较少见的 Teams/Chat 特定变体)会回退为“任何修改操作均可满足”——宽泛权限确实可由部分写入能力满足,因此对于这些特定动词,该信号仍较为粗略。- 少数 Entra 角色完全没有发布 RBAC 操作(目前包括三个 Purview Workload Content 角色)——这些角色的权限由 Microsoft Purview 角色组和一款第一方同步应用在 Entra 之外管理,因此无法建立角色与权限的映射。可视化工具和搜索会将其标记为“未发布操作——在 Entra 之外管理”,而不会显示容易误导的“授予 0 项权限”。
- 角色的 Graph API 路由(
GET /roleManagement/directory/roleDefinitions)需要配置了RoleManagement.Read.Directory+Application.Read.All的应用注册,而本项目尚未配置此类注册——因此,collect-roles.js改为采用 PRD 记录的回退方案(抓取公开的 Microsoft Learn 权限参考文档)。 permissions.combined_with(某些端点需要同时具备多个范围,例如Application.Read.All and Policy.Read.All)未填充——Merill 页面的结构无法足够可靠地支持抓取此信息。
致谢
本项目基于 Entra 社区其他成员的数据和设计工作构建,以下将其列为数据来源和灵感来源,而非项目共同作者:
- Eric — changes.entra.ms 的创建者;该 CSDL 差异追踪器为我们的历史变更数据提供种子
- Merill Fernando — Graph Permissions Explorer 的创建者,是权限补充数据(§6)的来源
- EntraPulse Polyarchy — Darren Robinson 先前开发的 MCP;其 d3 力导向图 / MCP Apps 架构(设计系统、会话缓存、上下文切换交互模型)是 Graph Atlas 可视化工具的基础
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。