172 Commits

Author SHA1 Message Date
Eric Traut
343074d420 Report runtime MCP connection status (#40068)
## 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
2026-08-22 05:54:43 +00:00
jif
7f9832d0d0 Enforce issuer binding for MCP OAuth endpoints (#39935)
## 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
2026-08-21 13:28:28 +00:00
jif
93c54bca38 Resolve HTTP MCP bearer tokens in executor environments (#39926)
## 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
2026-08-21 12:50:15 +00:00
stevenlee-oai
a3bce23f3b Update rmcp to 3.1.3 (#39798)
## 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
2026-08-20 20:53:17 +00:00
victor-openai
097825f75a Add app-server MCP event streaming (#39761)
## 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
2026-08-20 17:49:35 +00:00
jif
d0cc662b8c Cache shell snapshots in the exec server (#39756)
## 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
2026-08-20 17:39:06 +00:00
Jeremy Rose
250b5ea2bf Bind MCP OAuth refresh tokens to their issuer (#39615)
## Why

An authorization server discovered for an MCP server can change. A stored refresh token must not be sent to a different issuer than the one that originally granted it.

## What changed

- Persist the discovered authorization server issuer with new OAuth credentials and preserve it across refreshes.
- Validate that issuer against a single pinned metadata snapshot before refreshing or adopting stored refresh credentials.
- Require reauthentication when refresh credentials have no issuer or the issuer changed. An unexpired access token can still be used without exposing its refresh token.

## Testing

Add coverage for issuer persistence, missing and changed issuers, metadata changes during startup, and refresh-token preservation.

GitOrigin-RevId: 07e48ba892f627428a28bbed5cca4ad703e2a5fd
2026-08-20 06:25:17 +00:00
jif
929e2b9c1d Harden MCP OAuth fallback credential writes (#39611)
## Why

The fallback file contains OAuth credentials, so it must be private from the
moment it is created and writes must not follow links to another path.

## What changed

- Create the fallback file with mode `0600` on Unix before writing credentials.
- Reject symlinks and other non-regular files on Unix and Windows, including
  Windows reparse points.
- Truncate and update an existing regular file through the validated file
  handle, restoring private Unix permissions when needed.

## Testing

Added coverage for creation under a permissive umask, updates through an
existing hard link, permission restoration, and symlink rejection.

GitOrigin-RevId: d3e4be52e8f4cebb66c59d496a7f77a952a2d0d9
2026-08-20 06:17:48 +00:00
thomas
f1087ff151 Expand OAuth metadata redirect test coverage (#39320)
## What changed

- Cover same-origin redirects for protected-resource and authorization-server metadata.
- Verify that cross-origin redirects are rejected before contacting their targets and that redirect cycles fail within a bounded timeout.
- Exercise issuer validation and resource-header isolation for both direct and redirected metadata across legacy and Agent Plugin discovery modes.
- Reuse the test environment's local HTTP client throughout the discovery tests.

GitOrigin-RevId: bd12ac232c3b020a1c098a413361f8e205699699
2026-08-19 00:05:23 +00:00
thomas
7500ab4c8d Update rmcp to 3.1.2 (#39101)
## What changed

- Upgrade `rmcp` from 3.0.0 to 3.1.2.
- Use `rmcp`'s native JSON-RPC decoding and remove the local compatibility layer for multi-round-trip tool results.
- Preserve response metadata on `input_required` SSE results.
- Support OAuth protected-resource metadata discovery and include the discovered resource audience when refreshing tokens.

## Testing

- Add coverage for metadata preservation on modern SSE `input_required` responses.
- Add an OAuth startup scenario that discovers protected-resource metadata and verifies the refresh-token resource audience.

GitOrigin-RevId: 689f009b4a33552b640304111b74585b4009eeb8
2026-08-17 23:04:09 +00:00
Eric Traut
ff770113ca Restrict MCP HTTP redirects to the configured origin (#39046)
## Why

MCP requests can contain sensitive headers and tool-call bodies. Following a
cross-origin redirect could disclose them to another server.

## What changed

- Follow redirects only when every hop remains on the configured server's
  origin, and require HTTPS for redirects on non-loopback hostnames.
- Preserve standard redirect method and body handling while sharing the
  original timeout and enforcing a 10-hop limit.
- Avoid replaying plaintext proxy credentials across redirects, while leaving
  OAuth requests that stop at redirects unchanged.

## Testing

Add coverage for same-origin and cross-origin redirects, redirect methods,
headers and bodies, proxy credentials, timeouts, hop limits, and legacy MCP
tool calls.

GitOrigin-RevId: 3e267911a1665ad8c2fc63825099a758770f4d68
2026-08-17 18:46:12 +00:00
Eric Traut
02360b48d1 Isolate MCP resource headers during OAuth requests (#39019)
## Why

Headers configured for an MCP resource can contain credentials and must not be
forwarded to a different origin during OAuth discovery, registration, or token
exchange.

## What changed

- Apply configured resource headers only to OAuth requests on the MCP resource
  origin, while allowing OAuth-generated headers to take precedence.
- Follow credentialed OAuth redirects only when each destination remains on the
  resource origin. Preserve redirect method semantics, the overall timeout, the
  response size limit, and a maximum of 10 redirects.
- Use the Codex MCP user agent for requests to authorization-server origins.

## Testing

Add coverage for cross-origin header isolation, same-origin dynamic client
registration redirects, OAuth header precedence, token refresh, timeout
accounting, and response size limits.

GitOrigin-RevId: 609d06e2b065e4aa9ca5382b4ae60455f9e26db9
2026-08-17 16:29:47 +00:00
Ankush Gupta
4d9f3021c8 Include node_repl images in Guardian review evidence (#38454)
## What changed

- Preserve valid image content from completed `node_repl` Code Mode responses alongside text evidence for Guardian reviews.
- Enable multimodal evidence for models that require automatic `node_repl` review, or when both `guardian_enhanced_node_repl_transcripts` and `guardian_node_repl_transcript_images` are enabled.
- Bound retained and rendered evidence, deduplicate images already present in review history, and fall back to text-only evidence when the reviewer lacks image support or prompt capacity.
- Keep review evidence out of the parent turn input.

## Testing

- Cover feature gating, mixed text and image ordering, truncation and eviction, unsupported reviewers, prompt pressure, image detail normalization, and reused review sessions.

GitOrigin-RevId: a3e482402f7b3484401b231dadc662e6e3504fdf
2026-08-13 23:29:52 +00:00
Ankush Gupta
053dda6b89 Include Node REPL results in Guardian reviews (#38397)
## What changed

- Capture accepted, successful `node_repl` results from Code Mode and include them as bounded, untrusted evidence in Guardian review prompts.
- Enable the enhanced transcript through `guardian_enhanced_node_repl_transcripts` or when the selected model requires automatic Node REPL review.
- Keep this evidence out of the parent model history, exclude encrypted and failed results, and avoid resending admitted evidence when a Guardian session is reused.
- Clear retained evidence and invalidate review sessions when a thread is rolled back.

## Testing

- Add unit coverage for evidence ordering, escaping, truncation, and empty responses.
- Add an integration test covering feature-disabled, feature-enabled, and model-required behavior, including filtering and review-session reuse.

GitOrigin-RevId: edc3dca5d5b88d472a492f35531ec46889a89d72
2026-08-13 15:50:48 +00:00
xl-openai
379cb68444 Add dynamic HTTP header helpers for MCP servers (#38245)
## What changed

- Add `http_headers_helper` configuration for local streamable HTTP MCP servers. The configured shell command runs once per connection and returns a JSON object of headers that is cached across requests.
- Apply helper headers to MCP startup and OAuth flows while restricting them to the server origin, stopping redirects, rejecting reserved or duplicate headers, and enforcing output and execution limits.
- Reject helpers for remote or managed-disabled servers, use the local environment working directory, and redact helper commands from `codex mcp list` and `codex mcp get` output.

## Testing

- Cover configuration validation, helper lifecycle and output parsing, origin isolation, OAuth discovery and token refresh, managed requirements, environment selection, and CLI redaction.

GitOrigin-RevId: 84e0e26ce75520b0869d37c72b1678e033bd6818
2026-08-12 20:36:32 +00:00
stevenlee-oai
4c89139da9 Add CIMD support to MCP OAuth registration (#38089)
## What changed

- Make automatic MCP OAuth registration prefer Client ID Metadata Documents
  (CIMD) when the authorization server advertises support for public clients and
  Codex is using its native loopback callback. Fall back to advertised Dynamic
  Client Registration (DCR) otherwise.
- Add explicit `cimd` and `dcr` registration overrides to the CLI and app-server
  OAuth login API. Validate CIMD metadata and callback URLs before starting the
  authorization flow.
- Use a callback-specific Codex client metadata URL for CIMD and retain the
  exact redirect URI through authorization and token exchange.

## Testing

- Cover automatic and forced CIMD selection, DCR fallback, invalid metadata and
  redirects, token refresh, authenticated MCP requests, and conformance
  regression checks.

GitOrigin-RevId: 4238372ca53b0f38e781e141ab5da97e0a6ddf45
2026-08-12 00:01:01 +00:00
stevenlee-oai
6dc3ac8721 Add per-login MCP OAuth client registration selection (#38052)
## What changed

- Add `--oauth-client-registration` with `auto` and `dcr` choices to `codex mcp add` and `codex mcp login`.
- Add the equivalent optional `clientRegistration` field to `mcpServer/oauth/login` and the generated protocol schemas.
- Keep automatic dynamic client registration as the default, prefer a configured OAuth client ID when present, and apply the selection only to the current login without persisting it in MCP configuration.

## Testing

- Cover dynamic registration and configured-client OAuth flows through the app server.
- Verify the CLI does not persist the per-login registration choice.

GitOrigin-RevId: 653a4a1054ff43c2c5d52ae863b6a96d21692a53
2026-08-11 18:35:03 +00:00
Eric Traut
b2543af02b Propagate custom CA settings to local MCP servers (#38040)
## Why

Local stdio MCP servers may start in a different working directory from Codex,
so inherited relative CA bundle paths can otherwise resolve to the wrong file.

## What changed

- Forward the supported custom CA environment variables to local stdio MCP
  servers, convert inherited non-empty paths to absolute paths, and let explicit
  MCP environment overrides take precedence.
- Match CA variable names and `PATH` case-insensitively where required, avoiding
  duplicate environment entries and preserving executable discovery on Windows.

## Testing

- Add an end-to-end stdio MCP test covering relative inherited CA paths, empty
  values, explicit overrides, alternate key casing, and a different server
  working directory.
- Exercise executable resolution with Windows-style `Path` casing.

GitOrigin-RevId: ea1bc0ae63bc0dc780acb8363b2ed102120f282e
2026-08-11 17:24:04 +00:00
jif
dd22460869 Add MCP OAuth credential contention regression tests (#37866)
## What changed

- Cover non-blocking credential probes when the file or secrets store is locked, including retaining only a matching prior credential snapshot and recovering after the lock is released.
- Extend the streamable HTTP OAuth round trip to verify that user turns continue during store contention, newly discovered servers recover after contention, and logged-out servers do not reuse authenticated connections.
- Cover reconciliation of authentication failures and effective `Authorization` headers.

GitOrigin-RevId: 8e377644001bd0be04dc9f79841080094d09d199
2026-08-10 18:40:02 +00:00
jif
afcc95b431 Speed up MCP OAuth credential reads (#37860)
## Why

Refreshing MCP connection identities should not stall the async executor while another process holds the OAuth credential-store lock.

## What changed

- Probe file and secrets credential stores without waiting during runtime refreshes, retaining the last known credentials when the store is contended.
- Reuse unchanged authentication failures while credentials are temporarily unavailable instead of restarting the connection.
- Run blocking credential loads on a blocking worker during MCP client construction.
- Allow OAuth fallback when a configured authorization header is missing, empty, or invalid.

GitOrigin-RevId: 38dad5606da9a1ceb30fe945000ec9151a5058fa
2026-08-10 17:58:15 +00:00
iceweasel-oai
8b1b065719 Speed up MCP OAuth credential reads (#37842)
## Why

Concurrent MCP startup and status checks should not serialize when they only read the shared credential store. Repeated reads of the encrypted MCP OAuth store also needlessly decrypted unchanged contents.

## What changed

- Use shared locks for `File` and `Secrets` credential reads while keeping saves and deletes exclusive.
- Cache decrypted MCP OAuth secrets by store path, ciphertext, and passphrase, and invalidate the cache after writes.

## Testing

- Cover concurrent readers, reader/writer exclusion, shared credential loads, and cache invalidation after updates and deletes.

GitOrigin-RevId: f13512e6404d4919879ba5ba77a3e34e52b35640
2026-08-10 15:43:10 +00:00
cooper-oai
c4513cb982 Prevent launch context from reaching child processes (#37607)
## Why

Model-reachable child processes should not inherit Codex launch context.

## What changed

- Treat `OPENAI_FEDERATION_RULE_ID` and `OPENAI_IDENTITY_TOKEN_FILE` as non-inheritable environment variables, with case-insensitive matching.
- Remove them after shell environment policy overrides and before spawning commands across execution, MCP, hooks, Git helpers, and remote helper processes.

## Testing

- Cover inherited and explicitly configured variants, including mixed-case names.
- Verify the variables are absent from real child environments and app-server command and process execution.

GitOrigin-RevId: 2535527893985fef0995617f4c5b2462bea7c136
2026-08-08 16:58:26 +00:00
Evan Fannin
41014b11bd Add MCP event discovery and subscriptions (#37494)
## What changed

- Expose hosted Plugin Runtime event definitions through `McpResourceClient::list_events`.
- Add cancellable `events/stream` subscriptions that route lifecycle notifications to the matching request and cancel when the stream is dropped.
- Bound event notification and queue sizes, time out stalled response headers, and close streamable HTTP responses locally on cancellation.

## Testing

- Add streamable HTTP integration coverage for isolated concurrent subscriptions, local cancellation, and stalled response-header timeouts.

GitOrigin-RevId: 98c6fffa8f004eb2638c1b0705f659222cbbdfdb
2026-08-07 19:36:52 +00:00
Cam moten
9daa491f7c Harden local MCP server process tree cleanup (#37366)
## Why

A local stdio MCP server can exit while its descendants remain alive. Cleaning up
only the server process can therefore leak processes after client shutdown.

## What changed

- Contain locally launched MCP servers in non-breakaway Windows job objects and
  terminate the job during shutdown so descendants exit with the server.
- Preserve compatibility when job creation or assignment is unavailable by
  retrying without containment and terminating an owned process handle instead.
- Use the process-group member fallback when terminating piped processes on
  macOS.

## Testing

- Cover descendant cleanup and breakaway prevention for both local MCP protocol
  modes on Windows.
- Cover the Windows nested-job assignment fallback and verify the suspended
  process resumes before handle-based termination.

GitOrigin-RevId: 33d3cc122de8f7ce0ae69a649b12ea0ff64b7c6f
2026-08-07 03:34:49 +00:00
jif
b3ffe3d001 Recover MCP servers after OAuth reauthentication (#37337)
## Why

An OAuth-backed Streamable HTTP MCP server can fail startup when its stored credentials are rejected. If a client then completes OAuth sign-in and replaces those credentials, the failed server needs to become available without restarting the Codex session.

## What changed

- Track the credential store and OAuth tokens used for each MCP connection, and detect replacements after authentication failures.
- Refresh affected MCP servers before the next turn and include their recovered tools in the model request.
- Classify HTTP authentication challenges and rejected refresh tokens as requiring reauthentication, with sign-in guidance appropriate to local and client-managed environments.

## Testing

- Cover recovery from expired credentials through an externally written replacement token.
- Cover authentication-error classification, startup messaging, and `Auto` store migration from file credentials to the keyring.

GitOrigin-RevId: 9b090089d4e7a44ffc182f4e25da20a18e97b70f
2026-08-07 00:17:46 +00:00
jif
74b8f8db93 Cover remote MCP discovery timeout cleanup (#37248)
## What changed

Extend the executor-backed Streamable HTTP timeout test to cover both legacy
`initialize` and MCP 2026 `server/discover` requests. Verify that each stalled
handshake times out and releases the serial executor for subsequent requests.

GitOrigin-RevId: 3493904433c95265b9f645813723e890b7610abb
2026-08-06 09:46:04 +00:00
jif
e244a9d94e Bound remote MCP handshake HTTP requests (#37168)
## Why

A streamable HTTP MCP handshake could time out while its executor-backed HTTP
request continued running, leaving the serial executor blocked for later
requests.

## What changed

- Track the remaining initialization deadline for streamable HTTP transports.
- Apply it to `initialize`, `notifications/initialized`, and discovery HTTP
  requests, then clear it when the handshake finishes.

## Testing

- Added a regression test that stalls the remote MCP endpoint, waits for the
  handshake timeout, and verifies that a subsequent executor request completes.

GitOrigin-RevId: d4980a332e898309c885cbaa4fdd598924b440e1
2026-08-05 21:52:09 +00:00
Cam moten
f2d825533c Fall back to per-process MCP cleanup on macOS (#37068)
## Why

Signaling an MCP server's process group can fail with `EPERM` on macOS,
preventing owned descendants from being terminated.

## What changed

- When a group signal is denied, enumerate the group's processes and signal
  members that still belong to the expected process group.
- Apply the fallback to both `SIGTERM` and `SIGKILL` during MCP stdio server
  cleanup, while retaining the existing group signaling behavior elsewhere.
- Reject invalid process group IDs and avoid signaling processes that have
  moved to another group.

## Testing

Added macOS tests covering cleanup with a live or exited group leader,
`SIGTERM`-resistant descendants, escalation to `SIGKILL`, and unsafe group IDs.

GitOrigin-RevId: db722475b94dece74244ce8109b3e92f6cfb202a
2026-08-05 09:43:26 +00:00
jacobzhou-oai
56b82e676c Enforce Agent Plugin runtime boundaries (#37027)
## What changed

- Track Agent Plugin manifests through plugin, skill, and MCP loading so their capabilities use format-specific behavior without changing legacy plugins.
- Discover only direct-child skills, exclude app and hook capabilities, isolate MCP data, and reject MCP configuration files that are non-regular or resolve outside the plugin root.
- Bound model-visible skill instructions, plugin instructions, MCP descriptions, schemas, individual tools, and the aggregate Agent Plugin MCP tool set.
- Stop MCP and OAuth redirects when Agent Plugins send configured or authorization headers, while retaining existing redirect behavior for legacy MCP servers.

## Testing

- Add coverage for capability filtering, skill discovery, isolated MCP data and reserved-path expansion, unsafe MCP configuration files, context limits, and redirect handling.

GitOrigin-RevId: c9af66b051269f3226628ca280a58d32c808c38f
2026-08-05 04:54:33 +00:00
jacobzhou-oai
bd12b3a9ec Add Agent Plugins MCP config parsing (#36796)
## What changed

- Add `parse_agent_plugin_mcp_config` to translate Agent Plugins v1 `mcp.json` files into Codex MCP server configuration.
- Normalize `stdio` and streamable HTTP transports, including `PLUGIN_ROOT` and `PLUGIN_DATA` expansion, contained plugin paths, secure endpoint validation, and filtering of client-owned HTTP headers.
- Keep valid sibling servers when another server is invalid, while returning per-server parse errors.
- Preserve UTF-8 HTTP header values when forwarding streamable HTTP protocol headers.

## Testing

- Cover transport mapping, placeholder expansion, path containment, schema and field validation, per-server errors, platform-specific environment handling, and UTF-8 headers.

GitOrigin-RevId: ed4ab0fcf495afbb381ce48beb93989629444c56
2026-08-03 20:36:59 +00:00
jif
164b3bfeab Isolate MCP OAuth credentials by environment (#36310)
## Why

MCP servers running in an executor must not reuse host-owned OAuth credentials,
even when they have the same configured server name and URL.

## What changed

- Derive environment-scoped credential names for executor-owned MCP servers and
  use them consistently for login, logout, authentication, and connection setup.
- Mark executor-owned entries in the file credential store and fail closed when
  loading or saving an entry could cross the host/executor boundary.
- Preserve compatibility with existing local OAuth credentials, including local
  server names that overlap the new reserved prefixes.

## Testing

- Extend the executor MCP integration test to verify that executor requests use
  the executor token, never send the host token, and persist both credentials
  separately.

GitOrigin-RevId: 4fc92d0533b0fe2e0df34f6d47b81e3d20d07807
2026-07-31 11:23:46 +00:00
jif
7ec480dda5 Distinguish unknown MCP authentication status (#36045)
## Why

OAuth discovery failures do not establish that an MCP server lacks OAuth
support. Reporting those failures as `unsupported` conflates an inconclusive
check with a confirmed result.

## What changed

- Add an `unknown` MCP authentication status across the protocol, app server,
  CLI, and TUI.
- Preserve OAuth discovery errors so callers can report `unknown`, while
  retaining `unsupported` for servers known not to support OAuth.
- Document the distinction in the app server API.

## Testing

- Verify transient HTTP discovery errors are preserved.
- Verify `codex mcp list --json` reports `unknown` when discovery is rate
  limited.

GitOrigin-RevId: e4562985971606740538e542ec7eeee502111964
2026-07-29 23:24:43 +00:00
jif
3e3ae08839 Limit MCP catalog pagination (#36039)
## Why

MCP catalog discovery must not allow a server to keep pagination running or
growing without bounds.

## What changed

- Apply the shared pagination collector to tool, resource, and resource-template
  discovery.
- Limit each catalog to 100 pages and 1,024 items, and reject pagination cursors
  larger than 64 KiB or any repeated cursor.
- Bound the entire pagination operation by the configured tool timeout, falling
  back to 30 seconds when no timeout is configured.

## Testing

Add unit coverage for every limit and an end-to-end MCP test that preserves
valid multi-page tools while excluding a server that returns an oversized
cursor.

GitOrigin-RevId: 961a1bfa5fe8a265daf56e342a919c980cd720fa
2026-07-29 22:37:09 +00:00
thomas
a05bcda3db Upgrade rmcp to 3.0.0 (#36001)
## What changed

- Update the Rust MCP SDK from `3.0.0-beta.3` to `3.0.0` and adapt to its renamed metadata and server discovery types.
- Accept discovery responses without server identity metadata, using the configured server name as a fallback, and rely on the SDK's native support for namespaced server identity metadata.
- Preserve typed OAuth HTTP errors so transport failures, cross-origin redirects, and transient HTTP responses are reported instead of being treated as anonymous access.

## Testing

- Cover modern discovery with namespaced or missing server identity over HTTP, SSE, and stdio.
- Cover OAuth discovery error propagation for transport failures, redirects, and transient status codes.

GitOrigin-RevId: 12c1e45136cca89ce4fb15986c2b5df14608682a
2026-07-29 17:38:20 +00:00
jif
ddf33ea802 Bound MCP namespace descriptions (#35941)
## What changed

- Limit model-facing MCP namespace descriptions to 1,000 bytes without splitting UTF-8 characters or mutating the stored server metadata.
- Cap the aggregate source-description list in `tool_search` at 4 KiB while retaining source names and discovery instructions.
- Cover direct and deferred MCP tool exposure, including multibyte descriptions and tool visibility.

GitOrigin-RevId: 92736ec39475a1d6b3b03f5e3063e28225d8a5f6
2026-07-29 11:49:47 +00:00
thomas
9f4c20aadc Handle legacy MCP discovery prevalidation errors (#35840)
## Why

Some legacy MCP servers reject `server/discover` before creating a session and
return a null-ID JSON-RPC error with a non-JSON content type or without echoing
the rejected protocol version. These responses prevented the client from
falling back to legacy initialization.

## What changed

- Parse HTTP 400 discovery errors without a session ID regardless of their
  declared content type.
- Fall back to `initialize` when error code `-32000` reports a missing session
  or advertises only known legacy protocol versions, including supported
  versions other than `2025-06-18`.
- Continue rejecting unrelated error codes, correlated responses, non-400
  statuses, malformed version lists, and lists containing modern or unknown
  versions.

## Testing

Added MCP discovery coverage for legacy error variants, server-selected legacy
protocol versions, non-JSON content types, and non-legacy rejection cases.

GitOrigin-RevId: 4d3ee2d7d852ce0d0ab3f486da23cb653a7ff5ca
2026-07-28 22:57:09 +00:00
Celia Chen
709283b432 Use configured HTTP clients for all MCP OAuth requests (#35814)
## What changed

- Require callers to provide an HTTP client for MCP OAuth discovery and login, removing the separate direct `reqwest` path.
- Use the shared `http` and `url` types throughout the MCP client and drop its direct `reqwest` dependency.
- Preserve configured MCP headers when routing OAuth discovery through the provided client.

## Testing

- Add coverage that routed OAuth discovery forwards configured headers.

GitOrigin-RevId: 1345f56bd794626533133447597a5908e57b9b48
2026-07-28 19:11:36 +00:00
Celia Chen
9ea975a2dc Route MCP OAuth through configured HTTP clients (#35806)
## What changed

- Pass resolved, route-aware HTTP clients through MCP OAuth discovery and login so CLI commands, plugin installation, and skill dependency setup honor configured proxies and execution environments.
- Apply per-plugin MCP server configuration and requirements before starting OAuth during installation, and skip disabled servers or servers assigned to unowned environments.
- Preserve configured MCP server policies when merging remotely installed plugin metadata.

## Testing

- Cover proxy-routed OAuth for `codex mcp add`, `codex mcp login`, plugin installation, and skill MCP dependencies.
- Cover plugin-install OAuth filtering for disabled servers, plugin requirements, and unowned environments.

GitOrigin-RevId: f84c88820e24a627faa78d6bed1b371682ecdc2f
2026-07-28 18:25:29 +00:00
thomas
f2bee854a7 Complete MCP 2026 client support (#35725)
## What changed

- Drive multi-round `tools/call` and `resources/read` requests through
  `input_required` responses, preserving opaque request state and elicitation
  metadata across JSON, SSE, and stdio transports.
- Decode modern discovery and elicitation result shapes while retaining legacy
  initialization, elicitation defaults, and discovery fallback behavior.
- Apply the 8 MiB modern-protocol response limit to JSON, SSE events, and stdio
  messages, and reject executor stream recovery when output sequence gaps would
  corrupt the protocol stream.

## Testing

Added integration coverage for discovery, multi-round requests, legacy
fallbacks, message limits, stdio launchers, SSE responses, session recovery,
and executor output recovery.

GitOrigin-RevId: d26a08883a2825e8ce2408ac498114b33859225e
2026-07-28 06:06:58 +00:00
thomas
be2e4afcd7 Add MCP 2026-07-28 discovery support (#35724)
## What changed

- Add an opt-in `mcp_2026_07_28` protocol mode while preserving the legacy
  lifecycle by default.
- Negotiate the new protocol over streamable HTTP with `server/discover`,
  including bounded responses, redirect protection, and fallback only when a
  response establishes that the endpoint is legacy-only.
- Require stdio servers to opt in with
  `CODEX_MCP_PROTOCOL_VERSION=2026-07-28`, and add a bounded local stdio
  transport for the modern lifecycle.
- Consume paginated tool, resource, and resource-template catalogs in modern
  mode, reject repeated cursors, and retain discovered server identity.
- Reconnect reusable MCP clients when their selected protocol mode changes.

## Testing

- Cover HTTP JSON and SSE discovery, legacy fallback and rejection cases,
  redirects, retries, response limits, and pagination.
- Cover local and executor stdio discovery, protocol markers, message limits,
  and legacy compatibility.

GitOrigin-RevId: f6a78816e127d2a482292d63b91c8384f1595903
2026-07-28 05:52:12 +00:00
thomas
61de0d8fe8 Upgrade rmcp to 3.0.0-beta.3 (#35720)
## What changed

- Update the `rmcp` model and transport integrations for `3.0.0-beta.3`.
- Preserve legacy `elicitation/create` form requests, schema defaults, metadata, and wire-format compatibility while adopting the new elicitation types.
- Harden OAuth discovery by using GET-first discovery without starting an MCP session, preventing cross-origin header redirects, validating authorization-server and callback issuers, and retaining compatibility with metadata that omits an issuer.
- Keep stored OAuth credentials readable and avoid requiring reauthorization after transient refresh failures.

## Testing

- Add coverage for legacy elicitation round trips, OAuth discovery variants, callback issuer validation, credential migration, and refresh failures.

GitOrigin-RevId: 756197d26f3fd347c28c400228f6b3d06ed493b7
2026-07-28 05:17:25 +00:00
Celia Chen
89a3b89c4c Route MCP auth discovery through runtime HTTP clients (#35239)
## Why

MCP authentication checks need to use the same HTTP routing as the MCP
transport so servers reached through configured proxies can be discovered
reliably.

## What changed

- Resolve OAuth discovery and authentication status through each server's
  runtime HTTP client for both local and managed environments.
- Keep local discovery capped at five seconds while allowing explicit login
  requests to retain their requested timeout.
- Resolve refreshed MCP configuration and its runtime context from the same
  snapshot.

## Testing

- Cover OAuth discovery through an environment proxy and macOS system proxy
  resolution.
- Cover proxied MCP startup and runtime refresh with updated authorization
  headers.
- Verify capped and preserved OAuth discovery timeout policies.

GitOrigin-RevId: 461fb1d4786e547df8b1e6b2215a8ac40438a3aa
2026-07-24 20:04:23 +00:00
Celia Chen
09241ae4db Decouple exec-server HTTP from reqwest types (#35059)
## What changed

- Rename `ReqwestHttpClient` to `RouteAwareHttpClient` to reflect that delegated HTTP uses Codex's shared route-aware transport.
- Use `codex_http_client` response and error types plus transport-neutral `http` and `url` types, removing the exec server's direct `reqwest` dependency.

## Testing

- Cover fragment stripping and Unicode hostname normalization for delegated HTTP requests.

GitOrigin-RevId: 8b0fc60a76004feb57198bfb4afb1371c9ceb1bd
2026-07-24 00:53:05 +00:00
Celia Chen
94ebae725e Route exec-server WebSockets through configured proxies (#35056)
## Why

Remote environment connections need to honor Codex's effective outbound proxy policy, including when a rendezvous connection reconnects.

## What changed

- Pass the configured `HttpClientFactory` into remote environment transports and use `WebSocketConnector` for exec-server and rendezvous WebSockets.
- Resolve proxy routes asynchronously so these connections can use the configured system proxy.
- Add connector options that preserve Tungstenite's default TLS behavior and enable `TCP_NODELAY` for latency-sensitive rendezvous traffic.

## Testing

- Verify prepared remote environments connect through a configured system proxy.
- Verify initial and reconnected encrypted relay peers use the system proxy.
- Cover default TLS selection and opt-in `TCP_NODELAY` behavior in the WebSocket client.

GitOrigin-RevId: 8a8da2116e37cb3a891269d0c0b037986fecdd3c
2026-07-24 00:16:42 +00:00
Celia Chen
1ee8f49175 Route exec-server HTTP through configured proxy policy (#35023)
## Why

Delegated HTTP requests need to honor the same outbound proxy policy as the
Codex process that starts the exec server.

## What changed

- Pass the configured `HttpClientFactory` through local and remote exec-server
  startup and use route-aware client pools for delegated HTTP and local MCP
  requests.
- Preserve per-request timeouts and follow-or-stop redirect behavior while
  keeping request URLs and sensitive response headers out of diagnostics.

## Testing

- Cover configured system-proxy routing across the exec-server transport.
- Cover both redirect policies and verify that success and failure logs do not
  expose request or response secrets.

GitOrigin-RevId: 4af6aec1d265c4db62dfcb6e1fb076fb31736137
2026-07-23 22:39:28 +00:00
jif
34b935e3e5 Replace closed MCP connections during reconciliation (#34957)
## Why

MCP connection reconciliation can otherwise reuse a client after its service or
underlying transport has stopped.

## What changed

- Add `RmcpClient::is_closed` to report closed client, service, and transport
  states.
- Exclude closed clients when selecting a reusable MCP connection so
  reconciliation starts a replacement.

## Testing

- Add a reconciliation test that disconnects an in-process MCP transport and
  verifies that its connection is replaced.

GitOrigin-RevId: 366a85c9959dbe1763923d7e33a4ecf52d9c3c6a
2026-07-23 15:29:10 +00:00
jif
e19e65317a Reuse MCP connections across runtime refreshes (#34952)
## Why

Refreshing MCP runtime state should not restart an unchanged, ready server or
relist its tools.

## What changed

- Reconcile refreshed MCP configuration against the published connection set
  and reuse connections whose transport, environment, authentication, OAuth
  credentials, and client capabilities are unchanged.
- Keep tool filters, timeouts, metadata, and plugin provenance in the published
  server view so those settings can change without reconnecting.
- Update elicitation authority in place for reused connections, and reconnect
  when connection-defining inputs or live OAuth credentials change.

## Testing

Added coverage for unchanged-server reuse, view-only and elicitation-policy
updates, connection identity changes, OAuth credential changes, and avoiding
redundant tool listing.

GitOrigin-RevId: f04f5db5fbdde127b6a14f6aa9673112c0b557e7
2026-07-23 14:55:31 +00:00
Eric Traut
6e0455fdc4 Set a default user agent for MCP HTTP requests (#34883)
## What changed

- Send `codex-mcp-client/<version>` as the default user agent for streamable HTTP and OAuth requests.
- Preserve user agents supplied through configured HTTP headers.

## Testing

- Verify the default user agent on OAuth discovery, token refresh, and MCP initialization requests.
- Verify that a configured user agent overrides the default.

GitOrigin-RevId: 659ef8f126df97b3c1b4d01e9e542a673b5ef42b
2026-07-23 06:13:12 +00:00
viyatb-oai
9f6c29e281 Launch managed network proxies on remote executors (#33906)
## Why

Remote executions need managed-network proxy listeners in the executor so their
loopback proxy addresses are reachable by the launched process.

## What changed

- Add a capability-gated exec-server protocol field for executor-local proxy
  launch configuration, including network policy, audit metadata, and execution
  attribution.
- Start the proxy while preparing a remote process, replace inherited proxy
  environment variables with its local addresses, and derive the sandbox
  context from its listeners.
- Keep the proxy alive until inherited output streams close, then shut it down.
- Reject unsupported remote settings such as MITM and credential injection.

## Testing

- Cover configuration round trips and rejection of unsupported settings.
- Verify executor-local startup, blocked-domain enforcement, protocol
  compatibility, and proxy lifetime through process closure.

GitOrigin-RevId: c984f54e3e600aa9ebcbf8cf4574046e2c199d11
2026-07-17 21:20:14 +00:00
rka-oai
cbc83d961e Preserve encrypted content in MCP tool outputs (#33509)
## What changed

- Convert MCP text content marked with `_meta["codex/encryptedContent"] = true`
  into `encrypted_content` function call output items.
- Prefer the content-item payload whenever encrypted content is present so that
  `structured_content` does not replace the encrypted output.

## Testing

- Add a stdio MCP integration test that round-trips mixed plaintext and
  encrypted tool output.

GitOrigin-RevId: c3997a16b06ad38ff22b21016ede35b97974d9ec
2026-07-16 05:38:36 +00:00