UrsaKit 封面,比較 MCP server 與純 HTTP API 這兩種讓 AI agent 存取同一個後端的方式

MCP server 和 API 很容易混在一起,因為同一個後端通常同時躲在兩者背後。API 是你的程式呼叫的契約;MCP server 是第二份契約,用 JSON-RPC 寫成,存在的目的是讓 AI host 能發現並叫用那個後端,而不必為每個模型各寫一套整合。

Model Context Protocol 在 2026 年仍然重要,但多數博客文章描述的是已經不存在的協定。2026-07-28 版拿掉了連線層級的握手、把 sampling 與 roots 列為 deprecated,並改成每個請求各自帶上版本與能力。這篇對照現行規格,比較 MCP server 與單純的 API,並說明這層包裝在哪裡值回票價。

01兩邊實際上各是什麼

REST API 是兩個程式之間的契約。你知道呼叫方是誰、client 由你寫,契約一動就有編譯期或測試期的回饋。形狀很固定:HTTP 方法、路徑、標頭、body 與狀態碼。

MCP server 是一個透過 Model Context Protocol 把 context 與能力暴露給 AI host 的程式。規格 定義三種角色:host 是 LLM 應用程式,client 是 host 裡的連接器,server 是提供 context 的程式。host 對每個 server 開一個 client,所以一個 coding assistant 可以同時跟檔案系統 server、資料庫 server 與第三方 SaaS server 對話。

真正改變一切的是「誰選了這次呼叫」。在 API 整合裡,呼叫點是你審過的程式碼。在 MCP 裡,是模型從清單中挑一個工具並填參數,所以當呼叫方會犯錯、會好奇、甚至帶有敵意時,server 也必須是安全的。

API 呼叫      :你的程式      -> 固定端點 -> 有型別的結果
MCP 工具呼叫  :模型自己挑    -> tools/call -> content[] + structuredContent

02MCP 在 API 之上加了什麼

MCP 標準化了四件原本每個整合者各自處理的事:

  • 探索。 宣告 tools 能力 的 server 必須用 tools/list 回答目前可用的工具。每一筆帶著名稱、描述與 inputSchema,所以 host 可以把最新工具清單交給模型,不必重新部署。
  • 代理決策。 模型可以在執行時挑工具與參數,當用戶請求很開放、你無法事先列舉所有路徑時,這正是你要的。
  • 每個 server 共用一個 client。 host 只要實作一次協定。之後新的整合等於新的 server,而不是每個廠商一套 SDK 與授權流程。
  • 同意介面。 規格要求應該永遠有人在循環裡、能拒絕工具呼叫,並要求 host 顯示暴露了哪些工具、什麼時候執行。

工具清單是一次很小的 JSON-RPC 請求與回應:

{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} }
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "search_orders",
        "description": "Search orders by status for the signed-in customer",
        "inputSchema": {
          "type": "object",
          "properties": { "status": { "type": "string", "enum": ["open", "shipped", "cancelled"] } },
          "required": ["status"]
        }
      }
    ]
  }
}

那個區塊裡的每一行都是 prompt 文字。名稱、描述與 schema 是給模型讀的,不是給編譯器讀的,所以工具設計更像在寫文件,而不是在寫 SDK。

03API 仍然做得更好的地方

MCP 是 facade,所以 API 靠著「呼叫方是確定的」所得到的好處全都還在:

面向純 APIMCP server
呼叫方你寫的程式可能挑錯工具的模型
契約檢查編譯器、型別、契約測試JSON Schema,執行時才檢查
批次作業分頁、批次端點、串流每次決策一個工具呼叫,或另寫工具
緩存標準 HTTP 語意每個工具的 TTL metadata,沒有通用緩存層
授權HTTP 堆疊原本就有的額外疊上 MCP 授權規格
除錯請求日誌與 trace日誌,外加 prompt 與工具選擇的脈絡

有兩項成本值得特別講。第一是 context。你暴露的每個工具都是 schema 與描述文字,會和用戶真正的問題搶同一個 context window,這也正是有人做出「過濾模型看到什麼」、把 context 消耗降低的 MCP server 的原因。第二是失敗模式。API 出錯是 bug;模型挑錯工具而出錯,是你必須事先設計的行為。

04什麼時候該用 MCP server

情境更好的選擇
你自己的服務呼叫自己的服務純 API,有型別的 client
多個 AI host 需要同一個後端MCP server,一個後端一個
模型必須在許多操作中挑一個用 MCP 工具,schema 收窄
大量批次傳輸純 API,不要放進工具介面
本機檔案、git、CLI 工具走 stdio 的本機 MCP server
共用的第三方服務加上授權流程的遠端 MCP server

判斷原則很簡單:模型需要做決定時才加 MCP,程式已經知道要做什麼的地方就留著純 API。把整份 API 一對一包成工具,是讓 agent 變慢、變貴、又更容易搞混的最常見做法。

05不改寫既有 API 也能包成 MCP

多數情況不需要新的後端。一層薄薄的 MCP server 負責把一次工具呼叫翻成一次 API 請求:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": { "name": "search_orders", "arguments": { "status": "shipped" } }
}

這次呼叫對應到單一 REST 請求:

GET /api/orders?status=shipped
Authorization: Bearer <已登入用戶的 token>

回應會回傳 content 區塊,任何機器可讀的值放進 structuredContent:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{ "type": "text", "text": "找到 3 筆已出貨訂單。" }],
    "structuredContent": { "orders": [ { "id": "A-1043", "status": "shipped" } ] },
    "isError": false
  }
}

三條實作原則能讓這層包裝保持薄:

出貨前,先用 JSON 驗證工具 把這個請求與回應跑過一遍,確認兩個形狀都解析得過。

  1. 工具名稱與 schema 保持穩定。 它們是模型讀的契約,所以就算 API 沒動,改欄位名稱也是破壞性變更。
  2. 把呼叫方的憑證帶著走,並且收斂範圍。 server 回傳的工具可能依請求帶的授權而不同,所以 scope 較少的 token 會看到較小的工具清單,而不是看到一份它其實無權使用的清單。
  3. 回傳模型能據以行動的錯誤。 參數不合法時要回 isError 結果並附上清楚訊息,而不是默默回一個空清單。

06傳輸方式決定部署模式

MCP 把「訊息代表什麼」和「訊息怎麼走」分開。規格 定義兩種標準綁定:

  • stdio 在 client 啟動的子程序標準串流上,用換行分幀傳 JSON-RPC。它通常服務單一 client,適合檔案系統這類本機工具。
  • Streamable HTTP 把每個訊息以 HTTP POST 送到單一 MCP 端點,回應會是一個 JSON 物件,或一條與該請求綁定的伺服器推送事件串流。它同時服務多個 client,正是共用遠端 server 需要的形式。

較舊的 HTTP+SSE 傳輸已被標為 deprecated,改用 Streamable HTTP。遠端 server 也一併繼承以 OAuth 2.1 為基礎的 MCP 授權規格,所以選了 HTTP 並不代表可以跳過授權設計。

最後一個傳輸細節:metadata 現在放在訊息 body 裡。每個請求都在 _meta 欄位帶上協定版本與 client 能力,而 Streamable HTTP 綁定可以把部分欄位映到標頭,方便中介層處理。body 仍然是唯一的事實來源。

07安全模型變了

API 會受到的攻擊來自能連上它網絡的人。MCP server 受到的攻擊,除了那些人,還多了一批能影響模型在呼叫工具前所讀文字的人。MCP 安全指引 把這些失敗模式寫得很清楚,值得在推出遠端 server 之前讀一遍:

風險它利用什麼對策
Confused deputy代理 server 同時使用靜態 client ID、動態 client 註冊與同意 cookie,讓惡意 client 拿到授權碼代理 server 必須實作逐 client 同意
Token passthroughserver 接受了不是發給它的 token驗證 token 的受眾就是你這個 server
SSRFserver 去抓 client 提供的 URL白名單目的地,封鎖內部位址
State handle hijacking資源與工具 handle 被跨 session 重用或猜中把 handle 綁定到建立它的 client
本機 server 被入侵走 stdio 的 server 以你的用戶權限執行,你讀得到的它都讀得到用最小權限執行,並鎖定版本

規格自己的原則講得很直白:用戶必須明確同意資料存取與操作,host 未經同意不得把用戶資料轉給 server,而工具描述除非來自可信任的 server,否則都該視為不可信輸入。這些不是口號,而是「展示品」與「撐得住惡意文件」之間的差別。

工具描述是別人寫的 prompt 文字。

MCP 要求實作者把工具描述當成不可信輸入,因為被入侵或惡意的 server 可以用它來操縱模型。審查第三方 server 要像審查依賴套件,而不是像審查一個 REST 端點。

08版本更迭是常態

MCP 的版本用日期標記,不是編號。撰稿當下最新的是 2026-07-28,前一個被廣泛部署的版本是 2025-06-18。2026-07-28 版對照著博客文章實作的人來說是破壞性變更:

  • initialize 握手沒了。每個請求自己宣告協定版本與 client 能力,server 逐筆獨立接受或拒絕。請求一個 server 不支援的版本會回傳 UnsupportedProtocolVersionError 並附上支援清單。
  • roots、sampling、logging 與 dynamic client registration 自 2026-07-28 起列為 deprecated,最快可從下一個版本之後移除。
  • server 不再發起 JSON-RPC 請求,client 也不再送 JSON-RPC 回應。這一條規則就把 sampling 式的遞迴從核心協定裡拿掉。

如果某份整合指南叫你開一個有狀態的 session,然後協商一次能力,那是寫給舊版規格的。把你 server 實作的版本鎖住,並且在版本不合時回報支援清單,而不是含糊地失敗。

09常見錯誤

錯誤為什麼有害修正
把每個 REST 端點都映成一個工具context 膨脹,幾乎一樣的工具讓模型混淆只暴露少數「決策形狀」的工具
把工具描述當文件寫模型會把描述當指令讀當契約寫,並當不可信輸入對待
相信模型給的參數被劫持的模型可以送任何值行動前先用 inputSchema 驗證
繼續用舊版握手2026-07-28 的 client 不會照你預期協商每個請求宣告版本與能力
代理 server 跳過逐 client 同意confused deputy 把 token 交給攻擊者依 client ID 與用戶儲存同意
用你的用戶身分跑本機 server你讀得到的檔案它都讀得到收斂它的檔案系統與網絡存取

schema 有變動時,先用 diff 比對工具 把新舊兩版並排看過,再讓模型看到新契約;底層 REST 的狀態碼則用 HTTP 狀態碼對照表 確認沒說錯。

10資料來源

常見問題

MCP server 會取代我的 API 嗎?

不會,它是 API 前面的一層 facade。MCP server 仍然呼叫你的 HTTP 端點,只是把它們包成帶 JSON Schema 的工具,讓 AI host 能發現並叫用。

MCP 用什麼協定?

MCP 使用 JSON-RPC 2.0 訊息。請求、回應與通知都遵循 JSON-RPC 的格式,stdio 與 Streamable HTTP 這類傳輸綁定則定義這些訊息怎麼分幀與傳遞。

MCP 還需要 initialize 握手嗎?

2026-07-28 版不需要。現在每個請求都在 _meta 欄位裡帶上自己的協定版本與 client 能力,server 逐筆獨立接受或拒絕。initialize 握手屬於更早的舊版規格。

MCP 工具和 REST 端點差在哪?

REST 端點是你的程式呼叫的固定契約。MCP 工具則是一份 JSON Schema 加一段描述,讓模型自行選擇要不要呼叫,所以工具名稱與描述會變成 prompt 的一部分,模型也可能挑錯。

MCP server 該跑在本機還是遠端?

本機 server 使用 stdio 傳輸,由 host 以子程序啟動,適合檔案系統與 CLI 存取。遠端 server 使用 Streamable HTTP,同時服務多個 client,適合共用服務,但必須加上 MCP 授權流程。

MCP server 比 API 不安全嗎?

它是不同的安全模型,不是自動比較弱。MCP 規格要求用戶明確同意、提醒工具描述是不可信輸入,並把 confused deputy、token passthrough、SSRF 與 handle hijacking 列為實作必須處理的風險。

什麼時候 MCP server 是多餘的?

當兩端都由你控制、呼叫方是你自己的程式時。有型別的 REST client 比模型驅動的工具呼叫更便宜、更快、也更好測試,所以留著 API,只在模型真的需要自己選呼叫時才加上 MCP。

返回文章列表

相關文章

相關工具