graph-atlas-mcp について
graph-atlas-mcp は、Entra などの ID 領域を含む Microsoft Graph の公開・未公開のスキーマ変更を履歴とともに追跡します。開発者や管理者は変更を検索し、権限やロールとの関係を確認して、MCP Apps のビジュアライザーで探索できます。
主な機能
- 01キーワードや意味によるスキーマ変更検索
- 02日付やオブジェクトによる変更の絞り込み
- 03オブジェクトの変更履歴確認
- 04Graph オブジェクトと権限・ロールの関連付け
- 05ビジュアルなスキーマグラフの探索
活用シーン
- 01Graph API エンドポイントの最近の変更確認
- 02API オブジェクトに関連する権限の確認
- 03Entra ロールがアクセスできる範囲の探索
MCP 対応
Microsoft Graph のスキーマ変更、スナップショット、権限、ロールを照会する MCP ツールを提供します。MCP Apps ビジュアライザーで、対応する MCP クライアント内からスキーマグラフを表示・探索できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Microsoft Graph Atlas MCP
Microsoft Graph API 全体にわたるスキーマ変更を追跡する MCP サーバーです。Microsoft が文書化している変更と、文書化していない変更の両方を追跡します。Entra ID、Entra ID Governance、Identity & Access Management、Entra Agent ID、Information Protection の全領域を対象としており、公開時点で過去1年分の履歴が登録されています。MCP Apps を介して MCP クライアント内に表示される、インタラクティブなスキーマビジュアライザーも付属しています。

理由
Microsoft Graph は v1.0 と beta の両方で継続的に進化しています。公式の変更履歴は編集されており、不完全です。文書化されていないスキーマ変更(新しいプロパティ、削除されたリレーションシップ、新しい列挙型の値など)は、発表される前に本番環境へ反映されます。この MCP は、実際の $metadata CSDL を毎日比較し、公開コミュニティトラッカーと公式の変更履歴から過去1年分のデータを補完することで、このギャップを埋めます。
データソース
| ソース | 内容 | 粒度 |
|---|---|---|
seed-entra-ms | changes.entra.ms の過去の CSDL 差分を一度だけインポート | プロパティ単位 |
backfill-graph-changelog | Microsoft の公式「What's New」履歴を一度だけスクレイピングし、IAM のオブジェクトファミリー8種類に分類 | 機能単位 |
self | $metadata を毎日取得して差分を比較。初回の収集以降、継続して実施 | プロパティ単位 |
さらに2つのテーブルが、すべての変更に実際のアクセス許可/ロールのコンテキストを付与します。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)を使用します。このスクリプトはコミット済みのリポジトリには含まれていません。
DB は 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 パッケージではなく、ビルドとローカル DB をクライアントに指定します。
{
"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 は、明示的に指定した DB ファイルをサーバーに参照させます。設定されていない場合、サーバーはまず ~/.graph-atlas-mcp/graph-atlas.db(最新の GitHub Release から自動ダウンロード)を探し、次に現在の作業ディレクトリにある ./graph-atlas.db を探します。
ツール
| ツール | 目的 |
|---|---|
search_changes | すべてのソースを対象に、自然言語またはキーワードで検索します。OpenAI キーが設定されている場合はハイブリッド方式(キーワード検索+Reciprocal Rank Fusion によるセマンティック検索)、設定されていない場合はキーワード検索のみです。 |
get_recent_changes | 構造化クエリです。日付、エンドポイント、オブジェクトの種類/名前、変更の種類、ソースで絞り込みます。 |
get_object_history | 1 つのオブジェクト(例:group、accessPackage)の変更履歴全体を、古い順に表示します。すべてのソースを対象に、大文字と小文字を区別せずに照合します。 |
get_change_detail | 1 件の変更レコードの詳細全体と、同じ日付/オブジェクトに関する関連変更を表示します。 |
get_snapshot_summary | スナップショットごとのエンティティ、プロパティ、列挙型の数を表示します。「Graph API は現在どのくらいの規模ですか?」といった質問に使えます。 |
get_server_info | サーバー自体に関する情報(実行中のバージョン、変更履歴のエントリ、データの鮮度、2 つのリリースチャネル(日付タグ付きのデータベースの日次リリースと、semver による npm サーバーリリース))を表示します。 |
get_permission_context | Graph オブジェクトに関係する権限、それぞれの権限で可能になること、付与できるユーザー(ヒューリスティック。制限事項を参照)、および最近の変更を表示します。 |
schema_change_report | スキーマ/権限/ロールのグラフを構造化 JSON(UI なし)で出力します。ノードとエッジ、変更アクティビティの件数を含み、推論に利用できます。 |
visualize_schema_graph | MCP クライアント内で、インタラクティブな Graph Atlas ビジュアライザーを開きます(MCP Apps経由)。検索、展開、ノードごとの詳細表示が可能な D3 の力学ベースのグラフです。以下を参照してください。 |
expand_schema_node | 開いているビジュアライザーのノードを 1 つ展開します(または、モデルに 1 ノードの近傍差分を提供します)。アプリのダブルクリック/展開操作を支えます。 |
search_schema_objects | エンティティの種類、権限、ロールを名前で検索し、曖昧な名前を正規のノード ID に解決します。アプリの検索ボックスを支えます。 |
get_node_timeline | アプリ専用です。ビジュアライザーの詳細パネル用に、簡潔な変更タイムラインを表示します(モデルは代わりに get_object_history を使用します)。 |
クエリの例
- 「Agent ID Graph API の最近の変更は何ですか?」
- 「グループの API に入れ子化に関する変更はありましたか?」
- 「accessPackageSuggestion リソースの履歴はどうなっていますか?」
- 「過去 7 日間に beta エンドポイントで何が変更されましたか?」
- 「機密ラベルまたは DLP ポリシーの変更を表示してください」
スキーマビジュアライザー
visualize_schema_graph は Graph Atlas ビジュアライザーを開きます。これは、MCP Apps
(Claude Desktop、ChatGPT、VS Code などの準拠ホスト)を通じて、MCP クライアント内に直接表示される d3 の力学ベース SVG グラフです。アーキテクチャとルック&フィールは、EntraPulse Polyarchy から移植されています。
- ダークテーマのクローム(ライトテーマはホストに準拠):ピル型のビュータブ、ガラス風パネル、ノード/エッジ/ツール呼び出しのライブ件数を表示する下部ステータスバー。
- 追加型キャンバス+セッションキャッシュ — 探索するにつれてグラフが蓄積されます。任意のノードをダブルクリックするか、パネルの フォーカスに設定 ボタンを押すと、そのノードにコンテキストが切り替わります。ホップ距離が再設定され、キャンバスがノードを中央に表示するよう移動し、その近傍が展開されます。このセッションですでに取得済みの項目は、キャッシュから即座に再展開され、ツール呼び出しの再実行はゼロです。リセットするとキャンバスはクリアされますが、キャッシュは保持されます。
- 検索 — ツールバーの検索ボックス(
search_schema_objectsを使用)で、エンティティの種類、アクセス許可、ロールを名前で検索し、選択した項目にフォーカスを切り替えます。 - 詳細パネル — 種類ごとのフィールド(エンティティの場合はプロパティ/ナビゲーション/変更、アクセス許可の場合はアプリ/委任の同意と説明、ロールの場合は影響範囲/公開アクション/テンプレート ID)に加えて、パネル内に変更履歴のタイムラインを表示します(
get_node_timelineを使用)。 - 配置変更可能なレイアウト — ノードをドラッグするとドロップした場所に固定されるため、密集した近傍を読みやすくするためにクラスターを引き離せます。新たな展開は、展開元のノードから広がります。
- カラー表現 — エンティティの種類はフォーカスからの距離に応じた色合い(青のグラデーション)で表示されます。アクセス許可とロールは関連性を示す色(緑の 関連/琥珀色の 付与)をまとい、距離に応じて色が薄くなります。赤はシグナルとして使われます。赤い実線のリングは特権ロールと管理者の同意が必要なアクセス許可を示し、琥珀色/赤色のアクティビティドットは最近変更されたエンティティを示します。凡例(左下)は表示フィルターも兼ねており、関連性やオブジェクトの種類のチェックを外すと、その項目が薄く表示されます。
- モデル認識 — フォーカスや展開が変わるたびにアプリが
updateModelContextを送信するため、アシスタントは追加のツール呼び出しなしで画面上の内容を把握できます。
質問の起点に合わせて、view(またはアプリ内のタブ)で選べる3つのピボット軸があります。Role、Permission、またはエンティティ/APIから開始できます。
entity— グラフのエンティティの種類。エッジはナビゲーションプロパティと継承を表します。focus_object=groupのようなエンティティ。Permission タブでエンティティを展開すると、それに関連するアクセス許可が表示されます。Role タブでは2ホップ先まで表示され、それらのアクセス許可に加え、それを付与するロールも表示されます(そのため、userを展開すると User Administrator、Helpdesk Administrator などが表示されます)。permission— アクセス許可スコープ、それに関連するエンティティ、およびそれを付与するロール。focus_object=User.Invite.Allのようなアクセス許可。role— Entra ロール、それが付与するアクセス許可、およびそれらが関連するエンティティ(2ホップ先まで)。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)について知っておくべき注意点が2つあります。ウィジェットが表示されるのは MCP Jam ホストプロファイル のみです(「Claude」ホストエミュレーションプロファイルでは、ウィジェットの iframe が「loading」のままになります)。また、ウィジェットが空白になる原因を診断するには、ウィジェットの Sandbox タブと debug/widget-visibility トレースイベントを確認するのが最も手早い方法です。
注意:エンティティノード ID はどこでも小文字(accessreview)ですが、表示ラベルでは CSDL の大文字小文字を維持します(accessReview)。CSDL と権限ソースデータではエンティティ名の大文字小文字が一貫していないため、正規 ID を使うことで、すべてのビューで同じエンティティを1つのノードとして扱えます。
この実装中に検出して修正した実際のバグ:
- CSDL の短縮
graph.名前空間エイリアスが削除されず、エッジがすべて黙ってゼロになっていました。 permissions.resourcesのエンティティ名は Merill のページ間で大文字小文字が一貫しておらず、同じエンティティが見た目の似た2つのノードに分割され、その間に接続先のないエッジができるところでした。- MCP Apps の
autoResize(デフォルトで有効)は、アプリ自身のドキュメントのコンテンツの高さを基に iframe のサイズを決めます。高さ全体を使うフレックスアプリには役立ちません。現在、アプリではこれを無効にし、スペースを明示的に確保します(対応している場合は全画面表示、それ以外の場合は高さのあるインラインフレーム)。 - 元の force-graph(canvas)実装では、
graphData()の直後、デバウンスされたレイアウトによってノードの位置が割り当てられる前に、同期的にzoomToFitを呼び出していました。その結果、ズーム変換が NaN になり、初回以降の再レンダリングで canvas が常に空白になっていました。d3/SVG への移植により、この種のバグを解消しました。シミュレーションは同期的に実行され、中央揃え処理では配置されていないノードを考慮します。 - UI は変更期間ピッカーの値(
"30")を送信していましたが、サーバーは ISO 日付を辞書順で比較していたため、変更数がすべて黙ってゼロになっていました。現在はsinceで両方の形式を受け付け(日数はサーバー側で正規化)、UI も引き続き ISO 日付に変換します。 - ブラウザーは非表示の iframe 内で
requestAnimationFrameを停止するため、ホストがウィジェットを非表示にしている間にグラフを初期化すると、d3 のシミュレーションでレイアウトされず、すべてのノードが原点に重なって表示されていました。新しいノードには展開元の隣に明示的な初期位置を設定し、構造のレンダリングごとにレイアウトを同期的に1回実行します。また、canvas が再び表示されると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 クライアントは、ローカルキャッシュより新しい最新リリースがあれば、起動時に自動でダウンロードします。
既知の制限事項
- キーワード検索では、実際の BM25 ではなく、
LIKEベースの照合を使用します。Node に組み込まれているnode:sqliteには FTS5 拡張機能が含まれていません。ランキングには、単純な用語の網羅率と出現頻度に基づくヒューリスティックを使用します。 - セマンティック検索には
OPENAI_API_KEYが必要です。ベクトルの保存には sqlite-vec を使用します(同梱されており、外部のベクトルデータベースは不要です)。 $metadataの差分検出が対象とするのはスキーマレベルの変更のみです。CSDL 自体に現れない動作、権限、エンドポイントレベルの変更は対象外です。- 遡及入力された変更履歴レコードは、シードデータや自己収集データのようなプロパティレベルではなく、「X リソース型を追加」のような機能レベルの内容です。公式の変更履歴には CSDL フラグメントが含まれていません。
get_permission_contextはレスポンスサイズを制限します。userのような一般的なオブジェクトは 190 件以上の権限に一致し、Directory.ReadWrite.Allのような広範な権限には 300 件以上のエンドポイントが列挙されます。テストでは、上限のないレスポンスが 417KB に達し、実際に 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など)の公式な対応表を公開していません。この 2 つは、たまたま重複するリソース型を管理する別々の認可システムです。scripts/build-role-permission-map.jsは、権限の主なリソース(権限名から導出。例:AdministrativeUnit.Read.All→administrativeUnit)を、同じリソースに対するロールのアクションと照合します。grantable_byの結果を信頼できるものとして扱う前に、必ず確認してください。照合は、単純な「読み取り対書き込み」という大まかな二分法ではなく、操作カテゴリ(read/create/update/delete/restore/enable/disable/invite/license/session/all)に基づきます。以前の二分法によるバージョンでは、誤検出が確認されていました。「Directory Writers」にはusersに対する create/update/enable/disable アクションはありますが、delete/restore アクションはありません。それにもかかわらず、両方が「write-tier」であるというだけで、User.DeleteRestore.Allに対してgrantable_byに表示されていました。Graph の細分化された権限名(DeleteRestore、EnableDisableAccount、Invite、ReadUpdateなど)は、設計上、操作ごとに分かれています。そのため、permissionRequiredCategories()は各動詞セグメントを、それを満たす特定のアクションカテゴリに対応付けます。Microsoft の組み込みロールのリファレンスを使い、ゲストのライフサイクルに関する一連の操作(invite/create/update/enable-disable/delete-restore × Guest Inviter/Directory Writers/User Administrator、計 15 通り)すべてで照合を検証済みです。認識されない動詞や利用頻度の低い動詞(ReadWrite、Write、Manage、FullControl、および Teams/Chat 固有の比較的まれな約 75 種類のバリエーション)では、「何らかの変更アクションがあれば満たす」という判定にフォールバックします。広範な権限は、部分的な書き込み機能でも実際に満たされるため、これらの特定の動詞では、引き続きやや大まかな指標となります。- RBAC アクションが一切公開されていない Entra ロールもあります(現在は Purview Workload Content ロール 3 種類)。これらの権限は、Entra の外部で Microsoft Purview のロールグループとファーストパーティの同期アプリを通じて管理されるため、ロールと権限の対応付けはできません。ビジュアライザーと検索では、「0 件の権限を付与」と誤解を招く表示をするのではなく、「公開されたアクションなし — Entra の外部で管理」と表示します。
- ロールの 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 force-graph/MCP Apps アーキテクチャ(デザインシステム、セッションキャッシュ、コンテキスト切り替えのインタラクションモデル)が、Graph Atlas ビジュアライザーの基盤となっています
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。