CLI
The npm package ships an mcp-authz binary. It reads a JSON policy file, so a
Python project can use it on the same file.
explain
Section titled “explain”npx mcp-authz explain policy.json --identity alice.json --capabilities caps.jsonalice@acme.com
Matched rules rule 0 domain=acme.com -> reader rule 1 email=alice@acme.com -> editor rule 2 org.groups=qa-leads -> admin
Effective roles reader editor admin
Permissions cases:read cases:write * (every permission)
Capabilities get_case update_case prompt:triage_case--identity takes an Identity or a decoded token payload (iss, sub,
email, email_verified, hd), or - to read one from stdin. It answers a
what-if, so it trusts the file it is handed rather than verifying a signature.
npx mcp-authz check policy.json --capabilities caps.json--capabilities is the map naming every capability the server registers. Read it
off the server with recordCapabilities
rather than maintaining it by hand.
npx mcp-authz check policy.json --capabilities caps.jsoncheck runs the same reconciliation your server runs at boot, so a capability
no role can reach fails the pull request rather than the deploy.
It exits 1 on that and on an invalid policy, and 0 on an unused permission, which stays a warning because granting a role ahead of the tool that will use it is how a staged rollout works.
record
Section titled “record”Record the capabilities an MCP server exposes into a permission-map module:
# In-process factory (connector module exporting a server builder).npx mcp-authz record ./connector.ts --out permissions.ts
# URL-only upstream (service credential).npx mcp-authz record \ --upstream https://vendor.example.com/mcp \ --token "$UPSTREAM_TOKEN" \ --out permissions.tsThe module carries PERMISSIONS, DEFINITIONS (each capability’s definition as
served, and the server’s instructions as 'server:instructions' when it gives
any) and, when the server has resources, RESOURCE_URIS.
--upstream connects as an MCP 2026-07-28 client, so it works against a server
that speaks only that. A connector module is recorded in process, in whichever
version the server negotiates.
--check permissions.ts compares the live catalogue and definitions to a
committed file and exits 1 on drift — the usual CI guard before deploy or before
standing up a proxy. For each changed capability
it prints the fields that changed, with was: and now: lines, and a ⚠ line
when the new text looks like it is addressed to the model. Changed instructions
show as ~ server instructions. A priced capability that DEFINITIONS has no
record of fails too (? name … priced, but DEFINITIONS has no record of it), so
a map with no DEFINITIONS fails.
tools and wrap
Section titled “tools and wrap”npx mcp-authz tools --out some.jsonc [--client-out .mcp.json] -- npx -y some-mcpnpx mcp-authz tools --check some.jsoncnpx mcp-authz tools --refresh some.jsoncnpx mcp-authz wrap some.jsoncSave a stdio server’s tools as a config, check it against the server, and run
the server with only the tools it lists. wrap <file> and tools --check
refuse to start without the record tools writes beside the config. See
Trim a server’s tools.
In code
Section titled “In code”policy.explain(identity) answers the same question inside a process, and
nothing on the request path calls it. See
Policies.