mcpjam xaa run drives a complete Cross-App Access flow, the
Identity Assertion Authorization Grant
(ID-JAG, an active IETF Internet-Draft), against your authorization server and
MCP server. MCPJam plays the enterprise identity provider (it mints and
signs the ID-JAG) and the client/agent (it redeems the ID-JAG and calls
your MCP server with the resulting access token). Your authorization server
and MCP server are the system under test.
Recommended: use with Agent Skills
The easiest way to use the CLI is through the MCPJam skill, which gives your agent full context on every command and workflow.mcpjam commands
automatically, and how to read xaa run output conservatively (advertisement
is evidence, redemption is the verdict; an issuer it can’t reach is your setup,
not a server bug).
The three parties
Cross-App Access separates trust into three relationships that are easy to conflate. The CLI covers two of them and simulates the third:Before you run: make the issuer reachable
The CLI signs ID-JAGs with a local key pair (~/.mcpjam/xaa-idp-private.pem;
override the directory with XAA_IDP_KEY_DIR). Your authorization server must
be able to fetch the matching public key, so --issuer-base-url must be an
origin that publishes that same key, not your real IdP’s URL.
The local MCPJam inspector serves exactly this: it publishes the issuer
metadata and JWKS from the same key directory at
/api/mcp/xaa/.well-known/openid-configuration and
/api/mcp/xaa/.well-known/jwks.json, no authentication required.
- Local authorization server: pass
--issuer-base-url http://localhost:6274/api/mcp. - Cloud authorization server: it cannot reach your localhost. Expose the inspector origin through a tunnel and pass the public origin instead.
<issuer-base-url>/xaa as an ID-JAG issuer and point it at the JWKS URL above.
The first flow step, verify_issuer_publication, fails fast if the issuer
origin is unreachable or publishes a different key. Nothing is sent to your
servers until it passes.
What a run checks
Each run walks the grant chain and reports every step:verify_issuer_publication: the configured issuer publishes the CLI’s local signing keydiscover_resource_metadata: protected-resource metadata (RFC 9728) names the authorization server protecting--urldiscover_authz_metadata: authorization-server metadata (RFC 8414) provides the token endpoint and capability advertisementsmint_id_jag: the mock IdP exchanges the simulated user’s identity assertion for an ID-JAG (typ: oauth-id-jag+jwt, audience = your authorization server,resource= your MCP server)redeem_id_jag: the ID-JAG is presented at your token endpoint via the JWT bearer grant (RFC 7523); your server validates it and issues its own access tokenauthenticated_mcp_request: an MCPinitializewith the issued token, advertising the Enterprise-Managed Authorization extension
advertised, not_advertised
(the metadata key was present but did not include the expected value), or
unknown (the metadata key was absent entirely). unknown is weaker evidence
than not_advertised. The two are not equivalent.
The decoded ID-JAG claims and a local signature-verification verdict
(idJag.verified) are included in the result so you can inspect exactly what
your authorization server received. idJag.verified confirms the CLI’s own
mint was well-formed and correctly signed; it is not evidence that your
authorization server validated the assertion. The AS’s behavior is in the
redemption block. Raw tokens, assertions, and secrets are always
[REDACTED] in the output, including when a server reflects them back inside
an error body.
Registration strategies
--registration selects how the CLI identifies itself to your authorization
server, mirroring the client-registration models MCP clients use:
The
registration.warnings[] array in the result uses these codes:
For confidential CIMD, the key is the identity: the reflector URL derived
from the public key becomes the
client_id. Deleting
~/.mcpjam/xaa-client-private.pem (or changing XAA_CLIENT_PRIVATE_KEY)
mints a new identity, and any allowlisting on your authorization server must
be updated.
Identity assertion formats
--assertion-format selects the identity rail the simulated enterprise uses:
oidc(default): the mock IdP mints an OIDC ID token as the token-exchange subject token.saml: the mock IdP mints a SAML 2.0 assertion as the subject token, and the ID-JAG carries asaml-nameidsub_idclaim so a SAML-federated authorization server can resolve the user.
--sub (and optionally --email) to control the simulated user, and
--scopes for the permissions requested in both the ID-JAG and the token
request.
Scenarios
First run against a local authorization server
Confidential client without pre-registration
SAML-federated enterprise
CI
The JSON result goes to stdout; progress and advisory notes go to stderr. The exit code is0 when the flow completes and 1 otherwise, so a run can gate
a pipeline directly. Pass --quiet to suppress the advisory notes.
Skipping discovery
--authz-server-issuerpins the authorization server and skips protected-resource discovery (useful while your MCP server’s RFC 9728 metadata is still in progress).--token-endpointpins the token endpoint and skips authorization-server discovery entirely. Not valid withdcrorcimd, which need the metadata document for the registration endpoint / CIMD advertisement.--https-onlyrejects non-HTTPS and private targets; by default the CLI allowshttp://localhostfor local development.

