Commit Graph
75 Commits
Author SHA1 Message Date
thomas c465563aa9 Enable app routing for remote curated Agent Plugins (#55667)
## Why

Agent Plugin manifests previously skipped app declarations, including service-generated declarations installed with remote curated plugins. This prevented those plugins from using app routing and suppressing matching direct MCP connections.

## What changed

- Recognize app declarations for Agent Plugins from `openai-curated-remote` across loading, capability summaries, plugin details, tool suggestions, and install authentication.
- Apply app routing to suppress same-name MCP servers when an app route is available. Keep unrelated MCP servers available and preserve direct MCP access in API-key mode.
- Keep app declarations inactive for Agent Plugins from other marketplaces.

## Testing

Add coverage for marketplace and authentication routing, service-generated app declarations during installation with both manifest formats, and app tools reaching turns. Verify that disabling Apps does not restore matching direct MCP connections.

GitOrigin-RevId: 791739569f0e01c898040bc2d028cf517f767e00
2026-10-20 20:27:32 +00:00
Matthew Zeng aff92080f2 Add remote plugin metadata to plugin configuration (#54424)
## What changed

Add optional `remote_plugin_id`, `release_id`, and `auto_provision` fields to `PluginConfig` and the configuration schema. Store remote plugin identity, release, and provisioning metadata without fetching releases or triggering provisioning. Entries containing only this metadata continue to inherit existing plugin activation defaults.

## Testing

Extend configuration round-trip and plugin loader tests to cover remote metadata entries with inherited enablement and with `plugins._default.enabled = false`.

GitOrigin-RevId: bb657c25929cab100982b37120ab62b089eb7044
2026-10-15 21:44:12 +00:00
Philipp Spiess 5d4922595a Prefer remote Visualize installs over the bundled plugin (#53747)
## What changed

When the remote global catalog is active, let a cached `visualize@openai-curated-remote` install supersede `visualize@openai-bundled`, matching the existing Sites behavior. A disabled remote install also suppresses the bundled plugin; a missing remote bundle preserves the bundled fallback.

## Testing

Extend the agent-turn compatibility tests to cover Visualize with enabled, disabled, and missing remote bundles, asserting which skills appear in the developer prompt.

GitOrigin-RevId: 7d0cc564189249e597d5bd29b5800353d89a9060
2026-10-13 19:28:21 +00:00
stevenlee-oai 89d68bc8d2 Add configurable default plugin activation policy (#52220)
## What changed

Support `plugins._default.enabled` with explicit per-plugin `enabled` overrides. Omission preserves existing source and account enablement; configuration cannot activate a plugin disabled at its source. Plugin settings such as remembered tool approvals inherit the default unless `enabled` is explicitly set.

Apply the policy to plugin skills, MCP servers, Apps, and hooks, including selected executor roots and runtime configuration refreshes. Preserve the latest plugin policy when adding MCP dependencies and rebuild hooks when concurrent configuration updates replace their inputs.

Report effective enablement in `plugin/list`, `plugin/installed`, `plugin/read`, and `plugin/share/list`. Remote installation still installs disabled packages, but skips MCP and Apps authentication setup without writing an enablement override.

## Testing

Add regression coverage for default inheritance and explicit overrides, source-disabled plugins, policy refreshes during active turns, disabled or malformed selected plugin roots, and remote installation authentication behavior.

GitOrigin-RevId: 83b70c5b47fc95474fec292f248683f1f887221e
2026-10-08 18:42:58 +00:00
Adam Perry @ OpenAI c9870d0157 Use PathUri for skill identity and path matching (#51482)
## Why

Skill selection and disabled-path matching need to recognize equivalent Windows paths across case and separator differences while preserving literal spaces, `%`, and `#` in native filenames.

## What changed

- Carry `PathUri` through skill metadata, discovery mappings, filesystem lookups, disabled-path sets, and invocation analytics.
- Match linked skill mentions and TUI selections by parsed path identity.
- Use `LegacyAppPathString` for app-server skill paths and regenerate schemas and SDK types, preserving native path strings on the wire.
- Preserve native catalog display paths and ordering. Keep host filesystem probes and configuration writes restricted to host-compatible paths.

## Testing

Add regression tests for Windows path identity and disabled-skill matching, literal filename characters, catalog resource reads, native path ordering, and foreign-path analytics normalization.

GitOrigin-RevId: c212916dc9fef0e7616542726e107f0d6a313267
2026-10-06 21:29:35 +00:00
Nick Steele af0d68a236 Restrict enterprise MCP auth and fail closed on config refresh (#49260)
## Why

Configuration reloads must honor current managed restrictions without granting new enterprise MCP authority to existing sessions or overwriting newer configuration with stale snapshots.

## What changed

- Allow enterprise managed authentication only for configured MCP servers. Remove plugin `ema_auth` overlays from the schema and disable servers that still use them.
- Refresh ordinary MCP settings while preserving session settings and initially admitted enterprise registrations. Disable enterprise MCP when its registration changes, policy revokes access, or configuration loading or resolution fails; require a new session to restore enterprise authority.
- Publish refreshes only when their captured configuration is still current, with bounded retries in app-server reloads. Preserve updated managed restrictions even when a refresh is rejected.
- Finish processing other thread refreshes before `config/mcpServer/reload` reports a rejection, and document that an error can accompany partially applied changes.

## Testing

Add regression coverage for stale refreshes, bounded retries, managed-policy revocation, persistent enterprise disablement, ordinary MCP transport changes, and rejection of plugin enterprise authentication. Verify that denied enterprise servers receive no requests.

GitOrigin-RevId: 34429cd339c1ec152a2ee8697cb29f0cff5d9e5f
2026-09-29 13:08:37 +00:00
Dmitriy Kovalenko 1260716393 Cache parsed plugin manifests across plugin workflows (#49099)
## Why

Repeated plugin discovery and loading reparse unchanged manifests and repeat warnings for invalid fields.

## What changed

- Share a manifest cache through `PluginStore` across marketplace listing, plugin loading, capability inspection, and tool suggestion metadata.
- Reuse successful parses by plugin root, manifest path, and content digests, including the Codex overlay. Reread files on each load so manifest edits and overlay changes or removal remain visible.
- Bound the cache to 128 entries and bypass caching for inputs larger than 64 KiB. Retry failed parses and share entries across store clones while keeping independent stores isolated.
- Reuse loaded manifest data when loading apps and MCP metadata.

## Testing

Add unit coverage for parse reuse, warning deduplication, revision invalidation, repair after parse failures, equivalent Windows paths, store isolation, and oversized inputs. Add an app-server regression test that verifies repeated `plugin/list` requests observe manifest and overlay revisions in one running server.

GitOrigin-RevId: ed082cd7d198015cd8ed35db7f2af74e13f49915
2026-09-28 23:32:45 +00:00
Jiwon Kim 108e6a6dbe Replace Sites migration state with a runtime compatibility guard (#46108)
## Why

Older Desktop clients can still provide bundled Sites to an independently updated SSH app-server. A cached remote Sites install must take precedence, even when disabled, while a missing remote bundle must preserve the bundled fallback.

## What changed

- Remove persisted bundled-plugin exclusions, Sites migration checks, and the migration wait when loading local plugin configuration.
- Suppress `sites@openai-bundled` during plugin loading when the remote global catalog is active and a cached remote Sites install is available.
- Remove exclusion-based catalog filtering and read/install guards, and simplify `install_plugin` to accept `ConfigLayerStack`.

## Testing

Expand the agent-turn Sites test to cover enabled remote precedence, disabled remote suppression of bundled Sites, and fallback when the remote bundle is missing.

GitOrigin-RevId: e2758596e5493ccee051cdfbf6b4afbe4f98948c
2026-09-17 04:23:45 +00:00
Nick Steele 374c4b2d82 Resolve enterprise-managed MCP registrations in the catalog (#45459)
## What changed

- Retain the trusted enterprise identity provider in runtime configuration and bind winning MCP registrations during catalog finalization. Require `features.use_xaa` and a configured identity provider for activation, while preserving existing server restrictions.
- Apply plugin `ema_auth` client, issuer, resource, and scope settings to installed and selected plugins. Disable registrations with mismatched endpoints or empty resources without rewriting plugin endpoints.
- Preserve enterprise auth policy across catalog rebuilds and rebind registrations when materialized server settings change. Keep registration rejection separate from persistent server-name vetoes so it does not disable replacement hosted apps.

## Testing

Add coverage for activation gates, configuration ownership, plugin endpoint validation, catalog rebuilds, and skipping interactive OAuth during installation of enterprise-managed plugins. Stabilize the sandbox network proxy test by reading request headers before closing the loopback connection.

GitOrigin-RevId: 3374f507d120835b285767cedbbb511fc7b0fba2
2026-09-14 16:30:00 +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
Jiwon Kim b6ab99ed87 Prefer remote Sites over the bundled plugin (#42100)
## Why

When the remote Sites plugin is installed and its local bundle is available, exposing the bundled copy as well creates duplicate catalog entries and can load the wrong skills.

## What changed

- Persist an account- and backend-scoped exclusion for `sites@openai-bundled` once the remote replacement is installed and loadable.
- Apply the exclusion to plugin catalogs, search, direct reads and installs, runtime loading, hooks, and skill caches while preserving the remote plugin's server-owned enabled state.
- Restore the bundled fallback when the remote plugin is absent or its local files are unavailable, and throttle repeated availability checks for 60 seconds.

## Testing

- Added manager tests for persistence across restarts, account/backend isolation, fallback restoration, concurrent checks, and refresh throttling.
- Added app-server and agent-turn tests confirming that catalog, search, and skill loading prefer remote Sites.

GitOrigin-RevId: bc1154f79d3107910fee9fa27389a0ddb48ce6cf
2026-09-01 16:58:54 +00:00
pakrym-oai f742dabc6f Support per-tool MCP output limits (#41421)
## What changed

- Add a positive `output_token_limit` setting to each entry under an MCP server's `tools` configuration.
- Apply the most restrictive limit when plugin and user policies overlap, while keeping approval policy independent.
- Carry the effective MCP output budget in conversation history so tool output, post-tool hook responses, and resumed sessions use the same truncation limit.

## Testing

- Cover configuration parsing, serialization, schema validation, and plugin policy merging.
- Cover MCP output below and above the configured limit, post-tool hook responses, and session resume.

GitOrigin-RevId: d0beb4fca9ba6055d9e1d31c137373b465d50d61
2026-08-28 21:40:23 +00:00
Matthew Zeng 56239d7a61 Report affected capabilities from remote plugin syncs (#41193)
## Why

Remote plugin sync results need to identify which runtime categories may require
invalidation when a cached bundle changes.

## What changed

- Add `RemotePluginCapabilities` hints for MCP servers, Apps, hooks, and skills.
- Attach capability hints to materialized and removed plugins. Updates union the
  declarations from the old and new bundles, while removals inspect the active
  bundle before deleting its cache.
- Discover declarations without applying runtime policy or creating runtime
  data directories.

## Testing

- Cover Agent Plugin capability discovery with an unavailable runtime data
  directory.
- Cover capability accumulation across bundle versions and removal reporting.

GitOrigin-RevId: 338075d22d86f30f52be5785a2d87c77b33609c6
2026-08-27 19:54:40 +00:00
willwang-openai 6ac012a0d4 Honor layered configuration when loading plugins (#40954)
## What changed

- Resolve plugin activation, MCP server policy, and marketplace definitions from the effective configuration stack, including system settings and trusted project overrides.
- Load plugin skills independently for each working directory passed to `skills/list`.
- Exclude project configuration from catalog requests whose `cwds` are omitted or empty.
- Cache up to eight loaded plugin configurations with least-recently-used eviction so requests for different working directories can reuse their results.

## Testing

- Cover layered plugin and MCP policy across trusted and untrusted projects.
- Cover per-directory skill and plugin catalog results, cache reuse and eviction, and system-defined marketplaces.

GitOrigin-RevId: cb68b2b1bdab1da48e05ca7562bc05014431fc71
2026-08-26 19:02:02 +00:00
jif 40b7560169 Forward local env vars to Agent Plugin MCP servers (#40363)
## What changed

- Apply local `env_vars` declarations from `.codex-plugin/plugin.json` to matching stdio servers loaded from an Agent Plugin manifest.
- Replace matching `${NAME}` entries in the portable server environment with host environment forwarding while preserving the portable command, arguments, and unrelated servers.
- Ignore remote-sourced environment variables and support both inline and file-based Codex MCP declarations.

## Testing

- Cover matching-server filtering, local and remote sources, inline declarations, and an end-to-end `PATH` forwarding round trip.

GitOrigin-RevId: 843e1232a084fa5f571fe56e07266995b87fd53d
2026-08-24 08:43:25 +00:00
Charlie Marsh ffad922340 Isolate automatic plugin Git operations (#39520)
## Why

Background marketplace and plugin refreshes can otherwise inherit repository-local or command-scoped Git configuration from the project that launched Codex. That configuration can redirect remotes or invoke Git helpers during an automatic operation.

## What changed

- Run automatic marketplace upgrades, plugin cache refreshes, and curated marketplace lookups with repository-scoped Git environment variables removed and a temporary trusted repository under the Codex home.
- Carry the automatic/manual trust mode through marketplace upgrades and plugin materialization.
- Preserve the caller's Git configuration for explicit marketplace upgrades, plugin installs, and refreshes.

## Testing

- Add regression coverage for repository URL rewrites, protocol helpers, command-scoped configuration, and manual Git filters.

GitOrigin-RevId: 957f45fa3bd7ce7e1b83355f276cf65dc5e99c8e
2026-08-19 17:34:00 +00:00
jif 8ef139667f Apply user MCP policy to selected executor plugins (#39079)
## What changed

- Resolve MCP server policy directly from the effective user configuration for selected executor-plugin roots.
- Apply server enablement, tool allow/deny lists, and default and per-tool approval modes while preserving stricter plugin-declared restrictions.
- Cover policy merging and opaque selected-root IDs in the executor-plugin MCP integration tests.

GitOrigin-RevId: dce3021969ba71e642de52312449cab6277515c3
2026-08-17 20:55:04 +00:00
felixxia-oai b3278e96cb Move skill config rule resolution into codex-config (#37466)
## What changed

- Define skill config selectors, ordered rules, and layer-stack parsing in `codex-config`.
- Resolve disabled skill paths from generic skill name/path pairs, so configuration logic no longer depends on `SkillMetadata`.
- Update plugin and host skill consumers to use the `codex-config` API and consolidate the rule tests with the skill config tests.

GitOrigin-RevId: 3fe67869708df2652befe28d58cdeba933256f84
2026-08-07 16:20:38 +00:00
felixxia-oai c5d9431971 Unify plugin skill loading through the shared loader (#37452)
## What changed

- Route plugin inventory loading and capability summaries through the injected
  `SkillRootLoader`.
- Preserve recursive discovery for legacy plugins while restricting agent-plugin
  skill discovery to direct children of the skills root.

## Testing

- Verify `plugin/read` excludes nested agent-plugin skills.
- Verify installed agent-plugin telemetry reports skills only for portable,
  direct-child layouts.

GitOrigin-RevId: 9e78dd0c70a632d510c780963a6ceb3ad4bc2522
2026-08-07 14:35:42 +00:00
felixxia-oai e58d9ef447 Unify plugin skill loading with the host skill service (#37444)
## What changed

- Inject the host skill loader into `PluginsManager` so plugin discovery and agent turns use the same loading and product-policy behavior.
- Share plugin skill snapshots across those paths, preserving a consistent view of skills across workspaces.
- Apply migrated-command precedence after product filtering, allowing an eligible migrated command to replace a filtered native skill with the same name.

## Testing

- Add coverage for product-restricted plugin skills, native-versus-migrated command precedence, and the skills exposed to agent turns.

GitOrigin-RevId: f5ef0d0766ebeeb30d73ffaf044d003c2906ea4d
2026-08-07 13:54:24 +00:00
felixxia-oai e75a1888d7 Load plugin skill roots through the host skills service (#37440)
## What changed

- Implement `SkillRootLoader<PluginSkillRoot>` for `HostSkillsService`.
- Load roots concurrently while preserving request order, product restrictions, cached snapshots, skill errors, and per-skill filesystem metadata.
- Deduplicate overlapping roots and prefer native plugin skills over migrated commands with the same plugin ID and skill name.

## Testing

- Cover native and migrated skill precedence, nested and overlapping roots, product filtering, snapshot reuse, error propagation, and symlinked migration roots.

GitOrigin-RevId: 2270d10616b3a0463852c563ee071c524cd11e6b
2026-08-07 13:23:23 +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
Jeremy Rose 7ada37a15e Reject implicitly discovered bare Git repositories (#36924)
## Why

A repository can contain a tracked directory that Git implicitly treats as a bare
repository. Its configuration may select helpers such as `core.fsmonitor`, causing
Codex Git operations in that directory to execute repository-controlled code.

## What changed

- Pass `-c safe.bareRepository=explicit` to Codex-managed Git commands so they
  reject implicitly discovered bare repositories.
- Continue to support repositories explicitly selected with `--git-dir` or
  `GIT_DIR`.

## Testing

Add a regression test that clones a repository containing a tracked embedded Git
repository and verifies that guarded Git inspection rejects it without running
its configured filesystem monitor.

GitOrigin-RevId: 344b5bc1e0ffa94f2a1b788488aa653222da10f3
2026-08-04 16:53:33 +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
felixxia-oai 294d813263 Route curated plugins by authentication mode (#35671)
## Why

Curated plugin capabilities need to follow the active authentication mode, including after an account switch and when the configured model provider differs from the authentication source.

## What changed

- Select the ChatGPT, remote, or API curated marketplace from the current authentication mode, with an API marketplace fallback for ambient Amazon Bedrock credentials.
- Apply that selection consistently to plugin loading, hooks, skills, installed-plugin conflict filtering, marketplace listing, and `codex mcp` discovery.
- Start the local curated repository sync when an account change makes the remote catalog unavailable, and refresh existing thread MCP runtimes when the effective plugin cache changes.

## Testing

Added coverage for account switches, ChatGPT-authenticated Bedrock sessions, API-key MCP discovery, curated marketplace filtering, hook and skill routing, and existing-thread MCP refreshes.

GitOrigin-RevId: dbefdba3a3ea7281e7b6013e057a418770ccfc95
2026-07-27 21:17:42 +00:00
jameswt-oai 07fd04abb1 Propagate remote plugin IDs to skill metadata (#35261)
## What changed

- Carry a plugin's local and remote identities together from plugin loading into
  `SkillMetadata`.
- Resolve remote IDs from the installed-plugin snapshot when available, falling
  back to persisted install metadata only when no snapshot exists.
- Include plugin identity in skill cache keys so identity changes refresh cached
  skill metadata.

## Testing

- Cover snapshot and persisted identity resolution, local marketplace isolation,
  cached skill refreshes, and propagation through plugin skill snapshots.

GitOrigin-RevId: aabeeb631a43361fe817358ace7f1ea8ba5db708
2026-07-24 23:36:11 +00:00
jacobzhou-oai a28374e0db Support Agent Plugins manifests (#35105)
## What changed

- Recognize root `plugin.json` files using the Agent Plugins 1.0 schema and map their portable metadata, `skills/`, and `mcp.json` into Codex plugin manifests.
- Apply Codex-specific apps, hooks, and interface settings from the inline `com.openai` extension, with `.codex-plugin/plugin.json` as a fallback overlay.
- Preserve legacy manifest precedence when a root `plugin.json` is unrelated, and reject unsupported Agent Plugins schema versions.
- Add a direct-child skill discovery mode that excludes nested skills and paths resolving outside the plugin root.

## Testing

- Cover manifest metadata, validation, extension precedence, legacy fallback, and direct-child skill path boundaries.

GitOrigin-RevId: eab24139f13a5cc5cb3ad3fb444d8e904511aca6
2026-07-24 05:59:16 +00:00
caseysilver-oai 690995b7c1 Verify Git plugin SHA checkouts (#34644)
## Why

Git can interpret a requested commit SHA as a branch name when the remote's
default branch has the same name. This can cause a marketplace plugin source
to materialize a different commit than the one it pinned.

## What changed

Resolve `HEAD` after checking out a SHA-pinned Git plugin source and reject the
source when the resolved commit does not exactly match the requested SHA.
Ref-name checkouts retain their existing behavior.

## Testing

Add a regression test with a default branch named after another commit's SHA
and verify that materialization rejects the mismatched checkout.

GitOrigin-RevId: c19cbd98ee6167dad7b2ee72e283b3bd30b59713
2026-07-22 01:20:13 +00:00
felixxia-oai 56c11cf658 Move shared skill models into codex-skills (#34429)
## What changed

- Define and export skill metadata, policy, dependency, interface, and configuration rule types from `codex-skills`.
- Update core, plugin, and extension consumers to use the shared models while retaining compatibility re-exports from `codex-core-skills`.
- Share product-restriction handling between host and environment skill metadata.

## Testing

- Add unit coverage for default and explicit implicit-invocation and product policies.

GitOrigin-RevId: 9093469f8fff8e2d902dc9781235f64709827a87
2026-07-20 23:22:48 +00:00
charlesgong-openai 2cd6ed7509 Migrate plugin commands into skills on install (#33411)
## What changed

- Convert supported plugin command Markdown into generated skills when a plugin is installed.
- Read command sources from the manifest's `commands` field, falling back to the plugin's `commands/` directory.
- Load generated command skills alongside native plugin skills while preferring native skills with the same name.
- Skip commands with unsupported templates, missing descriptions, name collisions, or generated skills larger than 4 KB, and keep migration failures from blocking plugin installation.

## Testing

- Cover default and manifest-configured command paths, stale generated skill cleanup, size limits, native-skill precedence, invalid manifest fields, and non-fatal migration errors.

GitOrigin-RevId: 67d910048544b160b191066569bca69b2b951ebc
2026-07-15 19:51:37 +00:00
Adam Perry @ OpenAI 2e4f55608b Scan skill roots concurrently (#33369)
## What changed

- Scan up to eight skill roots concurrently instead of loading them one at a time.
- Share scan capacity across host-skill and plugin-skill loads to bound aggregate filesystem work.
- Merge completed scans in input order so root precedence and error ordering remain deterministic.
- Skip canonicalization and parsing work for empty roots.

## Testing

- Add coverage for out-of-order scan completion and shared-capacity blocking.

GitOrigin-RevId: 33a47aaa02aee7fe31a050bb04d51c1e2043d6ae
2026-07-15 15:56:53 +00:00
xl-openai 9dbdb4e2c0 [plugins] Enforce marketplace source policy at runtime (#29691)
## Summary

- project effective marketplace/plugin config through the enterprise
source policy so blocked installed plugins become inactive
- filter plugin list/read/discovery and CLI marketplace source/snapshot
reporting using the same policy
- enforce source admission for background marketplace cache refreshes
- continue refreshing/upgrading independent marketplaces and plugins
when one entry fails, returning per-entry errors
- include policy-projected plugin state in cache and refresh keys so
requirement changes invalidate stale results

## Stack

This is PR 2 of 2 and is based on #29690. Review the admission model and
source matcher in #29690 first; this PR contains only runtime
enforcement.

## Test plan

- `just test -p codex-core-plugins` (287 tests)
- `just test -p codex-cli
plugin_list_ignores_implicit_system_marketplace_roots_without_manifests`
- `cargo check -p codex-cli -p codex-app-server --tests`
2026-06-27 15:22:05 -07:00
charlesgong-openai 6509f3148a [codex] Support npm marketplace plugin sources (#29375)
## Why

Marketplace source deserialization treated `{"source":"npm", ...}` as
unsupported. The loader logged and skipped the entry, so npm-backed
plugins never appeared in `plugin list --available` and `plugin add`
returned "plugin not found".

Codex plugins are installed from a plugin root, not from an npm
dependency tree. For npm-backed marketplace entries, Codex should fetch
the published package contents without running package scripts or
installing unrelated dependencies.

## What changed

- Add `npm` marketplace plugin sources with `package`, optional semver
`version` or version range, and optional HTTPS `registry`.
- Reject unsafe npm source fields before materialization, including
invalid package names, non-semver version selectors, plaintext or
credential-bearing registry URLs, and registry query/fragment data.
- Materialize npm plugins with `npm pack --ignore-scripts`, then unpack
the resulting tarball through the existing hardened plugin bundle
extractor.
- Enforce npm archive and extracted-size limits, require the standard
npm `package/` archive root, and verify the extracted `package.json`
name matches the requested package before installing.
- Keep plugin listings, install-source descriptions, CLI JSON/human
output, app-server v2 `PluginSource`, TUI source summaries, regenerated
schema fixtures, and app-server documentation in sync.

## Impact

Marketplaces can distribute Codex plugins from public or configured
private HTTPS npm registries using the same install flow as existing
materialized plugin sources. `npm` must be available on `PATH` when an
npm-backed plugin is installed.

Fixes #27831

## Validation

- `just write-app-server-schema`
- `just test -p codex-core-plugins -p codex-app-server-protocol -p
codex-app-server -p codex-cli`
  - npm/schema/core-plugin coverage passed in the run.
- The full focused command finished with `1739 passed`, `11 failed`, and
`6 timed out`; the failures were unrelated local app-server environment
failures from `sandbox-exec: sandbox_apply: Operation not permitted`
plus one missing `test_stdio_server` helper binary.
- Installed an npm-published Codex plugin package through a throwaway
local marketplace and throwaway `CODEX_HOME` to exercise the real npm
materialization path end to end.
2026-06-26 17:24:46 -04:00
jif 4e0f863df3 Add a connector declaration snapshot (#29851)
## Why

Connector declarations currently enter Codex through broad plugin
capability summaries, then MCP setup, turn tooling, and `app/list` each
reconstruct the same information. That makes executor-selected
connectors difficult to add without coupling connector behavior to the
host plugin loader.

This PR introduces a small connector-owned value that later stack layers
can populate before thread startup.

## What changed

- Move the pure app-declaration parser into `codex-connectors`,
preserving declaration order and category cleanup while leaving
host-side validation and deduplication unchanged.
- Add an immutable `ConnectorSnapshot` with ordered connector IDs and
plugin display-name provenance.
- Adapt the existing local-plugin capability summaries into that
snapshot at current consumer boundaries.
- Use the snapshot for MCP tool provenance, turn connector inventory,
and `app/list`.
- Keep the crate API narrow: no test-only snapshot accessors are
exposed.

The externally visible behavior is unchanged. Connector tools still come
from the orchestrator-owned `/ps/mcp` server, and local plugin
enablement remains owned by the existing plugin loader.

## Stack scope

This is the foundation only. It does not read selected executor packages
or change thread startup. #29852 adds the executor-backed declaration
reader, and #29856 composes selected declarations into a thread
snapshot.
2026-06-24 23:24:01 +01:00
jif 3e39e92f03 Keep executor plugin MCP paths URI-native (#29628)
## Why

Executor-owned plugin roots are `PathUri`, but MCP config normalization
still converts them into a native `Path` using the app-server host's
rules. Relative `cwd` values can therefore resolve against the wrong
filesystem when host and executor path conventions differ.

This PR keeps executor MCP paths URI-native until the selected
environment launches the server, while retaining the existing host
parser behavior.

## What changed

- Keep one shared MCP normalization path with narrow host-`Path` and
executor-`PathUri` entrypoints.
- Preserve native host resolution for locally installed plugin MCP
configs.
- For executor configs, default `cwd` to the plugin root and resolve
relative working directories with the root URI's path convention.
- Accept explicit executor `file:` URIs only when they remain within the
selected plugin root.
- Preserve the selected environment id and existing remote
environment-variable ownership rules.
- Route the executor plugin provider through the URI-native entrypoint
without converting the root on the host.
- Ensure `codex doctor` does not probe executor-owned stdio commands or
foreign working directories on the host.
- Cover foreign Windows roots, relative and absolute executor working
directories, traversal rejection, runtime resolution, and doctor
behavior.

```text
plugin root:    file:///C:/plugins/demo
configured cwd: scripts
                  |
                  v
resolved cwd:  file:///C:/plugins/demo/scripts
                  |
                  v
launch through the selected executor
```

No new provider or filesystem abstraction is introduced.

## Stack

1. #29614 — add lexical `PathUri` containment.
2. #29620 — share URI-native manifest path resolution.
3. #28918 — keep selected plugin roots and resources URI-native.
4. #29626 — load executor skills without host path conversion.
5. **This PR** — resolve executor MCP working directories without host
path conversion.
2026-06-24 09:46:07 +01:00
Adam Perry @ OpenAI 31372078d1 auth: move domain mode below app wire types (#29721)
## Why

Authentication mode is a domain concept used by login, model selection,
telemetry, and transports. Keeping the canonical type in app-server
protocol forces those lower-level crates to depend on an unrelated wire
API.

## What changed

- Added canonical `codex_protocol::auth::AuthMode` domain values.
- Kept the app-server wire DTO unchanged and added an explicit app-side
conversion.
- Removed production app-server-protocol dependencies from login,
model-provider-info, models-manager, and otel call paths.

## Stack

This is PR 2 of 6, stacked on [PR
#29714](https://github.com/openai/codex/pull/29714). Review only the
delta from `codex/split-json-rpc-protocols`. Next: [PR
#29722](https://github.com/openai/codex/pull/29722).

## Validation

- Auth and login coverage passed in the focused protocol/domain test
run.
- App-server account and auth conversion coverage passed.
2026-06-24 03:10:20 +00:00
xl-openai ff78e21215 [codex] Ignore local curated plugins when remote catalog is active (#29765)
## Summary

- suppress configured `openai-curated` plugins when the remote plugin
feature is enabled and auth uses the Codex backend
- preserve `openai-api-curated` and non-Codex-backend behavior while
including remote catalog activation in the plugin load cache key
- add core plugin coverage and an app-server integration test for
runtime feature enablement

## Why

The Codex app enables remote plugins through process-local runtime
feature enablement, which can happen after app-server startup tasks have
already observed legacy local plugin state. The existing conflict logic
only preferred a remote plugin when the same plugin was already
installed remotely, so a configured legacy-only plugin could continue
exposing skills and other capabilities from `openai-curated`.

## Impact

When the remote catalog is active, legacy `openai-curated` plugins no
longer contribute skills, MCP servers, apps, or hooks. Remote installed
plugins continue to load normally, and `openai-api-curated` remains
unaffected. This does not change remote fetch, bundle sync, or uninstall
behavior.

## Validation

- `just test -p codex-core-plugins
remote_global_catalog_ignores_local_curated_plugins
remote_plugin_feature_keeps_local_curated_without_codex_backend`
- `just test -p codex-app-server
runtime_remote_plugin_enablement_excludes_local_curated_plugin_skills`
- `just fmt`
- `git diff --check`
2026-06-23 19:51:31 -07:00
jameswt-oai 44dbae90eb [codex] Centralize Plugin Analytics Metadata (#27102)
This PR moves construction of `PluginTelemetryMetadata` from loader and
model helpers into `PluginsManager`, which already owns installed plugin
state and will eventually perform remote identity enrichment. The
metadata type remains in `codex-plugin`, and serialized analytics events
remain unchanged.

## Before

```mermaid
flowchart LR
    subgraph Events["Analytics event paths"]
        direction TB
        Lifecycle["Local install / uninstall"]
        Config["Enable / disable"]
        Remote["Remote install"]
        Used["Plugin used"]
    end

    subgraph Construction["Metadata construction"]
        direction TB
        Loader["Loader telemetry helpers"]
        Summary["PluginCapabilitySummary::telemetry_metadata"]
        Override["Caller adds remote_plugin_id"]
    end

    Metadata["PluginTelemetryMetadata"]

    Lifecycle --> Loader
    Config --> Loader
    Remote --> Loader
    Loader -->|"local events"| Metadata
    Loader -->|"remote install"| Override
    Override --> Metadata
    Used --> Summary
    Summary --> Metadata
```

Telemetry metadata was constructed through loader helpers, a
capability-summary method, and a remote-install call-site override.

## After

```mermaid
flowchart LR
    subgraph Events["Analytics event paths"]
        direction TB
        Lifecycle["Local install / uninstall"]
        Config["Enable / disable"]
        Remote["Remote install"]
        Used["Plugin used"]
    end

    Manager["PluginsManager — single construction owner"]
    Metadata["PluginTelemetryMetadata"]

    Lifecycle --> Manager
    Config --> Manager
    Remote -->|"authoritative remote ID"| Manager
    Used -->|"capability summary"| Manager
    Manager --> Metadata
```

Every analytics path delegates metadata construction to
`PluginsManager`. Remote install still supplies its authoritative
backend ID explicitly.

## What Changes

- Make loader code return a focused plugin capability summary instead of
constructing analytics metadata.
- Centralize immutable plugin telemetry metadata construction in
`PluginsManager`.
- Route local install/uninstall, remote install, enable/disable, and
plugin-used emitters through the manager.
- Preserve the current serialized analytics contract exactly.

Normal metadata still has no remote override. Remote install continues
to provide its authoritative backend ID explicitly, so the existing
serializer continues reporting that ID through `plugin_id`.
Snapshot-based enrichment is intentionally deferred to the final PR.

## Testing

- `just test -p codex-core-plugins` (238 tests passed)
- `just test -p codex-plugin` (3 tests passed)
- Scoped Clippy/compile checks passed for `codex-plugin`,
`codex-core-plugins`, `codex-app-server`, and `codex-core`.

## Split Overview

```text
main
├── #27093  Debug analytics capture                 (merged)
├── #27099  Non-mutating plugin smoke               (merged)
├── #27100  Remote install/uninstall smoke          (merged)
└── #27102  Plugin telemetry metadata refactor      ← you are here
    └── #27669  Persist remote plugin identity

After #27102 and #27669 merge:
└── Final PR: add explicit local and remote IDs to plugin analytics
```

Review order and dependencies:

1. [#27093 Add debug-only analytics event
capture](https://github.com/openai/codex/pull/27093) (merged)
2. [#27099 Add a plugin analytics smoke
workflow](https://github.com/openai/codex/pull/27099) (merged)
3. [#27100 Add a remote plugin analytics mutation smoke
workflow](https://github.com/openai/codex/pull/27100) (merged)
4. This metadata refactor, independent and based on `main`
5. [#27669 Persist remote plugin
identity](https://github.com/openai/codex/pull/27669), stacked on this
PR
6. Final remote-ID behavior PR, created after the prerequisites merge

The original [#26281](https://github.com/openai/codex/pull/26281)
remains open as the aggregate reference until the final replacement PR
is published.
2026-06-22 10:27:23 -07:00
xl-openai e83b7841b0 [codex] Reuse parsed plugin skills during session startup (#28844)
## Summary

- Preserve raw plugin skill-root snapshots in the matching loaded-plugin
cache entry, keyed by the effective plugin root identity including
namespace.
- Pass those snapshots through `SkillsLoadInput` as an optional preload,
so session startup reuses plugin parsing while ordinary skill loads pass
`None`.
- Keep plugin skill loading cohesive: the existing loaders accept the
optional snapshots directly, and uncached or marketplace-detail paths do
not create a cache.

## Why

Plugin discovery already parses plugin skills to determine available
capabilities. Cold session startup then scanned and parsed the same
roots again while building the skills snapshot.

This solves the same duplicate-work problem as #28623 while keeping
ownership narrow: `PluginsManager` creates and owns
`PluginSkillSnapshots` only for its loaded-plugin cache entry;
`SkillsService` consumes an optional clone. Entry replacement or
clearing naturally drops the snapshots, with no separate generation,
capacity policy, or watcher coupling.

## Validation

- `cargo clippy -p codex-core-skills --all-targets -- -D warnings`
- `just test -p codex-core-plugins
skills_service_reuses_skills_parsed_during_plugin_load`
- `just test -p codex-core-skills
namespaces_plugin_skills_using_provided_namespace`
- `just fmt`
2026-06-18 16:45:58 -07:00
charlesgong-openai 772c5c5195 [codex] Support marketplace plugin manifest fallback (#28789)
## Summary

Support marketplace plugins whose source directory does not include a
discoverable plugin manifest. Metadata-rich `marketplace.json` entries
now act as fallback plugin manifests for listing, local detail reads,
install, and non-curated cache refresh.

The fallback preserves marketplace-entry plugin fields wholesale, then
adds the small Codex-facing compatibility bridge for presentation
metadata. A real source `plugin.json` always wins when present.

## Details

- Capture flattened marketplace-entry fields into
`MarketplacePluginManifestFallback`, preserving fields such as
`version`, `description`, `skills`, `mcpServers`, `apps`, `hooks`,
`agents`, `commands`, `strict`, `author`, and future manifest fields
without a per-field translation list.
- Bridge Claude-style top-level `displayName`, `author.name`,
`homepage`, and marketplace `category` into Codex's nested `interface`
fields only when the nested values are absent.
- Treat fallback metadata as installable only when the marketplace entry
contributes metadata beyond bare `name` and `source`; existing
missing-manifest behavior remains for metadata-free entries.
- Read local plugin details from the already parsed fallback manifest,
including fallback-declared app and MCP paths, instead of rereading only
an on-disk manifest.
- Pass fallback contents into `PluginStore`, which validates them and
injects `.codex-plugin/plugin.json` into Store's existing atomic copy.
Local marketplace source directories are never mutated, and the fallback
path no longer needs an additional staging directory.
- Keep Git source materialization unchanged; Git clones still use the
existing marketplace source staging area before Store installation.
2026-06-18 15:49:27 -07:00
Matthew Zeng a52a3b5197 [codex] Cache plugin metadata for tool suggestions (#27812)
## Why

`built_tools` runs for every sampling request, and local plugin
discovery was repeatedly rereading plugin manifests, skills, MCP
configuration, and app declarations to build the same tool-suggest
metadata.

That source-derived metadata is stable until the existing plugin manager
reloads its cache. Runtime eligibility still needs to reflect the
current install, disable, policy, app-overlap, and authentication state.

## What changed

- Add a bounded, in-memory tool-suggest metadata cache owned by
`PluginsManager`.
- Key cached metadata by plugin identity and source, while applying
authentication routing each time the metadata is projected.
- Invalidate the metadata alongside the existing loaded-plugin cache,
including its normal configuration, marketplace refresh, and
remote-installed-plugin invalidation paths.
- Guard against an in-flight load repopulating stale metadata after
invalidation.
- Keep marketplace membership and all runtime eligibility filtering live
rather than introducing a separate catalog or revision model.

## Impact

Repeated sampling requests reuse already-loaded plugin capability
metadata while retaining the existing plugin-manager lifecycle as the
single freshness boundary.

## Validation

- `just test -p codex-core-plugins` — 252 passed
- Added focused coverage for cache invalidation and authentication
reprojection.
2026-06-18 12:25:07 -07:00
Matthew Zeng c73296a0f0 [codex] Pass plugin namespace into skill loading (#28608)
## What changed

- retain the parsed plugin manifest namespace on loaded plugins
- carry that namespace through `PluginSkillRoot` and `SkillRoot`
- use the provided namespace when qualifying plugin skill names
- include the namespace in the skills cache key

## Why

Plugin loading has already parsed `plugin.json`, but skill parsing
currently walks every `SKILL.md` ancestor and probes/reads the manifest
again to reconstruct the same namespace. Passing the parsed namespace
removes those repeated filesystem calls, which are particularly costly
on remote filesystems.

Context:
https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4

## Impact

Plugin skill names remain unchanged. A regression test uses a
deliberately different on-disk manifest name to verify that plugin roots
use the provided parsed namespace.

## Validation

- `just test -p codex-core-skills -p codex-core-plugins -p codex-plugin
-p codex-utils-plugins` (352 passed)
- `just fix -p codex-core-skills -p codex-core-plugins -p codex-plugin
-p codex-utils-plugins`
- `just fmt`
2026-06-18 00:16:46 -07:00
charlesgong-openai e12dd73b7d [codex] Support plugin manifest path lists (#28790)
## Summary

Allow plugin manifests to declare `skills` as either a single path
string or an array of path strings in the core plugin loader.

## Why

Some plugin packages need to expose skills from more than one directory.
Before this change, `plugin.json` only accepted a single string for
`skills`, so manifests like this were ignored as an invalid `skills`
shape:

```json
{
  "skills": ["./skills/abc", "./skills/edk"]
}
```

This keeps the existing single-string form working while adding support
for the list form. The final scope is intentionally limited to the core
plugin manifest/load path for `skills`; `apps`, file-backed
`mcpServers`, and the bundled plugin-creator assets are unchanged in
this PR.

## What changed

- Parse `skills` as either a string or an array of strings in
`plugin.json`.
- Store resolved skill paths as a list in `PluginManifestPaths`.
- Load manifest-declared skill roots in addition to the default
`./skills` root.
- Deduplicate exact duplicate skill roots before loading.
- Rely on existing skill-loader dedupe by canonical `SKILL.md` path for
overlapping roots such as `./skills` plus `./skills/abc`.
- Update plugin manifest tests to cover:
  - single string `skills`
  - list of string `skills`
  - duplicate skill roots
  - `./skills` as a manifest path
  - explicit child roots like `./skills/abc` and `./skills/edk`
  - overlapping-root dedupe

## Validation

- `just test -p codex-plugin`
- `just test -p codex-core-plugins`
- `just test -p codex-mcp-extension`
- `git diff --check`
2026-06-17 21:33:53 -07:00
charlesgong-openai 1883dedc0e [codex] Support object-valued plugin MCP manifests (#28580)
## Summary
This fixes plugin manifest parsing for MCP servers declared as an object
directly in `plugin.json`.

Before this change, Codex modeled `mcpServers` as only a string path,
for example:

```json
{
  "name": "counter-sample",
  "version": "1.1.1",
  "mcpServers": "./.mcp.json"
}
```

Some migrated plugins instead provide the server map directly in the
manifest:

```json
{
  "name": "counter-sample",
  "version": "1.1.1",
  "description": "Plugin that declares MCP servers in the manifest",
  "mcpServers": {
    "counter": {
      "type": "http",
      "url": "https://sample.example/counter/mcp"
    }
  }
}
```

That object form previously failed during install/load with an error
like:

```text
failed to parse plugin manifest: invalid type: map, expected a string
```

## What changed
- Add a manifest representation for `mcpServers` as either
`Path(Resource)` or `Object(map)`.
- Parse `plugin.json` `mcpServers` as either a string path or an object.
- Route object-valued MCP server maps through the existing plugin MCP
config parser instead of adding a second parser.
- Apply existing per-plugin MCP server policy to object-valued MCP
servers the same way as file-backed MCP servers.
- Include object-valued MCP server names in plugin telemetry/capability
metadata.
- Support object-valued MCP config for executor plugins without
requiring a `.mcp.json` filesystem read.
- Update the bundled plugin-creator validator and `plugin-json-spec.md`
so generated-plugin validation accepts the same object-valued shape.

## Compatibility
Existing plugin manifests that use `"mcpServers": "./.mcp.json"`
continue to work. Plugins can now also use the object shape shown above.

## Tests
Added coverage for the new manifest attribute shape at the install,
normal load, telemetry, and executor-provider layers:

- `install_accepts_manifest_mcp_server_objects`
- `load_plugins_loads_manifest_mcp_server_objects`
- `plugin_telemetry_metadata_uses_manifest_mcp_server_objects`
- `reads_manifest_object_config_without_executor_file_system_access`

Also smoke-tested the plugin-creator validator against both supported
forms:

- `mcpServers` as a direct object in `plugin.json`
- `mcpServers` as `"./.mcp.json"` with a companion `.mcp.json`

## Validation
- `just test -p codex-plugin`
- `just test -p codex-core-plugins`
- `just test -p codex-mcp-extension`
- `just bazel-lock-update`
- `just bazel-lock-check`
- `just fmt`
- `git diff --check`
- Focused rename/object-form rerun: `just test -p codex-core-plugins
manager::tests::load_plugins_loads_manifest_mcp_server_objects
manager::tests::plugin_telemetry_metadata_uses_manifest_mcp_server_objects
store::tests::install_accepts_manifest_mcp_server_objects`
- Focused executor rerun: `just test -p codex-mcp-extension
executor_plugin::provider::tests::reads_manifest_object_config_without_executor_file_system_access`
- `python3
codex-rs/skills/src/assets/samples/plugin-creator/scripts/validate_plugin.py
/private/tmp/codex-validator-object`
- `python3
codex-rs/skills/src/assets/samples/plugin-creator/scripts/validate_plugin.py
/private/tmp/codex-validator-path`
2026-06-16 19:22:57 -07:00
xl-openai de1f77bfdd [codex] Clarify plugin load and runtime capability stages (#28472)
## Summary

Plugin loading and auth projection both previously produced
`PluginLoadOutcome`. That made an unfiltered load result look like
runtime-ready capabilities and generated capability summaries before
auth routing had run.

This change keeps loaded plugin records in the cache, applies the
current auth policy in `PluginsManager`, and only then builds
`PluginLoadOutcome` and its summaries. Auth changes still reuse the
cached disk load and re-resolve apps and MCP servers without reloading
plugins.

The updated tests cover cached auth changes and verify that capability
summaries match the effective app/MCP surface.

## Testing

- `just test -p codex-core-plugins`
- `just test -p codex-plugin`
- `just fix -p codex-core-plugins`
2026-06-16 12:57:21 +01:00
felixxia-oai 02dce8eb8d [codex] Load API curated marketplace by auth (#28383)
## Summary
- choose the local OpenAI curated marketplace manifest based on auth:
Codex backend auth gets the existing marketplace, direct provider auth
gets `api_marketplace.json`
- include Bedrock API key auth in the direct-provider API marketplace
path
- safely skip the API marketplace when `api_marketplace.json` is absent

## Validation
- `just fmt`
- `git diff --check origin/main...HEAD`
- CI should run the full validation

## Manual Testing

### - New api marketplace not available for API key sign
1. Safely not display anything from api marketplace
<img width="1161" height="289" alt="Screenshot 2026-06-15 at 21 37 43"
src="https://github.com/user-attachments/assets/a5f16642-8a20-4ac1-a0de-1274a4c7b5b2"
/>

### - New api marketplace for API key sign in
1. Setup api_marketplace.json
```
{
  "name": "openai-curated",
  "interface": {
    "displayName": "Codex official"
  },
  "plugins": [
    {
      "name": "linear",
      "source": {
        "source": "local",
        "path": "./plugins/linear"
      },
      "policy": {
        "installation": "AVAILABLE",
        "authentication": "ON_INSTALL"
      },
      "category": "Productivity"
    }
  ]
}
```

2. Log in with API key, observe that only the defined plugin from
api_marketplace.json is available from "Codex Official" (outside of
local testing marketplaces)
<img width="1167" height="446" alt="Screenshot 2026-06-15 at 21 16 53"
src="https://github.com/user-attachments/assets/7cf61477-d826-4ef6-bc05-0a23ac1c0259"
/>

also checked functionality on codex app

### - SiWC users 
Still uses 'default' marketplace.json and renders all plugins
<img width="1171" height="502" alt="Screenshot 2026-06-15 at 21 40 25"
src="https://github.com/user-attachments/assets/d212ea9b-0aa5-470b-8ea4-450efe65bb2b"
/>

also checked functionality on codex app


## Notes
- `just test -p codex-core-plugins` was started locally before splitting
branches, but I stopped relying on local tests per follow-up and left
final validation to PR CI.
2026-06-16 01:16:11 +00:00
felixxia-oai 7e0dce91df [codex] Centralize plugin auth capability filtering (#27902)
## Summary

This is the first step in making plugin auth routing consistent. The
rule should not live as one-off checks in every place that loads or
displays plugin capabilities.

This PR introduces a small resolver for the auth-level policy: given a
plugin's declared apps, MCP servers, current auth mode, and active
state, return the capabilities that are actually usable in that context.

## Why

Product rule:
- SiWC auth can use app connectors, so app declarations stay available.
- API-key/direct auth cannot use app connectors, so app declarations are
removed.
- When an active plugin has both an app and an MCP server with the same
name, the app route wins for Codex-backed auth and the conflicting MCP
server is hidden.

Putting that rule in `capabilities.rs` gives the rest of the stack one
place to ask instead of duplicating auth checks in loader, manager,
marketplace, and details code.

## Validation

- `cargo fmt`
- `cargo test -p codex-core-plugins`
2026-06-16 00:13:27 +00:00
felixxia-oai e5253b97fb [codex] Skip plugin MCP OAuth for matching app routes (#27461)
## Context

This is PR5 in the plugin auth-routing stack. Earlier PRs make plugin
surface projection auth-aware, narrow App/MCP conflicts by App
declaration name, and keep connector listings auth-aware. This PR
applies the same name-based App/MCP conflict rule into plugin MCP
loading, so install-time MCP OAuth and plugin detail metadata both
reflect the MCPs available for the current auth route.

## Stack

- PR1: #27652 seed plugin manager auth at construction.
- PR2: #27459 route plugin surfaces by auth mode.
- PR3: #27607 dedupe plugin MCP servers by App declaration name.
- PR4: #27602 preserve plugin Apps in connector listings.
- PR5: #27461 skip install-time plugin MCP OAuth for matching App
routes.

## Summary

- Make `load_plugin_mcp_servers` auth-aware and let it load App
declarations before filtering same-name MCP servers for Codex-backend
auth.
- Use that filtered MCP list for both install-time MCP OAuth and
marketplace plugin detail metadata.
- Preserve API-key/direct auth behavior so plugin MCP servers remain
visible and can still start OAuth.

## Validation

```bash
cargo fmt --all
cargo test -p codex-core-plugins read_plugin_for_config_filters_mcp_servers_for_codex_backend_auth
cargo check -p codex-core-plugins -p codex-app-server
git diff --check
git diff --cached --check
```
2026-06-15 14:04:01 +01:00
jif b3c423e475 Discover stdio MCP servers from selected executor plugins (#27870)
## Why

**In short:** this PR discovers MCP registrations by reading a selected
plugin's `.mcp.json` on its executor. #27884 then resolves those
registrations in the shared catalog.

`thread/start.selectedCapabilityRoots` can select a plugin root owned by
an executor, and Codex can resolve that package through the executor
filesystem. MCP declarations inside the selected plugin are still
ignored.

This PR adds the source-specific discovery layer on top of the
selected-plugin catalog boundary in #27884:

```text
selected capability root
        |
        v
resolve the plugin through its executor filesystem
        |
        v
read and normalize its MCP config through the same filesystem
        |
        v
contribute stdio registrations bound to that environment ID
```

The existing MCP launcher and connection manager remain unchanged. MCP
config parsing is shared with local plugins through #27863.

## What changed

- Added an executor plugin MCP provider in the MCP extension.
- Retained only the exact filesystem capability used for package
resolution and reused it for the selected plugin's MCP config, with no
host-filesystem fallback or unrelated process/HTTP authority.
- Read either the manifest-declared MCP config or the default
`.mcp.json`; a missing default file means the plugin has no MCP servers.
- Accepted stdio servers only for this first vertical. Executor-owned
HTTP declarations are skipped with a warning until their placement
semantics are defined.
- Normalized stdio registrations with the owning environment's stable
logical ID and plugin-root working directory.
- Resolved environment-variable names on the owning executor and
rejected explicit local forwarding for non-local plugins.
- Froze discovered declarations once per active thread runtime, then
applied current managed plugin and MCP requirements when contributing
them.
- Carried the selected root ID, display name, and selection order into
the catalog contribution defined by #27884.

## Behavior and scope

There is intentionally no production behavior change yet. This PR
provides the executor provider and contribution boundary, but app-server
does not install it in this change. Existing local plugin MCP loading is
unchanged, and no MCP process is launched by this PR alone.

## Assumptions

- The selected root ID is the plugin policy identity; the manifest
display name is presentation metadata.
- An environment ID is a stable logical authority. Reconnection or
replacement under the same ID does not change ownership.
- Selected plugin packages and their manifests are trusted inputs.
- The selected package and MCP discovery snapshot remain frozen for the
active thread runtime.

## Follow-up

The next PR installs this contributor in app-server and adds an
end-to-end test proving that a selected plugin MCP tool launches on its
owning executor, can be called by the model, survives an explicit MCP
refresh, and is invisible when its root was not selected.

Resume, fork, environment removal or ID changes, dynamic catalog reload,
and executor-owned HTTP MCP placement remain separate lifecycle
decisions.

## Verification

Focused tests cover executor-only filesystem reads, missing and
malformed config, stdio filtering and normalization, managed
requirements, package attribution, and selection order. CI owns
execution of the test suite.
2026-06-15 11:52:05 +02:00
felixxia-oaiandXin Lin 51316ead4a [codex] Dedupe plugin MCPs by app declaration name (#27607)
## Context

This is the next step in the plugin auth-routing stack. The earlier PRs
make `PluginsManager` auth-aware and move the broad App/MCP surface
decision into that layer. This PR narrows the ChatGPT/SIWC behavior so
we only hide a plugin MCP server when it conflicts with an App
declaration of the same name.

In product terms: if a plugin exposes both an App route and MCP route
for `foo`, ChatGPT/SIWC sessions should use the App route for `foo`. If
the same plugin also exposes a separate MCP server like `foo2`, that MCP
server should remain available.

```json
// .app.json
{
  "apps": {
    "foo": {
      "id": "connector_abc"
    }
  }
}
```

```json
// .mcp.json
{
  "mcpServers": {
    "foo": {
      "url": "https://mcp.foo.com/mcp"
    },
    "foo2": {
      "url": "https://mcp.foo2.com/mcp"
    }
  }
}
```

## Stack

- PR1: #27652 seed plugin manager auth at construction.
- PR2: #27459 route plugin surfaces by auth mode.
- PR3: #27607 dedupe plugin MCP servers by App declaration name.
- PR4: #27602 preserve plugin Apps in connector listings.
- PR5: #27461 skip install-time plugin MCP OAuth for matching App
routes.

## Summary

- Preserve App declaration names in loaded plugin metadata.
- Keep public effective App outputs as deduped connector IDs for
existing callers.
- For ChatGPT/SIWC, suppress only plugin MCP servers whose names match
declared App names.

## Validation

```bash
cargo fmt --all
cargo test -p codex-core-plugins plugin_auth_projection
cargo test -p codex-core-plugins effective_apps
cargo test -p codex-core-plugins read_plugin_for_config_installed_git_source_reads_from_cache_without_cloning
cargo test -p codex-core explicit_plugin_mentions_use_apps_for_chatgpt_dual_surface_plugins
cargo test -p codex-core explicit_plugin_mentions_keep_non_conflicting_mcp_for_chatgpt_auth
cargo test -p codex-app-server --test all plugin_install_filters_disallowed_apps_needing_auth
git diff --check
```

---------

Co-authored-by: Xin Lin <xl@openai.com>
2026-06-13 17:53:09 -07:00