Commit Graph
24 Commits
Author SHA1 Message Date
cooper-oai 219ab4043e Use runtime authentication for OpenAI MCP and app requests (#59749)
## What changed

- Select fresh authentication for each HTTP operation on eligible OpenAI MCP connections while preserving the connection's credential source and account network policy. Stop redirects when requests carry runtime assertions.
- Pass the owning thread's authentication and runtime context through app discovery, connector metadata, and trusted-access requests. Include the runtime authentication mode in MCP connection and tool-cache identities.
- Give resumed actors analytics clients bound to their own authentication context, and serialize stored-credential reloads with token refresh while preserving host-provided credentials.

## Testing

Add coverage for fresh request assertions, revoked account policies, redirect handling, resumed-actor isolation, and MCP uploads in dual-header and assertion-only modes.

GitOrigin-RevId: f06900a6db61cd6cf53c3aa8075afeec4d5706d9
2026-11-05 22:03:29 +00:00
Charlie Marsh 0bc73bbeb1 Add opt-in protocol discovery for local stdio MCP servers (#57210)
## Why

Stdio servers without `CODEX_MCP_PROTOCOL_VERSION` use the legacy handshake, even when they support MCP `2026-07-28`.

## What changed

- Add the disabled-by-default `mcp_connection_sharing` feature to enable discovery for eligible local stdio servers.
- Recover from failed or late discovery with a fresh handshake when needed, waiting for the previous helper to release resources before restarting.
- Retain a working legacy connection when an upgrade attempt fails for the same account, except on authentication errors.
- Keep tool catalogs separate by protocol and invalidate legacy catalogs when discovery negotiates the modern protocol.

## Testing

Add regression coverage for failed and late discovery, legacy fallback, protocol-specific catalog reuse, message limits, and Windows descendant cleanup.

GitOrigin-RevId: 36c675ef3b81d32fccf06ccbddda2312cfe602c9
2026-10-26 19:37:06 +00:00
rreichel3-oai c7e80f873f Preserve executor MCP credential boundaries across reconnects (#48143)
## Why

Cached executor MCP declarations must not gain access to host environment credentials when reconnecting to an executor that lacks environment credential resolution.

## What changed

- Retain credential policy through MCP registration, catalog materialization, and runtime setup. Derive selected HTTP plugin policy from the plugin's source environment.
- Reject host bearer-token fallback and transports requiring host environment headers or helpers for executor-owned declarations. Preserve host-configured credential resolution.
- Include credential policy in connection and tool catalog cache identities, and avoid reading host environment values for executor-only identities.

## Testing

Add regression coverage for legacy executors, cached declarations after a capability downgrade, policy preservation through catalog rebuilds, and connection and tool cache isolation.

GitOrigin-RevId: 2d5b85e4e98668c637c538cbe528914c936bd831
2026-09-25 17:15:29 +00:00
willwang-openai 83b56bc5ad Support client secrets for pre-registered MCP OAuth clients (#47891)
## 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
2026-09-24 17:26:18 +00:00
Rennie b97abdbe30 Add read-only policy support to MCP tool requests (#46042)
## 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
2026-09-16 22:25:54 +00:00
Nick Steele 654b0a77d0 Add trusted enterprise MCP auth configuration (#44832)
## Why

Enterprise MCP authorization must remain controlled by host, user, or managed configuration. Project settings and plugin declarations must not redirect enterprise credentials or downgrade the selected authentication mode.

## What changed

- Add `auth = "ema_auth"`, shared `mcp_enterprise_managed_auth` IdP configuration, and per-plugin enterprise registration settings.
- Require enterprise registrations to come from one non-project configuration layer, preserve managed IdP precedence, and reject project overrides that change authorization or re-enable disabled enterprise servers.
- Add the disabled-by-default `use_xaa` feature flag and require non-project opt-in or a managed requirement.
- Reject plugin declarations that select `ema_auth`. Keep EMA connections unsupported and block ordinary MCP OAuth login and credential fallback for this mode.
- Extend the configuration schema and serialization for the new settings.

## Testing

Add coverage for IdP precedence, incomplete registrations, alternate credential validation, project-only opt-in, plugin self-declaration rejection, configuration round-tripping, and trusted-project attempts to downgrade enterprise auth to OAuth or ChatGPT auth.

GitOrigin-RevId: f193bdfda74208c98e496a23bf2916955b131a1c
2026-09-11 14:25:56 +00:00
Matthew Zeng bd89ce67cc Prepare MCP connections for coordinated OAuth refresh (#42128)
## 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
2026-09-01 20:26:57 +00:00
felixxia-oai aa89cf62bb Freeze plugin roots in MCP tool attribution (#41117)
## Why

Plugin MCP trust decisions must describe the exact host-discovered server
registration. Looking up a plugin again by ID can resolve a different root.

## What changed

- Retain the host plugin root in MCP catalog attribution and connection identity.
- Reconnect an MCP server when its attributed plugin root changes.
- Pass the retained root through tool lifecycle attribution and use it directly
  when building trusted tool context.

## Testing

Add coverage for catalog identity, connection reconciliation, lifecycle
attribution, and rejecting a different root associated with the same plugin ID.

GitOrigin-RevId: bc92743dd40ab44065a07c3ea972b4956ef8351f
2026-08-27 11:27:50 +00:00
Tamir Duberstein f5853cbe90 Reconnect MCP servers when authentication mode changes (#40634)
## What changed

- Include the configured authentication mode in the MCP connection identity so
  runtime reconciliation replaces connections instead of reusing them after an
  authentication-mode change.
- Add a regression test covering a switch from OAuth to ChatGPT authentication
  for an executor-owned MCP server.

GitOrigin-RevId: 18cd9df62a9a5ee44594dcde6a844ad7d5e67ee2
2026-08-25 16:14:26 +00:00
jif 8edb95f274 Preserve MCP compatibility with older executors (#39979)
## Why

Older executors do not support resolving HTTP header values from their own
environment. Sending environment-backed bearer tokens to them can prevent MCP
servers from starting.

## What changed

- Advertise executor support for environment-backed HTTP headers with the
  `httpHeaderEnvVars` capability.
- Delegate bearer-token resolution only when the selected executor advertises
  that capability; otherwise, resolve tokens available in the host environment.
- Exclude executor-owned MCP servers that require environment-backed bearer
  tokens when the executor cannot resolve them, while retaining compatible
  host-owned and executor-owned servers.

## Testing

Added protocol and environment-variable coverage plus an end-to-end test that
simulates an older executor and verifies compatible MCP servers remain usable.

GitOrigin-RevId: 43545926f6f7e0f3b1091eb29d34647f6372bc4a
2026-08-21 17:21:30 +00:00
jif 9c3da20b3f Track remote MCP header environment variables (#39930)
## Why

Remote HTTP MCP connections can source header values from the host environment,
so those variables must remain part of the connection identity even when the MCP
server runs in an executor environment.

## What changed

- Track `env_http_headers` variables for remote HTTP MCP connections.
- Continue tracking `bearer_token_env_var` only for local environments, where the
  host resolves the token.

## Testing

Add coverage that verifies remote connections track host header variables without
tracking executor bearer-token variables, while local connections track both.

GitOrigin-RevId: 8fe175c54a101721a27b76495dcd298f0c2bc6a3
2026-08-21 13:22:25 +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
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
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
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
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
Martin Au-Yeung ee46c5ba0e Negotiate MCP extensions per app-server session (#36910)
## Why

App-server clients need to advertise structured MCP extension settings, including supported MCP App UI MIME types, rather than only opting into OpenAI form elicitation with a boolean.

## What changed

- Add an `extensions` map to initialize capabilities and preserve `mcpServerOpenaiFormElicitation` as a legacy alias for `openai/form`.
- Capture the declared extension profile when a thread is started, resumed, or forked, propagate it to subagents, and advertise it to downstream MCP servers during initialization.
- Keep the profile stable for the lifetime of the loaded session instead of changing it on later turns or direct tool calls.

## Testing

- Cover extension conversion, downstream MCP initialization, session isolation, legacy form support, and subagent inheritance.

GitOrigin-RevId: fbcedbb74ce788e574b0f884a4c45c4cedb9de54
2026-08-04 15:23:43 +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 bf4d3f51ea Restrict hosted MCP credentials to local environments (#36306)
## Why

Executor-owned MCP servers must not receive hosted ChatGPT actor credentials or credentials from the host's OAuth store.

## What changed

- Provide the ChatGPT auth provider and consult stored OAuth credentials only for MCP servers in the local environment.
- Require non-local servers configured with `auth = "chatgpt"` to supply a non-empty, valid static `Authorization` header. Reject environment-backed authorization so host secrets are not resolved for an executor-owned server.
- Report unsupported authentication and fail startup before connecting when an executor-owned server has no acceptable explicit authorization.

## Testing

Add coverage for local credential forwarding, non-local credential isolation, static header validation, auth status, OAuth lookup avoidance, and startup rejection.

GitOrigin-RevId: e18f1878f260c93d9babd390a5a7eac86172299b
2026-07-31 10:42:02 +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
jif 790213ded0 Scope MCP sandbox metadata to server environment (#28914)
Scope MCP sandbox metadata to the MCP server's owning environment.

Previously, `codex/sandbox-state-meta` always used the turn's primary
cwd and rebuilt a legacy sandbox policy from that cwd. That can be wrong
for MCP servers owned by a different execution environment.

This now sends the owning environment cwd as a `file:` URI in
`sandboxCwd`, keeps `permissionProfile` as the permission source of
truth, and omits sandbox-state metadata when a non-default server
environment is not selected for the turn. Local/default MCP servers keep
the existing fallback cwd behavior.

Tests:
- `just fmt`
- `just bazel-lock-update`
- `just bazel-lock-check`
- `just test -p codex-mcp`
- `just test -p codex-core mcp_sandbox_cwd`
- `cargo build -p codex-rmcp-client --bin test_stdio_server`
- `just test -p codex-core
stdio_mcp_tool_call_includes_sandbox_state_meta`
2026-06-18 19:31:07 +02:00
jif c3a479620f Add selected-plugin precedence and attribution to the MCP catalog (#27884)
## Why

**In short:** this PR resolves already-discovered MCP registrations. It
does not read selected plugins or discover their MCP servers.

The resolved MCP catalog currently builds config and auto-discovered
plugin registrations before runtime contributors are applied. A
thread-selected plugin needs a distinct precedence tier in that same
initial resolution pass: otherwise a disabled lower-precedence winner
can leave stale name-level state behind, and the winning MCP tools
cannot be attributed to the selected package reliably.

This PR adds that catalog boundary before executor discovery is
connected.

## What changed

- Added an explicit selected-plugin registration tier between
auto-discovered plugins and explicit config.
- Collected selected-plugin contributions before the initial catalog
build, while leaving compatibility and generic extension overlays in
their existing runtime phase.
- Retained the winning plugin ID and display name directly on
plugin-owned catalog registrations.
- Derived MCP tool provenance from the winning catalog entry instead of
joining against local-only plugin summaries.
- Retained the winning selected server's tool approval policy in the
running connection manager, so a selected registration cannot inherit
approval behavior from a losing local plugin.
- Kept remembered approval session-scoped for selected plugins until
there is an authority-aware persistence contract; Codex will not write
approval back to an unrelated local plugin.
- Preserved existing name-level disabled vetoes for discovered plugins
and config, while keeping a selected package's own disabled registration
scoped to that registration.
- Preserved deterministic selection order and existing config,
compatibility, and extension precedence.

The resulting order is:

```text
auto-discovered plugin
  < selected plugin
  < explicit config
  < compatibility registration
  < extension overlay
```

## Behavior and scope

This is a catalog and provenance change only. No production host
contributes selected-plugin MCP registrations yet, so existing local MCP
behavior remains unchanged.

The stacked follow-up, #27870, installs the executor plugin provider
that produces these registrations. App-server activation remains a
separate final step.

## Verification

Focused tests cover precedence, deterministic selected-plugin conflicts,
disabled-veto behavior across catalog phases, managed requirements
before selected-plugin resolution, winning-server approval policy, and
attribution when local and selected packages share an ID or server name.
CI owns execution of the test suite.
2026-06-15 11:10:51 +02:00
jif-oai 32b1ae7099 chore: drop built-in MCPs (#22173)
Drop something that was never used
2026-05-11 19:45:08 +02:00
jif-oaiandCodex b2268999fe feat: make built-in MCPs first-class runtime servers (#21356)
## DISCLAIMER
This is experimental and no production service must rely on this

## Why

Built-in MCPs are product-owned runtime capabilities, but they were
previously flattened into the same config-backed stdio path as
user-configured servers. That made them depend on a hidden `codex
builtin-mcp` re-exec path, exposed them through config-oriented CLI
flows, and erased distinctions the runtime needs to preserve—most
notably whether an MCP call should count as external context for
memory-mode pollution.

## What changed

- Model product-owned built-ins separately from config-backed MCP
servers via `BuiltinMcpServer` and `EffectiveMcpServer`.
- Launch built-ins in process through a reusable async transport instead
of the hidden `builtin-mcp` stdio subcommand.
- Keep config-oriented CLI operations such as `codex mcp
list/get/login/logout` scoped to configured servers, while merging
built-ins only into the effective runtime server set.
- Retain server metadata after launch so parallel-tool support and
context classification come from the live server set; built-in
`memories` is now classified as local Codex state rather than external
context.

## Test plan

- `cargo test -p codex-mcp`
- `cargo test -p codex-core --test suite
builtin_memories_mcp_call_does_not_mark_thread_memory_mode_polluted_when_configured`

---------

Co-authored-by: Codex <noreply@openai.com>
2026-05-07 10:36:32 +02:00