Skip to main content
Glama
ugurkocde

Intune Assignment Checker MCP

by ugurkocde

Intune Assignment Checker MCP

A local, read-only Model Context Protocol server for inspecting and explaining Microsoft Intune assignments through Microsoft Graph /beta.

This repository is the TypeScript port and MCP surface. The existing PowerShell product remains separate and is the behavioral reference for assignment resolution.

Intune Assignment Checker MCP overview

Explore the installation guide and security model at intuneassignmentchecker.ugurkoc.de/mcp.

Current implementation

The first delegated vertical slice is implemented:

  • Local MCP transport over stdio.

  • Interactive browser sign-in with delegated Microsoft Graph permissions.

  • OS-protected persistent MSAL cache (Windows DPAPI, macOS Keychain, or Linux libsecret), with memory-only fallback if secure persistence is unavailable.

  • get_connection_status.

  • search_policies.

  • list_all_device_assignments for direct All Devices policy and application targeting.

  • list_all_user_assignments for direct All Users policy and application targeting.

  • list_unassigned_policies for policies and applications with no assignments.

  • get_policy_assignments.

  • Strict Microsoft Graph /beta URL construction and continuation validation.

  • Bounded calls, pages, execution time, response bytes, retries, and result sizes.

  • Opaque, one-time, tenant-bound MCP cursors; raw Graph @odata.nextLink values never enter model context.

  • Complete page records and opaque continuation cursors in both model-visible text and typed structuredContent for client compatibility.

  • Assignment collections reconcile Graph's sometimes-stale isAssigned flag; duplicate policy names require stable ID-based disambiguation.

  • Explicit partial-coverage and delegated-RBAC uncertainty reporting.

The one production app registration has been created, its public-client ID is embedded, and the package is available from npm. The code contains no second development registration. The embedded client ID also makes source builds testable without supplying a separate registration.

Related MCP server: sql-server-mcp

Architecture

AI client
  -> local stdio MCP process
     -> MSAL delegated sign-in in the user's browser
     -> OS-protected local token cache
     -> internally generated, read-only Microsoft Graph /beta requests

There is no hosted MCP endpoint, Auth0 tenant, customer token database, service certificate, or server-side Graph token exchange.

Install from npm

Requirements: Node.js 20 or newer and a supported local stdio MCP client. The client launches the package on demand; users do not install it globally or create an Entra app registration, client secret, or certificate.

Claude Desktop

Open Settings → Developer → Edit Config and add:

{
  "mcpServers": {
    "intune-assignment-checker": {
      "command": "npx",
      "args": ["-y", "intune-assignment-checker-mcp@latest"]
    }
  }
}

Restart Claude Desktop after saving the configuration.

Claude Code

Add the server at user scope so it is available in every project:

claude mcp add --transport stdio --scope user intune-assignment-checker -- npx -y intune-assignment-checker-mcp@latest

Run claude mcp list or open /mcp inside Claude Code to verify the connection.

ChatGPT Desktop and Codex

The ChatGPT desktop app, Codex CLI, and the Codex IDE extension share MCP configuration on the same machine. Add the server with:

codex mcp add intune-assignment-checker -- npx -y intune-assignment-checker-mcp@latest

The equivalent ~/.codex/config.toml entry is:

[mcp_servers.intune-assignment-checker]
command = "npx"
args = ["-y", "intune-assignment-checker-mcp@latest"]

Cursor

Add this server to Cursor's MCP configuration:

{
  "mcpServers": {
    "intune-assignment-checker": {
      "command": "npx",
      "args": ["-y", "intune-assignment-checker-mcp@latest"]
    }
  }
}

VS Code

Add this server through MCP: Add Server or place the following in the appropriate VS Code mcp.json file:

{
  "servers": {
    "intune-assignment-checker": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "intune-assignment-checker-mcp@latest"]
    }
  }
}

First use

Ask the client an Intune assignment question. The first functional tool call opens Microsoft sign-in in the browser. After delegated consent, the MCP stores the token cache under the current OS user's protection and reuses it on later launches. Sign in or revoke the local cache explicitly with:

npx -y intune-assignment-checker-mcp@latest login
npx -y intune-assignment-checker-mcp@latest status
npx -y intune-assignment-checker-mcp@latest logout

ChatGPT Web and Claude.ai cannot directly launch an npx process on the user's machine. This local installation path targets their desktop clients and other local stdio MCP hosts.

Local development

Requirements: Node.js 20 or newer. Linux secure persistence also requires a Secret Service implementation such as GNOME Keyring/libsecret.

npm install
npm run check
npm run build

The production client ID is embedded. IAC_MCP_CLIENT_ID remains available only as an explicit override for controlled testing:

export IAC_MCP_CLIENT_ID="your-test-public-client-id"

Optionally pin guest or multi-tenant administrators to a specific tenant GUID:

export IAC_MCP_TENANT_ID="your-tenant-id"

Sign in explicitly, or let the first functional tool open sign-in:

node dist/index.js login
node dist/index.js status
node dist/index.js logout

For a headless session:

node dist/index.js login --device-code

Set IAC_MCP_AUTO_SIGN_IN=false if model-triggered tool calls must return auth_required instead of opening a browser.

Diagnostics

The server logs to stderr only; stdout stays reserved for MCP JSON-RPC framing. Set IAC_MCP_LOG_LEVEL to debug, info (default), warn, or error. The startup line includes the running version, and every tool result carries a correlation ID that matches a stderr entry:

export IAC_MCP_LOG_LEVEL=debug
node dist/index.js --version

MCP client configuration during development

Build first, then point the client to the absolute local file:

{
  "mcpServers": {
    "intune-assignment-checker": {
      "command": "node",
      "args": ["/absolute/path/to/IntuneAssignmentChecker-MCP/dist/index.js"]
    }
  }
}

The public npx configurations are documented in Install from npm.

The one Entra app registration

The standard path uses exactly one publisher-owned registration named Intune Assignment Checker MCP:

  • Supported accounts: any organizational directory.

  • Public/native client; no client secret or certificate.

  • Delegated Graph permissions only.

  • Loopback redirect URI: http://localhost.

  • Authority: organizations, with IAC_MCP_TENANT_ID override.

  • No exposed MCP API and no application Graph permissions.

The current tools request only:

  • DeviceManagementConfiguration.Read.All

  • DeviceManagementApps.Read.All

  • GroupMember.Read.All

Additional delegated permissions will be added to this same registration only when the tools that use them ship. CloudPC.Read.All remains optional and is not part of the current consent bundle.

The publisher-only setup script is idempotent, requires the intended publisher tenant GUID, and supports -WhatIf:

./scripts/Register-IntuneAssignmentCheckerMcpApp.ps1 -TenantId '<publisher-tenant-guid>' -WhatIf
./scripts/Register-IntuneAssignmentCheckerMcpApp.ps1 -TenantId '<publisher-tenant-guid>'

The script refuses an unexpected tenant, another API, or application permissions, and always converges on the exact three current read-only delegated scopes. It does not grant customer consent. The production registration was created and read back through Microsoft Graph /beta; live delegated consent and tool calls are verified separately before package publication.

Security and privacy boundaries

  • Tokens never appear in tool arguments, tool results, stdout, or application logs.

  • stdout is reserved for MCP JSON-RPC; diagnostics use stderr.

  • No tool accepts a Graph URL or arbitrary Graph path.

  • Graph redirects are rejected rather than followed.

  • Policy, group, and filter names are untrusted data: control characters are stripped and lengths are bounded.

  • Delegated Intune RBAC can silently narrow successful Graph results. Coverage reports this uncertainty; an empty result is not proof that the tenant has no matching object.

  • Policy names, group names, filter rules, and other returned fields are sent by the MCP client to its configured model provider. Tokens and raw Graph payloads are not.

  • Secure cache initialization never falls back to an unencrypted token file. If the OS keyring is unavailable, tokens remain in memory for that process only.

Because this is a shared multi-tenant public client, the publisher registration itself is security-critical. Its owners should use phishing-resistant MFA and privileged access controls, and changes to redirect URIs, permissions, or credentials should be monitored.

Supported policy categories

The first slice includes configuration policies, device configurations, compliance policies, mobile applications, and managed app configuration policies. Search uses client-side matching because Intune $filter/$search behavior is inconsistent across these collections.

The live verification tenant confirmed that these collections can return @odata.nextLink, assignment targets are polymorphic and include assignment-filter fields, empty value arrays are valid, and @odata.type is returned automatically but rejected when placed in $select.

Verification

npm run format:check
npm run lint
npm run typecheck
npm test
npm run build
npm audit

The tests cover URL and /beta enforcement, opaque cursor isolation, throttling, polymorphic targets, filter/group normalization, category contracts, and an in-memory MCP client/server exchange.

Automated PowerShell parity

The PowerShell module remains the behavioral reference, but synchronization is now enforced rather than assumed:

  1. Tests/Parity/Export-McpParityFixtures.ps1 in the PowerShell repository generates a deterministic, versioned Graph beta fixture.

  2. PowerShell Pester tests fail when that committed fixture is stale.

  3. npm run parity:sync vendors the fixture into this repository.

  4. The TypeScript parity suite runs the same raw policies, polymorphic targets, filters, groups, app intents, and platform values through the MCP normalizer.

  5. Cross-repository CI fails until the TypeScript result matches the current PowerShell result.

Run the complete local handoff from this repository with:

npm run parity:sync
npm run parity:check
npm run check
npm run build

The MCP workflow also checks the PowerShell main branch every day. In the PowerShell GitHub repository, set the Actions variable IAC_MCP_REPOSITORY=ugurkocde/IntuneAssignmentChecker-MCP after this repository is published. If the MCP repository is private, also add an IAC_MCP_REPOSITORY_TOKEN secret with read access. Until that remote exists and the variable is configured, the PowerShell-side cross-repository job is safely skipped; local parity and the PowerShell fixture-drift test remain active.

This automation detects and blocks behavioral drift. It deliberately does not translate arbitrary PowerShell into TypeScript. After a reviewed version change is released on GitHub, the npm publication is performed by the provenance-enabled workflow documented in RELEASING.md.

Available Tools

6 tools
get_connection_statusGet Intune connection statusA
Read-onlyIdempotent

Checks local delegated Microsoft authentication without returning or logging any token.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
stateNo
statusYes
messageNo
tenantIdNo
autoSignInNo
accountNameNo
cacheBackendNo
grantedScopesNo
cacheProtectedNo
accountUsernameNo
requestedScopesNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already cover read-only, idempotent, non-destructive behavior. The description adds meaningful context beyond that: it explicitly states that no token is returned or logged, which is important security-related behavior an agent should know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, compact sentence that front-loads the core action and includes the most valuable security constraint without any filler. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only, idempotent tool with a rich annotation set and an output schema, the description is complete. It covers what the tool does and the critical privacy behavior, leaving no operational ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4. The description does not need to add parameter semantics, and it appropriately focuses on the operation's purpose and behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Checks') and identifies the exact resource and scope: 'local delegated Microsoft authentication'. It clearly distinguishes this from the sibling policy/assignment tools, which are unrelated in function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied: check authentication status before other operations. However, there is no explicit statement of when to use this tool versus alternatives, and no mention of exclusions or preconditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_policy_assignmentsGet Intune policy assignmentsA
Read-onlyIdempotent

Returns normalized include, exclude, all-user, all-device, group, intent, and assignment-filter details for one supported policy. It never accepts a Graph URL or path.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
categoryYes
policyIdYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
policyYes
statusYes
coverageYes
tenantIdYes
graphUsageYes
nextCursorYes
assignmentsYes
resultCountYes
schemaVersionYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, and non-destructive behavior, lowering the bar. The description adds the constraint about not accepting Graph URLs/paths, which is extra behavioral context, but does not cover error handling or side effects beyond that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no unnecessary words. It front-loads the primary action (Returns) and scope (one supported policy), and the second sentence adds a clear constraint. Perfectly sized for the information provided.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that the tool has an output schema, the description need not explain return values. It adequately covers the core purpose and a key input constraint. However, it does not mention prerequisites like authentication or typical error conditions, though these may be implicit in the tool context. Overall, sufficient for a simple read-only operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for all parameters. The description only hints at a policy but does not explain policyId, category, limit, or cursor. It fails to map the 'one supported policy' concept to the policyId parameter or clarify the category enum's role, leaving the agent to guess parameter meanings from names alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Returns) and resource (policy assignments) and scope (one supported policy), clearly distinguishing it from sibling tools like list_all_device_assignments or list_all_user_assignments. The added note 'It never accepts a Graph URL or path' further clarifies the input expectation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage for a single policy via 'for one supported policy' and clarifies input format with the URL/path prohibition, but does not explicitly compare to alternatives or state when to use them. The sibling names suggest the context, but the description itself could be more explicit about when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_all_device_assignmentsList assignments targeting All DevicesA
Read-onlyIdempotent

Lists policies and applications that directly target All Devices. For questions about apps assigned to All Devices, set category to application. Results include policyId, app or policy name, application intent when available, assignment filters, pageSummary, coverage, and an opaque continuation cursor. resultCount, pageSummary, and graphUsage describe only the current tool call; follow nextCursor for complete coverage.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
categoryNo
platformNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
coverageYes
tenantIdYes
graphUsageYes
nextCursorYes
assignmentsYes
pageSummaryYes
resultCountYes
schemaVersionYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds valuable behavioral context: it discloses pagination scope ('resultCount, pageSummary, and graphUsage describe only the current tool call; follow nextCursor for complete coverage'), the opaque nature of the cursor, and conditional fields ('application intent when available'). These details go beyond annotations and help the agent understand the paginated, per-call nature of results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no filler. The primary purpose is stated first, followed by a focused usage tip, then a concise explanation of pagination behavior. Every sentence carries meaning, and the structure is logical.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 4 parameters (none required) and an output schema, so per the rubric we don't demand return-field explanations. The description covers the core function, filters (category), and pagination (cursor), which are the most critical for correct invocation. It omits explicit guidance on 'limit' and 'platform', which could be inferred but are not documented. Given the pagination behavior is clearly stated, the description feels fairly complete for an agent to use successfully, though a brief note on limit would round it out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description bears the burden of parameter explanation. It does clarify two of the four parameters: 'category' (via 'set category to application') and 'cursor' (via 'opaque continuation cursor' and 'follow nextCursor'). However, 'limit' and 'platform' are not explained at all—no mention of pagination size or filtering by OS. Thus, only partial compensation for the low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Lists policies and applications that directly target All Devices.' It clearly differentiates from siblings like list_all_user_assignments (targets users) and list_unassigned_policies, and even narrows scope to 'directly target' to exclude inherited assignments. This leaves no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides one direct usage tip: 'For questions about apps assigned to All Devices, set category to application.' However, it does not explicitly state when to use this tool over the siblings (e.g., 'use this for All Devices, not for user assignments') or mention exclusions. The implicit scope is clear from the name, but explicit routing to alternatives is absent, so it falls at implied usage rather than explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_all_user_assignmentsList assignments targeting All UsersA
Read-onlyIdempotent

Lists policies and applications that directly target All Users. For questions about apps assigned to All Users, set category to application. Results include policyId, app or policy name, application intent when available, assignment filters, pageSummary, coverage, and an opaque continuation cursor. resultCount, pageSummary, and graphUsage describe only the current tool call; follow nextCursor for complete coverage.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
categoryNo
platformNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
coverageYes
tenantIdYes
graphUsageYes
nextCursorYes
assignmentsYes
pageSummaryYes
resultCountYes
schemaVersionYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Given readOnlyHint, idempotentHint and destructiveHint are already declared, the description adds meaningful behavioral context: pagination semantics, opaque continuation cursor, and the caveat that resultCount/pageSummary/graphUsage only cover the current call. This is valuable beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three purposeful sentences with no filler. Scope is front-loaded and pagination details are succinctly placed at the end. Every sentence adds information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description provides the operation scope, category-specific use, and pagination behavior, plus the key output fields. With the output schema present and simple parameters, no critical aspects of correct usage are missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains the category parameter's meaning and the continuation cursor's purpose, but does not describe the limit parameter or explicitly map the input cursor to the returned nextCursor. Partial compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Lists') and a concrete resource ('policies and applications that directly target All Users'), plus a distinguishing scope. This clearly separates it from siblings like list_all_device_assignments and get_policy_assignments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance for one key decision: 'For questions about apps assigned to All Users, set category to application.' It does not explicitly name alternatives or exclusions, but the scope statement makes the intended use obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_unassigned_policiesList unassigned Intune policiesA
Read-onlyIdempotent

Lists supported Intune policies and applications whose assignment collection is empty. For unassigned apps, set category to application. Results include stable policy IDs, category IDs, platform metadata, pageSummary, explicit coverage, and an opaque continuation cursor. graphUsage describes only the current tool call; resultCount is the number of records on this page.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
categoryNo
platformNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
recordsYes
coverageYes
tenantIdYes
graphUsageYes
nextCursorYes
pageSummaryYes
resultCountYes
schemaVersionYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly and idempotent, but the description adds meaningful behavioral context: results include 'an opaque continuation cursor' (pagination mechanism), 'graphUsage describes only the current tool call', and 'resultCount is the number of records on this page.' This clarifies pagination semantics and avoids misinterpretation of counts. It also discloses the specific field set returned. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences long, each earning its place: the first defines the tool's scope, the second gives a specific parameter instruction, and the third describes output contents and pagination semantics. The main purpose is front-loaded, and there is no redundant or filler content. It is efficiently structured and easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is sufficient for a read-only list tool with an output schema that already defines the return structure. It covers pagination (cursor, per-page count) and key output fields. Minor gaps remain: it does not explain the 'platform' parameter or explicitly state how to request the next page (though the cursor implies it), and the meaning of 'supported' is not elaborated. Overall, the description is highly complete but slightly missing on parameter guidance.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description carries the full burden of parameter explanation. It partially compensates by explaining the 'category' parameter ('set category to application') and implying the cursor's purpose ('opaque continuation cursor'), but it leaves 'limit' and 'platform' completely unexplained. The agent can infer limit from context, but the description does not explicitly state its meaning or range, so the parameter semantics are only partially addressed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Lists') and a precise resource: 'supported Intune policies and applications whose assignment collection is empty.' This clearly distinguishes the tool from siblings by focusing on unassigned items, and the additional instruction 'For unassigned apps, set category to application' reinforces the special case. It is unambiguous and differentiates the tool's purpose without needing to open the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates when to use the tool: when you need policies/applications with empty assignment collections. It also provides a conditional guideline ('For unassigned apps, set category to application'), which helps the agent select the right category value. However, it does not explicitly name alternative tools like search_policies or list_all_device_assignments, nor does it state when NOT to use this tool, leaving some exclusion guidance implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_policiesSearch Intune policiesA
Read-onlyIdempotent

Searches supported Intune policy and application categories through internally generated Microsoft Graph /beta requests. Every record returns an id and categoryId; pass those values as policyId and category to get_policy_assignments. Display names are not unique: never silently choose one record when multiple results match. Search isAssigned values are Graph-reported hints; get_policy_assignments reconciles them against the assignment collection. Results can be RBAC-filtered for the signed-in administrator.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryNo
cursorNo
categoryNo
platformNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
recordsYes
coverageYes
tenantIdYes
graphUsageYes
nextCursorYes
resultCountYes
schemaVersionYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal readOnly, openWorld, idempotent, and non-destructive behavior. The description adds valuable context beyond annotations by revealing that results come from 'internally generated Microsoft Graph /beta requests', that isAssigned values are 'Graph-reported hints', and that results can be RBAC-filtered. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact, front-loads the core action, and every sentence delivers either a caveat (non-unique display names) or a routing hint (get_policy_assignments). It is slightly dense but remains readable and well-organized. It earns a high score, but not a 5 because it could be tighter by removing the redundant 'Searches supported' phrasing with the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a search-and-return tool, the description explains how to consume results and what caveats apply, and the output schema covers expected return values. It does not explicitly discuss pagination or cursor semantics, but those are parameters documented in the schema, so the description need not repeat them. The presence of an output schema further reduces the burden on the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden. It explains the key output semantics (id and categoryId) and the critical non-uniqueness caveat. It does not explicitly name limit, cursor, or platform, but given the 0% schema coverage, the description compensates enough for an agent to understand the primary inputs and expected outputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('searches') and resource ('supported Intune policy and application categories') and differentiates it from siblings by being the path to get_policy_assignments via id/categoryId. It also calls out the non-uniqueness of display names, which clarifies a subtle edge case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states that returned id and categoryId should be passed as policyId and category to get_policy_assignments, and warns not to silently choose a single record when display names are not unique. It also clarifies that isAssigned values are only hints and get_policy_assignments reconciles them, giving clear, decision-relevant usage context.

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. Dates show when Glama detected each change.

  1. 6 tool updatesv0.4.0
    • Changedget_connection_status10 fields changed
      • addedOutput schema / properties / accountName
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / accountUsername
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / autoSignIn
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / cacheBackend
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / cacheProtected
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / grantedScopes
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / message
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / requestedScopes
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / state
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / tenantId
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
    • Changedget_policy_assignments10 fields changed
      • addedOutput schema / properties / assignments
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "assignmentId": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "assignmentMode": {
        +        "type": "string"
        +      },
        +      "assignmentReason": {
        +        "type": "string"
        +      },
        +      "category": {
        +        "type": "string"
        +      },
        +      "categoryId": {
        +        "type": "string"
        +      },
        +      "filterId": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "filterMode": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "filterName": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "filterPlatform": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "filterRule": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "intent": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "platform": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "policyId": {
        +        "type": "string"
        +      },
        +      "policyName": {
        +        "type": "string"
        +      },
        +      "roleScopeTagIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "schemaVersion": {
        +        "const": 1,
        +        "type": "number"
        +      },
        +      "source": {
        +        "type": "string"
        +      },
        +      "targetId": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "targetName": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "targetType": {
        +        "type": "string"
        +      },
        +      "tenantId": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "schemaVersion",
        +      "tenantId",
        +      "categoryId",
        +      "category",
        +      "policyId",
        +      "policyName",
        +      "platform",
        +      "roleScopeTagIds",
        +      "assignmentId",
        +      "assignmentMode",
        +      "targetType",
        +      "targetId",
        +      "targetName",
        +      "intent",
        +      "filterId",
        +      "filterName",
        +      "filterMode",
        +      "filterRule",
        +      "filterPlatform",
        +      "assignmentReason",
        +      "source"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / coverage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "authorizationContext": {
        +      "const": "delegated_may_be_rbac_filtered",
        +      "type": "string"
        +    },
        +    "continuationRequired": {
        +      "type": "boolean"
        +    },
        +    "failedCategories": {
        +      "type": "number"
        +    },
        +    "failedSources": {
        +      "type": "number"
        +    },
        +    "pendingCategories": {
        +      "type": "number"
        +    },
        +    "sources": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "code": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "requestIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "source",
        +          "status",
        +          "code",
        +          "requestIds"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    "successfulCategories": {
        +      "type": "number"
        +    },
        +    "successfulSources": {
        +      "type": "number"
        +    },
        +    "totalCategories": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "status",
        +    "continuationRequired",
        +    "authorizationContext",
        +    "successfulCategories",
        +    "failedCategories",
        +    "pendingCategories",
        +    "totalCategories",
        +    "successfulSources",
        +    "failedSources",
        +    "sources"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / graphUsage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "calls": {
        +      "type": "number"
        +    },
        +    "elapsedMs": {
        +      "type": "number"
        +    },
        +    "pages": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "calls",
        +    "pages",
        +    "elapsedMs"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / nextCursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / policy
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "category": {
        +      "type": "string"
        +    },
        +    "categoryId": {
        +      "type": "string"
        +    },
        +    "displayName": {
        +      "type": "string"
        +    },
        +    "graphType": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "id": {
        +      "type": "string"
        +    },
        +    "isAssigned": {
        +      "anyOf": [
        +        {
        +          "type": "boolean"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "platform": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    },
        +    "roleScopeTagIds": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "technology": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ]
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "displayName",
        +    "categoryId",
        +    "category",
        +    "platform",
        +    "technology",
        +    "graphType",
        +    "roleScopeTagIds",
        +    "isAssigned"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / resultCount
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / schemaVersion
        Added value: +{
        +  "const": 1,
        +  "type": "number"
        +}
      • addedOutput schema / properties / status / enum
        Added value: +[
        +  "ok",
        +  "partial"
        +]
      • addedOutput schema / properties / tenantId
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "status"
        -]New value: +[
        +  "status",
        +  "schemaVersion",
        +  "tenantId",
        +  "policy",
        +  "assignments",
        +  "resultCount",
        +  "nextCursor",
        +  "coverage",
        +  "graphUsage"
        +]
    • Changedlist_all_device_assignments10 fields changed
      • addedOutput schema / properties / assignments
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "assignmentId": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "categoryId": {
        +        "type": "string"
        +      },
        +      "filter": {
        +        "anyOf": [
        +          {
        +            "type": "null"
        +          },
        +          {
        +            "additionalProperties": {},
        +            "properties": {
        +              "id": {
        +                "type": "string"
        +              },
        +              "mode": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "name": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "platform": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "rule": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              }
        +            },
        +            "required": [
        +              "id",
        +              "name",
        +              "mode",
        +              "platform",
        +              "rule"
        +            ],
        +            "type": "object"
        +          }
        +        ]
        +      },
        +      "intent": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "platform": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "policyId": {
        +        "type": "string"
        +      },
        +      "policyName": {
        +        "type": "string"
        +      },
        +      "roleScopeTagIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "targetType": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "policyId",
        +      "policyName",
        +      "categoryId",
        +      "platform",
        +      "roleScopeTagIds",
        +      "assignmentId",
        +      "targetType",
        +      "intent",
        +      "filter"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / coverage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "authorizationContext": {
        +      "const": "delegated_may_be_rbac_filtered",
        +      "type": "string"
        +    },
        +    "continuationRequired": {
        +      "type": "boolean"
        +    },
        +    "failedCategories": {
        +      "type": "number"
        +    },
        +    "failedSources": {
        +      "type": "number"
        +    },
        +    "pendingCategories": {
        +      "type": "number"
        +    },
        +    "sources": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "code": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "requestIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "source",
        +          "status",
        +          "code",
        +          "requestIds"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    "successfulCategories": {
        +      "type": "number"
        +    },
        +    "successfulSources": {
        +      "type": "number"
        +    },
        +    "totalCategories": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "status",
        +    "continuationRequired",
        +    "authorizationContext",
        +    "successfulCategories",
        +    "failedCategories",
        +    "pendingCategories",
        +    "totalCategories",
        +    "successfulSources",
        +    "failedSources",
        +    "sources"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / graphUsage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "calls": {
        +      "type": "number"
        +    },
        +    "elapsedMs": {
        +      "type": "number"
        +    },
        +    "pages": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "calls",
        +    "pages",
        +    "elapsedMs"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / nextCursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / pageSummary
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "assignmentRecords": {
        +      "type": "number"
        +    },
        +    "byCategory": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "value",
        +          "count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "byIntent": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "value",
        +          "count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "uniquePolicies": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "assignmentRecords",
        +    "uniquePolicies",
        +    "byCategory",
        +    "byIntent"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / resultCount
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / schemaVersion
        Added value: +{
        +  "const": 1,
        +  "type": "number"
        +}
      • addedOutput schema / properties / status / enum
        Added value: +[
        +  "ok",
        +  "partial"
        +]
      • addedOutput schema / properties / tenantId
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "status"
        -]New value: +[
        +  "status",
        +  "schemaVersion",
        +  "tenantId",
        +  "resultCount",
        +  "nextCursor",
        +  "coverage",
        +  "graphUsage",
        +  "pageSummary",
        +  "assignments"
        +]
    • Changedlist_all_user_assignments10 fields changed
      • addedOutput schema / properties / assignments
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "assignmentId": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "categoryId": {
        +        "type": "string"
        +      },
        +      "filter": {
        +        "anyOf": [
        +          {
        +            "type": "null"
        +          },
        +          {
        +            "additionalProperties": {},
        +            "properties": {
        +              "id": {
        +                "type": "string"
        +              },
        +              "mode": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "name": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "platform": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "rule": {
        +                "anyOf": [
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              }
        +            },
        +            "required": [
        +              "id",
        +              "name",
        +              "mode",
        +              "platform",
        +              "rule"
        +            ],
        +            "type": "object"
        +          }
        +        ]
        +      },
        +      "intent": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "platform": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "policyId": {
        +        "type": "string"
        +      },
        +      "policyName": {
        +        "type": "string"
        +      },
        +      "roleScopeTagIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "targetType": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "policyId",
        +      "policyName",
        +      "categoryId",
        +      "platform",
        +      "roleScopeTagIds",
        +      "assignmentId",
        +      "targetType",
        +      "intent",
        +      "filter"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / coverage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "authorizationContext": {
        +      "const": "delegated_may_be_rbac_filtered",
        +      "type": "string"
        +    },
        +    "continuationRequired": {
        +      "type": "boolean"
        +    },
        +    "failedCategories": {
        +      "type": "number"
        +    },
        +    "failedSources": {
        +      "type": "number"
        +    },
        +    "pendingCategories": {
        +      "type": "number"
        +    },
        +    "sources": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "code": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "requestIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "source",
        +          "status",
        +          "code",
        +          "requestIds"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    "successfulCategories": {
        +      "type": "number"
        +    },
        +    "successfulSources": {
        +      "type": "number"
        +    },
        +    "totalCategories": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "status",
        +    "continuationRequired",
        +    "authorizationContext",
        +    "successfulCategories",
        +    "failedCategories",
        +    "pendingCategories",
        +    "totalCategories",
        +    "successfulSources",
        +    "failedSources",
        +    "sources"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / graphUsage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "calls": {
        +      "type": "number"
        +    },
        +    "elapsedMs": {
        +      "type": "number"
        +    },
        +    "pages": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "calls",
        +    "pages",
        +    "elapsedMs"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / nextCursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / pageSummary
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "assignmentRecords": {
        +      "type": "number"
        +    },
        +    "byCategory": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "value",
        +          "count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "byIntent": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "value",
        +          "count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "uniquePolicies": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "assignmentRecords",
        +    "uniquePolicies",
        +    "byCategory",
        +    "byIntent"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / resultCount
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / schemaVersion
        Added value: +{
        +  "const": 1,
        +  "type": "number"
        +}
      • addedOutput schema / properties / status / enum
        Added value: +[
        +  "ok",
        +  "partial"
        +]
      • addedOutput schema / properties / tenantId
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "status"
        -]New value: +[
        +  "status",
        +  "schemaVersion",
        +  "tenantId",
        +  "resultCount",
        +  "nextCursor",
        +  "coverage",
        +  "graphUsage",
        +  "pageSummary",
        +  "assignments"
        +]
    • Changedlist_unassigned_policies10 fields changed
      • addedOutput schema / properties / coverage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "authorizationContext": {
        +      "const": "delegated_may_be_rbac_filtered",
        +      "type": "string"
        +    },
        +    "continuationRequired": {
        +      "type": "boolean"
        +    },
        +    "failedCategories": {
        +      "type": "number"
        +    },
        +    "failedSources": {
        +      "type": "number"
        +    },
        +    "pendingCategories": {
        +      "type": "number"
        +    },
        +    "sources": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "code": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "requestIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "source",
        +          "status",
        +          "code",
        +          "requestIds"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    "successfulCategories": {
        +      "type": "number"
        +    },
        +    "successfulSources": {
        +      "type": "number"
        +    },
        +    "totalCategories": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "status",
        +    "continuationRequired",
        +    "authorizationContext",
        +    "successfulCategories",
        +    "failedCategories",
        +    "pendingCategories",
        +    "totalCategories",
        +    "successfulSources",
        +    "failedSources",
        +    "sources"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / graphUsage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "calls": {
        +      "type": "number"
        +    },
        +    "elapsedMs": {
        +      "type": "number"
        +    },
        +    "pages": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "calls",
        +    "pages",
        +    "elapsedMs"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / nextCursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / pageSummary
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "byCategory": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "value",
        +          "count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "byPlatform": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "count": {
        +            "type": "number"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          }
        +        },
        +        "required": [
        +          "value",
        +          "count"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "policies": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "policies",
        +    "byCategory",
        +    "byPlatform"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / records
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "categoryId": {
        +        "type": "string"
        +      },
        +      "displayName": {
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "platform": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "roleScopeTagIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "id",
        +      "displayName",
        +      "categoryId",
        +      "platform",
        +      "roleScopeTagIds"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / resultCount
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / schemaVersion
        Added value: +{
        +  "const": 1,
        +  "type": "number"
        +}
      • addedOutput schema / properties / status / enum
        Added value: +[
        +  "ok",
        +  "partial"
        +]
      • addedOutput schema / properties / tenantId
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "status"
        -]New value: +[
        +  "status",
        +  "schemaVersion",
        +  "tenantId",
        +  "resultCount",
        +  "nextCursor",
        +  "coverage",
        +  "graphUsage",
        +  "pageSummary",
        +  "records"
        +]
    • Changedsearch_policies9 fields changed
      • addedOutput schema / properties / coverage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "authorizationContext": {
        +      "const": "delegated_may_be_rbac_filtered",
        +      "type": "string"
        +    },
        +    "continuationRequired": {
        +      "type": "boolean"
        +    },
        +    "failedCategories": {
        +      "type": "number"
        +    },
        +    "failedSources": {
        +      "type": "number"
        +    },
        +    "pendingCategories": {
        +      "type": "number"
        +    },
        +    "sources": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "code": {
        +            "anyOf": [
        +              {
        +                "type": "string"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ]
        +          },
        +          "requestIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "source": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "source",
        +          "status",
        +          "code",
        +          "requestIds"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "complete",
        +        "partial"
        +      ],
        +      "type": "string"
        +    },
        +    "successfulCategories": {
        +      "type": "number"
        +    },
        +    "successfulSources": {
        +      "type": "number"
        +    },
        +    "totalCategories": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "status",
        +    "continuationRequired",
        +    "authorizationContext",
        +    "successfulCategories",
        +    "failedCategories",
        +    "pendingCategories",
        +    "totalCategories",
        +    "successfulSources",
        +    "failedSources",
        +    "sources"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / graphUsage
        Added value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "calls": {
        +      "type": "number"
        +    },
        +    "elapsedMs": {
        +      "type": "number"
        +    },
        +    "pages": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "calls",
        +    "pages",
        +    "elapsedMs"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / nextCursor
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / records
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "category": {
        +        "type": "string"
        +      },
        +      "categoryId": {
        +        "type": "string"
        +      },
        +      "displayName": {
        +        "type": "string"
        +      },
        +      "graphType": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "isAssigned": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "platform": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "roleScopeTagIds": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "technology": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      }
        +    },
        +    "required": [
        +      "id",
        +      "displayName",
        +      "categoryId",
        +      "category",
        +      "platform",
        +      "technology",
        +      "graphType",
        +      "roleScopeTagIds",
        +      "isAssigned"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / resultCount
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / schemaVersion
        Added value: +{
        +  "const": 1,
        +  "type": "number"
        +}
      • addedOutput schema / properties / status / enum
        Added value: +[
        +  "ok",
        +  "partial"
        +]
      • addedOutput schema / properties / tenantId
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "status"
        -]New value: +[
        +  "status",
        +  "schemaVersion",
        +  "tenantId",
        +  "records",
        +  "resultCount",
        +  "nextCursor",
        +  "coverage",
        +  "graphUsage"
        +]
  2. 3 tool updatesv0.3.0
    • Addedlist_all_device_assignments
    • Addedlist_all_user_assignments
    • Addedlist_unassigned_policies
  3. 3 tool updatesv0.1.1
    • First observedget_connection_status
    • First observedget_policy_assignments
    • First observedsearch_policies

TDQS

A4.1/5.0
Disambiguation4/5

The tools are mostly distinct: connection checking, policy search, all-device listing, all-user listing, unassigned listing, and assignment lookup are separable operations. However, list_all_device_assignments, list_all_user_assignments, and list_unassigned_policies all return similar record shapes (policyId, pageSummary, coverage, cursor), which could cause an agent to conflate which list answers a given question.

Naming Consistency4/5

Seven of the expected tools use a consistent verb_noun pattern (get_connection_status, search_policies, list_all_device_assignments, list_all_user_assignments, list_unassigned_policies, get_policy_assignments). The naming is coherent and predictable, with only minor asymmetry around 'list_*' versus 'get_*' for read operations.

Tool Count5/5

Six tools is a well-scoped surface for an Intune assignment checker. Each tool fills a distinct role in the query workflow: authentication check, policy discovery, assignment targeting, and detailed assignment retrieval. The count is within the ideal 3-15 range and nothing feels redundant or missing at a coarse level.

Completeness3/5

The server covers the core assignment-checking workflow well: search, list by target, list unassigned, and get detailed assignments for one policy. However, there are notable gaps in the lifecycle—there is no way to see assignments for a specific discovered group beyond the single-policy lookup, no bulk get across multiple policies, and no overview/hierarchy tool that aggregates coverage. The domain is inherently about analysis, so create/update/delete don't apply, but the query surface has some dead ends (e.g., get_policy_assignments requires already knowing exact policyId and category from another tool).

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    A Model Context Protocol server for Microsoft 365 administration using Graph API application permissions, enabling security monitoring, identity audits, incident response, and service health management.
    169
    12
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A local MCP server for read-only SQL Server / MS Fabric queries. It authenticates as the user via Entra ID and runs one server process per tenant.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for managing Microsoft Intune and Entra ID via the Microsoft Graph API, offering 34 tools for device, app, compliance, security, identity, and reporting operations.
    1
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    A read-only MCP server for Microsoft Intune and Entra ID that enables list, get, search, and reporting operations for tenant visibility, audits, troubleshooting, and health reporting without write actions. It includes authentication helpers, report exports, and metadata discovery tools.
    36
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ugurkocde/IntuneAssignmentChecker-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server