codex - 💡(How to fix) Fix Plugin MCP servers need a supported user secret/env configuration path

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

I maintain a Codex plugin that bundles an MCP server via .codex-plugin/plugin.json:

{
  "mcpServers": "./.mcp.codex.json"
}

The plugin MCP config includes defaults and declares a user-provided secret through env_vars:

{
  "mcpServers": {
    "poka": {
      "command": "node",
      "args": ["mcp-server/dist/index.js"],
      "cwd": ".",
      "env": {
        "POKA_BROKER_URL": "wss://...",
        "WORKPLUS_API_ENDPOINT": "https://...",
        "WORKPLUS_READ_ONLY": "false"
      },
      "env_vars": [
        "WORKPLUS_ACCESS_TOKEN"
      ]
    }
  }
}

The unclear part is: what is the intended UX for a plugin user to provide their own WORKPLUS_ACCESS_TOKEN?

Root Cause

Many MCP plugins need per-user credentials: API keys, access tokens, internal service tokens, etc.

As a plugin maintainer, I currently do not know what to tell users. Asking users to copy the full MCP server config is brittle because plugin cache paths and versions can change. Asking Desktop users to set parent process environment variables is not a reasonable product UX.

Fix Action

Fix / Workaround

So there does not appear to be a stable way for users to provide a secret env var for a plugin-provided MCP server without one of the following workarounds:

Allow this to merge into the plugin-provided server named poka:

Code Example

{
  "mcpServers": "./.mcp.codex.json"
}

---

{
  "mcpServers": {
    "poka": {
      "command": "node",
      "args": ["mcp-server/dist/index.js"],
      "cwd": ".",
      "env": {
        "POKA_BROKER_URL": "wss://...",
        "WORKPLUS_API_ENDPOINT": "https://...",
        "WORKPLUS_READ_ONLY": "false"
      },
      "env_vars": [
        "WORKPLUS_ACCESS_TOKEN"
      ]
    }
  }
}

---

[mcp_servers.my_server]
command = "..."
args = ["..."]
env_vars = ["MY_TOKEN"]

---

[mcp_servers.my_server.env]
MY_TOKEN = "..."

---

[mcp_servers.poka.env]
WORKPLUS_ACCESS_TOKEN = "..."

---

[mcp_servers.poka.env]
WORKPLUS_ACCESS_TOKEN = "..."

---

{
  "user_config": {
    "workplus_access_token": {
      "type": "string",
      "sensitive": true,
      "required": false
    }
  }
}

---

{
  "env": {
    "WORKPLUS_ACCESS_TOKEN": "${user_config.workplus_access_token}"
  }
}

---

[mcp_servers.poka.env]
WORKPLUS_ACCESS_TOKEN = "..."
RAW_BUFFERClick to expand / collapse

Summary

I maintain a Codex plugin that bundles an MCP server via .codex-plugin/plugin.json:

{
  "mcpServers": "./.mcp.codex.json"
}

The plugin MCP config includes defaults and declares a user-provided secret through env_vars:

{
  "mcpServers": {
    "poka": {
      "command": "node",
      "args": ["mcp-server/dist/index.js"],
      "cwd": ".",
      "env": {
        "POKA_BROKER_URL": "wss://...",
        "WORKPLUS_API_ENDPOINT": "https://...",
        "WORKPLUS_READ_ONLY": "false"
      },
      "env_vars": [
        "WORKPLUS_ACCESS_TOKEN"
      ]
    }
  }
}

The unclear part is: what is the intended UX for a plugin user to provide their own WORKPLUS_ACCESS_TOKEN?

Problem

For normal MCP servers, users can write a complete block in ~/.codex/config.toml:

[mcp_servers.my_server]
command = "..."
args = ["..."]
env_vars = ["MY_TOKEN"]

or:

[mcp_servers.my_server.env]
MY_TOKEN = "..."

But for a plugin-provided MCP server, the server definition already comes from the plugin bundle. If the user adds only:

[mcp_servers.poka.env]
WORKPLUS_ACCESS_TOKEN = "..."

Codex appears to treat this as an incomplete user-defined MCP server config instead of a partial override/merge for the plugin-provided server. The MCP config then breaks because command / url is missing.

So there does not appear to be a stable way for users to provide a secret env var for a plugin-provided MCP server without one of the following workarounds:

  1. Launching Codex with a parent environment variable already set.
  2. Duplicating the entire plugin MCP server block in config.toml, including plugin cache paths.
  3. Having the plugin implement its own credential storage outside Codex config.

All three are awkward for end users, especially in Codex Desktop.

Expected Behavior

Codex should provide a documented, supported way for users to configure secret values for plugin-provided MCP servers.

Possible designs:

Option A: Partial plugin MCP env override

Allow this to merge into the plugin-provided server named poka:

[mcp_servers.poka.env]
WORKPLUS_ACCESS_TOKEN = "..."

without requiring users to repeat command, args, or cwd.

Option B: Plugin user config / secrets

Allow plugin manifests to declare configurable secret fields, similar to:

{
  "user_config": {
    "workplus_access_token": {
      "type": "string",
      "sensitive": true,
      "required": false
    }
  }
}

and allow .mcp.codex.json to reference them:

{
  "env": {
    "WORKPLUS_ACCESS_TOKEN": "${user_config.workplus_access_token}"
  }
}

Ideally Codex Desktop would expose this in plugin settings and store sensitive values securely.

Option C: Documented env_vars UX for Desktop

If env_vars is the intended solution, please document how a Codex Desktop user is supposed to set those values persistently without relying on shell-specific launch behavior.

Actual Behavior

Plugin MCP config loads and works. However, user-level env customization for that plugin server is unclear.

Adding only:

[mcp_servers.poka.env]
WORKPLUS_ACCESS_TOKEN = "..."

breaks the server config because Codex appears to treat it as a separate incomplete server definition rather than an override for the plugin-provided server.

Why This Matters

Many MCP plugins need per-user credentials: API keys, access tokens, internal service tokens, etc.

As a plugin maintainer, I currently do not know what to tell users. Asking users to copy the full MCP server config is brittle because plugin cache paths and versions can change. Asking Desktop users to set parent process environment variables is not a reasonable product UX.

Environment

  • Codex version: 0.133.0-alpha.1
  • Platform: macOS
  • Plugin MCP server via .codex-plugin/plugin.json mcpServers
  • MCP transport: stdio

Related Observations

  • env_vars is documented/used for allowing selected parent environment variables into MCP subprocesses.
  • config.toml does not appear to support shell-style env expansion like TOKEN = "$TOKEN".
  • Plugin-provided MCP config and user config.toml MCP server config do not appear to support partial deep merge for env overrides.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING