Skip to main content
Use runEmulatedOAuthPreflight to execute an emulated client’s authentication ladder against a real MCP server, headlessly. The runner compiles an evidence-backed OAuth profile into ordered attempts, executes each one over the hardened OAuth networking path, and returns a structured result with three independent dimensions: outcome, coverage, and comparison.
runEmulatedOAuthPreflight is Node-only. The redirect-planning utilities (planCompletionSafeRedirects, isInvalidRedirectUriRejection) and their types are also exported from the browser-safe entry point.

Import


Quick start


runEmulatedOAuthPreflight

EmulatedOAuthPreflightConfig

EmulatedOAuthPreflightOutcome

EmulatedOAuthPreflightResult

EmulatedAuthAttemptResult


Attempt ladder

The authModel field of an OAuth profile compiles into an ordered attempt ladder. The runner executes each rung in sequence, with these fallback rules:
  • Consecutive oauth2-* entries collapse into one OAuth attempt carrying their relative order as a registration preference. A client that lists ["oauth2-cimd", "oauth2-dcr"] performs a single OAuth dance preferring CIMD, not two separate dances.
  • api-key and none stay in position as direct MCP probes, so a “static bearer first, OAuth on 401” client reproduces that sequence exactly.
  • A static credential falls through to OAuth only on a 401. Any other status stops the ladder.
  • An OAuth attempt falls through to the next strategy only while nothing has been committed on the wire — once a registration request has been sent or authorization has begun, failure stops the ladder.
When authModel has no evidence, the runner uses MCPJam’s own AUTO precedence: preregisteredcimddcr, filtered to what the negotiated protocol version supports.

Completion-safe redirects

The runner must replay the real client’s registration body while still finishing the dance with a real token. It resolves this with planCompletionSafeRedirects:
  • The registration body carries the captured redirect_uris in captured order, with MCPJam’s callback appended. The appended entry is a declared divergence.
  • The authorization and token legs always use MCPJam’s callback, so the code comes back and can be exchanged.
  • If the server rejects the registration with a structured RFC 7591 invalid_redirect_uri (exactly HTTP 400 with { "error": "invalid_redirect_uri" }), the runner re-registers with MCPJam’s callback alone. That is the second and final registration a run will ever perform.

planCompletionSafeRedirects

Input: Output (CompletionSafeRedirectPlan):

isInvalidRedirectUriRejection

Returns true only when a registration response is exactly HTTP 400 with { "error": "invalid_redirect_uri" } in the body — the structured RFC 7591 error that authorizes a retry. Any other status or body shape returns false.

Diagnostics hygiene

Credentials are returned once, in result.credentials, and are kept out of every other surface:
  • result.attempts[*].httpHistory is redacted — no tokens, codes, secrets, or PKCE values.
  • A caller-supplied staticCredential is scrubbed by header name and value before the generic redactor runs, because no generic redactor can know an unconventional header name like X-Acme-Tenant-Token.
  • result.comparison is always "not_compared" — a run never claims parity with a golden trace on its own.