## Why
Authorization can change during token renewal before a revocation watcher runs. Requests must check that their authority is still current before dispatch.
## What changed
- Let `EmaRequestAuthority` accept a cancellation token and a synchronous authority check, revoking itself when the check fails.
- Recheck authority after authentication and after receiving HTTP responses for both regular and streaming requests.
- Add `CloudConfigBundleBinding::invalidated()` to wait until a captured policy binding is no longer current.
## Testing
Update tests to cover ownership changing during token renewal without explicit revocation, preventing HTTP dispatch, and parent-token cancellation ending an existing response stream.
GitOrigin-RevId: a142d6bcd0cd7a3d2e9d438a45dc640d93235656
## Why
MCP tool discovery discarded response-level `_meta`, leaving server-status clients unable to inspect metadata associated with the tool catalog.
## What changed
- Preserve opaque `_meta` from the first `tools/list` page through catalog refreshes and caches.
- Expose it as `toolListMeta` in `McpServerStatus`, with `null` when unavailable, and update generated schemas and bindings.
- Scope cached Apps catalog metadata to discovery settings, including client capabilities and extensions, while retaining tools from older caches without metadata.
- Restrict server capabilities in status snapshots to the selected servers.
## Testing
Add regression coverage for listing legacy cached Apps tools during failed startup, and update protocol serialization expectations for nullable `toolListMeta`.
GitOrigin-RevId: 62335e2fd8c482067a7a78a7612b58c3eaa9fb55
## Why
MCP servers can expose new tools during discovery. Refreshing the catalog after a tool-list notification lets Codex discover and call those tools in the same turn.
## What changed
- Add the disabled-by-default `mcp_tool_list_changed` feature for ordinary MCP servers.
- Track notifications in transport order and refresh catalogs before subsequent discovery or tool binding. Coalesce concurrent refreshes and retry listings invalidated by notifications, including during pagination.
- Retain the previous catalog on refresh failure, apply a retry cooldown, and invalidate affected startup caches. Allow notification refreshes to proceed while admitted calls finish.
## Testing
Add coverage for same-turn discovery and invocation in direct and Code Mode, notifications during startup and pagination, disabled behavior, cache invalidation, and concurrent refreshes with timeout recovery.
GitOrigin-RevId: 9afee8deba00dd9851b5f32625f61f96965aa00c
## Why
Authorization server metadata can advertise scopes unrelated to the MCP resource. Using that list for discovery can request broader scopes than the resource requires.
## What changed
Update `rmcp` and use its initial scope selection during OAuth discovery: prefer scopes from the initial `WWW-Authenticate` challenge, fall back to protected resource metadata, and include `offline_access` when supported. Stop using the authorization server's general scope list as the discovered resource scopes.
## Testing
Add coverage for challenge scope precedence, resource metadata fallback, scope normalization, and exclusion of unrelated authorization server scopes. Add a no-browser login regression test for a preregistered client whose authorization server advertises neither scopes nor dynamic registration.
GitOrigin-RevId: 68d83cf61fb0b73dac9e861e476f484990fd93b6
## Why
MCP request failures and tool errors reported only through `codex/telemetry` metadata previously received an `unknown` error code, obscuring the failure category.
## What changed
- Classify typed request failures into bounded codes such as `request_timeout`, `transport_closed`, and `protocol_error`, and carry them into MCP call metrics and spans before errors become strings.
- Preserve typed timeouts when a prepared tool call exhausts its deadline during trusted access lookup.
- Accept allowlisted `error_code` values from `codex/telemetry` as a fallback after structured content and connector authentication metadata. Keep model output unchanged and ignore unrecognized metadata codes.
## Testing
Add coverage for typed errors wrapped in context, prepared-call timeout classification, metadata precedence and rejection, unchanged model output, and exported span error attributes.
GitOrigin-RevId: d7a440a6c9119b8a07a7f1fad697eb25af506f00
## Why
Coordinated MCP OAuth refresh must stop retrying a definitively rejected refresh token, including after the runtime is rebuilt.
## What changed
Remove the rejected refresh token while preserving the access token and credential record. Compare stored credentials under the appropriate locks before writing so a replacement login is preserved, and update file entries using their existing keys.
Keep rejection handling alive through caller cancellation and prevent reuse within the runtime even if persistence fails. For ordinary direct-keyring credentials shared across `CODEX_HOME` directories, retire the token only in the current runtime because locking does not span those directories. Report persistence failures without exposing backend diagnostics.
## Testing
Add coverage for reauthentication after runtime rebuild, legacy file keys, cancellation with a concurrent credential replacement, keyring scope, and persistence failures with diagnostic redaction.
GitOrigin-RevId: a6e602ca2e2893ed711d853becc45142d9575fab
## Why
Remote MCP environment filtering could drop `SystemDrive` and `LocalAppData`. Explicit overrides also need Windows-aware merging to replace inherited variables with differently cased names.
## What changed
- Preserve `SYSTEMDRIVE` and `LOCALAPPDATA` when remote environment variables activate the allowlist.
- Apply explicit environment overrides through the executor environment policy, while retaining the final overlay for variables excluded by the allowlist.
## Testing
Extend environment-policy tests to cover the additional Windows variables, overrides with differently cased names, and the final overlay used by older executors.
GitOrigin-RevId: 36df69117f248536e47cf7e1d855b99a138fe698
## Why
MCP servers must forward sandbox policy unchanged to `codex sandbox --sandbox-state-json`, while interpreting launcher information to find the Codex CLI. Keep those contracts separate so consumers can preserve unknown policy fields.
## What changed
- Accept the experimental `codex/sandbox-state` capability alongside the deprecated `codex/sandbox-state-meta` capability, and send identical policy values under both `_meta` keys.
- Move `codexExecutable` out of the policy into `codex/sandbox-launcher`, supplied only when a verified CLI path is available for a local stdio server.
- Replace stale sandbox metadata while retaining unrelated entries, and remove stale launcher metadata when no launcher is available.
- Document the metadata contract and how servers should forward policy and retain authority for long-lived subprocesses.
## Testing
Update unit and integration coverage for policy serialization, identical state aliases, launcher availability across execution environments, and stale metadata replacement.
GitOrigin-RevId: e544c06e6e023953b1fc8069b7b1affa065262d1
## What changed
- Update the pinned `rmcp` dependency and Cargo/Bazel lockfiles, and migrate MCP handlers and fixtures to `ClientConfig` and `ServerConfig`.
- Stop requiring responses for cancelled elicitation requests in cancellation tests while retaining checks for cleanup and continued connection usability.
- Handle client disconnects during WebSocket writes in the TUI test server, use an asynchronous HTTP mock for loopback proxy testing, and improve remote executor test diagnostics and the Windows subprocess fixture.
- Use `invalid_prompt` for the memory worker failure fixture.
## Testing
Add a regression test covering transport EOF during both form elicitation and user verification. Keep the client alive while checking that pending response channels close, the timeout pause clears, and the service exits with `QuitReason::Closed`.
GitOrigin-RevId: c0166b83fab3b59d84a5207c6630cb6adcf3b230
## Why
User-verification cancellations previously discarded failure reasons, leaving MCP servers unable to distinguish user cancellation from unavailable approval, interruption, or invalid proof.
## What changed
- Carry a bounded `openai/userVerificationReason` value in response `_meta` for verification failures, declines, and cancellations across the TUI, app server, and MCP client.
- Preserve recognized reasons and classify invalid responses, missing or invalid proofs, response errors, closed response channels, interruptions, and unavailable approval.
- Discard unknown reasons and unrelated metadata. Keep proof material out of decline and cancellation responses, and keep display messages and raw error diagnostics out of response metadata.
## Testing
Add and update tests for typed failure propagation, metadata filtering, invalid proofs, response-channel failures, interrupted requests, and unavailable approval, including TUI RPC and native MCP response coverage.
GitOrigin-RevId: 6b7f855ce8eb13e759b5b86d0dc2b1afdfcff7b3
## Why
Tokio runtime tracing can cause SQLite log writes to enqueue more writes and exporter activity to generate further OTLP exports.
## What changed
- Exclude `tokio` and `runtime` spans from OTLP export alongside `h2` spans.
- Limit `tokio::` and `runtime::` targets to `INFO` in the default log filter, and reject their `TRACE` events directly in the SQLite sink even without an outer filter.
- Box and pin the session-loop future before spawning it.
- Reorder tracing and Tokio test attributes, restrict the skills concurrency test's subscriber to the catalog-refresh span, and use the default log filter in the SQLite formatter comparison test.
GitOrigin-RevId: f545013a2469088d7f9890c1f46bb93eb5446d2d
Replace fixed 500 ms sleeps in `helper_attempt_is_shared_after_cancellation` with polling of the helper completion marker every 10 ms, bounded by a five-second timeout.
This lets the test observe completion independently of the cancelled headers or refresh request without assuming the helper finishes within 500 ms. Preserve the assertions that subsequent calls reuse the same helper attempt.
GitOrigin-RevId: 2612679aff756306ea3e05ef7bb9b4db02633fd5
## Why
Remote executors need to recover from confirmed authentication-service outages and spread reconnect attempts after a shared outage. Registration retries must remain limited to confirmed failures before a write, since replaying an ambiguous request can replace a newer registration.
## What changed
- Retry registry responses with HTTP 502 and `authentication_service_unavailable`, alongside the existing HTTP 503 `registration_conflict` retries.
- Accept structured registry errors in `detail`, keeping the canonical `error` authoritative when both are present.
- Randomize reconnect delays between half and all of the current exponential backoff, retaining the 30-second cap.
## Testing
Add coverage for reconnect jitter bounds, authentication-outage retry cancellation, error-envelope precedence, and preservation of Noise identity and initialized sessions across retries. Make the HTTP-header helper cleanup test wait for the helper PID before cancellation and verify process termination when the provider is dropped.
GitOrigin-RevId: 35fdb57732d17b0bbfeca8a4dc557a0988e29a31
## What changed
Allow the issuer `https://mcp.mercadopago.com/mcp` to use authorization endpoints on `https://auth.mercadopago.com` and token endpoints on `https://mcp.mercadopago.com` without issuer-bound callbacks. Remove the previous Figma exception.
## Testing
Update the provider-exception test to accept the Mercado Pago combination and reject lookalike issuer hosts, unrelated token hosts, and HTTP issuer and token URLs.
GitOrigin-RevId: 3838c7e4c32d6a2022f0011d6020e383035fe67f
## Why
When Codex runs on Unix and launches a stdio MCP server on a Windows executor, explicit remote environment variables activate an allowlist based on Unix defaults. This can filter out Windows runtime and temporary-directory variables.
## What changed
Include `SYSTEMROOT`, `TEMP`, and `TMP` in the remote environment allowlist whenever explicit remote variables are requested.
## Testing
Extend the environment-filtering test to verify that `SystemRoot`, `TEMP`, and `TMP` survive alongside requested variables while unrequested secrets remain excluded.
GitOrigin-RevId: 059c9e23833be66aaf5b65ba5f95013f94f0f792
## What changed
- Centralize `windows-sys` at version `0.61.2` in the workspace and migrate dependent crates to it.
- Adapt Windows API calls to the updated handle, boolean, and type definitions. Replace custom handle owners with `OwnedHandle` and use `BorrowedHandle` where ownership stays with the caller.
- Add explicit wrappers for non-owning Windows handles passed between threads.
## Testing
Enable the MCP refresh cleanup test on Windows. Retain process handles to verify that a superseded MCP server stays alive during an in-flight call, exits after cancellation, and leaves the replacement running until shutdown.
GitOrigin-RevId: 86f53d9b300d13edff7154f4a7c32e34dacd2919
## Why
Concurrent Linux test spawns can inherit writable descriptors for executable fixtures, preventing those fixtures from being executed even after the writing test closes its descriptor.
## What changed
Replace direct executable fixture writes and copies across the Rust tests with `codex_utils_cargo_bin::write_executable` and `copy_executable`. These existing helpers complete writes and copies in separate processes on Linux.
Remove the empty temporary inode before creating fake bubblewrap executables, and stage tampered bubblewrap bytes in a separate data file before copying them into the executable fixture. Add the required test dependencies.
GitOrigin-RevId: c875c83088731a4933ef1574e8d79d8cecc12f54
## What changed
- Add `EmaAuthenticatedHttpClient` to cache and renew resource bearers, serialize concurrent renewals, and include authentication time in the request deadline. Confine bearers to the configured MCP endpoint and reject redirects.
- Return authentication-required errors for `401` responses without replaying MCP operations. Preserve a newer cached bearer when a delayed response rejects an older one.
- Add revocable request authority that cancels pending requests and ends response streams.
- Pin enterprise credentials to a persistent version advanced on save or deletion. Use short credential locks and invalidate rejected grants only when their record and version are still current, preserving newer logins.
- Hide keyring account identifiers from enterprise credential errors and traces while preserving authentication failure classification.
## Testing
Add tests for token expiry and renewal, endpoint confinement, redirects, request deadlines, revocation during renewal and streaming, delayed `401` responses, credential replacement and logout races, and credential error privacy.
GitOrigin-RevId: ee3e5cf7ecbba3d09e1ab29ed4fbb2a35eacc60d
## Why
Retaining process output, publishing events, and serving reads cloned the underlying byte buffers. Sharing those buffers avoids copying output bytes when chunks are cloned.
## What changed
Store `ByteChunk` bytes in `Arc<Vec<u8>>` and retain `ProcessOutputChunk` values directly. Add borrowed byte access for the MCP process transport while preserving base64 serialization and owned byte extraction through `into_inner()`.
## Testing
Add a unit test covering base64 serialization, deserialization, and independent owned bytes extracted from shared chunks.
GitOrigin-RevId: 6bba114af48424aa844487aa75163cfc604e0575
## What changed
Add `exchange_ema_auth_token` to discover and validate the MCP resource's authorization server before resolving enterprise identity credentials and performing the ID-JAG token exchange. Keep the lower-level exchange primitive private.
- Probe `server/discover` with the enterprise-managed authorization extension, support recognized legacy discovery rejections, and follow protected-resource metadata challenges or well-known fallbacks.
- Match configured resource and issuer constraints, require advertised public-client JWT bearer support, and validate token endpoint metadata without requiring an authorization endpoint.
- Bound discovery with a shared timeout, redirect and authorization-server limits, reject cross-origin metadata redirects, and restrict private authorization-server destinations while allowing local loopback discovery.
## Testing
Add tests covering resource and issuer mismatches before identity access, metadata capability validation, query preservation, modern challenges, JSON and SSE legacy fallback behavior, cross-origin redirect rejection, and private or malformed issuer destinations.
GitOrigin-RevId: 9a55233a20ff42c293f9bd8175e01141ac2d8576
## What changed
Upgrade `rmcp` to a pinned Git revision of version `3.3.0` and enable `auth-enterprise-managed`. Delegate the two-stage ID-JAG exchange and token validation to the SDK, replacing the local implementation while retaining Codex HTTP routing and credential lifecycle policy.
Map SDK errors by exchange stage so `invalid_grant` distinguishes enterprise identity failures from resource authorization failures, and preserve handling of `insufficient_user_authentication`.
## Testing
Update exchange tests to verify rejection of unsupported `authorization_details` and malformed signed scopes. Exercise errors from both token endpoints to check credential policy, prevent credential reflection in diagnostics, and ensure rejected grants are not retried.
GitOrigin-RevId: a56034aa3fd70002754ea552fd2da70bdcd85b31
## What changed
- Instrument MCP OAuth loads, saves, deletes, fallback cleanup, and refresh persistence with credential-free storage metrics, distinguishing configured policy from operations on a pinned store.
- Retain the originating client across background tasks, blocking storage operations, and session recovery, including recovery after startup found no credentials.
- Preserve typed keyring and lock error categories for metrics and remove raw error details from storage warnings.
## Testing
Add tests for policy and pinned-store outcomes, best-effort cleanup failures, wrapped lock errors, and successful or failed refresh persistence without duplicate observations. Add recovery tests that verify client attribution after anonymous startup and across threads with different originators.
GitOrigin-RevId: 5ea4528bcdcf500c8ffdf1d9c7008ea52112c726
## Why
The app server previously rejected OAuth login for enterprise-managed MCP servers. These servers need an explicit sign-in flow that ties saved authorization to the active Codex user and workspace and prevents canceled or superseded attempts from saving credentials.
## What changed
- Enable enterprise sign-in through `mcpServer/oauth/login` for configured servers with a connected thread, trusted IdP registration, and `features.use_xaa` enabled. Scope shared enterprise credentials by user, workspace, issuer, and client ID.
- Add `loginId` to MCP OAuth login responses and completion notifications, preserving compatibility with older servers that omit it.
- Support enterprise login replacement and `account/login/cancel`, wait for callback listener shutdown before replacement, and recheck account and configuration before saving grants. Fence stale attempts across processes and account changes.
- Remove shared enterprise authorization during account logout and `codex mcp logout`, including when the feature is disabled. Continue account logout if enterprise cleanup fails, and invalidate MCP runtimes on account changes.
Start a fresh session after successful enterprise sign-in to use the saved grant.
## Testing
Add regression coverage for login replacement and cancellation, callback port reuse, account changes during setup, cross-process logout invalidation, persisted workspace policy selection, cleanup failures, and responses from older servers without `loginId`.
GitOrigin-RevId: 7ed4caaab4659ed1e67064262cf5cee48e3a26ac
## Why
Background helpers launched from a detached Windows process can allocate console windows. Job Object launches and containment fallbacks need to preserve console suppression as well.
## What changed
- Add `codex_utils_process::background_command` to set `CREATE_NO_WINDOW` on Windows, and use it across background subprocess launches, including Git, plugins, authentication, diagnostics, and sandbox helpers.
- Centralize console suppression in Job Object launches. Keep `CREATE_NO_WINDOW` when retrying without containment, and clear `CREATE_SUSPENDED` so the fallback child can run.
- Preserve console inheritance for interactive shell launches and interactive AWS authentication refreshes.
## Testing
Add Windows regression tests covering console-free launches from detached parents through standard and Tokio commands, stdout/stderr capture, successful containment, Job Object creation and assignment failures, and sandbox setup refresh helpers.
GitOrigin-RevId: b2c238fa7d4f9fbd868e5adf7d4be9958ff01e6c
## Why
Concurrent tests can inherit writable descriptors for executable fixtures, causing `ETXTBSY` when those fixtures launch on Linux.
## What changed
Expose shared `write_executable` and `copy_executable` helpers from `codex_utils_cargo_bin` and adopt them in CLI, exec-server, and MCP tests. On Linux, writes and copies complete in separate processes so sibling test spawns cannot inherit the writable descriptors. Script fixtures receive mode `0o755`, and copied executables retain their source permissions.
Remove the executable-busy retry loop from the program resolver test now that its script uses the shared helper.
GitOrigin-RevId: 61624158190bb1e75c27d9eb9c87a2defc147fb7
## Why
Concurrent test spawns can inherit a writable descriptor for the MCP server
wrapper, causing `ETXTBSY` when launching it on Linux.
## What changed
Write the wrapper through a separate `/bin/sh` process on Linux so its writable
descriptor stays out of the test process. Check the writer's exit status and
include stderr on failure. Retain direct file writes on other Unix platforms.
GitOrigin-RevId: f99952ec000ba7317243e87fd664dc0e31bb7b24
## What changed
Expose Windows process creation flags on the shared command wrapper and use
`CREATE_NO_WINDOW` when launching local stdio MCP servers, including fallback
launches without Job Object containment. Preserve `CREATE_SUSPENDED` when
assigning the server to a Job Object before execution.
## Testing
Add a Windows regression test covering direct launches and launches through
`cmd.exe`. Verify that the server has no console, initializes successfully,
returns tools, and exits after shutdown.
GitOrigin-RevId: 84475e82999d91a431e09327d4f5639b59c01427
## Why
MCP OAuth configuration supported a pre-registered client ID but could not supply a client secret for token exchange or refresh.
## What changed
- Add `oauth.client_secret` and `codex mcp add --oauth-client-secret`, requiring a nonempty secret and client ID. Persist the secret in server configuration and accept `clientSecret` in plugin configuration.
- Pass configured credentials through CLI, app-server, and plugin login flows and token refresh. Require a new login when a configured confidential client's ID differs from stored credentials.
- Redact secrets in debug output and keep them out of authorization URLs and persisted OAuth token records.
- Invalidate cached OAuth connections when the configured client ID or secret changes.
## Testing
Add coverage for configuration validation and round trips, CLI argument redaction and subsequent login, app-server login, connection invalidation, and refresh with `client_secret_basic` and `client_secret_post` in both refresh modes. Verify secret exclusion from token records and reject mismatched client IDs before contacting the provider.
GitOrigin-RevId: 85bb0e410e9e68e6cd68eb6359badfc7eac78147
## Why
Linux descriptor cleanup used allocating directory enumeration after `fork`. The child needs allocation-free cleanup while preserving Rust's spawn-error channel until `exec` succeeds.
## What changed
- Mark unrelated descriptors close-on-exec with `close_range(CLOSE_RANGE_CLOEXEC)`, leaving stdio and explicitly preserved descriptors' flags untouched.
- Fall back to stack-backed `getdents64` enumeration of the child's descriptor table when `close_range` fails.
- Document best-effort cleanup: failures allow launch to proceed and may leave unrelated descriptors inherited.
## Testing
Add Linux tests for descriptor inheritance, unsorted and duplicate allowlists, unchanged parent descriptors, fallback cleanup above a lowered descriptor limit, preserved exec-error reporting, and successful launch when both cleanup paths fail. Retain MCP coverage for descriptor exclusion in servers and descendants.
GitOrigin-RevId: 13abb95f82557324c7b40feb36bd6f806d60674e
## What changed
- Add `ProcessMode::NewSession`, null stdin, and opt-in Linux parent-death termination to the shared child command API.
- Replace `DescriptorPolicy::StdioOnly` with `Explicit` and add `preserve_fds` to allow selected inheritable Unix descriptors alongside stdio. Preserve descriptor numbers without duplicating or closing the parent's descriptors, keeping POSIX record locks intact.
- Support session creation and preserved descriptors in the native macOS backend, with a compatible fallback for high descriptor numbers rejected by native file actions.
## Testing
Add regression coverage for process groups and sessions, descriptor preservation across native and executable-text launches, the last descriptor slot below the file limit, and retention of parent record locks.
GitOrigin-RevId: 29ecd859d3b673da6ae6412cc06a32fa10d11346
## What changed
Reject authorization endpoints with schemes other than `http` or `https` before client registration or authorization URL return. Document this constraint for `mcpServer/oauth/login`.
## Testing
Make existing asynchronous tests wait for cleanup: wait for `ThreadIdle` before injecting user input in the guardian cached-score test, and poll for queue consumption before asserting that dispatched items are gone.
GitOrigin-RevId: e5f6b4c5556234c3cc2aa56910486e892c011116
## Why
MCP requests pass through background transport queues, so HTTP requests need the caller's trace context carried explicitly to preserve trace ancestry.
## What changed
- Capture W3C trace context in request metadata for tool and resource operations, custom requests, and event streams.
- Restore that context in an `mcp.http.request` span around HTTP POSTs, linking outgoing HTTP traces to the originating request.
- Preserve application metadata while replacing trace fields with the current caller's context and removing stale `tracestate`. Read the SDK's merged metadata so extension fields retain precedence over parameter metadata.
## Testing
Add a unit test for metadata merge precedence and an integration test covering concurrent paginated requests, tool calls, custom requests, and tool-call continuations across legacy and `2026-07-28` protocol modes. Verify HTTP trace ancestry, metadata preservation, and removal of stale `tracestate`.
GitOrigin-RevId: 0b22cd75f31f9fcb855b27fa8d34ecdffd6e3549
## Why
Local MCP servers communicate over stdio, so unrelated parent file descriptors should not propagate into the server or its descendants.
## What changed
Apply `DescriptorPolicy::StdioOnly` when launching local stdio MCP servers on Unix, preserving their explicit transport stdio.
## Testing
Add Unix integration tests that check inheritable pipe, socket, and file descriptors are absent from servers and descendants across absolute, relative, and shell-fallback launches. Verify MCP communication, arguments, environment, working directory, parent descriptor ownership, and exec failure reporting remain intact.
GitOrigin-RevId: 37409a5673dbaafa851fd1f78e3a2443eda5f7c6
## Why
Native `openai/userVerification` requests need to carry optional `_meta` to clients for extension-specific presentation.
## What changed
- Accept optional metadata objects with the same validation as MCP elicitation.
- Restore metadata from the MCP request context, excluding `progressToken`, and forward it through `mcpServer/elicitation/request`.
- Update protocol types, schemas, and documentation while retaining support for requests without metadata. Challenge bytes and acceptance proofs remain unchanged.
## Testing
Add coverage for metadata validation, transport context restoration, and protocol round trips. Extend MCP integration tests to check that verification metadata reaches the client.
GitOrigin-RevId: 5d04004244cf33effac675c19e543157c48d1504
## Why
The native macOS backend cannot inspect every setting or callback on a Tokio command. A shared, constrained launch API makes the supported settings explicit for both backends.
## What changed
- Replace `spawn_child` with `codex_utils_pty::Command`, enforcing an explicitly supplied environment, piped stdio, and kill-on-drop behavior.
- Add `ProcessMode::Inherit` and `ProcessMode::NewGroup`, honoring the selected mode in native macOS and Tokio spawning.
- Share the `Child` wrapper across platforms and migrate local MCP server launching to the new API, retaining its new process group and Windows suspended-spawn support.
## Testing
Adapt the existing macOS spawn compatibility and child lifecycle tests to the new API. Add a regression test that checks inherited and new process groups with both backends.
GitOrigin-RevId: 3e7a401659e3a8a94a13c4ff58d67bdcd2eea33d
## What changed
Expose the shared `Child` type and `spawn_child` function from `codex-utils-pty`, and update the MCP stdio transport to use them. Move the existing macOS spawning implementation and its tests into the utility crate, preserving platform-specific spawning, piped stdio, and kill-on-drop behavior.
GitOrigin-RevId: 26c2fb2f22cdba907aa9d18cab7dc8c4ac1c909e
## Why
On macOS, process-group signals can be denied even when individual members can be signalled. Core execution cleanup used helpers that did not retry those signals against group members.
## What changed
- Make `terminate_process_group` and `kill_process_group` use the existing member fallback on macOS, and simplify MCP and pipe callers to use the shared helpers.
- Use the saved process-group ID when escalating cancellation after the termination grace period, so this path also uses the fallback.
- Update the unsafe process-group ID test to exercise `terminate_process_group`.
GitOrigin-RevId: 1bab28d3d53cd401b51ffe71d41fbece12aed66d
## What changed
- Export `GatewayAuthConfig` and `GatewayAuthManager` with PKCE browser sign-in, loopback callbacks, cached token resolution, and refresh after expiry or rejection.
- Store gateway credentials in a dedicated encrypted namespace with an independent keyring key. Serialize token exchanges and persistence across processes, preserve refresh rotations after caller cancellation, and retain pending credentials when saving fails.
- Validate OAuth endpoints and token responses, disable token-request redirects and logging, and redact sensitive error details.
## Testing
Add tests covering browser authorization, callback state validation and cleanup, concurrent refreshes, cancellation, failed-save recovery, storage isolation, endpoint validation, and credential redaction.
GitOrigin-RevId: e0c17f1eab7acca378a14b2d00b80940d8542e47
## Why
Read-only MCP discovery and invocation need a consistent policy across requests, connection reuse, and tool catalogs. Reusing an unrestricted connection or cached catalog can bypass filtered discovery.
## What changed
- Thread `requires_read_only_mcp_tools` through MCP configuration and client setup, leaving it disabled by default.
- When enabled, set `openai/readOnly` to `true` in `tools/list` and `tools/call` request metadata, overriding a caller-supplied `false` while preserving other metadata, pagination, and arguments.
- Include the policy in connection identity and bypass shared Apps and persistent tool catalog caches for read-only connections.
## Testing
Add coverage for metadata propagation in legacy and modern protocol modes, preservation through session recovery, and isolation from unrestricted connections and shared Apps catalogs.
GitOrigin-RevId: f4a3a4021a54e302bffd53f08092b080c056246b
## Why
A `503` from an issuer's OAuth metadata endpoint can block discovery even when its OIDC metadata is available, preventing expired OAuth tokens from being refreshed during MCP startup.
## What changed
Try the same issuer's OIDC discovery endpoints when an OAuth authorization-server metadata GET returns `503`. Support issuers with path components and keep all attempts within the original request's timeout.
Reuse existing header, origin, and response-size checks, leave issuer validation to RMCP, and do not follow fallback redirects. Preserve discovery errors when fallback fails instead of enabling legacy endpoint fallback, and propagate terminal HTTP failures.
## Testing
Add tests for OIDC candidate order, malformed metadata, issuer mismatches, header isolation, redirects, terminal failures, unaffected requests, and the shared timeout. Add startup coverage for refreshing expired persisted tokens after OIDC fallback in both legacy and coordinated refresh modes.
GitOrigin-RevId: 6d94fd09e9ba26cb83e029171449e91410a0f6cb
## Why
Allow MCP authentication to complete when the browser cannot reach the callback page by accepting the full redirect URL copied from its address bar.
## What changed
- Add `codex mcp login <name> --no-browser` to print the authorization URL and accept a pasted callback without launching a browser. HTTP callbacks remain supported while waiting for input.
- Validate pasted redirect URLs and OAuth responses before exchanging tokens, hide terminal input, bound input size, and avoid echoing callback values in diagnostics.
- Preserve manual input across discovered-scope retries and support cancellation during callback input and token exchange.
## Testing
Add unit and CLI integration tests for callback validation, bounded input, credential storage, HTTP callback completion with stdin open, scope retries, and cancellation during token exchange.
GitOrigin-RevId: 16ea9c3221f72d93e6e3e5acdc6b9465293a0a65
## What changed
- Consolidate callback address and port parsing in `enterprise_callback_settings`.
- Reuse `StoredOAuthTokens::has_refresh_token` for credential validation.
- Keep `EnterpriseOAuthHttpClient` private and inline removal of the `resource` parameter from authorization code token requests.
- Share the `complete_login` test helper across login and logout tests.
## Testing
Expand callback settings coverage to check default and configured ports, ports from callback URLs, and rejection of conflicting ports alongside loopback address validation.
GitOrigin-RevId: 42c9be5663ce13b7349cefac2c6a20c4fa974aef
## Why
RMCP's standard input request union excludes custom methods, so tool continuations need explicit handling for OpenAI form elicitation and native user verification.
## What changed
- Route MCP `2026-07-28` tool inputs through the existing client service, preserving capability checks and verification response validation.
- Support `openai/elicitation/create` form and `openai/userVerification` inputs alongside standard MCP inputs, and return responses with the server's opaque `requestState`.
- Bound continuation rounds, back off for state-only responses, and reject unsupported or malformed inputs.
- Give concurrent verification prompts distinct cancellation ownership and release pending prompts and timeout pauses when the connection closes.
- Prevent session recovery from restarting a tool after submitting a verification proof while preserving authentication challenges.
## Testing
Add HTTP continuation tests covering mixed input types, proof validation, request metadata preservation, invalid requests, round limits, authentication challenges, session expiry after proof submission, and independent prompt cancellation. Add duplex transport tests for pending-input cleanup on cancellation and transport closure.
GitOrigin-RevId: b7db6d47fa0969b6a938220dfe3610e5ba5188b2
## Why
Form and URL elicitations could keep waiting for a response and leave tool timeouts paused after cancellation. Remembered cancellations could also affect reused request IDs on a new connection.
## What changed
- Honor request cancellation and server cancellation notifications for all elicitations, without requiring user-verification support. Return `cancel` and release pending response routes and timeout pauses.
- Create a fresh elicitation service for each connection attempt, including initialization retries and session recovery, so cancellation state stays scoped to its connection.
## Testing
Add regression tests for form and URL elicitation cancellation, cleanup on service shutdown, and acceptance of previously cancelled request IDs after connection recovery.
GitOrigin-RevId: 388a8d72e55e89ad3d44d4739d8434485588aa1a
## Why
Refresh failures could leave expired MCP OAuth credentials reporting ordinary errors instead of signaling that authentication is required, preventing tool calls from offering a reconnect signal.
## What changed
- Classify provider failures and timeouts as `AuthorizationRequired` when the access token has expired. Keep proactive refresh failures as ordinary errors while the token remains valid.
- Reread stored credentials after a failed refresh and adopt a valid login completed during the request, enforcing the existing issuer binding for refresh tokens. Preserve stored credentials for later retries.
- Convert authentication-required tool-call errors into a reconnect message with `mcp/www_authenticate` metadata, without exposing provider or transport details.
## Testing
Add coverage for startup and runtime OAuth recovery, proactive refresh failures, concurrent login adoption, issuer mismatches, credential preservation, and successful retries. Verify failed local refreshes do not send tool calls and server-rejected calls are not replayed.
GitOrigin-RevId: 9cf64b0452685d2085df5dc0bcecee16ffe42e47
## Why
A descendant outside an MCP server's process group can keep stderr open after the server exits, leaving the reader task and its file descriptor alive.
## What changed
Signal the local stderr reader during explicit shutdown and when the process handle is dropped. Allow up to 250 ms to drain queued diagnostics before closing the reader, even if stderr never reaches EOF.
## Testing
Add a Unix regression test covering explicit shutdown and client drop with a descendant that keeps stderr open. Verify that file descriptor counts return to baseline while the descendant remains alive and that queued diagnostics are logged.
GitOrigin-RevId: 1b544e8dba2b5616db6739d075e7232564c92884
## Why
Enterprise sign-in needs to keep browser completion separate from credential storage so callers can recheck the active account and configuration before saving a grant. Logout must also prevent an earlier sign-in from restoring credentials, including from another process sharing `CODEX_HOME`.
## What changed
- Add enterprise login APIs in `rmcp-client` that return an authorization URL and stage validated credentials for an explicit `commit_if` call. Store grants only in the keyring after rechecking caller authority under the credential lock.
- Require a registered client ID, published metadata matching the configured issuer, HTTP loopback callbacks, a refresh token, and a valid OIDC identity assertion. Request `openid` and `offline_access` with `prompt=consent`, and omit MCP resource indicators from authorization and code exchange.
- Persist a login generation under the credential lock so logout invalidates pending and staged sign-ins across processes, even when no grant is stored.
- Keep credentials and account identifiers out of enterprise error chains and logs, and avoid logging callback payloads when the receiver has closed.
## Testing
Add coverage for discovery validation, loopback callbacks, PKCE, staged keyring storage, cancellation, stale attempts, cross-process logout, and error/log privacy. Preserve ordinary MCP OAuth login without a refresh token, and adjust the terminal polling test deadline to include the minimum empty-poll wait.
GitOrigin-RevId: 2a27b9a26505a2f6fdecce8877f6e2c21e148f72
## What changed
- Handle `openai/userVerification` requests through `openai/elicitation/create` when the client advertises `userVerification` support.
- Validate request fields, size limits, and base64url encoding. Require a correctly shaped, bounded proof for acceptance; cancel invalid acceptance responses and discard proof material on decline or cancellation.
- Handle request and service cancellation, including cancellation received before request dispatch. Bound early-cancellation storage and cancel new verifications when capacity is exceeded.
- Keep verification inactive in Codex: cancel requests without prompting until the typed app-server and UI path is available.
## Testing
Add tests for request and proof validation, malformed modes, cancellation races and capacity limits, timeout-pause cleanup, and independent concurrent requests. Add integration coverage showing that verification does not prompt or prevent tool and turn completion before activation.
GitOrigin-RevId: 6313c1be40fae0b33cc3ce0f8fe025b4124ed2ef
## Why
The test helper previously released its reserved port before starting the
streamable HTTP server. Another concurrent test could claim that port and
satisfy the readiness probe for the wrong process.
## What changed
Start the child server on an OS-assigned port and wait for it to publish its
actual bound address. Use that address to build the base URL returned to the
streamable HTTP integration tests.
GitOrigin-RevId: 606ae446f947d39424e4ec996ac647881777ff44
## Why
When silent OAuth refresh cannot recover a rejected MCP tool call, the caller
needs the server's authentication challenge to initiate interactive login. The
rejected call must not be replayed automatically after refresh has failed.
## What changed
- Convert `401 Unauthorized` responses with `WWW-Authenticate` headers into an
MCP tool error containing `mcp/www_authenticate` metadata.
- Preserve multiple authentication challenges by combining all
`WWW-Authenticate` header values.
- Keep successful silent refresh behavior while avoiding replay when refresh
fails.
## Testing
Added coverage for successful and failed refresh, multiple authentication
headers, propagation through agent tool-call events, and no-replay behavior.
GitOrigin-RevId: c560cff6286d7ab09b1f5c6cf3618d4650cde47d