graph-atlas-mcp
This server provides a comprehensive toolset for exploring and analyzing the Microsoft Graph API's schema and change history, enriched with permission and role context.
Search & Query: Perform natural-language or keyword search across all historical changes (hybrid semantic+keyword with OpenAI key, keyword-only otherwise), and query recent changes with structured filters (date range, endpoint, object type/name, change kind, source).
Historical Analysis: Retrieve full change history for any Graph object, get detailed info on a single change (including related changes and permission context), and compare snapshot summaries (entity/property/enum counts) over time.
Permission & Role Insights: Investigate which permissions touch a given object or which objects a permission affects, see which Entra roles can grant permissions, and compare permission scopes for least-privilege alternatives.
Interactive Visualization: Open a D3 force-directed graph (via MCP Apps) to explore entities, permissions, or roles visually, with node expansion, search, and compact change timelines per node.
Data Export: Generate structured JSON reports of the schema, permission, or role graphs (nodes + edges + change activity counts) for programmatic analysis.
Name Resolution: Resolve fuzzy object names to canonical IDs for use in visualizations or tool calls.
Coverage includes ~1 year of backfilled history from daily CSDL diffs, community sources, and official changelogs, encompassing documented and undocumented changes across 1,036 permission scopes and 135 built-in Entra roles.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@graph-atlas-mcpShow me recent changes to the calendar event schema."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Microsoft Graph Atlas MCP
An MCP server that tracks schema changes across the Microsoft Graph API — both the changes Microsoft documents and the ones it doesn't. Covers the full Entra ID, Entra ID Governance, Identity & Access Management, Entra Agent ID, and Information Protection surface, seeded with a year of history at launch. Ships with an interactive schema visualiser rendered inside the MCP client via MCP Apps.

Why
Microsoft Graph evolves continuously across v1.0 and beta. The official changelog is curated and incomplete — undocumented schema changes (new properties, removed relationships, new enum values) land in production before they're announced. This MCP closes that gap by diffing the actual $metadata CSDL daily, and backfills a year of history from both a public community tracker and the official changelog.
Related MCP server: ms-365-admin-mcp-server
Data sources
Source | What it is | Granularity |
| One-time import of changes.entra.ms's historical CSDL diffs | Property-level |
| One-time scrape of Microsoft's official "What's New" history, classified into 8 IAM object families | Feature-level |
| Daily | Property-level |
Two further tables enrich every change with real-world permission/role context: permissions (1,036 scopes scraped from Merill's Graph Permissions Explorer) and roles (135 Entra built-in roles and their microsoft.directory/* actions, from the Microsoft Learn permissions reference), cross-referenced into role_permission_map.
Quick start (npx)
Requires Node.js 22+ (uses the built-in node:sqlite). Add to your MCP client — e.g.
Claude Desktop's claude_desktop_config.json:
{
"mcpServers": {
"graph-atlas": {
"command": "npx",
"args": ["-y", "graph-atlas-mcp"]
}
}
}That's the whole setup: on first launch the server auto-downloads the latest published
database (change history, permissions, roles, embeddings) from this repo's GitHub Releases
into ~/.graph-atlas-mcp/, and keeps it current against the daily release cadence.
Developing from source
git clone https://github.com/darrenjrobinson/graph-atlas-mcp.git
cd graph-atlas-mcp
npm install
npm run buildPopulate the database (first run)
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)This produces graph-atlas.db in the project root. npm run seed uses a gitignored,
one-off local script (scripts/seed-from-entra-ms.js) — it isn't part of the committed repo.
The DB uses WAL journal mode so these collection scripts can run concurrently with an MCP client that already has the file open (e.g. Claude Desktop) without lock contention.
Optional: semantic search
search_changes runs in hybrid (keyword + semantic) mode automatically if OPENAI_API_KEY
is set, and degrades to keyword-only otherwise:
export OPENAI_API_KEY=sk-...
npm run embed # generates embeddings for any change records that don't have one yetRe-running npm run embed after a collect only embeds new records — it's incremental, not a full re-embed.
Connect a source checkout to an MCP client
When developing, point the client at your build and local DB instead of the npm package:
{
"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 points the server at an explicit DB file. Without it, the server looks for
~/.graph-atlas-mcp/graph-atlas.db (auto-downloaded from the latest GitHub Release), then
falls back to ./graph-atlas.db in the current working directory.
Tools
Tool | Purpose |
| Natural-language or keyword search across all sources. Hybrid (keyword + semantic via Reciprocal Rank Fusion) when an OpenAI key is configured, keyword-only otherwise. |
| Structured query — filter by date, endpoint, object type/name, change kind, source. |
| Full change history for one object (e.g. |
| Full detail for a single change record, plus related changes from the same day/object. |
| Entity/property/enum counts per snapshot — "how big is Graph API right now?" |
| About the server itself — running version, changelog entry, data freshness, and the two release channels (daily calendar-tagged database releases vs semver npm server releases). |
| Which permissions touch a Graph object, what each unlocks, who can grant them (heuristic — see limitations), and its recent changes. |
| Structured JSON (no UI) of the schema/permission/role graph — nodes + edges + change-activity counts, for reasoning over. |
| Opens the interactive Graph Atlas visualiser inside the MCP client (via MCP Apps) — a D3 force-directed graph with search, expand, and per-node detail. See below. |
| Expands one node of the open visualiser (or feeds the model a one-node neighborhood delta) — powers the app's double-click/Expand interactions. |
| Name search across entity types, permissions, and roles — resolves fuzzy names to canonical node ids; powers the app's search box. |
| App-only: compact change timeline for the visualiser's detail panel (the model uses |
Example queries
"What are the recent changes to Agent ID Graph APIs?"
"Have there been changes to groups APIs for nesting?"
"What's the history of the accessPackageSuggestion resource?"
"What changed in the last 7 days on the beta endpoint?"
"Show me sensitivity label or DLP policy changes"
Schema visualiser
visualize_schema_graph opens the Graph Atlas visualiser — a d3 force-directed SVG graph rendered
directly inside the MCP client via MCP Apps
(Claude Desktop, ChatGPT, VS Code, and other compliant hosts). Its architecture and look & feel are
ported from EntraPulse Polyarchy:
Dark-themed chrome (light theme follows the host): pill view tabs, glass panels, a bottom status bar with live node/edge/tool-call counts.
Additive canvas + session cache — the graph accumulates as you explore. Double-click any node (or the panel's Set as focus button) to flip context to it: hop distances re-anchor, the canvas glides to center it, and its neighborhood expands. Anything already fetched this session re-expands instantly from cache with zero repeat tool calls. Reset clears the canvas but keeps the cache.
Search — the toolbar search box (backed by
search_schema_objects) matches entity types, permissions, and roles by name and flips focus to your pick.Detail panel — per-kind fields (properties/navigations/changes for entities, split app/delegated consent + description for permissions, blast radius/published actions/template id for roles), plus an in-panel change-history timeline (backed by
get_node_timeline).Rearrangeable layout — drag a node and it stays pinned where you drop it, so you can pull clusters apart to read dense neighborhoods; new expansions bloom out of the node they came from.
Color language — entity types shade by distance from the focus (blue ramp); permissions and roles wear their relationship colour (green touches / amber grants), faded with distance. Red is reserved as a signal: a solid red ring marks privileged roles and admin-consent permissions, and an amber/red activity dot marks recently-changed entities. A legend (bottom-left) doubles as a visibility filter — unchecking a relationship or object type dims it.
Model awareness — the app pushes
updateModelContextafter every focus/expansion, so the assistant knows what's on screen without extra tool calls.
Three pivot dimensions, chosen via view (or the in-app tabs) so you can start wherever the
question starts — a Role, a Permission, or an entity/API:
entity— Graph entity types; edges are navigation properties and inheritance.focus_object= an entity likegroup. Expanding an entity on the Permission tab reveals the permissions that touch it; on the Role tab it goes two hops — those permissions plus the roles that grant them (so expandingusersurfaces User Administrator, Helpdesk Administrator, and friends).permission— a permission scope, the entities it touches, and the roles that grant it.focus_object= a permission likeUser.Invite.All.role— an Entra role, the permissions it grants, and the entities those touch (two hops).focus_object= a role likeUser Administrator. This is the one that answers "what can this role actually do" / least-privilege comparison questions.
Build it with npm run build (server tsc, an app-ui typecheck, then esbuild bundles
app-ui/atlas-app/ into a single self-contained dist/app-ui/atlas-app.html — MCP App resources
must be one blob with no external network dependencies; the resource URI is
ui://graph-atlas/atlas-app.html). The server reads the built HTML once at startup, so restart
your MCP client (or the server connection) after rebuilding.
Testing with 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.jsFor source checkouts all paths must be absolute — MCP Jam spawns the server from its own
working directory. Two
MCP Jam (v2.34) quirks to know about: widgets only render under the MCP Jam host profile
(the "Claude" host-emulation profile leaves the widget iframe stuck at "loading"), and the
widget's Sandbox tab / debug/widget-visibility trace events are the fastest way to diagnose a
blank widget.
Note: entity node ids are lowercase everywhere (accessreview), with display labels keeping CSDL
casing (accessReview) — entity names aren't consistently cased across the CSDL and the
permission source data, and a canonical id is what lets one entity stay one node across all views.
Real bugs caught and fixed while building this:
CSDL's short
graph.namespace alias wasn't stripped (silently produced zero edges).permissions.resourcesentity names aren't consistently cased across Merill's pages (would have silently split one entity into two duplicate-looking nodes with a dangling edge between them).MCP Apps'
autoResize(on by default) sizes the iframe off the app's own document content height — useless for a full-height flex app. The app now disables it and claims space explicitly (fullscreen where supported, a tall inline frame otherwise).The original force-graph (canvas) implementation called
zoomToFitsynchronously aftergraphData()— before the debounced layout had assigned node positions — producing a NaN zoom transform and a permanently blank canvas on every re-render after the first. The d3/SVG port eliminates the bug class: the simulation is synchronous and centering guards unplaced nodes.The UI sent its change-window picker values (
"30") where the server compares ISO dates lexicographically, silently zeroing every change count.sincenow accepts both (day counts are normalized server-side) and the UI converts to ISO dates anyway.Browsers freeze
requestAnimationFramein hidden iframes, so a graph seeded while the host had the widget hidden never got laid out by d3's simulation — every node rendered stacked at the origin. New nodes now get explicit starting positions next to their expansion source, every structural render ticks the layout synchronously once, and anIntersectionObserverreheats the simulation when the canvas becomes visible again.With
autoResizeoff, some hosts (Claude Desktop's app surface) still size the iframe from the app's reported height — the app now always reports a size after display-mode negotiation, using the host'scontainerDimensionswhen published, and re-reports on host-context changes.
How it works
Daily collection (
.github/workflows/collect.yml, 02:00 UTC) fetches$metadatafor both endpoints — both are publicly accessible, no Entra app registration required.scripts/parse-csdl.jsparses the CSDL XML into structured JSON (entity/complex/enum types, properties, navigation properties, entity sets, singletons, functions/actions).scripts/diff-snapshots.jscompares today's parse against the most recent stored snapshot insnapshots/v1.0/andsnapshots/beta/(committed to the repo as the audit trail).Detected changes are inserted into
graph-atlas.dbwithsource = 'self'; if any changes were found,scripts/create-release.jspublishes an updated GitHub Release.MCP clients auto-download the latest release on startup if newer than their local cache.
Known limitations
Keyword search uses
LIKE-based matching, not real BM25 — Node's bundlednode:sqlitedoesn't ship the FTS5 extension. Ranking is a simple term-coverage/frequency heuristic.Semantic search requires
OPENAI_API_KEY; vector storage uses sqlite-vec (bundled, no external vector DB).$metadatadiffing covers schema-level changes only — not behavioral, permission, or endpoint-level changes that don't show up in the CSDL itself.Backfilled changelog records are feature-level ("Added the X resource type"), not property-level like the seed and self-collected data — the official changelog doesn't include CSDL fragments.
get_permission_contextcaps response size. A common object likeusermatches 190+ permissions, and broad permissions likeDirectory.ReadWrite.Alllist 300+ endpoints — an uncapped response hit 417KB in testing and caused a real MCP transport disconnect. Object-name queries are capped to 25 permissions (narrowest-first by resource count,limitparam up towith
total_matching_counttelling you if more exist; each permission'sgraph_endpointsis capped to 10 withgraph_endpoints_total_count/graph_endpoints_truncated. Filter to a specificpermission_nameto get one permission's full, untruncated detail.
grantable_by(role<->permission mapping) is a heuristic correlation, not an authoritative mapping. Microsoft doesn't publish an official crosswalk between Entra RBAC actions (microsoft.directory/*) and OAuth permission scopes (User.Read.All, etc.) — they're two separate authorization systems that happen to govern overlapping resource types.scripts/build-role-permission-map.jsmatches a permission's primary resource (derived from its own name, e.g.AdministrativeUnit.Read.All->administrativeUnit) against roles' actions on that same resource. Verifygrantable_byresults before treating them as authoritative. Matching is by operation category (read/create/update/delete/restore/enable/disable/invite/ license/session/all), not a coarse read-vs-write binary — an earlier binary version produced a confirmed false positive ("Directory Writers" has create/update/enable/disable actions onusersbut no delete/restore action, yet appeared grantable_by forUser.DeleteRestore.Allsimply because both were "write-tier"). Graph's own granular permission names (DeleteRestore,EnableDisableAccount,Invite,ReadUpdate, ...) are operation-specific by design, sopermissionRequiredCategories()maps each verb segment to the specific action categories that satisfy it — verified against Microsoft's built-in roles reference across the full guest-lifecycle operation set (invite/create/update/enable-disable/delete-restore × Guest Inviter/Directory Writers/User Administrator, all 15 combinations exact). Unrecognized/ long-tail verbs (ReadWrite,Write,Manage,FullControl, and ~75 rarer Teams/Chat-specific variants) fall back to "any mutate action satisfies" — a broad permission genuinely is satisfied by partial write capability, so this remains a coarser signal for those specific verbs.A few Entra roles publish no RBAC actions at all (currently the three Purview Workload Content roles) — their permissions are managed outside Entra via Microsoft Purview role groups and a first-party sync app, so no role↔permission mapping is possible. The visualiser and search label these "no published actions — managed outside Entra" rather than showing a misleading "grants 0 permissions".
Roles' Graph API route (
GET /roleManagement/directory/roleDefinitions) requires an app registration withRoleManagement.Read.Directory+Application.Read.Allthat this project doesn't have configured —collect-roles.jsuses the PRD's documented fallback (scraping the public Microsoft Learn permissions reference) instead.permissions.combined_with(some endpoints require multiple scopes together, e.g.Application.Read.All and Policy.Read.All) isn't populated — Merill's page structure doesn't expose this reliably enough to scrape.
Acknowledgments
This project builds on data and design work from others in the Entra community — credited here as data sources and inspiration, not as project co-authors:
Eric — creator of changes.entra.ms, the CSDL-diff tracker that seeds our historical change data
Merill Fernando — creator of the Graph Permissions Explorer, the data source for permission enrichment (§6)
EntraPulse Polyarchy — Darren Robinson's own prior MCP; its d3 force-graph / MCP Apps architecture (design system, session cache, context-flip interaction model) is the foundation of the Graph Atlas visualiser
License
MIT
Available Tools
12 toolsexpand_schema_nodeA
Expand one node of the schema graph and return a {nodes, edges, message} delta to merge into the canvas — the interactive companion to visualize_schema_graph. kind="EntityType" with view="entity" returns the schema neighborhood (navigation targets, base type, referrers); with view="permission" the permissions that touch the entity; with view="role" those permissions plus the roles granting them (heuristic role map). kind="Permission" returns touched entities plus the roles granting it. kind="Role" returns granted permissions and their entities.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | ||
| view | No | Steers EntityType expansion: schema neighborhood vs permission usage | entity |
| since | No | Change-activity window — ISO date or day count (e.g. "30") | |
| node_id | Yes | Node id — a lowercase entity type, or a permission or role name (casing ignored) | |
| endpoint | No | Only applies to EntityType schema neighborhoods | v1.0 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does reasonably well: it discloses the delta-merge return contract, warns that the role map is a 'heuristic', and scopes `endpoint` to EntityType neighborhoods only. It does not state that expansion is a read-only/no-side-effect operation or discuss failure modes, which leaves a gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and return shape, then a compact per-kind enumeration. It is dense but every clause conveys distinct behavior; only slight tightening (e.g., the parenthetical heuristic caveat) would be possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description must carry return semantics — it does so via the {nodes, edges, message} contract and per-kind results. What the 'message' field contains and how the delta reconciles with existing canvas state remain unspecified, a minor residual gap for a 5-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80% (baseline 3), and the description goes beyond the schema by explaining the kind×view interaction — e.g. view='permission' yields 'permissions that touch the entity' and view='role' adds granting roles. This is genuine semantic value the enum descriptions alone don't convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('expand one node of the schema graph'), names the return payload ({nodes, edges, message} delta), and explicitly positions itself as the interactive companion to visualize_schema_graph. The per-kind breakdown lets an agent distinguish exact behavior without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'interactive companion to visualize_schema_graph' framing tells the agent this is the incremental-expansion path versus full-graph visualization, and each kind/view combination is mapped to a described outcome. It stops short of explicit when-not guidance (e.g., when to prefer get_permission_context for permission questions).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_change_detailB
Full detail for a single change record, including related changes from the same snapshot/object, and permission context (required permissions, admin consent, grantable-by roles — see get_permission_context for the heuristic caveat).
| Name | Required | Description | Default |
|---|---|---|---|
| change_id | Yes | Change record ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It usefully discloses the returned scope (related changes, permission context) and notes the heuristic caveat in get_permission_context, but it does not describe operational behavior such as read-only nature, error cases, or return format details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted framing. The parenthetical caveat is dense but earns its place by warning about the heuristic permission context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema, the description covers the main return components and a caveat, but it leaves gaps about how to obtain change_id and how this tool relates to sibling history/snapshot tools. It is adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the single change_id parameter is already documented in the schema. The description does not add syntax, source, or meaning beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb-resource pair: full detail for a single change record. It also enumerates what the detail includes (related changes and permission context), though it does not explicitly distinguish this from sibling detail/history tools such as get_object_history or get_snapshot_summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use this tool versus the many siblings, nor any when-not conditions. The only sibling reference is a pointer to get_permission_context for a caveat, which is not usage guidance for selecting this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_node_timelineB
Compact newest-first change timeline for one schema object, sized for the visualizer detail panel. App-facing companion to get_object_history.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| since | No | ISO date or day count (e.g. "90") | |
| node_id | Yes | Entity type name (case-insensitive) | |
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden: it discloses newest-first ordering and compact/sized output, which is genuine behavioral context. However it does not state that it is a read-only operation, whether results are paginated/truncated by a hidden cap, or any permission requirements, leaving meaningful gaps for a history tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the resource and ordering front-loaded, and the sibling relationship last. Minimal waste, though 'App-facing companion' is slightly redundant with 'visualizer detail panel'.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-param, no-output-schema tool, the description covers purpose and one behavioral trait (ordering) but omits param meaning, pagination/limits, and read-only nature. Adequate to recognize the tool, insufficient to invoke it confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% and the description mentions zero parameters. It never explains node_id, limit default/cap, or the 'since' date-vs-day-count format, so it adds nothing beyond the schema and does not compensate for the undocumented half.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource and shape: 'newest-first change timeline for one schema object'. It clarifies the purpose via 'sized for the visualizer detail panel' and distinguishes itself from get_object_history as a 'companion'. Slightly less crisp than a 5 because 'compact' and 'App-facing' are jargon that don't sharpen the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage via 'visualizer detail panel' and names get_object_history as the sibling it companions, but never states when to pick this one over get_object_history (e.g. compact/preview vs full history). No exclusions or prerequisites given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_object_historyB
Full change history for a specific Graph object type, oldest to newest — "what has happened to X over time?"
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | ISO date (YYYY-MM-DD) | |
| endpoint | No | ||
| object_name | Yes | e.g. group, application, accessPackage, conditionalAccessPolicy |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden. It does add the 'oldest to newest' ordering, but says nothing about whether results are truncated, whether 'since' limits the window or the word 'Full' conflicts with it, or what the response looks like. A mutation-history read tool needs more than one ordering clause.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence plus a clarifying gloss, with no filler. Every phrase (full, specific object type, oldest to newest) contributes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema and no annotations, so the description had to explain scope, result size, and the effect of 'since'/'endpoint'. It leaves the return shape and the interaction between 'Full' and 'since' unresolved, which is a real gap for a 3-parameter history tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is a middling 67% and the description mentions no parameters. It never explains what 'object_name' identifies at the type-vs-instance level or what 'since' and 'endpoint' do, leaving the description to add zero meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
It states a specific verb and resource (full change history for a Graph object type) plus an ordering guarantee and a plain-language gloss. It does not name or contrast with the obvious siblings (get_recent_changes, get_node_timeline, search_changes), so an agent must infer the split.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied through the quoted question 'what has happened to X over time?', which suggests investigating a single object type's past. There is no explicit when-to-use, when-not-to-use, or routing to get_recent_changes / search_changes / get_change_detail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_permission_contextA
Two modes. (1) Pass object_name: which permissions touch a Graph object, what each unlocks, who can grant them, and its recent changes. (2) Pass permission_name alone (e.g. when comparing "is there a less-privileged alternative to Synchronization.ReadWrite.All"): that permission's detail plus other permissions with overlapping resource scope, annotated with resource_count and is_ownership_scoped (OwnedBy-suffixed permissions restrict to owned objects only) so you can reason about the tradeoff yourself — this does NOT rank or claim to compute "least privilege" automatically, since resource-type count and instance-level ownership scoping are different privilege axes. Role<->permission cross-referencing is a heuristic correlation (no official Microsoft crosswalk exists) — treat "grantable_by" as a strong signal to verify, not ground truth.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max permissions to return when using object_name (sorted narrowest-first by resource count); broad objects like "user" can match 100+ | |
| endpoint | No | ||
| object_name | No | e.g. administrativeUnit, user, group, accessPackage, synchronizationJob | |
| permission_name | No | A specific permission scope, e.g. AdministrativeUnit.Read.All or Synchronization.ReadWrite.All. If object_name is omitted, returns this permission's detail plus resource-overlapping alternatives to compare. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so unusually well: it discloses that it does not rank or compute least privilege, that role<->permission cross-referencing is a heuristic with no official Microsoft crosswalk, and that grantable_by must be verified rather than trusted. It also explains the semantics of is_ownership_scoped as a distinct privilege axis.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with 'Two modes' and enumerated (1)/(2), so an agent can parse the branching quickly. Mode 2 is dense and clause-heavy with parenthetical asides, but every sentence carries substantive constraints rather than boilerplate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by describing what each mode returns, including named output fields. Remaining gaps are the interaction between object_name and permission_name when both or neither are passed (all four params are optional), and how limit/endpoint apply across modes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, so the schema already documents most parameters; the description still adds real meaning by explaining what each parameter yields (object_name → unlock/grant/change data; permission_name → overlapping-scope alternatives with resource_count and is_ownership_scoped). It does not clarify what happens if both parameters are supplied or omitted, leaving a small gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb+resource per mode: mode 1 answers 'which permissions touch a Graph object, what each unlocks, who can grant them, and its recent changes'; mode 2 returns 'that permission's detail plus other permissions with overlapping resource scope'. This is clearly distinct from siblings like search_changes or get_object_history, which operate on change/history rather than permission scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit mode-selection criteria keyed on the input parameter and supplies a concrete triggering scenario (comparing a less-privileged alternative to Synchronization.ReadWrite.All). It also states what the tool will NOT do (compute least privilege). It stops short of naming sibling alternatives or a when-not-to-use case, so it lands just below the top.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_changesB
Structured, filterable query over the change history — filter by date, endpoint, object type/name, change kind, and source.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| since | No | ISO date (YYYY-MM-DD); defaults to 7 days ago | |
| source | No | ||
| endpoint | No | ||
| change_kind | No | ||
| object_name | No | e.g. group, user, conditionalAccessPolicy | |
| object_type | No | e.g. EntityType, EnumType, ComplexType, ObjectInstance |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden, yet it says nothing about result ordering, pagination/limit behavior, the size or shape of the response, or read-only safety. 'Structured' hints at machine-readable output but no behavioral traits are actually disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the filterable dimensions listed compactly after a dash; zero filler. It is lean to the point that needed behavioral context is absent, but as prose it is well structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Seven optional parameters, no annotations, no output schema, and only 43% schema description coverage — this definition needed to explain the default 7-day window, the limit cap of 200, and result ordering. None of that is present, so an agent cannot predict what it will get back.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description enumerates the filter dimensions (date, endpoint, object type/name, change kind, source), which maps to 6 of the 7 parameters, but adds no semantics beyond the schema — the enums and the 'since' default are already documented. It omits 'limit' entirely and gives no hints on result-window behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('structured, filterable query over the change history') and enumerates the filter dimensions, so the operation is immediately clear. It never distinguishes itself from siblings like search_changes, get_object_history, or get_node_timeline, which also read change/history data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'structured, filterable' implies this is the path for narrowing a history query by known fields, but there is no explicit when-to-use, when-not, or named alternative (e.g., versus search_changes for free-text lookups). Usage is inferable only from the purpose statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_server_infoA
About this server — running version, its changelog entry, data freshness (latest snapshots and newest detected changes), and how releases work: the snapshot DATABASE is re-released daily as calendar-tagged GitHub releases (e.g. v2026.08.07) when changes are detected, while the SERVER code ships on npm with semver versions (e.g. v0.1.0). Call for "what version is this?", "what's new in the latest Graph Atlas release?", or to check whether the local data is current.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the burden, and it does well: it clarifies that there are two distinct version streams (daily calendar-tagged GitHub snapshot releases vs. npm semver server releases), which prevents misreading the output, and frames the call as a freshness check. It never explicitly states the call is read-only side-effect free, which keeps it off a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The payload is front-loaded — the resource statement comes first, then the freshness detail, then the versioning scheme, then use cases. It is on the long side and the release-mechanics sentence is dense, but it earns its place by disambiguating the two version formats shown in the output.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description compensates fully: it lists the returned fields (version, changelog entry, latest snapshots, newest detected changes) and explains why two different version numbers may appear. An agent has everything needed to call and interpret this no-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline of 4 applies. The description correctly implies no input is needed and focuses entirely on what the call yields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific resource and enumerates exactly what it returns: running version, changelog entry, data freshness (latest snapshots and newest detected changes), and release mechanics. None of the sibling tools (search_changes, get_node_timeline, get_object_history, etc.) overlap with server metadata, so an agent can route to it unambiguously.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives three concrete triggering questions in quotes ("what version is this?", "what's new in the latest Graph Atlas release?", "is the local data current?"), which is strong positive guidance. It does not name an alternative or an exclusion, but no sibling plausibly competes for these queries, so the gap is minor.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_snapshot_summaryB
Snapshot metadata — entity/property/enum counts, CSDL size, change count. "How big is Graph API now?" and trend analysis.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ISO date (YYYY-MM-DD); defaults to latest | |
| endpoint | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full burden. It discloses what metadata is included (counts, CSDL size, change count), which is useful, but omits operational details like permissions, data freshness, and cost. It is moderately transparent but not thorough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core content. The quoted use case is efficient and earns its place. Slightly fragmentary structure but no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter summary tool with no output schema, the description gives the returned metrics but leaves parameters and usage boundaries under-explained. An agent can call it, but with some ambiguity about when to choose it over siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not mention either parameter. The schema describes the date parameter but not the endpoint enum, giving 50% coverage. The description adds no semantic context for either parameter, so it fails to compensate for the gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource and set of metrics: entity/property/enum counts, CSDL size, change count. It is clear what the tool returns, though it does not explicitly differentiate itself from siblings like get_recent_changes or search_changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It offers two use cases ('How big is Graph API now?' and trend analysis), which implies when to use it. However, it does not name alternatives or state when not to use it, leaving the agent to infer the boundary with sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schema_change_reportA
Structured JSON of a schema/permission/role graph (nodes + edges) with change-activity counts, for reasoning over — no UI. view="entity": Graph entity types (focus_object = an entity like "group"). view="permission": permission scopes and the entities they touch (focus_object = a permission like "User.Invite.All"). view="role": Entra roles, the permissions they grant, and the entities those touch (focus_object = a role like "User Administrator") — use this to compare what different roles can actually do. Omit focus_object for an overview of the most consequential entities/permissions/roles. Same data as visualize_schema_graph, without rendering it.
| Name | Required | Description | Default |
|---|---|---|---|
| view | No | entity | |
| limit | No | ||
| since | No | ISO date for the change-activity window; defaults to 30 days ago | |
| endpoint | No | Only applies to view=entity | v1.0 |
| object_name | No | Focus node — an entity type, permission name, or role name depending on view |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose the return shape (structured JSON of nodes + edges with change-activity counts, non-visual) and the behavior when focus is omitted (overview of most consequential items), which is genuinely useful. It says nothing about pagination/limit effects, whether counts are scoped by `since`, or any auth/latency characteristics for a graph-producing read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core identity and the 'no UI' contrast are front-loaded, and each view sentence earns its place with a concrete example. It is dense but readable; the repeated 'focus_object = ...' phrasing is slightly redundant against the schema and could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No annotations and no output schema, so the description must cover behavior and returns — it partially does by describing the node/edge payload. Gaps: the `object_name` vs `focus_object` naming conflict, no explanation of `limit` or how `since` interacts with the reported change counts, and no routing to the many sibling tools that overlap (get_permission_context, expand_schema_node).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 60%, so the description must compensate, and it does well for `view` (all three enum values explained with example focus objects). However, it refers to the focus parameter as `focus_object` while the actual schema property is `object_name` — a naming mismatch that can lead an agent to pass the wrong key. `limit` (min 5, max 100) is undocumented anywhere.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the specific resource (the schema/permission/role graph as nodes + edges with change-activity counts) and explicitly distinguishes itself from the sibling visualizer ('Same data as visualize_schema_graph, without rendering it'). The three view modes are enumerated with concrete examples, so an agent knows exactly what it gets. It falls short of 5 only because there is no crisp verb framing of the operation itself.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It routes the agent per view with concrete guidance ('use this to compare what different roles can actually do') and states the omit-focus_object behavior for overview queries. The 'no UI' / 'same data as visualize_schema_graph, without rendering it' line implies when to pick this over the visualizer. There is no explicit statement of when NOT to use it or what other siblings (e.g. get_permission_context, expand_schema_node) cover instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_changesA
Search Microsoft Graph API change history using natural-language or keyword queries across all sources (seed-entra-ms, backfill-graph-changelog, self). Hybrid BM25-style keyword + semantic search, fused via Reciprocal Rank Fusion; degrades to keyword-only without OPENAI_API_KEY configured.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Search mode — hybrid degrades to keyword automatically without an OpenAI key | hybrid |
| limit | No | Max results (default 10, max 50) | |
| query | Yes | Natural-language or keyword query, e.g. "groups API nesting", "ID Governance separation of duties" | |
| endpoint | No | Filter to a specific Graph endpoint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does disclose meaningful traits: hybrid BM25-style plus semantic search fused by Reciprocal Rank Fusion, and automatic degradation to keyword-only without an OpenAI key. It still omits permissions, rate limits, and result-return details, but it adds substantive behavioral context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense sentence that front-loads the core purpose before technical search details. It is appropriately sized, though the semicolon-heavy structure is slightly run-on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, source coverage, search behavior, and fallback behavior, which is enough to understand invocation context. However, with no output schema and no explanation of returned result shape, it is only partially complete for interpreting or using search results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents all four parameters. The description does not add significant parameter-level meaning beyond noting hybrid degradation, which is also covered in the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: searching Microsoft Graph API change history. It also names the search modes and source coverage, making the purpose clear, although it does not explicitly contrast itself with sibling tools like get_recent_changes or get_object_history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies usage for natural-language or keyword queries across all change-history sources, but it does not state when to prefer this tool over alternatives such as get_recent_changes, get_object_history, or get_change_detail. The usage context is present but not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_schema_objectsA
Name search across Graph entity types, permission scopes, and Entra roles — resolves fuzzy names to canonical node ids for visualize_schema_graph / expand_schema_node. Returns ranked candidates {id, kind, label, sub}; prefix matches rank first.
| Name | Required | Description | Default |
|---|---|---|---|
| kinds | No | Restrict to these kinds; default all | |
| limit | No | ||
| query | Yes | ||
| endpoint | No | Snapshot used for entity type names | v1.0 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does a decent job: it discloses the return shape ({id, kind, label, sub}) and the ranking rule (prefix matches first), which are behavioral traits an agent can't infer elsewhere. It omits any note on cost, scope coverage, or what happens on zero matches.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the search scope front-loaded, followed by the downstream-use hint and return contract. No filler or restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly compensates by specifying the returned fields and ordering, which is the key missing piece for a search tool. Minor gaps remain around limit behavior and empty-result handling, but nothing essential to invoking it is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: kinds and endpoint are documented in the schema, and the description conceptually maps the kind set ('entity types, permission scopes, Entra roles'). It adds nothing about the query string's minimum length or the limit parameter's cap, so half the parameters remain solely schema-defined — baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (name search) and enumerates the three object kinds searched (Graph entity types, permission scopes, Entra roles), plus the resolution behavior (fuzzy names to canonical node ids). This clearly distinguishes it from change-oriented siblings like search_changes and get_object_history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the output as input to visualize_schema_graph / expand_schema_node, which tells an agent when this tool is the right first step. However, it doesn't state when-not-to-use or contrast with search_changes directly, so the routing is implied rather than fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
visualize_schema_graphA
Open the interactive Graph Atlas visualizer — a force-directed schema graph the user can search, expand node-by-node, and pivot across views. Pick the view that puts the pivot object in the right place for the question: "entity" for the Graph schema (nodes = entity types, colored by distance from the focus, with recent-change activity badges; edges = navigation properties/inheritance) — focus_object = an entity like "group". "permission" for a permission scope and the entities it touches plus the roles granting it — focus_object = a permission like "User.Invite.All". "role" for an Entra role, the permissions it grants, and the entities those touch — focus_object = a role like "User Administrator". Omit focus_object for an overview of the most consequential nodes. The user can continue exploring in the UI (expand_schema_node powers that); use schema_change_report for the same data without rendering.
| Name | Required | Description | Default |
|---|---|---|---|
| view | No | entity | |
| since | No | Change-activity window — ISO date or day count (e.g. "30"); defaults to 30 days ago | |
| endpoint | No | Only applies to view=entity | v1.0 |
| focus_object | No | Focus node — an entity type, permission name, or role name depending on view |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so the description carries the burden, and it does disclose the key behavioral trait: this opens/renders a visual artifact for the user rather than returning structured data, and the user continues interactively in the UI. It also discloses what the visualization encodes (color by distance from focus, recent-change activity badges, edge semantics). It doesn't say what the tool returns to the agent itself or whether an existing session is reused, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then organized view-by-view so an agent can scan to the relevant case. It is on the long side, but nearly every clause carries decision-relevant information (view semantics, examples, alternatives). The nested quoting makes it slightly dense but not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description covers the rendering behavior, all three view modes, the focus-object mapping, and the no-focus overview. The main remaining gap is what the tool hands back to the agent (URL, handle, or confirmation) versus the visual side, which matters for a UI-launching tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, and the description compensates for the gaps well: it explains the meaning of each view value and what focus_object should be per view (entity type, permission name, role name) with concrete examples, and clarifies the overview case when it is omitted. It adds nothing for 'since' or 'endpoint' (endpoint scoping is only in the schema description), so it earns a 4 rather than 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource (open the interactive Graph Atlas visualizer) plus exactly what the artifact is: a force-directed schema graph with search, node expansion, and view pivots. Distinguishes itself from siblings explicitly (expand_schema_node for in-UI expansion, schema_change_report for the same data unrendered), so an agent can separate it from the string of get_* and search_* tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives per-view selection criteria with worked examples ('entity' for Graph schema nodes like "group"; 'permission' for a scope like "User.Invite.All"; 'role' for a role like "User Administrator") and states the omission case (omit focus_object for an overview). It also names alternatives: continue exploring via expand_schema_node, use schema_change_report for the same data without rendering.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
12 tool updates
v2026.10.23- Changed
expand_schema_node1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_change_detail1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_node_timeline1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_object_history1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_permission_context1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_recent_changes1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_server_info1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
get_snapshot_summary1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
schema_change_report1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
search_changes1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
search_schema_objects1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
visualize_schema_graph1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
TDQS
Scored across 12 tools
The change-history cluster (search_changes, get_recent_changes, get_object_history, get_node_timeline, get_change_detail) has real overlap, but descriptions clearly separate natural-language search, filtered recent queries, per-object history, compact visualizer timeline, and single-record detail. schema_change_report and visualize_schema_graph intentionally expose the same data with and without rendering, which is explained but still a potential source of confusion.
Most tools follow a predictable verb_noun pattern (search_changes, get_object_history, expand_schema_node, visualize_schema_graph). schema_change_report is noun-only, a minor deviation in an otherwise consistent set.
Twelve tools is well within a healthy range and each serves a distinct role: change discovery, detail/history, snapshot metadata, permission reasoning, visualization, and server info. No obvious filler tools.
The surface covers change search, filtering, history, detail, snapshot summaries, permissions/roles, schema exploration, and visualizer support quite thoroughly. Minor gaps exist around explicit snapshot/release listing and change diffing between snapshots, though get_server_info and get_snapshot_summary partially mitigate these.
Maintenance
Related MCP Connectors
Official Microsoft MCP Server to query Microsoft Entra data using natural language
Independent trust scores, tool surfaces and change history for MCP servers.
Search 70,510 indexed MCP servers, install-risk scoring and Ed25519-signed Agent Trust Cards.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server for Microsoft 365 via the Microsoft Graph API, providing read-only access to profile, calendar, email, Teams chats, OneDrive files, and meeting transcripts from any MCP client.1612 npm3MIT
- AlicenseNot gradedqualityAmaintenanceA Model Context Protocol server for Microsoft 365 administration using Graph API application permissions, enabling security monitoring, identity audits, incident response, and service health management.88 npm18MIT
- AlicenseCqualityAmaintenanceA FastMCP server for interacting with Microsoft Entra ID via the Microsoft Graph API, enabling management of users, groups, sign-in logs, MFA, applications, devices, conditional access, and more.48MIT
- FlicenseNot gradedqualityBmaintenanceMCP server providing access to Microsoft Teams chats/channels, Outlook emails, calendar events, and SharePoint files via Microsoft Graph API.-