mcp-defender-xdr
An MCP server that exposes Microsoft Defender XDR — Advanced Hunting KQL, incidents, and alerts — to Claude. Read-only, certificate auth, multi-tenant.
What it does
Three read-only tools against the Defender for Endpoint / Graph
Security APIs: run an Advanced Hunting KQL query, list and read
incidents, list and read alerts. Each tool takes an optional tenant
parameter. Omit it and the call goes to the default tenant. Name a
tenant from the config to switch. Pass "*" to run the same query
across every configured tenant. The server runs locally over stdio and
plugs into Claude Desktop or Claude Code with the standard MCP config.
Auth is OAuth 2.0 client credentials with an X.509 certificate per
tenant — no shared client secrets.
Why I built it
As a cyber lead at Propulsion, I spend time managing events across multiple Microsoft tenants at the same time. Microsoft Defender’s UI is single-tenant per session, so the pivots are manual: switch tenant, re-run the KQL, copy a host name into a new tab, open the incident, back to KQL. The Graph API does all of this already — wrapping it isn’t where the work is. The work is what makes it safe to point a model at a tenant: certificate auth instead of a shared client secret, a tenants config that refuses to load with the wrong file permissions, every Graph response treated as untrusted before it goes back into the prompt. Most of the time on this went into the auth and the trust boundary, not the tools themselves.
Status
v0.1.0 shipped 2026-05-12, MIT. v0.2 adds per-tool audit logging and starts on the OWASP MCP Top 10 — tool description integrity and KQL result sanitization first.
Threat model
Read-only by construction — the three Graph permissions are all `*.Read.All`, so nothing the model invokes can change tenant state. Auth is OAuth 2.0 client credentials with an X.509 certificate per App Registration; no shared client secrets, no on-behalf-of flow. The multi-tenant JSON config refuses to load if its POSIX permissions are looser than `0600`. Every Graph response is treated as untrusted before it goes back to the model. The wider OWASP MCP Top 10 surface — tool poisoning, confused deputy, indirect prompt injection — comes in v0.2 and v0.3; v0.1 ships the read-only base those controls sit on top of.