Hub Codex CLI 完整教學

第 9 章

連接外部工具:MCP

MCP 是一個讓 AI 助手接上「外掛工具箱」的標準插座。

想像你買了一台很強的電動工具主機,但它本身只能做最基本的事。原廠又出了一堆可以「卡上去」的擴充頭:有的能查最新的技術文件、有的能讀你 Figma 上的設計稿、有的能直接操作 GitHub。只要插座規格統一,任何擴充頭插上去就能用——你不用為每個工具重學一套接法。

MCP(Model Context Protocol,模型上下文協定) 就是這個「統一插座規格」。它是一套公開標準,規定 AI agent 要怎麼跟外部工具、資料來源溝通。Codex CLI 支援這套標準,所以你可以把別人寫好的工具(官方叫 MCP server)接到 Codex 上,讓它在幫你寫程式時,順便會查文件、讀設計稿、調 API。

這一章你會學到:

  • 「幫我用 Context7 查一下這個套件的最新用法。」——接上文件查詢工具。
  • 「讀我 Figma 上這個畫面的設計,照著切版。」——接上設計稿來源。
  • 「這個 MCP server 我暫時不想用,但別把設定刪掉。」——一鍵停用。
  • 「這個工具裡有個 delete_file 太危險,把它擋掉。」——工具白黑名單。

重要提醒

本章只談 Codex CLI(終端) 的 MCP 用法。Codex 還有 cloud、IDE 擴充等其他「座位」,它們共用同一份 MCP 設定(等下會講),但本章的指令都是在終端機裡跑的。看到別處教學叫你在 IDE 點選單,那是 IDE 的事,不是 CLI 指令。

9.1 MCP 是什麼、Codex 扮演哪兩種角色

先把心智模型建立起來。在 MCP 這套「插座 + 擴充頭」的世界裡,Codex CLI 可以站在兩個位置:

角色白話你會用到嗎
MCP client(最常用)Codex 去接別人的工具,把那些工具掛進自己的對話裡一起用✅ 幾乎每個人遲早會用到
MCP server(實驗性)把 Codex 本身包成一個工具,讓別的 AI 來驅動它進階玩家才會碰(見 9.4)

新手九成的時間都在當 client:你連到 Context7、Figma、GitHub 這類現成的 MCP server,把它們提供的工具掛進 Codex session,跟 Codex 的內建工具(讀檔、改檔、跑指令)並排使用。

兩種「傳輸方式」(transport)

MCP server 住在哪、Codex 怎麼跟它連線,有兩種:

傳輸方式白話設定關鍵
STDIOserver 是你電腦上的一支小程式,Codex 直接把它啟動起來,透過標準輸入輸出(stdin/stdout)對話給一條啟動 command
Streamable HTTPserver 是一個遠端網址,Codex 連過去給一個 url

簡單記:本機程式走 STDIO,遠端網址走 HTTP。等下 9.2 兩種都會示範。

小技巧

Codex 在每次 session 啟動時,會自動把你設定好的 MCP server 拉起來,並把它們的工具暴露在內建工具旁邊。你不用每次手動開——設定一次,以後開 Codex 就有。

重要提醒

網路上有些比較舊的 CLI 比較文章會寫「Codex 只支援本機 STDIO,不像其他工具能接遠端 server」——這是過時說法。官方 MCP 頁面明確列出 Streamable HTTP 這個傳輸方式,GitHub、Figma 都有官方託管的遠端版本可以直接接(9.3 會示範)。看到類似的舊說法,以官方頁面或你實機 codex mcp --help 的輸出為準。

CLI 和 IDE 共用同一份設定

這點很省事:Codex CLI、Codex 的 IDE 擴充,再加上 ChatGPT 桌面版 App,三個介面共用同一份 MCP 設定。你在終端機用 codex mcp add 加好一個 server,切去 IDE 或桌面 App 都是同一套,不用重設一次。

9.2 用 codex mcp add 接 STDIO / HTTP server

接 MCP server 有兩條路:codex mcp 指令(互動式,新手首選),或直接編設定檔(下一節)。這一節先學指令法。

codex mcp 指令家族

這一系列指令都是在管理存放於 ~/.codex/config.toml 裡的 MCP server 設定。逐字對照表:

我想做的事指令
新增一個 servercodex mcp add <name> ...
列出所有已設定的 servercodex mcp list [--json]
看某個 server 的詳細設定codex mcp get <name> [--json]
刪掉某個 server 設定codex mcp remove <name>
對 HTTP server 做 OAuth 登入codex mcp login <name> [--scopes a,b]
移除已存的 OAuth 憑證codex mcp logout <name>

--json 會印出機器可讀的格式,適合腳本處理;一般人看就用不加 --json 的版本。

範例一:接一個 STDIO server(Context7,查最新文件)

Context7 是一個常見的 MCP server,專門幫 AI 查套件、框架的最新文件。官方文件就拿它當範例。它是用 npx 啟動的本機程式,所以走 STDIO;也就是說,這不是內建功能,而是要下載並執行第三方程式。

先驗證,才把第三方程式設成每次啟動都會跑

codex mcp add 會把啟動指令存進長期設定;之後開 Codex 時,它可能自動下載、啟動這支程式,且其他共用此設定的介面也可能看得到。第一次接 MCP 前,請先從該服務的官方網站或官方儲存庫核對維護者、套件名稱、明確版本與工具權限;不確定來源、用途或資料會送到哪裡,就先不要執行。每次只接一個,接好後先用 codex mcp list/mcp 看工具清單。

# 將 <已核對版本> 換成官方文件列出的明確版本
codex mcp add context7 -- npx -y @upstash/context7-mcp@<已核對版本>

拆開看這條指令:

  • codex mcp add context7 — 新增一個叫 context7 的 server(這個名字你自己取,之後拿它來查/刪)。
  • -- — 一個分隔符。它的意思是「後面這一整串,都是用來啟動 server 的指令」。
  • npx -y @upstash/context7-mcp@<已核對版本> — 真正拿來啟動 server 的指令;-y 會略過 npm 的確認提問,所以只在已核對來源與版本後使用。

小技巧

-- 這個分隔符很關鍵。它之前是 Codex 自己的旗標,之後是要交給 server 的啟動指令。少了它,Codex 會搞不清楚 npx 是要給誰的。

範例二:只有非敏感設定才用 --env

--env KEY=VALUE 適合傳遞像顯示等級這種非敏感設定,且可重複使用。它的值會寫進 MCP 設定,也可能留在終端機歷程;因此絕對不要在這裡放 API key、token、密碼或任何憑證。

# 只放可公開的設定值
codex mcp add <server-name> --env LOG_LEVEL=info -- <stdio-server-command>

注意 --env 要寫在 -- 之前(那是 Codex 的旗標),啟動指令寫在 -- 之後。若 server 需要密鑰,請用作業系統或 CI 的祕密管理功能先提供一個環境變數,再在 config.toml 只寫變數名稱(9.3 的 env_vars 範例),不在命令列或設定檔寫值。

範例三:接一個 HTTP server(遠端網址)

如果 server 是個遠端網址,就用 --urlcodex mcp add 支援的旗標逐字如下:

旗標用途
--env KEY=VALUESTDIO server 的非敏感環境設定,可重複;不放密鑰
--url https://…指定 HTTP server 的網址
--bearer-token-env-var ENV_VARHTTP server 的 bearer token 要從哪個環境變數讀
--oauth-client-id CLIENT_IDOAuth client id
--oauth-resource RESOURCEOAuth resource 參數
--分隔符,其後為 STDIO 啟動指令

重要提醒

官方 MCP 教學頁沒有給「codex mcp add 加 HTTP server」的完整範例(只確認了有 --url 這個旗標)。新手如果要接 HTTP server,最穩的做法是直接編 config.toml(見 9.3 範例 B),設定鍵比較清楚,也比較好對照。

OAuth 登入(需要授權的 HTTP server)

有些 HTTP server(像 Figma)要你用帳號授權才能用。流程是先 add 設定好,再跑:

codex mcp login <server-name>

它會幫支援 OAuth 的 HTTP server 啟動一次登入流程。要指定授權範圍就加 --scopes

codex mcp login figma --scopes read,write

不想再授權了就 codex mcp logout <server-name> 移除憑證。

小技巧

codex mcp login 預設會挑一個隨機本機埠接收 OAuth 的 callback。如果你的 OAuth 服務商規定要用固定埠,或你是在遠端 devbox 這種需要自訂 callback 網址的環境跑 Codex,官方另外提供 mcp_oauth_callback_portmcp_oauth_callback_url 兩個全域設定鍵可以指定。這兩個鍵牽涉到 callback 綁定本機介面還是對外暴露的資安細節,第 15 章會講更深。

接好之後怎麼確認?

兩個方法:

  • 終端機外codex mcp list 看清單。
  • Codex TUI 內:在對話框輸入 /mcp,會顯示目前啟用的 server 與它們的工具。

小技巧

改完 config.toml 後,Codex CLI 跟 VS Code 擴充套件都不會自動偵測到新設定——官方文件明確說沒有熱重載機制,一定要整個重開(結束目前的 session 再重新啟動)新增或改過的 server 才會生效。這是排查「怎麼加了卻沒用」該先試的第一步,比懷疑設定寫錯、或懷疑要升級都更基本。

重要提醒

確認重開過還是不生效,再升級 Codex CLIcodex update,詳見第 2 章)試試。社群曾回報過「config 裡有 MCP 卻不生效」的問題,通常升級後改善。

接不上、卡住、逾時:幾個環境面的常見坑

以下幾種狀況通常不是你的 config.toml 寫錯,而是作業系統、網路、套件快取這類外部環境造成的常見絆腳石。先對照這裡,再回頭懷疑設定本身。

症狀可能原因與解法
Windows 上加 npx 系列的 STDIO server,報類似「program not found」的啟動失敗,但同一行指令貼到 PowerShell 卻能正常跑npxpnpmyarn 在 Windows 上其實是 .cmd 批次檔,Codex 底層啟動子程序的方式不像 shell 那樣會自動幫你解析副檔名。改用 cmd /c 包一層,或直接指到 npx.cmd 的完整路徑(下面有範例)
第一次加某個 npx -y 型的 server 就逾時失敗,重跑一次卻正常npx -y 第一次執行要連 npm registry、下載套件,Windows 上還會多一層 Defender 即時掃描,很容易吃光預設 startup_timeout_sec = 10 秒。把它調到 15~30 秒,或提前在終端機手動跑一次同樣的指令幫 npm 快取「暖身」,之後 Codex 啟動就不用再重付這筆冷啟動成本
設了 bearer_token_env_var,呼叫卻回未授權,或 token 像是空的Codex 不會自動讀 .env 檔。指定的環境變數必須在啟動 Codex 之前就由作業系統的憑證管理或 CI 的 secret 注入;不要在終端機輸入真正 token,也不要把它寫進可能被 Git 追蹤的 .env

Windows 上包一層 cmd 繞開 .cmd 執行檔辨識問題,實際寫法:

[mcp_servers.chrome_devtools]
command = "cmd"
args = ["/c", "npx", "-y", "chrome-devtools-mcp@<已核對版本>"]

小技巧

如果你在別處看到 @latest,正式使用建議釘死已核對的明確版本號(例如 @upstash/context7-mcp@1.2.3)。用 @latest 會讓每次啟動抓到的版本、啟動時間、甚至工具行為都可能悄悄改變,除錯時很難判斷「是我環境變了,還是套件本身變了」。真的想接遠端版本、又想整個繞開 Windows 這類本機執行檔的坑,更乾脆的做法是優先找官方託管的 Streamable HTTP 版本(像 GitHub、Figma 都有),直接用 url 接,連 Node/npx 環境都不用管。

其他已知回報(少見,先知道有這回事就好)

Codex 內建一個連去 ChatGPT Apps/connector 的 codex_apps MCP,若它跟後端握手逾時或網路不穩,曾有使用者回報整個 CLI 會卡在「Starting MCP servers」畫面數分鐘、沒有任何進度提示,容易誤以為程式當掉(社群回報,對應 openai/codex issue #20167,目前無官方 workaround,只能重啟或檢查網路)。另外,同一組 MCP 設定用 Codex CLI 在 WSL 裡直接跑是正常的,但透過 VS Code 擴充套件在 WSL 裡啟動時,MCP 伺服器有時會完全偵測不到——這是 IDE 擴充套件與 WSL 之間橋接的獨立問題,跟 CLI 本身、也跟第 16 章講的其他 WSL 坑不是同一件事,遇到時兩者要分開排查。

9.3 [mcp_servers.*] 設定鍵、工具白黑名單與核准

codex mcp add 跑完,其實就是幫你把設定寫進 ~/.codex/config.toml[mcp_servers.<id>] 區段。你也可以直接編這個檔,功能更完整(像 HTTP header、工具過濾、逐工具核准,有些只能手動編)。

config.toml 當成啟動清單,不是筆記本

這是長期設定:每次新開 session 都可能依它啟動外部程式或連線。先備份原檔、一次只加一個已驗證的 server,確認工具清單與權限後再留著;試用完不需要就停用或移除。檔案與命令列都不可出現 API key、token、密碼、cookie 或私鑰;只保留非敏感設定與環境變數名稱。

關於 config.toml 的位置、優先序、什麼叫「信任專案」,詳見第 8 章。這裡只聚焦 MCP 相關的鍵。

重要提醒

Codex 沒有 codex mcp add --scope global|project 這種旗標(別處 CLI 工具有,Codex 沒有)。如果你想把 MCP server 設定只放在某個專案(寫進專案目錄的 .codex/config.toml),目前只能手動編那個檔,沒有指令幫你做。社群有提案要加 --scoped/-s 旗標(issue #23487),但尚未實作。以後是否有,以實機 codex mcp add --help 為準。

STDIO server 的鍵

型別意思
command字串啟動 server 的指令(例如 "npx"
args陣列傳給上面指令的參數(例如 ["-y", "@upstash/context7-mcp@<已核對版本>"]
env字典寫入要轉發給 server 的非敏感環境設定(key=value)
env_vars陣列白名單:只列出要轉發的既有環境變數名稱;密鑰值不寫入檔案
cwd字串server 程序的工作目錄

重要提醒

command字串args陣列,這兩個別搞混。網路上有些範例會把整串 ["npx", "-y", "..."] 全塞進 command,那是錯的。正確是 command = "npx"args = ["-y", "..."]

把「設定值」和「密鑰」分開

env 是「我直接給值」,只適合公開設定,例如 env = { LOG_LEVEL = "info" }env_vars 是「把我電腦或 CI 已經安全提供的這幾個變數名稱放行進去」,例如 env_vars = ["MCP_SERVICE_TOKEN"];設定檔不會寫出 token 的值。任何密鑰都用後者,不要把真實值填進 env

HTTP server 的鍵

型別意思
url字串HTTP server 的網址端點
bearer_token_env_var字串bearer token 要從哪個環境變數讀(不要把 token 明文寫進檔案
http_headers字典每次請求都帶上的非敏感固定 HTTP header
env_http_headers字典由環境變數填值的 HTTP header;需要憑證時用這個,不寫死值

通用鍵(STDIO 和 HTTP 都能用)

型別/預設意思
enabled布林false停用某 server 但保留設定(不用刪)
startup_timeout_sec數字(預設 10)server 啟動逾時秒數;啟動慢就調大
tool_timeout_sec數字(預設 60)單一工具執行逾時秒數
required布林true 時,這個 server 起不來就讓整個 Codex 啟動/續接直接失敗

工具過濾與核准(安全相關)

接進來的 server 可能帶一堆工具,有些你不想讓 AI 用(例如會刪檔的)。用這些鍵控制:

意思
enabled_tools陣列白名單:只允許列出的工具名
disabled_tools陣列黑名單:在白名單之後再套用,擋掉這些工具
default_tools_approval_modeauto / prompt / writes / approve這個 server 的工具預設要不要先問你
tools.<tool>.approval_modeauto / prompt / writes / approve單一工具的核准行為覆寫

核准模式可以對照第 6 章學過的「approval」概念來理解:prompt 會在用工具前先問你、auto 不問直接用。writes 這個值官方頁面也有列,但目前查到的說明不夠細,精確行為(例如是不是只針對「會寫入」的操作放行、其餘仍要問)建議用 codex mcp get <name> --json 或官方 config-reference 實機核對,不要用猜的下判斷。

重要提醒

不管 approval_mode 怎麼設,官方文件講了一條安全下限:只要某個 MCP/App 工具呼叫被標記為 destructive(具破壞性),Codex 一律要求核准,不會因為你設了 auto 就悄悄放行。approval_mode 能幫你放寬「無害」操作的核准,但擋不掉這條底線——這是刻意留的安全網,不是設定沒生效。

範例 A:STDIO server(本機程式)

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp@<已核對版本>"]

# 若需要密鑰,只列出已由系統/CI 提供的變數名稱,不寫值
env_vars = ["MCP_SERVICE_TOKEN"]

# 可選:只傳遞非敏感設定值
[mcp_servers.context7.env]
LOG_LEVEL = "info"

範例 B:HTTP / Streamable server(遠端網址,含 Figma)

[mcp_servers.figma]
url = "https://mcp.figma.com/mcp"
bearer_token_env_var = "FIGMA_OAUTH_TOKEN"
http_headers = { "X-Figma-Region" = "us-east-1" }

小技巧

上面那行 http_headers = { "X-Figma-Region" = "us-east-1" } 只是示範 http_headers 這個鍵怎麼寫(每次請求帶一個非敏感 header)——X-Figma-Region 這個 header 名與值是舉例,Figma 並不要求這一行。真正接 Figma 時若不需要自訂 header,整行可以省略;認證用的 Authorization 或 token 不可寫在 http_headers,應使用 bearer_token_env_varenv_http_headers。要不要帶哪些 header,以該 server 的官方文件為準。

重要提醒

注意這裡是 bearer_token_env_var = "FIGMA_OAUTH_TOKEN"——填的是環境變數的名字,不是 token 本身。真正的 token 應由作業系統憑證管理或 CI secret 注入;千萬別把它寫進命令列、config.toml、截圖或可能被提交的 .env,否則一旦外流就必須立刻撤銷並換發。

範例 C:工具過濾 + 逐工具核准

[mcp_servers.mytools]
command = "my-mcp-server"
enabled_tools = ["search", "read_file"]   # 白名單:只開這兩個
disabled_tools = ["delete_file"]          # 黑名單:在白名單後再擋掉

default_tools_approval_mode = "prompt"     # 這個 server 預設用工具前先問

[mcp_servers.mytools.tools.search]
approval_mode = "auto"                      # 但 search 這個工具不用問,直接用

這個範例示範了一個好習慣:預設保守(prompt),只對安全的工具放寬(auto

OAuth 進階鍵(需要授權的 server)

意思
oauth_resource(per-server)OAuth resource 參數(RFC 8707)
scopes(per-server)登入時要求的 OAuth 授權範圍
mcp_oauth_credentials_store(頂層)OAuth 憑證存哪:auto / file / keyring

另一條路:不手動編檔,用 /plugins 裝官方整合包

前面教的都是「自己動手」——用 codex mcp add 或直接編 config.toml。從 v0.117.0 起,Codex 多了第三條路:外掛(plugin)。一個外掛可以把 SKILL.md(技能說明)、MCP 伺服器設定(.mcp.json)、App connector 設定(.app.json)打包成一個單位,在對話框輸入 /plugins 就會跳出瀏覽/安裝介面,你完全不用碰 config.toml 的語法。

OpenAI 官方目前出貨20 多個第一方整合,常見的像 Slack、Figma、Notion、Gmail、Google Drive、Cloudflare 都在其中。選一個裝下去,幕後的 PluginsManager 會自動把裡面捆的 skills、MCP server、connector 全部接好,不用你逐項設定。裝好的外掛會記錄在 ~/.codex/config.toml[plugins] 表格裡——平常不需要手動去改它,但打開看一眼可以確認到底裝了什麼。

小技巧

外掛裡包的 MCP server,一樣支援本節前面教的過濾與核准鍵——只是寫法上要多帶一層外掛的命名空間去覆寫,不直接動外掛本體,這塊「plugin-scoped 覆寫」的細節與寫法留給第 15 章講。/plugins 跟 skills 自己宣告 MCP 依賴(dependencies.tools)之間的分工,則見第 12 章

9.4 把 Codex 自己當成 MCP server(進階)

前面都在講 Codex 當 client(去接別人的工具)。反過來,你也可以把本機的 Codex 引擎包成一個 MCP server,讓別的 AI agent(例如 OpenAI Agents SDK、其他 MCP client)透過 MCP 協定來驅動 Codex——開對話、跑回合、管帳號設定都行。

重要提醒

這個功能官方標明是實驗性(experimental and subject to change without notice)——方法名、欄位、事件格式都可能在沒有預告的情況下改變。這節給進階讀者建立概念,不建議新手把它寫進正式流程。一切以官方 repo 的最新文件為準。

啟動指令

指令名是 codex mcp-server連字號連起來),不是 codex mcp serve

# 直接把輸出接到你的 MCP client
codex mcp-server | your_mcp_client

# 用 MCP Inspector 檢視它提供哪些方法;先核對來源與版本,不帶任何密鑰
npx @modelcontextprotocol/inspector@<已核對版本> codex mcp-server

npx 會執行套件中的第三方程式;即使這個 Inspector 只是暫時執行、沒有寫進 MCP 設定,也應先從官方來源核對套件與版本,並且不要透過命令列傳遞任何 token。

它用的傳輸是 standard MCP over stdio(JSON-RPC 2.0,line-delimited)。

它對外提供哪些能力(概念速覽)

不用記細節,知道「它能被外部完整控制」就好。大致分這幾類方法:

類別能做什麼
Thread開/續接/分支/讀取/列出對話線
Turn開始/引導/中斷一個回合
Account讀帳號、登入/登出、查額度
Config讀寫設定
Discovery列出模型、app、協作模式

重要提醒

官方的 MCP 教學頁(developers.openai.com/codex/mcp)完全沒提「把 Codex 當 server」這件事——它目前只出現在 GitHub repo 的 codex_mcp_interface.md 與 CLI reference。這也再次說明它還很早期。

小技巧

社群有第三方專案(例如 tuannvm/codex-mcp-server)把 Codex CLI 包成 MCP server 給別的 agent(如 Claude Code)呼叫。那些是非官方產物,使用前自行評估風險,別當成 OpenAI 官方功能。

9.5 🎓 高手進階

前面四節足夠你「接好、用上」MCP。這一節是給已經跑順、想榨出每一分掌控力的人:精修設定鍵的細語意、避開幾個會「靜默吃掉設定」的陷阱、學會在連不上時自己 trace。新手可先跳過,日後遇到怪問題再回來。

⚠️ 自建 MCP server(把 Codex 包成 server 給別的 agent 驅動)的深度內容——v2/v1 方法清單、approval handler 欄位形狀、Inspector 除錯——下放到第 15 章。本章 9.4 已給概念入口,這裡只補 client 端進階。

env vs env_vars:不只是「設值 vs 白名單」

9.3 已經分清 env(只放非敏感設定值)和 env_vars(放行既有環境變數名稱)。進階細節是:env_vars 的每個項目不只能寫字串,還能寫物件,用來指定「從哪個環境取值」;下例只有名稱,沒有任何密鑰值:

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp@<已核對版本>"]

# 兩種寫法可混用
env_vars = [
  "LOCAL_TOKEN",                              # 純字串 = 從 Codex 本機環境讀
  { name = "TOKEN", source = "remote" },     # 物件 = 從 remote executor 環境讀
]
  • 純字串(或 source = "local",預設值)→ 從你本機的環境變數讀。
  • source = "remote" → 從 remote executor 環境讀,但有前提:必須同時設 experimental_environment = "remote" 且該 server 是 remote stdio,否則無效。

重要提醒

experimental_environment = "remote" 是實驗性鍵,官方逐字說明它「透過 remote executor 啟動 stdio server」。官方頁只描述 remote 對 stdio 生效,未見 streamable HTTP server 的 remote placement 支援敘述——所以別期待 HTTP server 能 remote placement。一切以實機與官方 Configuration Reference 為準。

startup_timeout_ms:毫秒版逾時別名

9.3 列了 startup_timeout_sec(預設 10 秒)。其實還有一個毫秒別名 startup_timeout_ms,官方逐字定義是「startup_timeout_sec 的毫秒版」,兩者並存,需要更細精度時用它。

小技巧

tool_timeout_sec(預設 60 秒)目前沒有對應的 _ms 別名——別照樣造一個 tool_timeout_ms 出來,設了也不會被認得。

enabled_tools / disabled_tools 的求值順序(組合技關鍵)

接進一個 server 後,工具的可見與否,Codex 是按固定順序算出來的,搞錯順序就會疑惑「為什麼我明明開了卻看不到」:

  1. enabled_tools(白名單) 先決定可見集合(沒列 = 全部可見)。
  2. disabled_tools(黑名單) 在白名單之後套用——即使白名單列了某工具,黑名單仍能把它剔掉。
  3. default_tools_approval_mode(server 級預設核准)
  4. tools.<tool>.approval_mode(單一工具覆寫) 蓋過 server 級預設。

官方文件自己給了一個「看似矛盾、其實是示範」的例子:

[mcp_servers.chrome_devtools]
enabled_tools = ["open", "screenshot"]
disabled_tools = ["screenshot"]   # 後套用 → screenshot 最終被剔除

結果:open 留下,screenshot 雖然在白名單裡,卻被黑名單蓋掉。記法:黑名單後於白名單,衝突時黑名單贏。

codex mcp add 真的沒有 --scope(更正/重申)

9.3 已提過 Codex 沒有 codex mcp add --scope global|project 旗標。進階重申並補完:本輪查核 codex mcp add 的完整旗標只有 --env / --url / --bearer-token-env-var / --oauth-client-id / --oauth-resource / --(STDIO 啟動指令)這幾個。沒有 --scope--scoped--transport--header--startup-timeout 這些旗標——別處 CLI 工具(Claude Code、Gemini CLI)有,Codex 沒有,照抄會報錯。

所以:要把 MCP server 設定只放某個專案(project-local),目前只能手動編該專案的 .codex/config.toml,沒有指令幫你做。而且該專案還必須是「信任的」(trusted),否則 Codex 根本不載入專案層的 .codex/(信任機制見第 8 章)。

重要提醒

社群有提案要加 --scoped/-s 旗標(issue #23487),但尚未實作。以後是否有,以實機 codex mcp add --help 為準。

CLI 一行流:臨時覆寫 MCP 鍵(不改檔)

不想動 config.toml、只想這一次 session 改個設定?用全域 -c/--config 的點記法臨時覆寫任何 MCP 鍵:

# 臨時停用某 server(單次 session,不改檔)
codex --config mcp_servers.context7.enabled=false

# 臨時拉長啟動逾時(值含特殊字記得用 shell 引號包起來)
codex -c "mcp_servers.github.startup_timeout_sec=60"

小技巧

官方提醒「TOML 值要適當引號,避免被 shell 拆開」。值是純數字/純單字可以不引號,但只要含空白、等號以外的特殊字或陣列,就用引號把整個 key=value 包起來。

list --json / get --json:腳本盤點與單點診斷

9.2 提過 --json。進階用法:

  • codex mcp list --json — 機器可讀的全清單,官方說明它還會帶上 marketplace 資訊(一般 list 沒有),適合腳本盤點所有 server。
  • codex mcp get <name> --json — 印出單一 server 的 raw config entry。這是「我設定到底有沒有被讀進去」的第一手診斷工具:設定打錯、段名寫錯,這裡會直接看出來。

/mcp verbose:連線看起來正常、工具卻怪怪的時候

/mcp 平時給的是精簡摘要:哪些 server 連上了、各自帶了哪些工具。但遇到「明明顯示已連線,工具卻沒出現」或「工具在,行為卻怪怪的」這種模糊狀態,精簡摘要不夠用。這時換用 /mcp verbose(v0.123.0 起),它會多印出 resources、resource templates,以及該伺服器回報的 metadata——對照上面的 get --json(看的是設定端),/mcp verbose 看的是連線端的即時狀態,兩個合起來才是完整的診斷視角。

順便拆穿一個常被誤讀成「連線失敗」的假警報:Codex 在 session 一開始,會嘗試跟每個設定好的伺服器要 resources 與 resource templates 這兩份清單。但這兩個方法在 MCP 協定裡是選填的,很多只實作 tools、沒實作這兩個方法的極簡 server,依協定規範就該回應 -32601 Method not found——這其實是完全合規的行為,不代表 server 壞了。如果你在畫面上看到類似這樣的錯誤字樣,先別急著重裝或砍設定,回頭用 /mcp verbose 確認一下工具清單是不是其實好好的。

重要提醒

/mcp verbose 這個子指令、以及「-32601 會被顯示成疑似啟動失敗」這個因果,官方頁面未逐字列出,屬社群除錯知識整理。-32601 本身是 JSON-RPC 標準裡「方法不存在」的錯誤碼,這點是協定層面的事實;但 Codex 介面具體怎麼呈現它,以及 /mcp verbose 實際印出的欄位,請以你實機的輸出為準。

⚠️ 陷阱:段名底線,寫成連字號會「靜默忽略」

這是最容易讓人卡半天的坑:config.toml 裡的段名必須是底線版 [mcp_servers.名稱]。如果寫成:

  • [mcp-servers.名稱](連字號)
  • [mcpServers.名稱](駝峰)

Codex 會靜默忽略——不報錯,但 server 就是不會出現。你 /mcp 看不到、工具也掛不上,卻找不到任何錯誤訊息。

小技巧

接好卻不生效時,排查順序:① 先 codex mcp get <name> --json 看設定有沒有被讀到 → ② 沒讀到就查段名是不是底線、有沒有打錯 → ③ 讀到了卻工具沒出現,再 codex update 升級(見 9.2 末的提醒)。

⚠️ 「連字號段名靜默忽略」這個明文因果來自社群除錯文章(對應官方 issue #3441「config.toml 裡的 MCP 不生效」)。底線段名本身是官方範例一致的寫法;但「寫成連字號會被靜默吞掉」屬社群歸因。以實機行為為準。

RUST_LOG:連不上時自己 trace

Codex 是 Rust 寫的程式,所以吃標準的 RUST_LOG 環境變數來控制日誌詳細度。MCP server 連不上、握手失敗、莫名逾時時,可以開 trace 看底層發生什麼:

# 全開 codex_core 的 trace(最穩,先全開再縮)
RUST_LOG=codex_core=trace codex

社群知識庫進一步指出可用更精準的 module target codex_core::mcp_connection_manager=trace 只 trace MCP 連線管理器,以及 TUI 日誌檔位於 ~/.codex/log/codex-tui.log(可 grep -i mcp 篩 MCP 相關事件)。

重要提醒

codex_core::mcp_connection_manager=trace 這個精確 module 名~/.codex/log/codex-tui.log 這個精確路徑來自第三方知識庫,官方文件未逐字列出。RUST_LOG 機制本身、~/.codex/ 為設定根目錄是確定的;但確切 module 路徑與 log 檔名以實機為準。不確定時就先 RUST_LOG=codex_core=trace 全開,再依輸出縮小範圍。

v0.140.0 校正:enabled = false 的精確語意

9.3 教過 enabled = false 可「停用某 server 但保留設定」。配合 0.140.0(2026-06-15)的可靠性改進,這裡補一個精確語意:該版 changelog 逐字說明改善了「保留被明確 disabled 的 server」(preserving explicitly disabled servers)——也就是你手動設成 enabled = false 的 server,不會被自動重新拉起

同版另外兩項 MCP 相關改進,實用上要知道:

  • 暫時性啟動失敗會自動重試——以前 cold start(例如 npx -y 第一次下載)逾時你得手動重來,現在會自動 retry transient 失敗。
  • 失效的 OAuth 憑證會被當成「已登出」回報,而不是硬錯。看到某 HTTP server 變 logged-out,去 codex mcp login <name> 重登即可。
  • 同版起,CLI 與 MCP 的 OAuth 憑證採加密本地儲存

已知限制:codex exec 非互動模式下,MCP 工具呼叫可能被自動取消

第 10 章會教 codex --ask-for-approval never exec 這套組合,讓非互動(headless)流程不會卡在核准提示上。但如果這趟任務會呼叫 MCP 工具,有一個目前還沒修好的已知狀況要先知道:headless 模式下 stdin 是關閉的,核准提示的讀取端收到的是 EOF,Codex 會把這個 EOF 解讀成「使用者拒絕」——就算你已經照著設好 never,log 裡還是可能出現「mcp: xxx started」接著「mcp: xxx (failed)」「user cancelled MCP tool call」這樣的訊息,MCP 工具呼叫仍被取消。

社群測過 approval_policy = "never"default_tools_approval_mode = "never"--ignore-user-config 這幾種組合,對這個問題都沒有效果(對應 openai/codex issue #24135)。目前唯一回報有效的繞過法是加上 --dangerously-bypass-approvals-and-sandbox,但這個旗標會連沙箱一起關掉(見第 6 章紅線三),不適合用在正式環境。

重要提醒

這是 openai/codex 上一個尚未解決的開放 issue,不是你設定寫錯,也還沒有一個「安全又可靠」的解法——上面的 bypass 旗標是已知能動但有代價的權宜之計,不是官方建議的正式解法。如果你的自動化腳本一定要在非互動模式下呼叫 MCP 工具,目前最務實的做法是先在自己的環境實測一輪確認行為,或考慮把「需要 MCP」的那一步拆出來,改用互動模式跑。修復進度請留意官方 Changelog

進階安全 / 成本一句話帶過(交叉引用)

  • 減 context 開銷:每個 server 的工具 schema 都吃 context,server 一多 system prompt 就膨脹、選錯工具機率上升——社群曾實測一個 93 個工具的大型 server(GitHub 官方 MCP),光工具清單的 schema 就吃掉將近 55,000 token/回合,而且是你還沒打字前就先付掉的固定成本(數字隨版本浮動,當量級直覺看即可)。用 enabled_tools 只暴露真正會用的工具是最直接的瘦身手段(9.3 的工具過濾,這裡是它的「省成本」用途);另一個配套鍵 tool_output_token_limit 則是替工具的回傳內容加上限,兩者搭配的細節與更完整的量級數字,第 15 章第 16 章會深講。
  • token 不落盤三原則:HTTP server 用 bearer_token_env_var、stdio server 用 env_vars、OAuth 憑證用 mcp_oauth_credentials_store = "keyring"(9.3 已教鍵,安全心法見第 14 章資安章節)。
  • 自建 server / 被別的 agent 驅動:見第 15 章

小結

走完這一章,你學會了用「插座 + 擴充頭」的方式幫 Codex 擴充能力:

  • MCP 是讓 AI 接外部工具的標準協定;Codex 可當 client(常用,接別人的工具)或 server(實驗性)。
  • 兩種傳輸:STDIO(本機程式給 command)、HTTP(遠端網址給 url)。
  • codex mcp add / list / get / remove / login / logout 管理,或直接編 ~/.codex/config.toml[mcp_servers.*];把它當成會在往後 session 啟動外部程式的清單,每次只加入一個已驗證來源。
  • 安全要點:token 只用 bearer_token_env_var/env_vars 的名稱,不寫在命令列或設定檔、危險工具用 enabled_tools/disabled_tools 過濾、核准用 approval_mode 控制,destructive 工具無論怎麼設都會要求核准
  • 沒有 --scope 旗標——project-local 設定目前只能手動編檔(且專案須「信任」)。
  • 接不上時先查環境面:Windows 上 npx.cmd 常抓不到、npx -y 冷啟動易撞 10 秒逾時、bearer_token_env_var 必須先由安全的憑證管理或 CI secret 注入(.env 不會被自動讀)、改完設定要整個重開(無熱重載)。
  • 高手進階(9.5):env_vars 可帶 source 物件、startup_timeout_ms 毫秒別名、黑名單後於白名單的求值順序、-c 一行流臨時覆寫、list/get --json 診斷、/mcp verbose 揪出 -32601 假警報、段名必須底線(連字號會靜默忽略)RUST_LOG trace、0.140.0 起 enabled=false 的 server 不會被自動拉回 + 啟動失敗自動重試,以及 codex exec 非互動模式下 MCP 核准的已知限制。

時效提醒

本章的指令、旗標、設定鍵都對照 Codex CLI 0.140.0 與官方文件查核過。但 Codex 更新很快,官方頁面也沒標版本號。實際使用前,逐字以實機 codex mcp --helpcodex mcp add --help/mcp 的輸出為準。

動手試試

  1. 接一個文件查詢工具:先從官方來源核對維護者、套件名稱、明確版本與工具權限;確認後,將 <已核對版本> 換成版本號,再跑 codex mcp add context7 -- npx -y @upstash/context7-mcp@<已核對版本>,最後用 codex mcp list 確認它在清單裡。
  2. 進對話看一眼:啟動 codex,在對話框輸入 /mcp,看看 Context7 帶進來哪些工具。
  3. 試試停用不刪除:打開 ~/.codex/config.toml,在 [mcp_servers.context7] 下加一行 enabled = false,重開 Codex 後再 /mcp 看看它是不是消失了——確認後把這行刪掉復原。
  4. (進階)一行流臨時停用:不改檔,跑 codex --config mcp_servers.context7.enabled=false 開一次 session,確認 /mcp 裡看不到它,結束後下次正常開又回來了。
  5. (進階)結構化診斷:跑 codex mcp get context7 --json,看 Codex 實際讀進去的 raw 設定長什麼樣——這是排查「設定沒生效」的第一手工具。
  6. (進階)比較 /mcp/mcp verbose:Context7 接好之後,在對話框先打 /mcp,再打 /mcp verbose,比較兩者印出的內容有什麼不同——這是下次遇到「連線正常但工具怪怪的」時,你會想先跑的第一個指令。

本章官方文件參考