stdio MCP 不继承整份 shell,密钥用 env_vars 转发

子进程只拿到一小份默认环境。env_vars 从启动 Codex 的进程转发名字;env 表是字面量。TOML 里的占位符不会展开。这不是 shell_environment_policy。

stdio MCP 不会继承你整个 shell。Codex 清掉环境后,只放行一小份默认名单(PATHHOMEUSERTERMLANG 一类),再加上 env_vars[mcp_servers.docs.env] 里的字面量。codex mcp list 显示 enabled、终端里同一条命令也通,会话里却 Unauthorized、密钥管理器显示 locked、或 npxEACCES:先查环境,不要先换服务器。

[mcp_servers.docs]
command = "npx"
args = ["-y", "@example/docs-mcp"]
env_vars = ["DOCS_API_KEY"]
enabled = true

[mcp_servers.docs.env]
PATH = "/opt/homebrew/bin:/usr/bin:/bin"

env_vars启动 Codex 的那个进程按名字转发。env 表写入的是字面量,下面这样子进程拿到的是字符串本身,不是密钥:

[mcp_servers.docs.env]
DOCS_API_KEY = "${DOCS_API_KEY}"

args 里的 ${DOCS_API_KEY} 同样不会被 Codex 展开;要靠服务器自己读环境,名字必须先出现在 env_varsenv

公司代理注入的 HTTPS_PROXYNODE_EXTRA_CA_CERTS 也不在默认名单里。冷 npx 拉包证书失败时把它们加进 env_vars

这和 shell_environment_policy 不是同一条闸:后者管模型跑的 shell 命令,改 inherit = "all" 填不满 MCP 子进程。插件 mcp.jsonenv_vars 是另一份清单。source = "remote" 只有远端执行器那条才有效。HTTP MCP 用 bearer_token_env_var / env_http_headers,写 env_vars 无效;HTTP 进程环境见 bearer 那条。

从 Dock 打开的桌面常常没有你在 zshrc 里 export 的变量。env_vars 转发的是桌面自己的环境;终端里有、桌面没有时,彻底退出后再从已 export 的终端启动,或把非密钥的 PATH 写进 env。改完新开会话。codex doctor 会标出点了名却缺失的 env_vars

来源