插件 MCP 的 OAuth 写 camelCase,不要抄 config.toml 的蛇形键

mcp.json 里是 clientId、callbackUrl、callbackPort。callbackUrl 里的端口不会改监听口;没写 callbackPort 就走全局或临时端口。带 clientId 但回调缺 ID 时,这份 URL 会被忽略。

用户 ~/.codex/config.toml 用蛇形:client_idcallback_urlcallback_port。插件自带的 HTTP MCP 写在根目录 mcp.json.mcp.json,字段是 camelCase。抄成 client_id 不会被当成插件 OAuth。

{
  "mcpServers": {
    "sample": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "oauth": {
        "clientId": "my-pre-registered-client",
        "callbackUrl": "http://127.0.0.1/callback/registered",
        "callbackPort": 4321
      }
    }
  }
}

可移植 Agent Plugins 包还可以给文件加 $schema,并把 type 写成 streamable-http。OAuth 对象规则一样。密钥不要写进这份 json。

callbackUrl 里的端口不会选择监听口。要固定本机回环端口,callbackUrlcallbackPort 写成同一个数,例如 http://127.0.0.1:4321/callback/registered"callbackPort": 4321。插件的 callbackPort 盖过全局 mcp_oauth_callback_port;两边都空就用操作系统临时端口。代理入口的 URL 端口和本机监听口可以故意不同。

插件给了 clientId、授权服务器又不广告 issuer-bound 回调、而且 callbackUrl 缺少这台服务器的 callback ID 时,Codex 会忽略这份 URL,改用 mcp_oauth_callback_url(未设则 http://127.0.0.1/callback)再拼上 callback ID。磁盘里的 callbackUrl 不会被改写,所以看起来「清单写对了却登不上」。登录时登记终端打印出的完整回调,不要只抄清单。

用户侧仍只能改开关和审批,改不了插件 MCP 的启动命令:

[plugins."sample@test".mcp_servers.sample]
enabled = true
default_tools_approval_mode = "prompt"

兼容布局里,根上的 .mcp.json 还要在 overlay 把 mcpServers 指到 ./.mcp.json,否则这份 OAuth 根本不会被导入。Admin 导入带 MCP 的插件仍是 Desktop only。

来源