Commit Graph
30 Commits
Author SHA1 Message Date
Eric Traut 94cbbddafc Support package-style MCP server names (#41700)
## 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
2026-08-30 16:45:34 +00:00
jif 92f887ec35 Use refreshed MCP tool caches during binding capture (#41344)
## Why

An MCP binding can wait for one server while another connection updates a
shared tool catalog. Preferring the catalog captured before that wait can omit
newly available tools from the first model request.

## What changed

- Recheck the current MCP tool catalog before using the captured fallback.
- Keep the captured catalog when it expires during the wait, while honoring a
  server that disables catalog caching.

## Testing

- Cover a shared Apps cache populated by a peer while binding capture waits.
- Cover cache opt-out while capture waits for another server.

GitOrigin-RevId: e4389c7ba23e4d8397dbae0930c9e36ba0a172fb
2026-08-28 14:53:53 +00:00
jif 7625343977 Preserve cached MCP tools during binding capture (#41336)
## Why

Binding capture can wait for multiple MCP servers concurrently. During that wait, a tool catalog may be published by another connection or expire after it has already allowed a server to remain dormant. Re-reading only the current cache could omit those tools or trigger unnecessary startup.

## What changed

- Retain the cached catalog that permits lazy startup for the duration of binding capture.
- Recheck the cache after the optional startup grace so catalogs published while waiting are included.
- Add regression coverage for catalogs published during startup and catalogs that expire while another server is resolving.

GitOrigin-RevId: b5c66831db8f9ebecc79ff25c5b4b0182ad68a2f
2026-08-28 13:42:37 +00:00
trolle-oai 124e560b93 Make the optional MCP startup grace configurable (#41199)
## What changed

- Add `mcp_optional_startup_grace_ms` with a default of 1,000 ms to control how long tool catalog capture waits for optional MCP servers.
- Treat a value of `0` as disabling the shared grace, so optional servers use their configured `startup_timeout_sec` instead.
- Apply updated grace values during runtime and MCP configuration refreshes, and reset cached startup deadlines when the configured duration changes.

## Testing

- Cover custom, disabled, refreshed, and shared startup grace behavior in MCP connection and core integration tests.

GitOrigin-RevId: 936196215ed6e0a29c9ec72cfee17663978df8ef
2026-08-27 20:31:40 +00:00
sayan-oai 4213b38f3c Honor attachment-owned permissions for MCP servers (#40728)
## Why

MCP servers attached to executor environments must retain their owner's
permission profile instead of inheriting the thread-wide sandbox authority.

## What changed

- Resolve and capture a permission profile for each enabled MCP server when
  publishing the runtime, and reject calls or elicitations when that authority
  is unavailable.
- Use the captured server profile for tool approval decisions, elicitation, and
  sandbox metadata, including after runtime refreshes.
- Materialize `:workspace_roots` from `PathUri` values so permissions preserve
  the path convention of remote executor environments.
- Give threadless app discovery and resource reads an explicit default
  permission profile.

## Testing

Added coverage for per-server elicitation authority, unresolved attachments,
runtime refreshes, restricted tool calls, and foreign-platform workspace roots.

GitOrigin-RevId: 6b188d4b08b29e9971ff7aa68a7785a0cdf9e394
2026-08-25 22:50:49 +00:00
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
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
Abhinav d35e5495f9 Route hook MCP calls through current connections (#39331)
## What changed

- Execute hook-triggered MCP calls through the runtime's latest connection set instead of preparing a separate catalog-bound call.
- Keep hook calls from waiting for server startup or reconnecting, and reject disconnected servers immediately.
- Apply the shorter of the hook-requested timeout and the server's configured tool timeout.

## Testing

- Update connection manager tests to cover non-waiting calls and disabled tool filters.

GitOrigin-RevId: 3166b2d1e26d9ae2b8b3a648b4d0897cc260eb93
2026-08-19 01:15:10 +00:00
Abhinav 87070a7792 Enable MCP tool hooks in Codex sessions (#39296)
## What changed

- Execute `mcp_tool` hook handlers through the session's shared MCP runtime, including managed hook configurations.
- Restrict hook calls to already-connected, cataloged, and policy-allowed tools. Unavailable servers fail immediately without starting or reconnecting them.
- Pass session metadata to hook tools, cap hook timeouts by the server timeout, and invoke hooks without model-tool approval or recursive hook dispatch.
- Record handler type and execution mode in hook telemetry, and mark memory as externally influenced after successful or blocking MCP hooks when configured.

## Testing

- Added end-to-end coverage for prompt interpolation, hidden tools, blocking decisions, unavailable servers, thread metadata, approval bypass, and memory-mode handling.
- Added MCP runtime coverage for startup readiness, tool filters, catalog revisions, and managed connector policy.

GitOrigin-RevId: 1647cb801ebc5fa385c7bda9d9c266a389c611b8
2026-08-18 22:10:43 +00:00
jif 880f1135ea Scope MCP app resource reads to their originating call (#39187)
## Why

App widgets need to read resources using the app and account context of the
tool call that produced them, including after a thread is restored.

## What changed

- Add an optional `originCallId` to `mcpServer/resource/read` requests and
  return it on successful scoped reads.
- Track bounded provenance for successful app tool calls in thread history and
  use the current tool binding, account link, and app policy when reading the
  associated widget resource.
- Reject missing, mismatched, failed, or ambiguous origins, while keeping
  app-only tools available for widget reads without exposing them to the model.

## Testing

Add app-server coverage for scoped widget reads across both history modes,
ephemeral and persistent threads, server restarts, app-only visibility, and
invalid origin cases.

GitOrigin-RevId: 11eaefc066b2a3b639599e4cbdef680233d150a2
2026-08-18 11:51:21 +00:00
Eric Traut f8a3db0b99 Clarify MCP OAuth reauthentication errors (#38418)
## Why

When an MCP server rejects existing OAuth credentials, reporting that the server
is merely not logged in obscures that the user needs to authenticate again.

## What changed

Pass the MCP startup failure reason into error formatting and report that the
server requires OAuth reauthentication when appropriate. Preserve the existing
recovery hint for either `codex mcp login` or the client's OAuth sign-in flow.

## Testing

Cover the reauthentication message for both login flows and verify it in the
streamable HTTP OAuth round-trip test.

GitOrigin-RevId: 6f6d5fe7519b1a476f8b70d976223b2ea1ec938e
2026-08-13 18:45:13 +00:00
jif 7093e8c480 Start required cached MCP servers lazily for subagents (#38217)
## Why

Subagents can reuse cached MCP tool definitions without opening another server
connection immediately, but marking a server as required previously forced eager
startup even when its cached tools were available.

## What changed

- Allow required MCP servers with usable cached tools to remain dormant under
  the lazy startup policy.
- Treat those cached tools as satisfying required-server validation and tool
  catalog capture until the server is needed.
- Preserve eager startup for required servers without cached tools and start a
  dormant server when one of its tools is called.

## Testing

Extend the cached HTTP MCP subagent test to cover both optional and required
servers, verifying that the required server stays dormant until its cached tool
is called.

GitOrigin-RevId: 48ea20b9ae447eef27461caee2320ea78465bb6a
2026-08-12 16:50:23 +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
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 1151b23f01 Start cached MCP servers lazily for subagents (#37261)
## Why

Subagents can reuse cached MCP tool definitions without starting every optional
server before any of its tools are used.

## What changed

- Defer startup for subagent-owned, optional MCP servers when their cache has at
  least one visible, allowed tool, and trigger startup on the first operation
  that needs the live client.
- Keep root sessions, required servers, selected plugin servers, and explicit
  reconnects eager.
- Exclude empty catalogs from cache eligibility and keep dormant servers out of
  the initial startup summary.

## Testing

- Extend MCP tool-cache coverage for eager root startup, unused and filtered
  subagent servers, deferred startup status events, and startup that survives an
  interrupted first tool call.

GitOrigin-RevId: e7528ff08312583a6747cbc6550ea5b6eabda9a6
2026-08-06 11:18:24 +00:00
jif 952e87d3f2 Reuse stable MCP bindings across sampling steps (#37101)
## What changed

- Cache an `McpBinding` on each published MCP runtime once server startup has
  settled and the tool catalog revision is stable.
- Reuse the cached binding while the catalog revision remains unchanged, and
  rebuild it after a runtime publish or catalog change.
- Treat terminal failures from optional servers as stable, while continuing to
  wait for required servers and reconnecting Codex Apps servers.

## Testing

- Cover binding reuse within one published runtime and invalidation after a
  republish.
- Cover stability checks for pending, failed optional, required, and
  reconnected servers.

GitOrigin-RevId: 783a6b04897f6c484a6d56fd9cee542814041759
2026-08-05 14:04:39 +00:00
jif e4e040881a Raise the host-owned Codex Apps catalog limit (#36772)
## Why

Codex Apps tool catalogs can exceed the standard MCP limit of 2,048 items and
still need to remain available through tool search.

## What changed

- Allow up to 8,192 catalog items for host-owned `codex_apps` registrations.
- Keep the 2,048-item limit for other MCP servers, including extensions that
  register the `codex_apps` name.
- Restrict the shared Codex Apps tool cache to host-owned registrations.

## Testing

- Cover large catalogs for built-in and hosted-plugin registrations while
  verifying that another extension retains the standard limit.
- Verify that a same-named extension cannot read the host-owned Apps cache.

GitOrigin-RevId: 2265693a460e9be63c4c849169cba7324def4f49
2026-08-03 17:06: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 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
jif 85c082cccc Share optional MCP startup grace across connection sets (#36011)
## Why

Each connection set could restart the one-second startup grace for the same
cacheable optional MCP server, repeatedly delaying catalog capture while that
server was still pending.

## What changed

- Store the optional startup deadline in the shared tool catalog cache entry.
- Reuse that deadline until a catalog is published, and allow a fresh grace
  period after the cached catalog expires.
- Preserve per-connection-set startup grace for servers that disable catalog
  caching.

## Testing

Added a paused-time test covering shared deadlines, immediate cached-tool reuse,
cache expiration, and disabled caching.

GitOrigin-RevId: 3494969ee7002c70ce9e4ffd370e46a22d38cc11
2026-07-29 18:53:15 +00:00
Charlie Marsh 84ccb2938b Resolve MCP tool catalogs concurrently (#35777)
## What changed

- Resolve per-server tool catalogs concurrently in `list_all_tools` and binding capture.
- After the shared startup wait, recheck servers that previously exposed cached tools so a newly ready client contributes its current catalog and callable client.

## Testing

- Add gated-client tests that verify multiple server catalogs start before any one server is released.
- Verify binding capture replaces cached Codex Apps tools with the ready client's tools when startup completes during capture.

GitOrigin-RevId: a30d1a535ed1588f2bba21f2741e8bbd9342e339
2026-07-28 14:13:03 +00:00
jif d9e1c9cd55 Avoid blocking turns on optional MCP startup (#35742)
## Why

A pending optional MCP server can delay the first model request even when the
turn does not need that server.

## What changed

- Give optional MCP servers a shared one-second startup grace, then omit servers
  that are still pending from the captured tool catalog.
- Continue waiting when the turn explicitly requires a server through a plugin,
  skill dependency, or `mcp://` mention, and preserve this behavior for input
  received between sampling steps.
- Route direct resource requests to the live connection set when a pending
  server was omitted from the binding, while keeping all-server resource
  discovery non-blocking.

## Testing

- Cover the shared grace period and resource behavior for pending optional
  servers.
- Verify plugin, plugin-skill, and direct MCP mentions wait for startup.
- Verify an Apps-enabled turn proceeds without tools from an unrelated pending
  optional server.

GitOrigin-RevId: b5f895c5a5362fe73f7d33250367662d4a217e4d
2026-07-28 09:32:48 +00:00
jif 3bbf1fe757 Expose cached MCP tools before server startup (#35590)
## Why

Cached MCP definitions can be supplied to inference without waiting for the
server to finish initializing.

## What changed

- Publish cached tools while startup is still in progress, clearing their
  potentially stale read-only hint.
- Wait for the selected server to start before executing a tool call, then
  prepare the call against the refreshed live binding.
- Keep cached tools visible in a binding even when no live client is available,
  while rejecting attempts to prepare those calls.

## Testing

- Cover cached-tool visibility before startup and replacement with live tool
  metadata afterward.
- Verify cached definitions reach inference before MCP initialization and that
  calls unavailable in the live catalog return the expected model-visible
  error.

GitOrigin-RevId: 3aae8f474c344ccdc5e08fe321bbad21d85bffd1
2026-07-27 10:25:32 +00:00
sayan-oai 74e9d7efc4 Allow omitting MCP tool prefixes per server (#34991)
## What changed

- Accept a table form of `features.non_prefixed_mcp_tool_names` with an
  optional `server_names` list while preserving the existing boolean form.
- Omit the legacy `mcp__` namespace prefix only for tools from selected MCP
  servers. When no server list is provided, the enabled feature continues to
  omit the prefix for every server.
- Cover configuration resolution, tool normalization, and an MCP stdio
  round trip with selected servers.

GitOrigin-RevId: bdfb7ac54226de5051f06610e2c6b78b23912ef0
2026-07-23 18:54:55 +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 e497325a6a Centralize thread MCP state in McpRuntime (#34930)
## What changed

- Make `McpRuntime` own the published MCP configuration, connections, elicitation routing, and selected capability roots for a thread.
- Capture immutable MCP bindings for model steps and tool calls so in-flight work keeps a consistent connection set and approval authority while refreshed state is published atomically.
- Mark MCP state dirty when relevant configuration, plugins, environments, authentication, or elicitation capabilities change, then rebuild it before the next sampling request or out-of-band MCP operation.
- Separate config reloads from server invalidation: `ReloadMcpConfig` applies resolved MCP inputs, while `RefreshMcpServers` requests reinitialization from the thread's latest state.

## Testing

- Cover refreshed state visibility for existing turns, stable step bindings, current approval authority, cancelled refresh retries, resource-client reconciliation, and Apps recovery between sampling requests.

GitOrigin-RevId: 59eabb1aa8dc083426bd18ef4d3630508f376401
2026-07-23 11:27:34 +00:00
jif 516f1e2aff Rename the MCP connection manager to McpConnectionSet (#34708)
## What changed

- Use `McpConnectionSet` as the primary name for the collection of active MCP
  server connections throughout `codex-mcp` and its callers.
- Keep `McpConnectionManager` as a backward-compatible type alias.

GitOrigin-RevId: 9753838b4fd0a0b6429a9c4af0c077137616f388
2026-07-22 09:25:22 +00:00
jif 65f8bf6853 Bind MCP calls to captured catalog revisions (#34588)
## Why

An MCP connection or tool catalog can change after a model step captures its
available tools. Calls from that step must not be rerouted to a replacement
client or run against a catalog revision the model did not see.

## What changed

- Add `McpBinding` to capture the ready clients, visible tools, resources, and
  server metadata for one sampling request.
- Prepare calls against the captured client and reject them if the tool catalog
  changes before call preparation and execution finish.
- Keep resource access and cache identity tied to the binding's exact connection
  set, and omit servers that do not have a ready client.
- Preserve each client's unfiltered tool catalog so bindings can apply the
  current filter consistently.

## Testing

Add coverage for connection replacement, stale catalog rejection, serialized
call preparation and refresh, ready-client capture, and binding-scoped resource
identity.

GitOrigin-RevId: a25da4d2c7f5ed06c41caa0c6d15c464c1698314
2026-07-21 18:13:41 +00:00
jif 2d85e6d3a6 Split MCP connection manager into focused modules (#34522)
## What changed

- Move required-server startup validation into `connection_manager/required.rs`.
- Move tool listing, lookup, metadata attachment, and Codex Apps cache refresh into `connection_manager/tool_catalog.rs`.
- Keep the existing connection-manager API and behavior unchanged.

GitOrigin-RevId: 7249896699f756bdbb6e00bc2bbc4a98098741a9
2026-07-21 11:45:36 +00:00