## 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
## What changed
- Honor `McpOAuthRefreshMode::Coordinated` for streamable HTTP MCP connections by letting RMCP refresh and persist credentials through the pinned credential store.
- Reread credentials while holding the refresh lock, persist refreshed tokens before retrying requests, and serialize login and logout writes with in-flight refreshes.
- Keep OAuth preparation outside MCP operation and handshake deadlines, and allow refresh persistence to finish if the initiating caller is cancelled.
## Testing
- Cover coordinated startup refresh, concurrent refreshes, `401` retries, credential mutation races, provider timeouts, and caller cancellation.
GitOrigin-RevId: 100ae788048087be23e26bb43f868b1fcebb007a
## What changed
- Add a test-only `CredentialStore` adapter that maps RMCP refreshes onto Codex's pinned OAuth credential backend.
- Require refresh transaction guards for mutations, preserve the pinned backend, and update the runtime credential snapshot only after persistence succeeds.
- Preserve scopes and token expiry metadata while rejecting credentials that no longer match the connection's client or issuer.
## Testing
- Cover guarded save and clear operations, persistence failures, pinned-store read failures, replacement and removal handling, and expiry round trips.
GitOrigin-RevId: eb1b98024322c03af94f5ab2e88c7dc4ae54893a
## Why
Exec-server process and network-policy events need stable attribution to the
launching tool call and executor without recording process payloads.
## What changed
- Add optional `ExecMetadata` to `ExecParams` and propagate the thread and tool
call IDs from unified exec.
- Emit bounded OpenTelemetry events for process start, spawn failure, sandbox
denial, and exit. Correlate them with the launch trace and registry-issued
executor identity while excluding arguments, paths, environment values,
output, and error text.
- Preserve launch attribution across long-running processes and reconnects, and
attach the same metadata to network-policy audit events.
- Keep the protocol backward compatible when metadata is omitted, and prevent
invalid trace headers from inheriting an unrelated active span.
## Testing
Add coverage for metadata serialization and propagation, lifecycle event
fields, trace relationships, reconnect behavior, spawn failures, sandbox
denials, and network-policy attribution.
GitOrigin-RevId: 7aa480a7289c73cb95e2c124c35500bb6f0d5084
## What changed
- Extend the macOS MCP launcher to use native spawning for bare command names as well as relative executable paths.
- Resolve bare commands against the child's configured `PATH`, including empty entries and the default path when `PATH` is unset, while preserving `argv[0]` and script spelling.
- Fall back to the existing command launcher for failed searches and executable text without a shebang so its errors and shell behavior remain unchanged.
## Testing
Add macOS coverage for child `PATH` resolution, default-path lookup, launch errors, and shebang-free executable fallback.
GitOrigin-RevId: 06e76bf8dbd515331b588da797eb57cb765a546d
## What changed
- Add the under-development `mcp_oauth_refresh_coordination` feature and pin its selected refresh mode to each MCP connection.
- Treat the refresh mode as part of OAuth connection identity so runtime and MCP configuration refreshes reconnect when the mode changes.
- Keep legacy refresh behavior in builds where coordination is unavailable and emit a warning when coordinated mode is selected.
## Testing
- Cover connection replacement when the feature is toggled through both runtime and MCP configuration refresh paths.
GitOrigin-RevId: 89596150f0338e6ede0e712badecea4450831766
## Why
Rust falls back to `fork` when a macOS command combines a relative executable
path with a working directory, due to a historical `posix_spawnp` issue. This
can make local MCP server startup less reliable.
## What changed
- Spawn relative macOS MCP executables directly with `posix_spawn`, preserving
the configured path, `argv[0]`, working directory, environment, stdio, and
process group.
- Keep the existing launcher for `PATH` lookup and executable text files without
a shebang.
- Use one local child wrapper for legacy and 2026-07-28 protocol framing, with
cancellation-safe waiting and cleanup that kills and reaps dropped children.
## Testing
Add macOS regression coverage for relative scripts, argument and descriptor
preservation, launch errors, cancelled waits, and cleanup after runtime shutdown.
GitOrigin-RevId: 1cbc6b90aed6f67e0a38f551964d80496ebc4471
## What changed
- Allow MCP server names to contain `:`, `@`, `/`, and `.`, enabling names such as `npm:@modelcontextprotocol/server-sequential.thinking`.
- Preserve these names across `mcp add`, `get`, `list`, and `remove`, runtime tool namespaces, and OAuth credential lookup.
- Quote non-bare server names in generated `config.toml` recovery hints and keep similarly escaped OAuth credential names isolated.
## Testing
- Add CLI and runtime round-trip coverage for npm-style names.
- Add snapshot coverage for quoted recovery hints and a regression test for OAuth credential-name collisions.
GitOrigin-RevId: 97e9353cdbc544db4eb2377ddbfa1d2d539b1e04
## What changed
- Advertise `openai/elicitation` form support when the client declares an
object-valued `form` capability, without deriving it from the legacy
`openai/form` capability.
- Handle `openai/elicitation/create` requests in `form` mode and forward their
metadata and opaque schema through app-server as `openaiForm`, preserving
`x-openai-*` annotations.
- Keep legacy form handling independent and have the TUI automatically decline
the new form requests it cannot render.
## Testing
- Add an app-server round-trip test for capability negotiation, request
forwarding, and accepted responses.
- Extend MCP capability filtering coverage for `openai/elicitation.form`.
GitOrigin-RevId: 88f39257bffafe4ee98a9c910e38507843cd7eeb
## What changed
- Re-run the HTTP headers helper after a same-origin `POST` receives a `401` or `403`, and retry the request once when the effective headers changed.
- Share refreshes across concurrent rejected requests, retain the previous headers when refresh fails, and keep the retry within the original timeout.
- Allow helpers to supply `Authorization` while preserving explicit OAuth or bearer credentials, OAuth insufficient-scope challenges, and redirect safety checks.
## Testing
- Cover rotating helper headers for MCP tool calls and same-origin OAuth token refreshes.
- Cover concurrent rejections, failed and unchanged refreshes, retry limits, timeouts, and redirects.
GitOrigin-RevId: c662edefdb1cd2876d9d02545a72d5bd6739864f
Expand Windows deny-read globs robustly across protected directories while preserving filesystem enforcement. Preserve structured MCP tool and resource errors through app-server responses. Bind cached Guardian classifications to current local and root authorization state so stale scores cannot approve actions.
Add regression coverage for the sandbox resolver, structured protocol errors, and authorization changes.
GitOrigin-RevId: 4b80ed724d869afeca79204222d8465fa99d3a24
## What changed
- Fetch ChatGPT account access and attach `cyber_trusted_access` under
`openai/entitlementContext` when an installed or selected plugin explicitly
requests it from a local, read-only stdio tool with no arguments.
- Reject caller-supplied entitlement context on direct MCP calls, and fall back
to an `unknown` status when access cannot be verified or the account changes
during the lookup.
- Count entitlement lookup time against the MCP tool-call timeout.
## Testing
- Cover eligible calls plus unowned, remote, HTTP, mutable, argument-bearing,
API-key, undeclared, direct, and account-switch cases in core and app-server
integration tests.
GitOrigin-RevId: 303b61585ef4530276c373d914a2d0ccef1f4ac2
## What changed
- Resolve stored enterprise IdP sessions against discovered authorization
metadata, requiring the configured issuer, public-client authentication, and
supported ID-JAG token exchange capabilities.
- Bind OIDC identity claims and MCP resource indicators to their configured
issuer, client, and server, and require reauthentication when pinned keyring
credentials are removed or replaced.
- Hold the credential lock while rereading refresh tokens, and isolate
enterprise credentials by reserved namespace and Codex home.
## Testing
- Cover metadata and claim validation, resource binding, credential replacement
and keyring failures, refresh locking, expired ID tokens, and credential
namespace isolation.
GitOrigin-RevId: edce3c6159f7d6831edf72e9608b3fc3f5823c83
## What changed
- Add a non-interactive two-step exchange that obtains an ID-JAG from an
enterprise identity provider and trades it for a resource-bound MCP bearer
token.
- Validate trusted endpoint URLs, request inputs, ID-JAG claims, resource and
scope bindings, and token responses before credentials are forwarded or a
bearer token is returned.
- Expose structured authentication failures while redacting credentials and
provider-controlled error details from diagnostics.
## Testing
- Cover successful exchanges, signed scope narrowing, invalid claims and token
responses, request validation, and error redaction.
GitOrigin-RevId: d716e0e1c2dc6b230cecbc0e9cc09afeee81d599
## Why
MCP servers can share an OAuth callback URL. Without a validated issuer or a
server-specific callback path, an authorization response could be associated
with the wrong server.
## What changed
- Use stable callbacks when authorization metadata advertises issuer-bound
responses, and validate the returned issuer before exchanging the code.
- Retain server-specific callback IDs for providers without issuer support,
including fallback to the global or default callback for legacy registered
clients.
- Persist registered callback URLs for MCP servers and plugins, and insert the
active listener port into portless loopback redirects.
## Testing
Add coverage for issuer validation, callback-mode discovery, registered and
legacy clients, plugin OAuth, CLI persistence, and loopback listener ports.
GitOrigin-RevId: 2878c92e237fc17fd3def0bd2e1cce3e104a3db8
## What changed
- Include `environmentInfo` in the exec-server `initialize` response and seed the Rust client's metadata cache from it.
- Fall back to one lazy `environment/info` request when connecting to older servers that omit initialization metadata, then share the cached result across client clones and session recovery.
- Keep app-server `environment/info` requests uncached so they continue to probe the executor.
## Testing
- Cover initialization metadata, the legacy-server fallback, shared caching, accepted WebSocket environments, and repeated uncached app-server probes.
GitOrigin-RevId: 380132d9db183998d73e8c6b0954e4d70c7e8406
## Why
MCP inventory can be cached or collected separately from a thread's live
connections, so tool availability alone does not describe the current runtime
state.
## What changed
- Add a nullable `runtimeStatus` to `mcpServerStatus/list` for thread-scoped
requests, covering not-started, starting, connected, authentication-required,
failed, cancelled, and disabled connections.
- Observe published connection state without starting or reconnecting servers,
and return an unknown status when no thread is supplied or the active
configuration no longer matches the published registration.
- Show connection state and tool counts in the compact `/mcp` view while
retaining the detailed inventory in `/mcp verbose` and compatibility with
servers that omit `runtimeStatus`.
## Testing
- Cover runtime status transitions, deferred and disabled servers, closed
transports, configuration changes, protocol compatibility, and TUI rendering.
GitOrigin-RevId: e3bb6efe652f0fa8b3c97d5c53e4729b3a87cd91
## Why
Interactive MCP OAuth must not trust authorization metadata that could route an
authorization code or PKCE verifier to an unrelated token endpoint.
## What changed
- Require an advertised issuer to match the origin that served authorization
metadata.
- Validate authorization and token endpoint origins before starting both
pre-registered and dynamically registered client flows.
- Allow delegated endpoint origins when the server advertises issuer-bound
authorization responses, while retaining narrow compatibility exceptions for
existing providers.
## Testing
Add coverage for rejected untrusted metadata, accepted issuer-bound delegation,
legacy provider exceptions, and both client registration paths.
GitOrigin-RevId: 43c9f94c9f6ba2d23d7e373576cf9fa26861cfc3
## Why
Executor-owned HTTP MCP servers need to read their bearer credentials from the
selected executor environment instead of the host process.
## What changed
- Preserve `bearer_token_env_var` for executor-owned HTTP MCP configurations and
resolve it when the executor sends each request.
- Extend delegated HTTP headers with executor-local environment references while
rejecting missing, empty, or protected credential variables.
- Keep transport-provided bearer authentication compatible with MCP redirect and
OAuth handling without sending a placeholder authorization value.
## Testing
- Cover authenticated executor-owned MCP requests end to end.
- Cover delegated header resolution and rejection of protected variables.
- Cover parsing executor-owned bearer configuration and transport-provided bearer
behavior.
GitOrigin-RevId: 442bf7382198ffb69eba797eb36d4c74faabda88
## What changed
- Upgrade `rmcp` and `rmcp-macros` from 3.1.2 to 3.1.3.
- Preserve authentication-required and retryable transport classifications when modern MCP discovery falls back to legacy initialization.
- Prevent unrelated discovery errors from triggering legacy fallback while retaining their diagnostics.
## Testing
- Cover authentication challenges and transient initialization failures during legacy fallback.
- Verify that a failed OAuth issuer check does not consume the pending authorization state.
GitOrigin-RevId: 957c0873fec1148883dd163fbaeb77d7593d8c53
## What changed
- Add experimental `mcpServer/event/stream/start` and `mcpServer/event/stream/stop` requests for hosted apps, plus `mcpServer/event/stream/notification` forwarding.
- Scope subscriptions to the owning app-server connection and subscribed thread, enforce unique IDs and a per-connection limit, and clean them up when the thread is unsubscribed or the connection closes.
- Wait for the MCP active notification before completing startup, retry streams that close immediately, and terminate them when authentication or hosted runtime ownership changes.
## Testing
- Add an app-server integration test covering activation, event forwarding, duplicate subscription rejection, and explicit cancellation.
GitOrigin-RevId: 8a6fc1615adfc5af7e67def3b824fa5909ab3e7b
## What changed
- Add the `shellSnapshotV2` executor capability and an optional shell snapshot request to `ExecParams`.
- Capture and restore Unix shell state and profile exports from an in-memory, attachment-scoped cache for `bash`, `zsh`, and `sh`.
- Apply environment policies, runtime `PATH` entries, sandbox context, and live managed-proxy settings when preparing restored commands.
- Bound snapshot size, capture time, scope length, and cache capacity, and fall back to the original command when capture fails.
## Testing
- Cover local, remote, TTY, sandboxed, and supported-shell execution, plus environment filtering, proxy handling, in-memory reuse, and capture failure fallback.
GitOrigin-RevId: 624f747972c249c88c6f10f42cf0af97b75b5541