MCP(Model Context Protocol) 的理解和快速實踐 精華
一、背景
此前筆者對 AI Agent 研究的涉獵比較少,也基本沒有系統(tǒng)介紹過與 Agent 相關的內容。然而,最近由 Anthropic 提出的 MCP(Model Context Protocol [1],模型上下文協(xié)議)在社區(qū)中引發(fā)廣泛關注,筆者也趁此機會“蹭蹭熱度”,了解下 MCP 到底是什么,了解一下 MCP 的基本概念和工作機制。
在最初接觸 MCP 時,也曾對其一些設計感到困惑。于是帶著這些疑問進行了進一步的調研,逐漸對 MCP 的組成及運作方式有了初步的認識,比如:
- MCP 中的 Resource、Prompt、Tool、Sampling、Root 是什么,有什么用。
- 誰來決定是否調用 Client。
- 如何判斷調用哪些 Client。
- Client 和 Server 之間如何傳輸,協(xié)議是什么。
- 怎么使用 Prompt。
本文將嘗試基于這些問題,對 MCP 進行一番介紹和解析。
二、MCP 架構
2.1 引言
Anthropic 的 MCP 是一種開放標準協(xié)議,旨在簡化 Agent/LLM 與外部數(shù)據(jù)源和工具之間的集成過程。它提供了一種統(tǒng)一的方式,使 AI 模型能夠高效、安全地訪問和利用各種資源。
如下圖所示,可以將 MCP 理解為一個 “AI 的 USB 接口”,提供了一個連接標準,使 Agent/LLM(如 Claude、ChatGPT、Qwen)能夠方便、安全的訪問各種外部工具和數(shù)據(jù)(比如 Gmai、Slack、本地文件等):
- 傳統(tǒng)方式的問題:每個服務(Gmail、Slack、Calendar)都有自己獨特的 API,每一個 Agent(LLM)都需要各自去適配。如果有 M 個 Agent、N 個服務,則相應的復雜度為 M x N。
- MCP 的優(yōu)勢:MCP 對各個服務的接口進行了統(tǒng)一,這樣 M 個 Agent 可以直接使用這 N 個服務,大幅降低重復開發(fā)和適配的成本。隨著更多組織或者開發(fā)者開始采用 MCP,其有望成為 AI 應用集成的主流協(xié)議。
2.2 MCP 架構概覽
如下圖所示(來自:Visual Guide to Model Context Protocol (MCP) [2])為 MCP 的關鍵架構,受到 Language Server Protocol(LSP)的啟發(fā),旨在標準化 AI 與外部系統(tǒng)的交互方式,包括 3 個關鍵組件:
- Host:通常是 AI 應用(Agent),比如 Anthropic Claude Desktop、Cursor、Cline 等,負責選擇并調用 MCP Client,以便使用各種 MCP Server 提供的能力。
- Client:Host 內的連接器,負責與 Server 建立 1 對 1 的連接,以便使用 Server。
- Server:提供資源、工具或 Prompts 的服務,如文件系統(tǒng)、數(shù)據(jù)庫、API 等。
如上圖所示,Client 和 Server 之間使用雙向的 JSON-RPC 2.0 進行通信。當前支持 stdio 和 Streamable HTTP 兩種傳輸機制。
- stdio:Client 以子進程方式啟動 MCP Server,并通過標準輸入輸出建立通信管道。Server 從 stdin 中讀取 JSON-RPC 消息(可以是 Request、Response 或 Notification),并將消息發(fā)送到 stdout。 (PS:Server 不能往 stdin 寫,Client 不能往 stdout 寫)
- Streamable HTTP + SSE:Client 發(fā)起 HTTP GET 并在 Accept: text/event-stream 下打開 SSE 流;Server 在該流上通過 SSE 推送 JSON?RPC Request 和 Notification,Client 監(jiān)聽并處理。Client 再通過 HTTP POST 將對應的 JSON?RPC 響應提交至同一 MCP 端點,實現(xiàn)完整的雙向交互。
- WebSocket:Transport Layer 也支持自定義的傳輸機制,比如常見的 WebSocket。Server 和 Client 均可充當 JSON?RPC 請求的發(fā)起者和接收者;Client 在連接時注冊自己支持的 method,Server 即可通過同一通道調用這些方法。
2.3 MCP 關鍵概念
2.3.1 Resources
Resources 在 MCP 中指的是 AI 可以訪問和讀取的數(shù)據(jù)來源。這些數(shù)據(jù)包括但不限于文件內容、數(shù)據(jù)庫記錄、屏幕截圖、圖像、日志文件、API 響應等。每一個 resource 都有一個獨立的 URI,包含文本或者二進制數(shù)據(jù),其可以為 AI 提供所需的上下文信息。如下所示為使用 MCP 的 Python SDK(The official Python SDK for Model Context Protocol servers and clients [3]) 在 MCP Server 中實現(xiàn) Resource 的簡單示例:
- list_resources():用于列出所有 resource(列表),以便后續(xù)選擇、訪問。resource 對應的數(shù)據(jù)類型為 types.Resource,其包含唯一的 uri,也有對應的 mimeType。
- read_resource():根據(jù) uri 訪問對應的 resource。
2.3.2 Prompts
Prompts 是預定義的模板或指令,旨在指導 AI 生成響應或執(zhí)行特定任務。它們是 MCP 擴展性的一部分,允許開發(fā)者根據(jù)具體需求創(chuàng)建新的 Prompt 模板,以增強 AI 與數(shù)據(jù)源的交互。如下所示為使用 MCP Python SDK 在 MCP Server 中實現(xiàn) Prompt 的簡單示例:
- list_prompts():列出所有可用的 Prompt(列表)。prompt 對應的類型為 types.Prompt,包含唯一的 name,必要的 description 以及一個 arguments 列表。
- get_prompt():根據(jù) name 獲取對應的 Prompt,返回的是 GetPromptResult,包含 description 和 messages 屬性。
Prompts 在 Anthropic 的分類中屬于“用戶控制”(user?controlled)級別,意味著最終由用戶在客戶端界面中主動選擇并執(zhí)行,具有以下特性:
- 動態(tài)參數(shù):支持在調用時傳入變量,生成個性化提示。
- 資源上下文:可將文件、日志等資源內容嵌入到提示中。
- 流程編排:可鏈式組合多輪交互,實現(xiàn)復雜工作流。
2.3.3 Tools
Tools 是 MCP Server 提供的功能(PS:也是當前使用最多,支持最好的功能),AI 可以調用這些功能執(zhí)行具體操作,如運行代碼、訪問外部 API 或自動化任務。這些工具需要用戶批準,確保安全性和可控性。和 Resources 類似,工具也需要包含唯一的 name,并且包含相應的描述(description),以便引導更好的使用該工具。如下所示為使用 MCP 的 Python SDK 在 MCP Server 中實現(xiàn) Tools 的簡單示例:
- list_tools():列出所有可用 Tools(列表)。tool 對應的類型為 types.Tool,同樣包含唯一的 name,必要的 description,以及相應的 inputSchema(對應 Anthropic Claude function call 中的 input_schema)。
- call_tool():根據(jù) name 以及對應的 arguments 調用相應的 tool,比如這里是執(zhí)行相應的求和計算。
2.3.4 Sampling
Sampling 允許 Server 通過 Client 請求 LLM 完成生成,支持復雜的代理行為,同時保持安全性和隱私。 不過當前 Sampling 特性在 Claude Desktop client 中還未支持。Sampling 擴展了 MCP 的 Client-Server 架構,使得 Server 無需自行承載或調用遠端模型,就能通過 Client 訪問預制的 LLM 能力,實現(xiàn)更強的交互能力。典型的流程包含如下 5 個步驟:
- Server 調用 sampling/createMessage 向 Client 發(fā)送請求(PS:可以雙向通信)。
- Client 接收后,可根據(jù)策略或人工審核,對請求進行修改或拒絕。
- Client 在本地或受信任環(huán)境中調用 LLM 執(zhí)行生成采樣。
- Client 可再次審核生成的 completion,并對結果進行過濾或調整。
- Client 將最終的 completion 通過 JSON-RPC 響應返回給 Server。
2.3.5 Roots
Roots 定義了 Server 可以操作的邊界。root 可以作為 URI,當 Client 連接 Server 時,聲明 Server 需要關注的范圍。主要是用于文件系統(tǒng)路徑(如file:///home/user/projects/myapp)或 HTTP URL(如 ??https://api.example.com/v1??),幫助服務器了解相關資源和位置,明確工作空間資源,并支持同時處理多個資源。如下圖所示為 MCP Client 聲明 roots 的典型方式,此配置表明 Server 同時聚焦于本地倉庫與遠程 API 端點,且在邏輯上保持二者獨立。
2.4 能力協(xié)商機制
MCP 采用基于能力的協(xié)商機制,Client 和 Server 需要在初始階段聲明各自支持的“能力”特性。“能力”聲明決定了會話階段可使用的協(xié)議特征和基本操作。
- 初始階段:
Server 需要聲明:可用 Resource、支持的 Tool、Prompt 模板。
Client 需要聲明:Sampling 支持,Notification 處理。
- 會話階段:Client 和 Server 需要嚴格遵守已聲明的能力范圍。
如下圖所示展示初始階段和會話階段的幾個過程:
- 紅框:初始階段,Host 調用 Client,Client 訪問 Server 獲取 Server 可支持的資源和能力(list_resources(),list_tools())。
- 藍框:會話階段(Host 發(fā)起),Host 中用戶或模型發(fā)起 Action,調用 Client,Client 請求 Server 來獲取資源或執(zhí)行工具(read_resource(),call_tool())。
- 綠框:會話階段(Server 發(fā)起),Server 調用 Client 獲得 Sampling 支持,Client 轉發(fā)給 Host 并獲取響應,然后返回給 Server。
三、實現(xiàn)細節(jié)
3.1 Tools 和 Resources 管理
在 Python SDK 中,Server 側使用 ToolManager 管理當前 Server 的所有 Tool,并提供 list_tools() 和 call_tool() 方法:
Host 端會管理所有的 Client,通過這些 Client 可以管理所有 Server 的所有 Tools。如下圖所示,OpenAI 的 Agents 庫中提供了 get_all_function_tools() 來獲取所有 Server 的所有 Tools(openai-agents-python/src/agents/mcp/util.py [4]),并且不允許 Tool name 有重復(即使在不同的 Server):
PS:不同的 Host 可以實現(xiàn)不同的管理方式,但是最終將這些 Tools 傳入 LLM 的方式都類似。此外,管理 Resources 的機制也類似。
3.2 與 LLM 的結合
3.2.1 Function Call
有了 Tools 和 Resources,Host 是怎么判斷使用哪個 Server 的哪個 tool/resource 呢?其實和之前的 AI Agent 沒有什么本質區(qū)別。依然是將可用的 tool 和 resource 傳入 LLM,依賴 LLM 的 Function Call 能力來智能選擇。
如下圖所示為 OpenAI 的 Function Call(Function calling - OpenAI API [5]) 調用方式及 Anthropic Claude 的 Function Call(Tool use with Claude - Anthropic [6])調用方式,整體基本一致,只是一個是 “parameters”,一個是“input_schema”。Qwen (Function Calling - Qwen [7])也基本類似,替換使用的 LLM 的成本也相對比較低。
3.2.2 Server & Tool 選擇
當前常見的 Host 中不會特意選擇 Server,而是將所有 Server 的 Tools 匯總,一起交由 LLM 來選擇。而 Tools 越多,就會導致 LLM 的 Input Token 數(shù)越多,造成 LLM 調用成本的增加,也可能導致效果的降低。如下所示,OpenAI Function Call 的文檔中建議 Tools 的數(shù)量不超過 20 個(Function calling - OpenAI API [5])
除此之外,有些場景并不需要使用 Tools,為此 OpenAI 中也提供 tool_choice 選項:
- Auto:表示由 LLM 判斷是否使用 tool,以及使用哪些 tool。
- Required:表示必須使用至少一個 tool。
- Forced Function:表示強制使用某個 tool。
當然,上述有個潛在的問題,無論是否使用 tool,都需要把全量 Tools 傳入 LLM,必然造成輸入 Token 數(shù)的增加,也就是成本的增加(PS:也可以通過 Prefix Cache 緩解)。隨著 MCP 的發(fā)展,Tools 的數(shù)量會越來越多,此時就會需要一種低成本的機制,調用 LLM 之前對 Tools 進行粗篩,然后再供 LLM 選擇。
3.3 MCP Prompt 的使用
在 MCP 中,Prompts 是服務器向客戶端暴露的“用戶可控”模板,用于標準化和復用與大模型交互的常見流程。Client 可以通過 JSON?RPC 調用 prompts/list 發(fā)現(xiàn)可用模板,再通過 prompts/get 獲取具體的消息序列(messages),并可傳入動態(tài)參數(shù)或嵌入資源上下文,從而自動化地生成用戶與模型之間的交互內容。相應的過程如下圖所示:
- Discovery:調用 prompts/list 方法,獲得所有可用 Prompts,對應我們前面介紹的 list_prompts()。
- Usage:調用 prompts/get 方法,并傳入必要的參數(shù),以便組裝 Prompt 或者嵌入資源(Resource)上下文,對應我們前面介紹的 get_prompt()。
- Changes:Server 也可以更新 Prompt 并通知 Client(notifications/prompts/list_changed) 相應的變更,Client 需要重新獲取 Prompts。
四、示例
4.1 MCP Server 開發(fā)和驗證
可以參考 The official Python SDK for Model Context Protocol servers and clients [3] 中的示例快速實現(xiàn)一些 Demo。如下圖所示,我們在 Demo Server 中提供兩個 Tool:
- pack:給定兩個整數(shù),返回的是打包過程,這里我們求和并額外加了 1000000,以便區(qū)分 LLM 自己生成的結果。
- get_paper_abstract:給定一個 Arxiv 論文的 ID,返回對應論文的摘要。
開發(fā)完可以先使用 mcp 的 Inspector 工具(Inspector - Model Context Protocol [8])對 Server 進行調試,使用 “Tools” 中的 “List Tools” 可以列出所有可用工具,有對應的 name 和 description。選中對應工具并輸入相關參數(shù)即可以 “Run Tool” 并獲得結果:
4.2 Claude Desktop 集成 MCP Server
驗證完 Server 的正確性即可以將其集成到 Claude Desktop 中使用。首次使用可以創(chuàng)建一個空的 “~/Library/Application\ Support/Claude/claude_desktop_config.json” 文件并編輯,即可激活 Claude Desktop 的 MCP 支持。如下所示,可以在 claude_desktop_config.json 中配置相應的 McpServers,這里是一個 Dict,可以配置多個 Server。這里用 uv 管理 Python 環(huán)境,command 中最好寫上絕對路徑,不然在 Mac 中可能異常:
配置完之后重啟 Claude Desktop 會發(fā)現(xiàn)多了如下的工具選項(PS:如果 Server 有問題,啟動時會有相應報錯,可以查看對應日志文件):
展開工具選項可以看到剛才配置的 Server 中的兩個工具(PS:當前 Claude Desktop 支持的還不完善,比如,配置了 Resource Template 沒有生效),如下所示:
4.3 Tool 驗證
集成之后就可以在 Claude Desktop 中使用相應的工具。
如下圖所示為 pack 工具的驗證:
- 問題:“請打包 321 和 654 兩個數(shù)。”
- 紅框:執(zhí)行了對應的 pack 工具,并輸出 “321 + 654 = 1000975”。
- 藍框:LLM 將工具返回的內容 “321 + 654 = 1000975” 再次輸入 LLM,獲得對應的文本輸出。
如下圖所示為 get_paper_abstract 工具的驗證:
- 問題:“請給我提供論文 2504.02263 的摘要”。
- 紅框:執(zhí)行了對應的 get_paper_abstract 工具,并輸出論文的英文摘要。
- 藍框:LLM 將工具返回的英文摘要重新輸入 LLM,由于我們用中文提問,因此 LLM 自動進行了中文翻譯,并輸出翻譯后的摘要。
五、參考鏈接
- ??https://modelcontextprotocol.io/introduction??
- ??https://www.dailydoseofds.com/p/visual-guide-to-model-context-protocol-mcp/??
- ??https://github.com/modelcontextprotocol/python-sdk??
- ??https://github.com/openai/openai-agents-python/blob/main/src/agents/mcp/util.py??
- ??https://platform.openai.com/docs/guides/function-calling/function-calling?api-mode=responses??
- ??https://docs.anthropic.com/en/docs/build-with-claude/tool-use/overview??
- ??https://qwen.readthedocs.io/en/latest/framework/function_call.html??
- ??https://modelcontextprotocol.io/docs/tools/inspector??
本文轉載自?????AI閑談?????,作者:AI閑談
