Agent skills, MCP servers 與 rules files 比較
解析 coding agent 三種上下文注入機制的成本差異。比較 rules files、skills 與 MCP servers 的 token 消耗與維護開銷,協助您根據專案需求選擇最佳方案。
Agent skills、MCP servers 與 rules files 的比較:簡短回答
Agent skills、MCP servers 與 rules files 都能為程式設計代理(coding agent)提供知識。請根據知識的用途進行選擇。MCP (Model Context Protocol) 適用於每次查看時可能變動的資料。Skill 適用於您今天寫下、六週後依然正確的程序。Rules file 則適用於在每個對話階段都必須遵守的少數事實。
這項選擇有其代價,而代價就是 context。代理不需要的指令每消耗一個 token,就代表讀取程式碼時可用的 token 減少一個。此外,由於整個 context window 會在每次請求時重新發送,這意味著您在每一輪對話中都要重複支付該 token 的成本。因此,真正重要的問題並非哪種機制「能」完成任務(大多數情況下三者皆可),而是哪一種機制在閒置時成本最低。
使用前各項功能的成本
這三種機制載入的時間點不同,而時間點的差異就是成本的關鍵。
規則檔案會在每次啟動對話時完整載入,無論是否相關。Claude Code 會在每次對話開始時讀取 CLAUDE.md,並忽略長度限制將其完整載入。建議的目標是每個檔案控制在 200 行以內,因為過長的檔案不僅會消耗更多 Context,且模型遵循規則的可靠度也會降低。這兩種效應方向一致,這就是為什麼 900 行的規則檔案不僅無用,甚至有害。
技能(Skill)分兩個階段載入。啟動時,僅有每個 SKILL.md 前言(frontmatter)中的 description 行會進入 Context,讓模型知道該技能存在及其大致適用時機。技能主體則在呼叫時才會載入。因此,一份 400 行的參考文件在被呼叫前幾乎不佔用任何成本。
MCP server 過去是成本最高的項目,這也是目前網路上大多數比較資訊過時的原因。在目前的 Claude Code 中,工具搜尋(tool search)預設為開啟。對話開始時僅載入工具名稱與 server 的指令欄位,完整的 JSON (JavaScript object notation) schema 會延遲到 Claude 搜尋時才載入。新增一個 server 不再需要預先消耗數千個 token。雖然仍有成本,但在關閉工具搜尋的設定下,才會在啟動時一次消耗所有成本。
The data behind this chart
[
{
"label": "Rules file, 200 lines",
"at_startup": "2,500",
"after_use": "2,500"
},
{
"label": "Skill, 12 KB body",
"at_startup": 40,
"after_use": "3,000"
},
{
"label": "MCP server, tool search on",
"at_startup": 500,
"after_use": "3,200"
},
{
"label": "MCP server, tool search off",
"at_startup": "4,500",
"after_use": "4,500"
}
]上述為估算值,並非您機器上的實際測量數據。這些數據來自各機制載入的文字大小,以每個 token 約 4 個字元計算:一份 200 行的規則檔案約為 10 KB 的 markdown,技能描述約為 160 個字元,而一個提供 12 個工具的 server 則包含約 18 KB 的 schema 與 2 KB 的指令區塊。Claude Code 會將每個工具描述與 server 指令欄位截斷在 2 KB,因此該部分有上限。下一節將說明如何讀取您自己的實際數據。
請同時閱讀前兩行數據。在無人使用的對話中,規則檔案的成本為 2,500 個 token。在同樣的對話中,技能的成本為 40 個 token,而在十分之一會觸發該技能的對話中,成本則為 3,000 個 token。最後兩行是同一個 server 在開啟與關閉工具搜尋時的對比:分別為 500 與 4,500 個 token。這個差距正是關於 MCP Context 膨脹的舊建議依然流傳的原因。
工具搜尋需要支援 tool_reference 區塊的模型,截至 2026 年 8 月,這意味著 Claude Sonnet 4.5、Haiku 4.5、Opus 4.5 及後續版本。當 ANTHROPIC_BASE_URL 指向非第一方(first party)主機時,Claude Code 會關閉此功能,因為大多數代理伺服器不會轉發這些區塊。請設定 ENABLE_TOOL_SEARCH 來控制此行為:false 會預先載入所有 schema,true 會延遲載入所有 schema,而 auto 則僅在 schema 大小符合 Context 視窗 10% 以內時才預先載入。
# Load schemas up front only if they fit in 5% of the window
ENABLE_TOOL_SEARCH=auto:5 claude關鍵問題:資料會在不同執行間變動嗎?
請先確認這一點,因為這能直接排除其中一個選項。如果代理程式(agent)需要讀取或寫入可能在下次檢查時發生變動的內容,你就需要一台伺服器。例如問題追蹤系統、資料庫、監控儀表板,或是你自有的內部 API(應用程式介面)。將資料寫下來並無幫助,因為一旦有人編輯了記錄,你寫下的內容隨即過時。
如果這份資料在六週後無人維護,其內容依然正確,那麼你需要的是一項技能(skill)。例如發布檢查清單、遷移程序、錯誤回應的格式,或是此儲存庫對測試撰寫的要求。技能就是 git 中的一個檔案。它沒有連接埠、沒有處理程序,也不會有除了「內容錯誤」以外的失敗模式,而內容錯誤可以透過程式碼審查(code review)來修正。
如果這是一個必須適用於你尚未規劃之工作的單一事實,請將其放入規則檔案(rules file)中。Run make lint before committing. Never push to main. Handlers live in src/api/handlers/. 每項規則佔一行。一旦條目發展成多個步驟,它就不再是事實,而是程序,此時應將其移至技能中。
何時使用規則檔案即已足夠
規則檔案會從多個位置載入,優先順序由廣泛至特定:受管理的原則檔案、您的個人 ~/.claude/CLAUDE.md、專案的 ./CLAUDE.md 或 ./.claude/CLAUDE.md,以及被 git 忽略的 ./CLAUDE.local.md。所有偵測到的檔案會進行串接而非相互覆蓋,且越靠近您工作目錄的檔案會越晚被讀取。
Claude Code 會讀取 CLAUDE.md,而非 AGENTS.md。若您的儲存庫已為其他工具維護了 AGENTS.md,請勿維護兩份會導致內容分歧的副本。
ln -s AGENTS.md CLAUDE.md符號連結在成功時不會輸出任何訊息。請啟動工作階段,執行 /context,並確認 CLAUDE.md 出現在 Memory files 下方。若該檔案未列於其中,表示代理程式未曾讀取過該檔案,任何文字調整皆無濟於事。若您同時需要 Claude 專用的規則,請改用匯入格式,並將其置於匯入語句下方。
@AGENTS.md
## Claude Code
Use plan mode for changes under `src/billing/`.此處有一個陷阱。@path 匯入不會儲存上下文。匯入的檔案會在啟動時與參照它的檔案一併展開並載入,最多支援四層深度。將 600 行的規則檔案拆分為六個匯入檔案,雖有助於人類閱讀,但對 Token 成本完全沒有影響。在決定配置方式前,建議閱讀 AGENTS.md 及其對應人類閱讀版本背後的慣例。
真正能降低成本的是帶有 paths 欄位的 .claude/rules/。帶有 paths 前置內容(frontmatter)的規則檔案,僅會在代理程式存取符合該模式的檔案時載入。
---
paths:
- "src/api/**/*.ts"
---
# API rules
- Every endpoint validates its input.
- Use the standard error response shape.沒有 paths 欄位的規則會在啟動時載入,其優先順序與 .claude/CLAUDE.md 相同。因此,建議的工作模式是:將簡短且無條件的規則放在一起,並針對僅在特定目錄內有效的規則使用 paths 清單。
當您需要技能時
技能是一個包含 SKILL.md 的目錄。個人技能位於 ~/.claude/skills/<name>/SKILL.md,適用於您機器上的所有專案。專案技能位於 .claude/skills/<name>/SKILL.md,會隨儲存庫一同移動,且能像其他檔案一樣透過 pull request 進行審查。
mkdir -p ~/.claude/skills/summarize-changes---
name: summarize-changes
description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---
Run `git status` and `git diff` against the merge base.
Group the changes by intent, not by file.
Call out anything touching auth, migrations or deletions.description 是該檔案中唯一在技能執行前處於上下文的部分,因此它具有雙重功能。它說明了技能的用途,並定義了何時應呼叫該技能。若描述僅寫「協助部署」,模型將無法根據請求進行匹配,導致技能靜默失效,讓您誤以為技能無法運作。
目錄名稱即為指令,因此上述範例會產生 /summarize-changes。在個人或專案技能中,frontmatter 的 name 僅用於設定列表中的顯示標籤。
一旦技能被呼叫,其渲染後的內容會以單一訊息進入對話,並在該對話的剩餘期間持續存在。Claude Code 不會在後續的回合中重新讀取該檔案。請撰寫常駐指令而非一次性步驟,並保持內容精簡,因為從該點開始,每一行內容都會成為後續每次請求的持續成本。在自動壓縮後,Claude Code 會重新附加每個技能最近一次的呼叫內容,並在 25,000 token 的總預算內,保留每個技能前 5,000 token 的內容。若在單次對話中呼叫多個大型技能,最舊的技能將會被完全移除,這就是為什麼技能在長時間對話後可能會失效的原因。再次呼叫即可恢復。當相同的程序適用於多個程式碼庫時,請 在多個儲存庫間共用同一個技能,而非複製檔案。
何時需要 MCP 伺服器
新增伺服器僅需執行單一指令,其運作形式取決於傳輸方式。
# Remote HTTP server
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Remote HTTP server behind a bearer token
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
# Local stdio server: everything after -- is passed through untouched
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-server-- 至關重要。對於 stdio 伺服器,它能區隔 Claude Code 自身的選項與啟動伺服器的指令。若省略此參數,原本屬於伺服器的 --port 8080 會被誤判為 claude mcp add 的選項,進而導致解析失敗。
claude mcp list
claude mcp get notionclaude mcp add 會以 Added ... 行確認,這僅代表設定已寫入磁碟。claude mcp list 才是驗證狀態的正確指令,它會列出每個伺服器的健康狀態:✔ Connected、! Needs authentication 或 ✘ Failed to connect。若顯示失敗狀態,代表 Claude Code 無法連接該伺服器,而非列出指令本身故障。在工作階段中,/mcp 可提供相同的伺服器檢視資訊,並包含工具數量。
每次對 MCP 伺服器的呼叫皆為獨立運作並攜帶所需資訊,這正是 MCP 伺服器不會記憶先前請求的原因。這是一項設計選擇,但也帶來了後續影響:任何需要保留的狀態都必須儲存在伺服器後端,例如資料庫或檔案中,而這些資源現在由您負責維護。
MCP 伺服器是一個必須執行的處理程序
這是廠商比較中忽略的成本。Skill 是一個檔案,而 MCP 伺服器是執行在某處的軟體;當該處是您的 VPS (virtual private server) 時,您必須負責其運作時間。
stdio 伺服器屬於低成本案例。Claude Code 會在工作階段開始時將其作為子處理程序啟動,並在工作階段結束時將其終止。無需監控,也無需依據獨立排程進行修補。遠端 HTTP 伺服器則屬於長駐服務,它需要任何長駐服務所具備的維護條件。
[Unit]
Description=Notes MCP server
After=network-online.target
Wants=network-online.target
[Service]
User=mcp
WorkingDirectory=/srv/notes-mcp
ExecStart=/usr/bin/node /srv/notes-mcp/dist/server.js
Environment=PORT=8931
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now notes-mcp
systemctl is-active notes-mcp
journalctl -u notes-mcp -n 50 --no-pagersystemctl is-active 應輸出 active。若輸出 failed,日誌中即包含原因;初次執行時,通常是因為遺漏環境變數,或是連接埠已被其他程式佔用。Restart=on-failure 在此並非選項,因為崩潰的 MCP 伺服器不會主動通知。您通常是在 Agent 告知無法讀取您的問題追蹤系統時才會發現。
將處理程序綁定至 127.0.0.1,並在其前方部署具備 TLS (transport layer security) 的反向代理。若 MCP 伺服器可存取您的資料庫,且在未經身份驗證的情況下於公開連接埠回應,等於您已將資料庫公開。在 VPS 上執行 MCP 伺服器 一文詳細說明了代理、憑證與防火牆的設定方式。
接著請誠實評估後續的維護工作。該服務有其獨立的安全性更新排程,與呼叫它的 Agent 無關。當 OAuth token 過期,claude mcp list 就會在不合時宜的時刻開始輸出 ! Needs authentication。其憑證存放於設定檔或 Authorization 標頭中,因此需要與其他機密資訊同等對待,這本身就是一個龐大的課題:避免 AI Agent 存取機密資訊。這些維護工作對於 Skill 而言皆不存在。
在建置前,請權衡上述替代方案。若伺服器背後的資料每季才變動一次,那麼編寫一個告知 Agent 搜尋位置與欄位定義的 Skill,其成本遠低於一個您必須持續維護的服務。
如何衡量您的 Context 成本
停止估算,直接在工作階段中執行 /context。它會列出啟動時的詳細分析:系統提示詞、記憶體檔案、工具以及 MCP 伺服器,並顯示各項的 Token 權重。
請檢查兩件事。在 Memory files 下方,確認您預期的每個規則檔案皆已列出。若檔案遺失,Agent 將無法讀取,因此當指令被忽略時,請優先排除此問題。接著查看伺服器的成本。若某個每月僅使用兩次的伺服器在清單中佔據極大比例,請在 /mcp 中將其關閉,並僅在需要的工作階段中重新開啟。無論設定為何,配置都會被保留。
遠端伺服器也可能回報 cached 2h ago · connects on first use · 5 tools 狀態。這代表 Claude Code 是讀取先前工作階段的工具清單,而非在啟動時進行連線,它會在首次呼叫工具時才進行連線。由於工具從您的第一則訊息起即為可用,因此無需進行任何修正。若您希望每個伺服器都在啟動時連線,請設定 MCP_DISCOVERY_CACHE=0。若需更全面的了解,管理 Claude Code Context 視窗 涵蓋了哪些內容會在壓縮後保留,而 這些 Token 的實際成本 則會將數值轉換為金錢。
為什麼我的技能無法觸發?
常見原因是 description 設定錯誤。這是技能執行前上下文中唯一的文字,若其未涵蓋當前情境,則無法觸發任何匹配。請將觸發條件寫入該語句,例如:「當使用者詢問變更內容、需要提交訊息或要求檢視差異時使用」。模糊的描述會導致靜默失敗,使問題難以察覺。
第二個原因是 frontmatter 拼字錯誤,這類錯誤會產生明顯提示。未知的鍵值會直接被拒絕:
Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, name第三個原因是位置問題。專案技能會從工作目錄及其往上至儲存庫根目錄的所有父目錄中的 .claude/skills/ 載入。位於啟動路徑「下方」巢狀目錄中的技能,在啟動時不會被載入。這些技能要等到代理程式首次讀取或編輯該子目錄內的檔案時才會載入;在此之前,它們不會出現在自動完成清單中,也無法透過名稱呼叫。
MCP 對應此類靜默失敗的情況,是 .mcp.json 項目中包含 url 但缺少 type。Claude Code 會將任何沒有 type 的項目視為 stdio 伺服器,因此會跳過該項目並回報:
MCP server "notes" has a "url" but no "type"; add "type": "http" (or "sse" / "ws") to this entry同時使用這三種機制
這些機制並非互斥。一套有效的架構會在各自最合適的環節運用它們。rules 檔案僅包含少數適用於所有情境的通用規則。Skills 則封裝具體程序,且僅在適用時載入。MCP server(通常為一個,偶爾為兩個)負責連接那些內容無法預測的系統。若您仍在建構對前者的認知模型,agent skill 的實際定義 一文詳細說明了其格式。
一項測試即可解決大多數關於歸屬權的爭議:刪除該項目,啟動一個全新的 session,並將任務交給 agent。如果 agent 只是執行速度變慢,則它屬於 skill;如果 agent 表現出自信但錯誤的結果,則它屬於 rules 檔案;如果 agent 完全無法取得資訊,則您需要一個 server,且現在還需要一套維護該 server 運作的計畫。
FAQ
我應該撰寫 skill 還是架設 MCP server?
請根據資訊在兩次呼叫間是否會變動來決定。若 Agent 必須讀取他人可隨時編輯的即時狀態(例如問題追蹤系統、資料庫或儀表板),則需要 MCP server,因為一旦記錄變更,您寫下的任何內容都會立即過期。若您寫下的答案在六週後依然正確,請撰寫 skill。Skill 只是 git 中的一個檔案,無需執行程序、無需開啟連接埠,也無需維護修補程式,因此只要可行,它就是成本較低的選擇。
MCP server 是否仍會佔用我的 context window?
比過去少得多。目前的 Claude Code 預設啟用工具搜尋功能,因此啟動工作階段時僅會載入工具名稱與 server 的 instructions 欄位,完整的 schema 則在 Claude 搜尋時才會擷取。若關閉工具搜尋,則仍會發生預先載入:例如使用 ENABLE_TOOL_SEARCH=false、將 ANTHROPIC_BASE_URL 指向非官方代理伺服器,或使用早於 Claude 4.5 世代的模型時。執行 /context 可查看您目前的狀態,因為舊版比較文章中的數據皆假設為預先載入。
Claude Code 會讀取 AGENTS.md 嗎?
不會。Claude Code 會讀取 CLAUDE.md。若您的儲存庫已為其他 Agent 準備了 AGENTS.md,請將其中一個指向另一個,避免維護兩份副本。執行 ln -s AGENTS.md CLAUDE.md 建立簡單的符號連結,或在 CLAUDE.md 的第一行寫入 @AGENTS.md,並在下方加入 Claude 專屬的指令。接著啟動工作階段並執行 /context,確認 CLAUDE.md 出現在 Memory files 下方。
為什麼我的 skill 在工作階段中途失效?
通常是因為自動壓縮(auto-compaction)所致。當對話進行摘要時,Claude Code 會重新附加每個 skill 最近一次的呼叫內容,保留每個 skill 前 5,000 個 token,總計上限為 25,000 個 token。系統會從最近呼叫的 skill 開始填滿此額度,因此若您呼叫了多個大型 skill,較舊的 skill 就會被完全移除。再次呼叫該 skill 即可恢復其完整內容。
如何避免長篇規則檔案在每個工作階段都載入?
將僅在特定情況下才需要的內容移至 .claude/rules/ 檔案,並在 frontmatter 中加入 paths 欄位,這樣只有當 Agent 觸及相符檔案時才會載入。將檔案拆分為 @path 匯入並無幫助,因為匯入的檔案會在啟動時與參照它的檔案一併展開並載入。任何屬於多步驟程序而非既定事實的內容,都應改為 skill,因為 skill 本體在被呼叫前不會佔用任何成本。