Inforcer MCP Tools & API Patterns
Overview
The Inforcer MCP server exposes a read-only Microsoft 365 security baseline governance surface for MSPs — managed tenants, baseline templates, alignment/drift, secure scores, identity inventory, and audit events — plus exactly one write action: triggering an assessment run. Read this skill first; the other Inforcer skills build on the connection, envelope, and tenant-id conventions described here.
Community-sourced API caveat. Inforcer publishes no official public API documentation. The API surface modelled here is community-sourced from the
royklo/InforcerCommunityproject. Endpoint paths, field names, and behaviour may change without notice. Tool names below are illustrative of the MCP surface, not a guaranteed contract.
Connection & Authentication
The gateway authenticates to Inforcer using two credentials, each
on its own X- header:
| Gateway header | Env var | Value |
|---|---|---|
X-Inforcer-Region |
INFORCER_REGION |
One of us, uk, eu, anz (required) |
X-Inforcer-Api-Key |
INFORCER_API_KEY |
Your raw Inforcer API key |
export INFORCER_REGION="us" # or uk / eu / anz
export INFORCER_API_KEY="your-inforcer-api-key"
The .mcp.json substitutes ${INFORCER_REGION} and
${INFORCER_API_KEY} into the X-Inforcer-Region and
X-Inforcer-Api-Key headers respectively.
What the MCP server does upstream
The gateway-facing X- headers are not what Inforcer's own API
expects. The MCP server translates them:
- Region → base URL host.
X-Inforcer-Regionselects the regional host. The upstream base URL ishttps://api-{region}.inforcer.com/api, e.g.https://api-us.inforcer.com/api. Region is required — there is no default host. - API key → upstream header.
X-Inforcer-Api-Keyis forwarded upstream as the customInf-Api-Keyheader that Inforcer's API actually reads.
You never set Inf-Api-Key or the base URL yourself — the MCP server
handles both. You only need the two X- headers (via the env vars).
Route prefix
Many Inforcer routes live under a /beta/ path prefix (the beta
API), e.g. https://api-{region}.inforcer.com/api/beta/.... The MCP
server builds these paths for you, but be aware that the surface is a
beta API and may evolve.
Response envelope
Inforcer responses are wrapped in a consistent envelope:
{
"success": true,
"message": "OK",
"errors": [],
"data": [ ... ]
}
| Field | Meaning |
|---|---|
success |
Boolean — whether the call succeeded |
message |
Human-readable status string |
errors |
Array of error detail (empty on success) |
data |
The actual payload (object or array) |
Always read from data. Treat success: false (or a non-empty
errors) as a failure even if an HTTP 200 came back.
Pagination
List endpoints paginate with a continuationToken:
- A response may include a
continuationToken. Pass it back on the next request to fetch the following page. - Absence of a
continuationTokenmeans you are on the last page.
Loop until no continuationToken is returned before claiming a result
set is complete — especially for portfolio-wide reports where a partial
page silently understates drift or inventory.
The Client Tenant ID gotcha
Tenant-scoped Inforcer paths take an integer Client Tenant ID — not the Azure AD tenant GUID and not the tenant domain.
| Identifier | Works in the path? |
|---|---|
Integer Client Tenant ID (e.g. 1423) |
Yes — this is what the path expects |
Azure AD tenant GUID (00000000-…) |
No — must be resolved to the integer id |
Tenant domain (contoso.onmicrosoft.com) |
No — must be resolved to the integer id |
Friendly display name (Contoso) |
No — must be resolved to the integer id |
The MCP server resolves friendly names, DNS domains, and Azure AD
GUIDs to the integer Client Tenant ID for you, so you can refer to a
tenant naturally. But the underlying API path is the integer id. If a
tenant-scoped call returns nothing, the most common cause is that a
GUID or domain reached the path without being resolved to the integer
Client Tenant ID — re-resolve via inforcer_tenants_list (see
tenant-management).
Error Handling
| Status | Meaning | Action |
|---|---|---|
| 400 | Bad request — often a malformed tenant id (GUID/domain where an integer is expected) | Resolve to the integer Client Tenant ID and retry |
| 401 | Missing or invalid API key | Re-check INFORCER_API_KEY → X-Inforcer-Api-Key (forwarded as Inf-Api-Key) |
| 403 | Key valid but not authorized for this resource/region | Check the key's scope and that INFORCER_REGION matches the key's region |
| 404 | Unknown tenant / baseline / assessment id | Re-list to confirm the id exists; check you used the integer Client Tenant ID |
| 429 | Rate limit | Back off and retry |
success: false in a 200 body |
Application-level failure | Read message and errors; do not trust data |
Best Practices
- Treat almost every Inforcer tool as read-only. The single
mutation is
inforcer_assessments_run— flag it explicitly before invoking (see assessments). - Always confirm
INFORCER_REGIONis set and matches the key's region — a missing or wrong region points the MCP server at the wrong host. - Page to completion using
continuationTokenbefore reporting totals. - Never pass a GUID or domain into a tenant-scoped path expecting it to work — resolve to the integer Client Tenant ID first.
- Remember the API is community-sourced; verify surprising shapes
against the
royklo/InforcerCommunityproject rather than assuming a stable contract.
Related Skills
- tenant-management - listing tenants and resolving names to the integer Client Tenant ID
- baseline-alignment - baselines, alignment scores, and per-policy drift detail
- compliance-reporting - secure score and posture roll-up with alignment thresholds
- identity-governance - users, groups, and roles inventory
- audit-events - searching audit events and listing event types
- assessments - listing and running assessments (the one write action)