Skip to content

🤖 fix: load Codex .mcp.json env_vars and untyped url entries; flag custom_header without headerName - #6487

Merged
ThomasK33 merged 7 commits into
mainfrom
fix/codex-mcp-compat
Oct 14, 2026
Merged

ThomasK33 merged 7 commits into
mainfrom
fix/codex-mcp-compat

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Summary

Xum now loads three Codex .mcp.json shapes that it used to skip or misreport. A stdio server with env_vars loads and receives the named host variables. A remote entry with a url and no type loads as streamable HTTP. An api_key auth block with headerScheme: custom_header and no headerName is reported as malformed.

Refs #6297. This PR covers three of its items: "Codex env_vars on stdio servers", "URL entries without type" and "custom_header without headerName".

Background

Codex review found these gaps after track A merged main (review threads PRRT_kwDOPxxmWM6rv0UV, PRRT_kwDOPxxmWM6rv0Ua and PRRT_kwDOPxxmWM6rv0Uh).

  1. Codex defines env_vars as the way to pass selected host environment variables to a stdio server (OpenAI plugins guide). Xum rejected the field as unknown, so the server did not load.
  2. The Codex plugin parser reads a url entry without type as streamable HTTP (codex-mcp/src/plugin_config.rs). Xum skipped it as an unknown type.
  3. OpenAI's auth reference requires headerName for custom_header (fixed bearer tokens and API keys). Xum listed the block as an unsupported setting instead of a malformed one.

Implementation

All three changes apply to the Codex dialect only. A root mcp.json stays strict: env_vars and an untyped url are still errors there. A new test covers that.

env_vars. The Codex translator turns env_vars into a new forwardEnv list of names on the stdio server record. Xum copies the semantics from Codex:

  • env_vars: null and source: null count as absent, as Codex's optional fields do.
  • An item is a bare name or { name, source } (McpServerEnvVar in config/src/mcp_types.rs).
  • Xum refuses source: "remote". Codex refuses it for a plugin that runs in the local environment (bind_environment_env_vars in plugin_config.rs).
  • Xum refuses env_vars on a remote server. Codex does the same (throw_if_set in mcp_types.rs).
  • At launch, prepareStdioLaunch copies only the named variables from the host. It reads only own properties of the host environment, so a name such as constructor is not an inherited value. It skips a name that the host does not set, as Codex's create_env_for_mcp_server does (rmcp-client/src/utils.rs). A configured env value wins over a host value.
  • Xum refuses PLUGIN_ROOT and PLUGIN_DATA in env_vars, as it already does in env.

Xum reads only the names at load time. It never stores or shows a host value.

The install consent preview shows the names, for example node (host env: 'API_TOKEN'). The consent fingerprint includes the names in the order they first appear (duplicates are dropped), so an update that adds, removes or reorders a name needs new consent. The server signature includes them too, so a changed list restarts the server.

Untyped url. The translator infers streamable-http when an entry has a url and no type. This mirrors how it already infers stdio from a command.

custom_header without headerName. readAuth now adds a warning that headerName is required, and it drops headerScheme. A bad headerName already used this warning class.

Validation

  • I wrote each test first and saw it fail on origin/main. Then I made it pass.
  • bun test (pinned Bun 1.4.3) of mcpConfig.test.ts, openaiMcpAuth.test.ts, installService.test.ts and mcpServerManager.test.ts: 558 pass, 0 fail.
  • make static-check passes.

Resolved since the hold

Risks

The risk is low. The env_vars and untyped-url changes apply only to Codex .mcp.json files, and those entries failed to load before. A stdio server without env_vars keeps the same launch environment, fingerprint and signature, because each of them leaves out an unset forwardEnv. Adding forwardEnv to the consent fingerprint does not change the fingerprint of an existing server, because pick skips an unset field.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $0.00

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T17:03:26.552850Z 362874d New commits
🔒 Security Review ✅ Completed 2026-10-14T17:12:29.172206Z 362874d New commits

Security findings

Advisory findings (1)

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 3beec0c361

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3beec0c361

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/mcpServerManager.ts Outdated
Comment thread src/node/services/mcpServerManager.ts
Comment thread src/node/services/agentPlugins/openaiMcpAuth.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Round 1 fixes are pushed: own-property env reads and env_vars: null as absent. The full-environment inheritance thread is older than this PR, so I deferred it with a reply.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56e610bb48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/agentPlugins/openaiMcpAuth.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 56e610bb48

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/node/services/agentPlugins/openaiMcpAuth.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Round 2 fix is pushed: an env_vars item with source: null now counts as unset.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 3b6177830d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 3b6177830d

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

Held: this PR waits for #6498. Do not merge it before #6498 lands.

Saved plugin imports and enablement store only component names. A stdio server that an older parser skipped can come back under an enabled name and start without consent. This PR adds a new way for that to happen (env_vars, untyped url). The fix in #6498 binds each import to the fingerprint the user reviewed. Once #6498 merges, this PR will be rebased onto it and go through normal review and security review again.

# Conflicts:
#	src/node/services/agentPlugins/installService.ts
#	src/node/services/mcpServerManager.ts
@mintlify

mintlify Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Mux 🟢 Ready View Preview Oct 14, 2026, 4:59 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Round 4 (blockers only): this branch now merges main with the #6498 consent gate and the #6581 minimal plugin environment. forwardEnv is now a fingerprinted field, a new test launches a plugin server through the real runtime, and the docs describe env_vars.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: b8e66e6cd2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: b8e66e6cd2

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 14, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 14, 2026
@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 14, 2026
# Conflicts:
#	src/node/services/agentPlugins/installService.ts
@ThomasK33
ThomasK33 removed this pull request from the merge queue due to a manual request Oct 14, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 362874dd0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/agentPlugins/openaiMcpAuth.ts
@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit e1c09db Oct 14, 2026
62 of 65 checks passed
@ThomasK33
ThomasK33 deleted the fix/codex-mcp-compat branch October 14, 2026 17:37
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Oct 14, 2026
…coder#6581)

## Summary

Managed plugin stdio MCP servers no longer inherit the whole host
environment. Xum starts them with a short allowlist of host variables
plus the `env` their MCP configuration declares. Tokens such as
`GITHUB_TOKEN` or `OPENAI_API_KEY` from the user's shell are no longer
passed to a plugin server. This is non-inheritance, not a sandbox: the
server still runs as the same OS user and can read what that user can
read (for example `/proc/<xum pid>/environ` on Linux). The docs say so.
User-configured servers and the bash tool keep the full environment.

Closes coder#6509

## Background

`LocalBaseRuntime.exec` spread all of `process.env` under every stdio
launch (found by the Codex security review of coder#6487, P1). A plugin that
names no variables still received every secret in the shell.

What other hosts do (sources read for this PR):

1. Codex (`openai/codex` @ `78dc250`):
`codex-rs/rmcp-client/src/utils.rs` `create_env_for_mcp_server` clears
the env and passes only `DEFAULT_ENV_VARS` (Unix) or
`WINDOWS_CORE_ENV_VARS` (`codex-rs/protocol/src/shell_environment.rs`),
the CA bundle keys (`network-proxy/src/certs.rs`), the names in
`env_vars`, and the literal `env`. No proxy variables.
2. MCP TypeScript SDK (`packages/client/src/client/stdio.ts`):
`getDefaultEnvironment()` passes `HOME LOGNAME PATH SHELL TERM USER` and
drops values that start with `()`.
3. Agent Plugins 1.0 (MCP runtime page): the client chooses the base
environment and can omit or sanitize ambient variables.

## Implementation

1. `childProcessEnv.ts`: `pickMinimalChildEnv` keeps the Codex lists
plus CA bundle paths (`SSL_CERT_DIR` added, `CODEX_CA_CERTIFICATE` left
out, `HOME` added on Windows for Git Bash). Windows names match
case-insensitively. Exported bash functions are dropped.
2. `ExecOptions.hostEnv` (`"inherit"` default, or `"minimal"`). Only
`LocalBaseRuntime` reads the host env, so remote runtimes ignore it.
3. `prepareStdioLaunch` returns `hostEnv: "minimal"` for servers with
plugin provenance. Both spawn sites pass it: workspace startup
(`startStdioInstance`) and the named Test connection (`runServerTest`).
4. Docs: `docs/config/mcp-servers.mdx` lists what a plugin server
receives.

## Validation

1. `LocalBaseRuntime` test: a host variable set in `process.env` is
invisible with `hostEnv: "minimal"` and visible by default. Declared
`env` and `HOME` pass in both.
2. Manager tests for the startup path and the Test button: plugin
servers get `"minimal"`, user servers get `"inherit"`. I removed each
wiring line in a scratch edit and saw the matching test fail.

## Risks

1. Behavior change for plugins that read ambient variables. A plugin
server that read a token from the shell (for example
`GITHUB_PERSONAL_ACCESS_TOKEN`) fails at startup or on its first tool
call. Servers started through `npx`/`uvx` or version-manager shims also
lose `NVM_DIR`, `VOLTA_HOME`, `npm_config_registry`, `UV_*` and
`XDG_CACHE_HOME`, as in Codex. Remedy: the plugin declares the value in
`env`, or, after coder#6487 lands, in Codex `env_vars`.
2. Proxies: `HTTP(S)_PROXY`/`NO_PROXY` are not passed (Codex parity).
Proxy URLs can carry credentials. A plugin server that downloads through
a proxy fails.
3. coder#6487 must add its forwarded `env_vars` names on top of this base
when it rebases, or those names will not reach the server.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`high` • Cost: `$38.84`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high
costs=38.84 -->
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Oct 15, 2026
… plugin servers (coder#6690)

## Summary

Four follow-ups from the coder#6487 reviews for Codex `.mcp.json` plugin
servers. Closes coder#6646.

## Changes

1. **Auth header names (item 1).** In `openaiMcpAuth.ts`, a `headerName`
that is not a valid header name, or is `Host`, now gets its own warning
("must be a valid HTTP header name other than Host"). Before, it got
"needs headerScheme custom_header", even when the scheme was
custom_header. A `custom_header` scheme without a valid name is now
dropped as well, not only when the name is missing. Nothing reads these
fields yet, because Xum has no api_key support.
2. **OAuth fields on stdio servers (item 2).** Xum reads OAuth only for
remote servers. A stdio entry with `oauth`, `scopes` or `oauth_resource`
now gets a review warning that names them, with or without `env_vars`.
Before, the fields were dropped silently. For this, the loader now
reports translation warnings for stdio servers too. The remote OAuth
handling moved, unchanged, into `remoteOAuthMessages`.
3. **Loader variables (item 3).** `env_vars` names that change how the
server loads code (`LD_PRELOAD`, `LD_LIBRARY_PATH`, `DYLD_*`,
`NODE_OPTIONS`) still load, but the review names them in a warning
(defense in depth).
4. **Windows env names (item 4).** On Windows, env names are
case-insensitive. The reserved-name check for `env_vars` and for `env`
keys now ignores case there, so `plugin_data` cannot shadow
`PLUGIN_DATA`. Duplicate `env_vars` names that differ only in case are
merged, keeping the first spelling. Other platforms are unchanged.

## Validation

New tests failed on main and pass now:
- the header-name warnings and dropped scheme (`openaiMcpAuth.test.ts`);
- the stdio OAuth and loader warnings through the real loader
(`mcpConfig.test.ts`);
- the Windows rules, with `process.platform` set to `win32` in the test,
as other tests in the repo do. The same test checks that Linux keeps
case-sensitive names.

## Risks

Low. Items 1 to 3 only add or reword warnings. Item 4 refuses a server
on Windows only when it names a case variant of a reserved variable.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`high` • Cost: `$91.52`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high
costs=91.52 -->

This branch was successfully deployed

1 active deployment
staging - docs — 362874dd Deployed Oct 14, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant