import { a as RetryPolicy } from './types-CI0Xyszt.js'; import { O as OAuthScopeRequest, k as OAuthTokenEndpointAuthMethod } from './types-HXAijHji.js'; type ResourceIndicatorSource = "prm" | "authorization" | "configured" | "server"; type ResourceIndicatorStatus = "valid" | "incompatible" | "invalid"; interface ResourceIndicatorDecision { /** * The value to send on the wire: the advertised candidate verbatim * (trimmed), or the canonicalized server URL for the `server` fallback. */ value: string; source: ResourceIndicatorSource; status: ResourceIndicatorStatus; /** * Whether the value also passes the official MCP SDK's strict binding * (origin equality AND the advertised path is a prefix of the server URL's * path). Always false when `status` is not `valid`. */ strictClientCompatible: boolean; /** * Whether the value satisfies the RFC 9728 requirements this evaluator can * determine from the resource and server URLs: HTTPS, no fragment, and the * official MCP SDK's server/path binding. This is deliberately separate * from `status`: an HTTP or same-origin non-prefix value can be safe enough * for an interoperability-first surface to try while still being unsuitable * for a conformance result. */ rfc9728Compliant: boolean; /** Human-readable explanation when `rfc9728Compliant` is false. */ rfc9728Reason?: string; /** Human-readable explanation when not fully valid/strict. */ reason?: string; } interface EvaluateResourceIndicatorInput { serverUrl: string; /** `resource` from the server's Protected Resource Metadata. */ prmResource?: string; /** `?resource=` recovered from a previously built authorization URL (callback paths). */ authorizationUrlResource?: string; /** Caller-configured override. */ configuredResource?: string; } declare function canonicalizeResourceUrl(url: string): string; /** * Convenience for flow-state readers: prefer the decision persisted at PRM * discovery, re-evaluate when the flow was seeded past discovery, and fall * back to the raw PRM value only when no server URL is known at all. * With a `serverUrl` present the result is always a string. */ declare function resolveResourceIndicatorValue(input: { serverUrl: string; prmResource?: string; resolved?: ResourceIndicatorDecision; }): string; declare function resolveResourceIndicatorValue(input: { serverUrl?: string; prmResource?: string; resolved?: ResourceIndicatorDecision; }): string | undefined; /** * Resolve the resource indicator once. Precedence: PRM-advertised value, then * the value recovered from an authorization URL, then a configured override, * then the (canonicalized) server URL itself. The first present candidate * wins and is evaluated against the server URL; later candidates are never * considered as fallbacks for an invalid earlier one — a broken advertised * value is a finding, not something to silently paper over. */ declare function evaluateResourceIndicator(input: EvaluateResourceIndicatorInput): ResourceIndicatorDecision; /** * OAuth client emulation — knob, coverage, and attempt types (HP-43). * * `OAuthEmulationConfig` is the ONLY thing the four debug OAuth state * machines see: generic wire knobs, derived from an evidence-backed * `HostConfigOAuthProfileV1|V2` by `deriveOAuthEmulation`. Client names and * profile records live in the private backend; this module is deliberately * client-name-free and pure (browser-safe, type-only imports). * * Every knob is optional and absent-by-default: an `undefined` knob (or an * absent `emulation` object) means the machine behaves exactly as today — * the no-emulation goldens in tests/oauth/no-emulation-goldens.test.ts pin * that contract. */ /** * Wire-level knobs consumed by the state machines via * `BaseOAuthStateMachineConfig.emulation`. */ interface OAuthEmulationConfig { /** * RFC 8707 resource indicator on the authorization URL and token request. * `false` → omitted at every wire site AND every display/info-log echo * (a display claiming a `resource` the wire does not carry would lie). * `true`/`undefined` → today's per-version behavior. */ sendResourceIndicator?: boolean; /** * Pin the MCP leg's protocol version: the `MCP-Protocol-Version` header on * MCP requests (probe + authenticated verification), the `initialize` body * `protocolVersion`, and the 2026-07-28 stateless `_meta` version. Free-form * revision string — a client can pin a revision this inspector does not * speak. The OAuth discovery ladder is NOT affected: that is selected by * the machine version (`oauthSpecVersion` → `deriveOAuthEmulation`). */ mcpProtocolVersion?: string; /** * Scope policy applied at every scope-emitting wire site (DCR registration * metadata and the authorization URL). Absent → today's precedence * (custom → challenged → supported). */ scopeRequest?: OAuthScopeRequest; /** * Byte-exact DCR `client_name` replay. Self-asserted metadata (RFC 7591) — * replayed exactly because servers in the wild gate on it; never used for * authorization policy on our side. */ dcrClientName?: string; /** Client `User-Agent` replay, merged into every request's headers. */ userAgent?: string; /** * Force the token-endpoint auth method, reflected in BOTH the DCR * registration metadata and the token request's client authentication. */ tokenEndpointAuthMethod?: OAuthTokenEndpointAuthMethod; /** * `redirect_uris` for the DCR registration body ONLY — the authorization and * token legs always use the machine's own `redirectUrl`. * * This asymmetry is the completion-safe design, not an oversight: the * registration body replays what the real client registers, while the code * still comes back to a callback MCPJam controls so the flow can finish with * a real token. Callers should not set this directly from a captured * profile — `planCompletionSafeRedirects` builds the value that keeps the * flow completable (see `emulation/redirects.ts`). */ dcrRedirectUris?: string[]; } /** A registration strategy an emulated client may prefer, in profile order. */ type EmulatedRegistrationPreference = "preregistered" | "dcr" | "cimd"; /** * One rung of the emulated client's authentication ladder, derived from the * profile's ordered `authModel`. * * Consecutive `oauth2-*` entries collapse into a single `oauth` attempt whose * `registrationPreference` preserves their relative order: they are one OAuth * dance with a strategy preference, not several independent attempts. * `api-key` and `none` are not registration strategies and never enter the * authorization plan — the runner executes them as direct MCP requests. */ type EmulatedAuthAttempt = { kind: "oauth"; registrationPreference: EmulatedRegistrationPreference[]; } | { kind: "api-key"; } | { kind: "none"; }; /** Profile fields the emulator can enforce. */ declare const OAUTH_EMULATION_FIELDS: readonly ["sendsResourceIndicator", "oauthSpecVersion", "protocolVersionPinning", "scopeRequest", "dcrIdentity", "tokenEndpointAuthMethod", "authModel"]; type OAuthEmulationField = (typeof OAUTH_EMULATION_FIELDS)[number]; /** * `modeled` — evidence-backed value compiled into a knob. * `not_modeled` — missing or unverifiable evidence: the run continues with * normal MCPJam behavior for that dimension, coverage becomes partial, and * parity can never be claimed for it. Never a silent default. */ type OAuthEmulationFieldStatus = "modeled" | "not_modeled"; type OAuthEmulationCoverage = Record; /** * A declared, deliberate difference between what the real client does and what * the emulated run did. Every one is reported: a run that diverged can never * be presented as an unqualified byte-for-byte match. */ interface OAuthEmulationDivergence { kind: "version-narrowed" /** MCPJam's callback appended to the captured registration redirect list. */ | "redirect-uri-appended" /** DCR re-sent with our callback only, after a structured * `invalid_redirect_uri` rejection (RFC 7591). */ | "dcr-retried" /** CIMD / pre-registered identity is MCPJam's, not the real client's. */ | "identity-substituted" /** Evidence exists but this step does not enforce it. */ | "not-enforced"; /** Human-readable, includes requested vs used values where applicable. */ detail: string; requested?: string; used?: string; } /** * Shared conformance policy for metadata an MCP authorization profile REQUIRES * a client to verify before it sends the user to an authorization server. * * Two checks live here. They are NOT gated on the same eras, because the spec * text behind them does not have the same history — one gate covering both * would either miss an era that genuinely states the requirement or invent one * for an era that is silent: * * - Protected-resource metadata. RFC 9728's `authorization_servers` is where * the resource says who may issue tokens for it. Substituting the MCP * server's own URL when the list is missing invents an authorization server * the resource never named, and the substitution is invisible in the trace. * Required from 2025-06-18 onward: that revision already said the PRM * document "MUST include the `authorization_servers` field containing at * least one authorization server," and 2025-11-25 and 2026-07-28 repeat it * verbatim. * - PKCE. The client must verify that the authorization server advertises * S256 in `code_challenge_methods_supported` before proceeding. A server * that advertises only `plain` cannot give the flow the protection PKCE * exists for, and a client that proceeds anyway has silently downgraded. * Gated at 2025-11-25 because 2025-06-18 says nothing at all about * `code_challenge_methods_supported` — staying silent there is the * version-faithful behavior, not a gap. * * `enforcement` exists because MCPJam is also a debugger, and the whole point * of pointing it at a half-built server is to SEE what that server does. But * that is a non-connect intent and has to be asked for: the default fails * closed, and only a surface that explicitly passes `"observe"` gets the * warn-and-continue behavior. */ /** * Rejection message for authorization-server metadata without RFC 8414's * REQUIRED `issuer`. Every era's machine throws it verbatim. * * A constant rather than four literals because consumers match on the exact * text: the inspector keeps this failure out of its own error reporting (it is * the server under test that is nonconforming, not MCPJam), and a rephrasing on * one side would silently break that match. One export, no drift. */ declare const AUTHORIZATION_SERVER_METADATA_MISSING_ISSUER = "Authorization server metadata missing required 'issuer' field"; type RequiredMetadataEnforcement = /** Fail closed. The default, and what every connect-like path uses. */ "reject" /** Warn and continue so the debugger can show nonconforming behavior. */ | "observe"; /** * Shared types for OAuth state machines */ type MaybePromise = T | Promise; type OAuthAuthMode = "interactive" | "headless" | "client_credentials"; type OAuthFlowStep = "idle" | "request_without_token" | "received_401_unauthorized" | "discovery_start" | "request_resource_metadata" | "received_resource_metadata" | "request_authorization_server_metadata" | "received_authorization_server_metadata" | "cimd_prepare" | "cimd_fetch_request" | "cimd_metadata_response" | "request_client_registration" | "received_client_credentials" | "generate_pkce_parameters" | "authorization_request" | "received_authorization_code" | "token_request" | "received_access_token" | "authenticated_mcp_request" | "complete" | "verify_list_tools" | "verify_call_tool"; interface OAuthFlowState { isInitiatingAuth: boolean; currentStep: OAuthFlowStep; serverUrl?: string; wwwAuthenticateHeader?: string; challengedScopes?: string[]; resourceMetadataUrl?: string; resourceMetadata?: { resource: string; authorization_servers?: string[]; bearer_methods_supported?: string[]; resource_signing_alg_values_supported?: string[]; scopes_supported?: string[]; }; resourceIndicator?: ResourceIndicatorDecision; resourceIndicatorSuppressed?: boolean; authorizationServerUrl?: string; authorizationServerMetadata?: { issuer: string; authorization_endpoint: string; token_endpoint: string; registration_endpoint?: string; scopes_supported?: string[]; response_types_supported: string[]; grant_types_supported?: string[]; code_challenge_methods_supported?: string[]; client_id_metadata_document_supported?: boolean; authorization_response_iss_parameter_supported?: boolean; }; clientId?: string; clientSecret?: string; tokenEndpointAuthMethod?: string; codeVerifier?: string; codeChallenge?: string; codeChallengeMethod?: string; authorizationUrl?: string; authorizationCode?: string; state?: string; recordedIssuer?: string; authorizationResponseIss?: string; requestedScopes?: string[]; accessToken?: string; refreshToken?: string; tokenType?: string; expiresIn?: number; lastRequest?: { method: string; url: string; headers: Record; body?: any; }; lastResponse?: { status: number; statusText: string; headers: Record; body: any; }; httpHistory?: Array; infoLogs?: Array; error?: string; } type InfoLogLevel = "info" | "warning" | "error"; type LogErrorDetails = { message: string; details?: unknown; }; type InfoLogEntry = { id: string; step: OAuthFlowStep; label: string; data: any; timestamp: number; level: InfoLogLevel; error?: LogErrorDetails; }; type HttpHistoryEntry = { step: OAuthFlowStep; timestamp: number; duration?: number; request: OAuthHttpRequest; response?: OAuthHttpResponse; error?: LogErrorDetails; }; interface OAuthHttpRequest { method: string; url: string; headers: Record; body?: any; /** Redirect handling for executors that proxy this request. Hosted * (httpsOnly) proxy execution always uses "manual"; otherwise an explicit * value is honored and omission preserves the historical "follow". */ redirect?: "follow" | "manual"; } interface OAuthHttpResponse { status: number; statusText: string; headers: Record; body: any; } interface OAuthRequestResult extends OAuthHttpResponse { ok: boolean; } type OAuthRequestExecutor = (request: OAuthHttpRequest) => Promise; type OAuthAutoAdvanceScheduler = (fn: () => void, delayMs: number) => void; interface OAuthDynamicRegistrationMetadata { client_name: string; client_uri?: string; logo_uri?: string; redirect_uris?: string[]; grant_types?: string[]; response_types?: string[]; token_endpoint_auth_method?: string; /** OIDC / SEP-837 client application type. */ application_type?: "native" | "web"; [key: string]: unknown; } interface PreregisteredCredentials { clientId?: string; clientSecret?: string; } type LoadPreregisteredCredentials = (input: { serverName: string; serverUrl: string; }) => MaybePromise; declare const EMPTY_OAUTH_FLOW_STATE: OAuthFlowState; interface OAuthStateMachine { state: OAuthFlowState; updateState: (updates: Partial) => void; proceedToNextStep: () => Promise; startGuidedFlow: () => Promise; resetFlow: () => void; } interface BaseOAuthStateMachineConfig { state: OAuthFlowState; getState?: () => OAuthFlowState; updateState: (updates: Partial) => void; serverUrl: string; serverName: string; redirectUrl: string; requestExecutor: OAuthRequestExecutor; scheduleAutoAdvance?: OAuthAutoAdvanceScheduler; loadPreregisteredCredentials?: LoadPreregisteredCredentials; hasClientSecret?: boolean; dynamicRegistration?: Partial; clientIdMetadataUrl?: string; customScopes?: string; customHeaders?: Record; /** * SEP-2350 step-up: an explicit protected-resource-metadata (PRM) URL to * discover from, sourced from a `WWW-Authenticate` `resource_metadata` hint * (e.g. the `403 insufficient_scope` challenge a runtime tool call surfaced). * When set, PRM discovery uses it verbatim instead of deriving the URL from * the server URL's well-known path — so a server that points its metadata * elsewhere (Asana) is honored on re-authorization. `undefined` (the default) * is today's behavior: derive from the fresh `WWW-Authenticate` header or the * server URL. The 2025-03-26 machine has no PRM step and ignores this field. * * The caller is responsible for validating this untrusted hint (the client * step-up path only threads a value on the SAME ORIGIN as the server URL); * the shared executor additionally enforces the outbound-host allowlist and * the discovery request strips MCP-server auth headers when it hops origin. */ resourceMetadataUrl?: string; authMode?: OAuthAuthMode; /** * What to do when metadata the current MCP profile REQUIRES a client to * verify is missing or unusable — the authorization server's advertised PKCE * methods, and the protected resource's `authorization_servers` list. * * `"reject"` (the default) fails closed before the browser is sent to an * authorization server, which is what every connect-like path needs. * `"observe"` warns and continues so the debugger can show a nonconforming * server's actual behavior; it is a non-connect intent and must be asked for * explicitly. Only eras governed by the current profile (2025-11-25 and * later) consult this — see `shared/required-metadata.ts`. * * Orthogonal to `strictConformance` (registration strictness) and to * `resourceIndicatorEnforcement` (the advertised resource indicator). */ requiredMetadataEnforcement?: RequiredMetadataEnforcement; strictConformance?: boolean; /** * Opt-in: accept authorization-server metadata whose advertised `issuer` is * the same-origin path-prefix ancestor (typically the origin root) of the * URL discovery started from — the shape of multi-tenant AS deployments * that scope endpoints under a path while issuing from the origin root * (e.g. Scalekit's `/resources/res_x`). Off (the default) keeps the strict * RFC 8414 §3.3 exact issuer match. Mirrors the XAA debugger's per-server * "Path-scoped authorization server" toggle. Only enforced by eras that * hard-reject the mismatch (2026-07-28); earlier machines ignore it. */ allowPathScopedIssuer?: boolean; resourceIndicatorEnforcement?: "warn" | "reject" | "reject-rfc9728"; /** * OAuth client emulation wire knobs (see oauth/emulation/) — generic, * client-name-free, derived from an evidence-backed profile by * `deriveOAuthEmulation`. Absent = exactly today's wire behavior (the * no-emulation goldens pin that contract). */ emulation?: OAuthEmulationConfig; } type RegistrationStrategy2025_03_26 = "dcr" | "preregistered"; type RegistrationStrategy2025_06_18 = "dcr" | "preregistered"; type RegistrationStrategy2025_11_25 = "cimd" | "dcr" | "preregistered"; type RegistrationStrategy2026_07_28 = "cimd" | "dcr" | "preregistered"; type OAuthProtocolVersion = "2025-03-26" | "2025-06-18" | "2025-11-25" | "2026-07-28"; interface ProbeMcpServerConfig { url: string; protocolVersion?: OAuthProtocolVersion; headers?: Record; accessToken?: string; clientCapabilities?: Record; timeoutMs?: number; fetchFn?: typeof fetch; clientName?: string; clientVersion?: string; retryPolicy?: RetryPolicy; } interface ProbeHttpAttempt { name: "streamable_initialize" | "sse_probe" | "resource_metadata" | "authorization_server_metadata"; request: { method: string; url: string; headers: Record; body?: unknown; }; response?: { status: number; statusText: string; headers: Record; body?: unknown; contentType?: string; }; error?: string; durationMs: number; } interface ProbeOAuthDetails { required: boolean; optional: boolean; wwwAuthenticate?: string; resourceMetadataUrl?: string; resourceMetadata?: Record; authorizationServerMetadataUrl?: string; authorizationServerMetadata?: Record; registrationStrategies: Array<"preregistered" | "dcr" | "cimd">; discoveryError?: string; /** * The status the challenge arrived on, when MCP does not allow it there. * Absent for a compliant 401 — set means the probe accepted a challenge the * spec says should not have been delivered this way, so callers reporting * conformance can say so rather than presenting the server as clean. */ nonCompliantChallengeStatus?: number; } interface ProbeInitializeInfo { protocolVersion?: string; serverInfo?: unknown; capabilities?: unknown; contentType?: string; } interface ProbeTransportResult { selected?: "streamable-http" | "sse"; attempts: ProbeHttpAttempt[]; } interface ProbeMcpServerResult { url: string; protocolVersion: OAuthProtocolVersion; status: "ready" | "oauth_required" | "reachable" | "error"; transport: ProbeTransportResult; initialize?: ProbeInitializeInfo; oauth: ProbeOAuthDetails; error?: string; } declare function probeMcpServer(config: ProbeMcpServerConfig): Promise; interface ServerDoctorError { code: string; message: string; details?: unknown; } interface ServerDoctorCheck { status: "ok" | "error" | "skipped"; detail: string; } interface ServerDoctorConnection { status: "connected" | "error" | "skipped"; detail: string; } interface ServerDoctorChecks { probe: ServerDoctorCheck; connection: ServerDoctorCheck; initialization: ServerDoctorCheck; capabilities: ServerDoctorCheck; tools: ServerDoctorCheck; resources: ServerDoctorCheck; resourceTemplates: ServerDoctorCheck; prompts: ServerDoctorCheck; } interface ServerDoctorResult { target: TTarget; generatedAt: string; status: "ready" | "oauth_required" | "partial" | "error"; probe: ProbeMcpServerResult | null; connection: ServerDoctorConnection; initInfo: unknown | null; capabilities: unknown | null; tools: unknown[]; toolsMetadata: Record; resources: unknown[]; resourceTemplates: unknown[]; prompts: unknown[]; checks: ServerDoctorChecks; error: ServerDoctorError | null; } interface ConnectedServerDoctorState { initInfo: unknown | null; capabilities: unknown | null; tools: unknown[]; toolsMetadata: Record; resources: unknown[]; resourceTemplates: unknown[]; prompts: unknown[]; checks: Pick; errors: ServerDoctorError[]; } declare function normalizeServerDoctorError(error: unknown): ServerDoctorError; export { AUTHORIZATION_SERVER_METADATA_MISSING_ISSUER as A, type OAuthRequestResult as B, type ConnectedServerDoctorState as C, type OAuthStateMachine as D, EMPTY_OAUTH_FLOW_STATE as E, type ResourceIndicatorDecision as F, type ResourceIndicatorSource as G, type HttpHistoryEntry as H, type InfoLogEntry as I, type ResourceIndicatorStatus as J, canonicalizeResourceUrl as K, type LogErrorDetails as L, evaluateResourceIndicator as M, resolveResourceIndicatorValue as N, type OAuthProtocolVersion as O, type ProbeHttpAttempt as P, type OAuthAuthMode as Q, type RegistrationStrategy2025_03_26 as R, type ServerDoctorResult as S, type BaseOAuthStateMachineConfig as T, type OAuthHttpRequest as U, type MaybePromise as V, type OAuthHttpResponse as W, normalizeServerDoctorError as X, type ProbeInitializeInfo as a, type ProbeMcpServerConfig as b, type ProbeMcpServerResult as c, type ProbeOAuthDetails as d, type ProbeTransportResult as e, type ServerDoctorCheck as f, type ServerDoctorChecks as g, type ServerDoctorConnection as h, type ServerDoctorError as i, type RegistrationStrategy2025_06_18 as j, type RegistrationStrategy2025_11_25 as k, type RegistrationStrategy2026_07_28 as l, type OAuthFlowState as m, type EmulatedAuthAttempt as n, type EmulatedRegistrationPreference as o, probeMcpServer as p, type InfoLogLevel as q, OAUTH_EMULATION_FIELDS as r, type OAuthDynamicRegistrationMetadata as s, type OAuthEmulationConfig as t, type OAuthEmulationCoverage as u, type OAuthEmulationDivergence as v, type OAuthEmulationField as w, type OAuthEmulationFieldStatus as x, type OAuthFlowStep as y, type OAuthRequestExecutor as z };