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.
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:| Relationship | Who configures it | In this test |
|---|---|---|
| Client ↔ IdP | Enterprise SSO registration | Simulated — the CLI is the IdP, so this leg always succeeds |
| RAS ↔ IdP | Your authorization server trusts the IdP’s issuer + JWKS | You set this up once (see below) |
| Client ↔ RAS | OAuth client registration at your authorization server | Exercised per run via --registration |
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
Registration strategies
--registration selects how the CLI identifies itself to your authorization
server, mirroring the client-registration models MCP clients use:
| Strategy | Credentials needed | Posture notes |
|---|---|---|
preregistered (default) | --client-id (+ optional --client-secret) | Matches the draft’s recommended deployment |
dcr | none | A diagnostic: the CLI performs open RFC 7591 registration and supplies the IdP→RAS client mapping itself. Each run may leave a registration behind. RFC 7591 conformance findings (e.g. missing Cache-Control: no-store) are reported as warnings |
cimd | none | Public client by default — the run completes but is flagged: the draft recommends confidential clients |
cimd + --client-auth private-key-jwt | none | Confidential CIMD: the CLI generates a local EC P-256 key, publishes it through the hosted reflector, and signs a client_assertion. The private key never leaves your machine |
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.

