官方 MCP 文件裡有兩個長得很像的小節。一個叫 Automatic backgrounding of long tool calls,一個叫 MCP tasks that run on the server。兩邊都說 Claude 會先去做別的事,結果好了再通知它,進度都擺在 /tasks。

那你的 MCP server 正在匯出一份報表,跑了十分鐘。這十分鐘裡,Claude Code 手上握著的到底是哪一個?

答案決定了你關掉終端機之後,那份報表還會不會做完。

這篇是讀 changelog 與官方文件整理的。本機 claude --version 回 2.1.322 (Claude Code),這是我唯一實際跑過的指令。我沒有架過支援 tasks 的 MCP server,也沒有觸發過任何一次 MCP task,下面每個行為都是「文件這樣寫」,不是「我看到它這樣跑」。

舊的那個:計時器到了,Claude 不再等

先拆比較早出現的。2.1.212 的 changelog 寫:

MCP tool calls running longer than 2 minutes now move to the background automatically so the session stays usable; configure the threshold or disable with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS

官方 MCP 頁的說法更完整:主對話裡的 MCP 呼叫跑超過兩分鐘,會變成背景任務,Claude 立刻拿到 task ID 繼續工作,呼叫結束時結果以 task notification 送回來。任務出現在 /tasks,你可以在那裡停掉它,而它「doesn’t survive exiting the session」。

這一段要抓的是:Claude 不再杵在原地等了。照文件的描述,它搬進背景之後仍是普通的工具呼叫,不是 MCP task。

拿櫃台寄件來比。你把一疊表單交給櫃台,櫃台人員站在你面前等你填完。站了兩分鐘,他說「我先去招呼別人,你填好叫我」,然後回到他的位子。這個安排只存在於他今天上班的這段時間。他下班,你的表單就沒人管了。

這個機制在站上已經講過一次,那篇談的是計時器怎麼砍東西,兩分鐘轉背景只是其中一小段:〈它不是壞掉,是被計時器砍掉〉。這篇不重講它,只拿它當對照組。

新的那個:server 收下工作,給你一張號碼牌

再拆新的。2.1.319 的 changelog 有三條相關的,第一條是:

Added support for MCP tasks in the terminal: when an MCP server runs a tool call as a task, Claude Code moves it to the background right away and tells Claude the result when it finishes

注意「right away」。這裡沒有兩分鐘的門檻。官方文件把 MCP task 定義成 server 自己用 MCP tasks extension 跑的長工作,舉的例子是報表匯出和建置。Claude 的呼叫在 server 接下工作的那一刻就回來了,之後畫面下方的 footer 會出現 1 MCP task 這類計數,Claude Code 靠定期問 server「做到哪了」來追蹤。文件還特別寫了:遠端 server 上的 task,你離開之後會繼續跑。

回到餐廳的比方。你點了一份要煮很久的菜,櫃台給你一張號碼牌,你回座位做自己的事。廚房做不做得完,跟你人在不在店裡無關。

一通呼叫要走到這條路,官方列了一串條件,我只挑跟本題有關的幾個:server 支援 tasks,用 HTTP、stdio 或 claude.ai connector 連上,協定版本是 2026-07-28;呼叫來自主對話,不是 subagent;session 是互動式的(Agent SDK 等非互動場合另有條件)。最後文件還補了兩句:任何不符合的呼叫「is a plain tool call」,一次性的 claude -p "<prompt>" 不會有 MCP tasks。

所以同一個工具,換個 server 或換個啟動方式,會走到完全不同的兩條路。server 不給 task,它就是普通呼叫,兩分鐘一到走舊機制。

開關改的是 Claude 要不要等,不是任務在誰手上

讓 Claude 等結果有兩個環境變數,文件的範例是放在 settings.json 的 env 區塊:

1
2
3
4
5
{
"env": {
"CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND": "1"
}
}

或是把 CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS 設成 0。兩個長得像,改的東西不一樣。

CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=0 比較粗暴:兩分鐘轉背景整個關掉,文件說 Claude 會等每一通 MCP 呼叫,等到它結束為止,MCP task 在互動 session 裡也一樣等。所以連那種你寧可它放著、自己去看 log 的慢呼叫,也會卡住整個 session。

CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND=1 只管 MCP task,而且文件有一句要特別看的話。設了它,Claude 會等 task 的結果;但只要自動背景化還開著,它仍然在兩分鐘後把這通呼叫搬進背景,短任務在原地做完,長的不擋你。接著是關鍵:

The moved call is a plain background call rather than an MCP task. It doesn’t survive exiting the session

也就是說,想「讓 Claude 等」而設的這個開關,對長工作的副作用是把一張號碼牌換回櫃台人員的口頭承諾。文件在這裡沒有說,被搬走之後 server 那邊的 job 會怎樣,我也不替它補。

另外有個容易誤會的設定:CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1。文件說它會讓 Claude Code 不再自動把 subagent、長 MCP 呼叫、逾時的 shell 指令搬進背景,但單靠它「doesn’t make Claude wait for MCP tasks」,MCP tasks 與 Monitor 工具照樣在背景跑。

我的選法,以及什麼會讓我改口

我會這樣排:預設什麼都不設,讓 server 回報 task 時就當 task 跑。只有一種情況設 DISABLE_MCP_TASK_BACKGROUND=1:下一步的輸入就是這個結果,而且你知道這類工作通常兩分鐘內做完。AUTO_BACKGROUND_MS=0 我會留到最後,因為它是整個 session 的全域行為,代價是所有慢呼叫一起卡。

這個排法壓在一個我沒驗證的解讀上:我把「moved call is a plain background call」讀成長任務被降級了。如果哪天我真的架起一個支援 tasks 的 server,設了 DISABLE_MCP_TASK_BACKGROUND=1,等過兩分鐘之後,/tasks 裡那一列仍然標著 runs on the server; survives exiting this session,那我就是讀錯了,上面「降級」那一段要整段收回。

版本號有個對不上的地方。changelog 把 CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND 列在 2.1.319(發佈頁 v2.1.319 的時間是 2026-11-06),官方 env-vars 頁對同一個變數寫的最低版本卻是另一個號碼。兩處我沒辦法判定哪個才對,所以本文的版本只引 changelog 明載的:MCP tasks 在 2.1.319,兩分鐘自動背景化在 2.1.212。

離開之前與重打之前

這類背景任務最容易出事的是兩個動作。

第一個是離開。文件說遠端 server 的 task 會一直跑,而且沒有任何離開選項會取消它,即使離開對話框把它列在「The following will stop when you exit」底下。stdio server 就不同:它的 process 隨 Claude Code 結束而停,但它的 task 在 /tasks 裡仍可能顯示 runs on the server; survives exiting this session。文件的建議是,除非那個 server 自己的文件說工作可以活過 process,否則先讓它跑完,或在 /tasks 選中它按 x 停掉。按 x 的意思是 Claude Code 不再追蹤,並請 server 取消,不過 server 仍可能做完。Esc 停不了背景任務。

第二個是重打。task 的狀態列裡有一種結尾是 outcome unknown.,文件對它的建議很直接:

A second call may repeat the work. Before calling the tool again, find out from the server what was done

匯出或建置這類工作,重做一次可能只是浪費時間,也可能不只。先問 server 做到哪,再決定要不要重打。

如果你是 server 作者

我讀到的規矩不多。只有在請求帶著 extension 時才能用 task 回答,否則呼叫會以 Unsupported result type 'task' for tools/call 失敗。官方的範例回應長這樣:

1
{"resultType":"task","taskId":"build-7f3a9c2e","status":"working","statusMessage":"Compiling, 40 of 212 files done","createdAt":"2026-10-22T14:03:07Z","lastUpdatedAt":"2026-10-22T14:03:07Z","ttlMs":null,"pollIntervalMs":5000}

收到之後 Claude Code 馬上送 tasks/get,再依 pollIntervalMs 反覆問;這個值會被夾在 250 到 30000 之間,欄位缺席或是 null 時用 2000。status 只能是 working、input_required、completed、failed、cancelled 其中之一。文件說 tasks/result、tasks/list、notifications/tasks 都「Not used」,結果要放進 tasks/get 的回應裡。這些我同樣只讀過,沒有寫過實作。

帶得走的一個問題

這兩種背景任務,差別可以收成一個問句:這份工作現在住在誰那裡。

住在 Claude Code 的 session 裡,session 沒了它就沒了;住在 server 裡,你只是拿著一張牌子。兩個環境變數都只是在決定你要不要站在櫃台前等。哪天你的 server 開始支援 tasks,不妨開一個測試用的長工作,進 /tasks 看那一列怎麼寫,再改一個開關,看它變了沒有。那一眼比讀完這篇更有用。

參考來源:Claude Code MCP 文件、環境變數文件、CHANGELOG