sequenceDiagram
participant U as 👤 使用者
participant C as 🖥️ MCP Client<br/>(Claude Desktop)
participant L as 🧠 LLM
participant S as 🔌 MCP Server
participant B as 🗄️ 你的服務<br/>(訂單系統)
C->>S: 啟動時:你有哪些工具?
S-->>C: 回一份 JSON schema
U->>C: 「A001 訂單狀態?」
C->>L: 訊息 + 可用工具清單
L-->>C: 決定呼叫 get_order_status("A001")
C->>S: 呼叫該函式
S->>B: 查資料庫 / 打 API
B-->>S: 「已出貨」
S-->>C: 「已出貨」
C->>L: 這是結果
L-->>U: 「訂單 A001 目前已出貨」
MCP 是什麼?跟 API 差在哪?寫一個能查訂單的 server 走一次流程
假設你想給 AI 助理一個能力:問「A001 這筆訂單狀態?」,AI 會自己去公司系統查、然後用人話回你。
過去要做這件事,你得寫一段串接程式,還要在 prompt(提示語,就是你打給 AI 的那段話)裡教 AI「要查訂單就打這個網址、參數名稱是 order_id、查詢值像 A001、拿到的 JSON 要挑第幾層」。每加一個工具,就多一段教學。
MCP(Model Context Protocol,模型上下文協定) 想解決的就是這件事:把「怎麼用工具」這件事從工程師手工教,變成 AI 自己看得懂。這篇會先講 MCP 想解決什麼、跟 API(Application Programming Interface,程式之間互相呼叫的介面)差在哪,然後動手做一個最小可跑的 MCP server。
為什麼要有 MCP?API 一個人做不到?
API 是為「程式對程式」設計的:
- 你先讀文件,知道 endpoint(端點:一個 API 對外開放的網址)長什麼樣
- 你先知道 payload(傳給 API 的資料本體)要放什麼欄位
- 兩邊都清楚彼此的規格,才通得起來
這對傳統軟體很剛好。但 LLM(大型語言模型)進場後,需求變了:
- 一個任務可能要串好幾支 API(先查訂單、再看物流、再回信)
- AI 要看得懂非結構化的東西(使用者的口語提問)
- AI 可能要自己決定要用哪支工具,而不是工程師寫死
API 沒有告訴 AI「這裡有什麼可以用」的機制。所以現在的作法是:工程師把工具說明塞在 prompt 裡,一次一次教 AI「要做 X 就呼叫 Y」。工具愈多,prompt 愈長,也愈容易漏教。
兩個比喻先建立畫面
比喻一:USB-C 之於充電線
- USB-C 統一前,Apple 一種頭、Samsung 一種頭、Nokia 又一種
- 你出門要帶三條線、每支新手機都要重新買
- USB-C 統一後,一條線通吃手機、平板、筆電、耳機
- 插上去,兩邊會自己協商要多少電、要傳資料還是充電
MCP 想做的:讓「AI ↔︎ 各種工具」變成 USB-C 那樣,插上去就通。
比喻二:新員工到公司
- API 的世界:第一天到職拿到 100 頁手冊 —— 請假打分機 2345 填表 A、報帳找財務用系統 B、買文具編號 007…你全部背起來才能做事
- MCP 的世界:桌上有一塊螢幕,自動列出「這裡能辦這些事」,每一項底下都寫清楚要給什麼資訊、會回什麼。你直接說「我要請假三天」,系統自己接到對的窗口
MCP 的兩個角色
MCP 不是取代 API,而是在 API 之上加一層翻譯。你的後端還是靠 API 運作,MCP server 只是把 API 包成 AI 看得懂的形式。
- MCP server:貼在你的服務旁邊的小程式,負責兩件事 ——「講清楚我能做什麼」+「接到指令後真的去做」
- MCP client:像 Claude Desktop、Cursor、你自己寫的 agent(代理程式,會替使用者自主完成任務的 AI)這種能連上 server 的 LLM 前端
你要「做 MCP」,通常就是寫一個 server,讓 client 連進來用。
一次完整的呼叫流程長這樣:
關鍵動作在第 2 步:Client 一啟動就問 server「你有什麼工具?」server 回一份 JSON schema(描述 JSON 資料結構的規格),內容包含每個工具的名字、參數、說明。這份 schema 就是 AI 的「說明書」。
動手寫一個最小可跑的 server
用 Anthropic 官方的 Python SDK(Software Development Kit,軟體開發套件),先裝套件:
pip install mcp新開一個檔案 order_server.py:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("order-service")
@mcp.tool()
def get_order_status(order_id: str) -> str:
"""查詢訂單狀態。傳入訂單編號,回傳目前的狀態。"""
# 這裡實際上會打公司內部 API 或資料庫
fake_db = {"A001": "已出貨", "A002": "備貨中"}
return fake_db.get(order_id, "找不到這筆訂單")
@mcp.tool()
def cancel_order(order_id: str, reason: str) -> str:
"""取消訂單。需要提供訂單編號和取消原因。"""
return f"訂單 {order_id} 已取消,原因:{reason}"
if __name__ == "__main__":
mcp.run()這幾行做了什麼:
FastMCP("order-service")建立一個 server,"order-service"是這個 server 的名字@mcp.tool()是 decorator(裝飾器:Python 用@標記函式的語法),把下面這支函式登記成「AI 可以用的工具」- 函式的參數名稱、型別、docstring(那段三引號的說明文字)會自動變成給 AI 看的 metadata(描述資料的資料,這裡就是工具的說明書)
mcp.run()啟動 server,等 client 連進來
你完全不用寫「AI 該怎麼呼叫我」的說明。docstring 和型別本身就是說明。
掛到 Claude Desktop 測試
Windows 打開這個檔(找不到就手動建立):
%APPDATA%\Claude\claude_desktop_config.json
加上:
{
"mcpServers": {
"order-service": {
"command": "python",
"args": ["D:/path/to/order_server.py"]
}
}
}重開 Claude Desktop,就能在對話裡直接問「A001 這筆訂單狀態?」—— Claude 會自己發現 get_order_status 和 cancel_order 這兩個工具、自己決定要呼叫哪一個、拿到結果後用人話回你。
中間發生了什麼(把上面那張流程圖走一次)
- Claude Desktop 啟動時,把你設定的
python order_server.py拉起來 - 兩邊透過 stdio(standard input/output,標準輸入輸出:程式跟外界溝通最基本的一種管道)講好協定
- Client 問 server:「你有哪些工具?」server 回一份 JSON schema
- 你打「A001 狀態?」給 Claude,Claude 看到「哦,有
get_order_status(order_id: str)可以用」 - Claude 自己填好參數
order_id="A001",透過 client 呼叫 server - Server 執行你寫的那支函式,拿到
"已出貨",回傳給 client - 結果餵回 Claude,Claude 用自然語言回你:「訂單 A001 目前狀態是已出貨」
你要寫的只有第 6 步的實作(函式本身)。前後那些協定、schema、路由,SDK 都處理掉了。
三種常見的實作路線
| 路線 | 適合什麼 | 怎麼跑 |
|---|---|---|
| 本機 stdio server | 自己電腦要用的(讀本機檔案、跑本地 script) | mcp.run() 預設就是 stdio |
| 遠端 HTTP server | 給團隊或別家公司連的(像 SaaS —— Software as a Service,網路上直接用的雲端服務) | mcp.run(transport="streamable-http") |
| 包裝現有 API | 已經有一堆 REST API(一種按 URL 路徑組織端點的常見 API 設計風格),想讓 AI 也能用 | 寫一層 MCP server 當翻譯者,每支 API 包成一個 tool |
第三種是實務上最常出現的做法 —— 你不用把後端重寫,只在中間加一層 MCP 翻譯層,把「原本給程式呼叫的 API」再包一層變成「AI 看得懂的工具」。
除了 tool 還有什麼
Tool 只是 MCP 的其中一種能力,還有兩種也常用:
- Resources:像檔案、文件、資料庫查詢結果 —— AI 可以「讀取」的東西。Tool 是動作、Resource 是資料
- Prompts:預先寫好的提示範本,使用者可以在 client 裡像選單那樣叫出來套用
三個加起來就是 MCP 的完整能力面。實務上從 tool 開始最直接,因為它對應到「AI 幫我做事」這件事,最有感。
目前踩得到的坑
- 權限沒設好:MCP server 拿到什麼權限,AI 就能做什麼。要清楚哪些 tool 是唯讀(查詢、列表)、哪些是會改東西(取消、刪除、寄信)。可以在 client 端設「執行前要人工確認」
- debug 麻煩:server 是 client 拉起來的子行程,錯誤訊息不會直接跑到你的終端機。Claude Desktop 有 log 目錄可以看
- 版本協調:SDK 還在快速演進,
pip install mcp之後 API 有可能微幅變動,遇到 example 跑不動時先看版本
從 API 到 MCP,工程師的位置變了
以前你要寫的是:「AI 該怎麼用我的工具」的教學(塞在 prompt 裡)。 現在你要寫的是:「我的工具能做什麼」的描述(寫在 server 的函式簽名和 docstring)。
前者是判斷「什麼時候做什麼」,那部分現在交給 LLM 自己推理。後者是「我這裡有什麼」,這是你的責任。
兩件事沒有誰取代誰的關係,只是分工線挪了 —— 你寫好一次 MCP server,之後任何相容的 client(Claude、Cursor、自寫的 agent)都能用。同一個「訂單查詢」的能力,不用再為每個 AI 客戶端各接一次。
小結
MCP 是一層放在 API 之上、給模型用的協定。你不用把後端重寫,只要多寫一層 server 描述「有哪些工具、怎麼用」,AI 就能自己發現、自己呼叫。
想試的話最快的路徑:
pip install mcp把上面那段 order_server.py 抄過去,改成自己的函式,掛到 Claude Desktop,5 分鐘可以跑起來第一版。之後不管要接內部系統、還是要包一層對外的 SaaS,都是同一套骨架。
延伸閱讀:官方文件 modelcontextprotocol.io、Anthropic Python SDK 的 github.com/modelcontextprotocol/python-sdk