Skip to main content
Glama
shigechika

entraadm-mcp

by shigechika

signin_failure_stats

Aggregate tenant-wide Entra ID sign-in failures by AADSTS code, top users, apps, and source IPs; flag IPs spraying passwords across multiple accounts.

Instructions

Tenant-wide sign-in failure aggregation -- the Entra ID counterpart to the RADIUS failure patrol.

Time-bounded (ENTRAADM_DEADLINE, default 45 s): on a wide window or a busy day the scan stops early and capped=true marks the counts as a lower bound; narrow hours for a full count.

Aggregates failed sign-ins across the whole tenant into four views: top AADSTS error codes (with the same meaning annotations as signin_logs), top failing users, top applications, and top source IPs. spray_suspects flags any IP with failed sign-ins against 5 or more distinct users -- Entra's smart lockout is per-account, so a low-and-slow password spray from one IP across many accounts does not trip it the way a brute force against one account does; this is the observation a per-account view cannot make on its own. This mirrors the KeyCloak-side spray detection this fleet already relies on; neither the official Microsoft MCP Server for Enterprise nor Graph itself offers this aggregation.

When ENTRAADM_SITES_INI names the tenant's own address ranges, IPs inside them get site (and site_name) in top_ips, and suspects inside them move from spray_suspects to internal_spray_suspects: a NAT egress or a room of shared workstations fails for many users every day, and would otherwise bury an outside source. Internal suspects are kept, not dropped, because an internal host can be compromised too. sites reports whether the file loaded; an invalid CIDR is reported in sites.error while the valid ranges are still used, and a file that cannot be read leaves every IP in spray_suspects.

Read-only (AuditLog.Read.All application permission, or -- for azure-cli auth -- the Reports Reader directory role). Graph cannot filter sign-ins on status/errorCode server-side, so this walks up to max_pages of the full sign-in log for the window and aggregates client-side -- capped=true means the page budget ran out before the window was fully scanned, so the counts below are a sample of the window, not a census of it.

Args: hours: How far back to look, clamped to [1, 720] (30 days). max_pages: Page budget (default: ENTRAADM_MAX_PAGES_DEFAULT). tenant: Tenant to read: a [tenant.] section name or one of its domains (default: the default tenant).

Input Schema

NameRequiredDescriptionDefault
hoursNo
tenantNo
max_pagesNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv1.8.0
    • addedInput schema / properties / tenant
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Tenant"
      +}
  2. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so: it discloses the read-only permission model (AuditLog.Read.All or Reports Reader), the ENTRAADM_DEADLINE cap and `capped=true` lower-bound semantics, the page-budget sampling behavior, and the fact that Graph cannot filter on status/errorCode server-side. Failure modes for the sites file (invalid CIDR still uses valid ranges, unreadable file demotes all IPs to `spray_suspects`) are also spelled out.

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

Conciseness3/5

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

Purpose and the time-bound caveat are front-loaded, but the text is roughly 400 words for a three-parameter tool. The `capped=true` lower-bound/sample explanation appears twice, and the paragraph about RADIUS/KeyCloak parity and the official Microsoft MCP Server is vendor positioning rather than agent-relevant instruction.

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?

There is no output schema, yet the description fully describes the returned views (`top_ips`, `spray_suspects`, `internal_spray_suspects`, `sites`/`sites.error`) and what the spray flag means. Combined with permissions, deadline behavior and degradation paths, an agent has everything needed to call and interpret it.

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

Parameters5/5

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

Schema coverage is 0%, so the description must compensate and does: `hours` is documented with its [1, 720] clamp, `max_pages` with its environment-variable default, and `tenant` with the accepted forms ([tenant.<name>] section or domain) and the default tenant fallback. Every parameter gains meaning not present in the bare schema.

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?

Names a specific verb and resource — tenant-wide aggregation of failed sign-ins — and enumerates the four output views (AADSTS codes, failing users, apps, source IPs). Explicitly distinguishes itself from sibling `signin_logs` (which it references for error-code meanings) and from per-account/per-IP views, so an agent can route correctly 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.

Usage Guidelines4/5

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

Gives concrete operational guidance — narrow `hours` when the scan caps and you need a census rather than a sample, and the tool is positioned as the failure/spray counterpart to the success statistics and per-IP siblings. It lacks an explicit 'do not use this when…' exclusion (e.g. use `signin_logs` for individual event detail), which keeps it from a 5.

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