MCP 規範完整中譯稿:2025-3-26 版
【引】儘管 AI 可以幫助我們順利地理解 MCP 規範,但一份完整的 MCP 規範中譯稿還是有意義的,可以進一步幫助我們理解 MCP 規範的來龍去脈,以及協議中細節的方方面面。如果希望希望極簡入門的話, 可以閱讀老碼農的新作——
1. 規範
模型上下文協議 (Model Context Protocol,MCP) 是一個開放的協議,支持 LLM 應用程序與外部數據源和工具之間的無縫集成。無論是構建基於 AI 的 IDE、增強聊天界面還是創建自定義 AI 工作流,MCP 都提供了一種標準化的方法來將 llm 與它們所需的上下文連接起來。
該規範基於 schema.ts 中的 TypeScript 模式定義了權威協議需求。
有關實現指南及示例,請瀏覽 modelcontextprotocol.io。
本文件中的關鍵詞 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY” 和 “OPTIONAL” 應按照 BCP 14 [RFC2119][RFC8174] 中的規定解釋,如本文件所示,當且僅當它們出現在所有大寫字母中時表示如上含義。
1.1 概覽
MCP 爲應用程序提供了一種標準化的方式:
-
與語言模型共享上下文信息
-
向人工智能系統公開工具和能力
-
構建可組合的集成和工作流
該協議使用 JSON-RPC 2.0 消息來建立以下組件之間的通信:
-
主機: 啓動連接的 LLM 應用程序
-
客戶端: 宿主應用程序中的連接器
-
服務器: 提供上下文和能力服務
MCP 從語言服務器協議 (Language Server Protocol) 中獲得了一些靈感,該協議標準化瞭如何在整個開發工具生態系統中添加對編程語言的支持。以類似的方式,MCP 標準化瞭如何將其他上下文和工具集成到 AI 應用程序的生態系統中。
1.2 主要內容
1.2.1 基本協議
-
JSON-RPC 消息格式
-
有狀態連接
-
服務器和客戶端能力協商
1.2.2 特性
服務器向客戶端提供以下特性:
-
資源: 上下文和數據,供用戶或 AI 模型使用
-
提示詞: 用戶的模板化消息和工作流
-
工具: AI 模型要執行的函數
客戶端可向服務器提供以下功能:
-
採樣: 服務器發起的代理化行爲和遞歸 的 LLM 交互
額外公用設施
-
配置
-
進度跟蹤
-
取消
-
錯誤報告
-
日誌
1.3 安全性和信任及保護
模型上下文協議通過任意的數據訪問和代碼執行路徑實現了強大的功能。這種能力帶來了重大的安全和信任問題,所有實現者都必須仔細考慮這些問題。
1.3.1 主要原則
1. 用戶同意及管制
-
用戶必須明確同意並理解所有數據訪問和操作
-
用戶必須保留對共享哪些數據和採取哪些操作的控制
實現者應該爲審查和授權活動提供清晰的用戶界面
2. 數據私隱
-
在向服務器公開用戶數據之前,主機必須獲得用戶的明確同意
-
未經用戶同意,主機不得在其他地方傳輸資源數據
-
應使用適當的訪問控制來保護用戶數據
3. 工具安全
-
工具代表任意的代碼執行,必須謹慎對待。
-
特別是,工具行爲的描述 (如註釋) 應該被認爲是不可信的,除非從受信任的服務器獲得。
-
在調用任何工具之前,主機必須獲得明確的用戶同意
-
在授權使用之前,用戶應該瞭解每個工具的作用
4. 採樣控制
-
用戶必須顯式批准任何 LLM 採樣請求
-
使用者應控制:
-
是否進行取樣
-
將要發送的實際提示詞
-
服務器可以看到的結果
-
該協議有意將服務器的可見性限制爲提示詞 ##1.4 實現指南
雖然 MCP 本身不能在協議級別上強制執行這些安全原則,但實現者應該:
-
在其應用程序中構建健壯的批准和授權流
-
提供安全影響的清晰文檔
-
實施適當的訪問控制和數據保護
-
在它們的集成中遵循安全最佳實踐
-
在他們的功能設計中考慮隱私問題
2. 關鍵變更
本文檔列出了自上一版本( 2024-11-05 )以來對模型上下文協議 (MCP) 規範所做的變更。
2.1 主要變化
-
增加了一個基於 OAuth 2.1 (PR # 133) 的全面授權框架
-
用更靈活的 Streamable HTTP 傳輸 (PR # 206) 取代了以前的 HTTP + SSE 傳輸
-
增加了對 JSON-RPC 批處理的支持 (PR # 228)
-
增加了全面的工具註釋,以更好地描述工具的行爲,如它是隻讀的還是破壞性的 (PR # 185)
2.2 其他模式的變更
-
向 ProgressNotification 添加了消息字段以提供描述性狀態更新
-
添加了對音頻數據的支持,加入了現有的文本和圖像的內容類型
-
添加了補全能力,以顯式指示對參數自動補全建議的支持
有關更多詳細信息,請參見更新的數據模式。
2.3 完整的變更記錄
有關自上次協議修訂以來所做的所有變更的完整列表,請參見 GitHub。
3. 架構
模型上下文協議 (Model Context Protocol,MCP) 遵循客戶端 - 主機 - 服務器的架構模式,其中每個主機可以運行多個客戶端實例。這種架構使用戶能夠在應用程序之間集成 AI 功能,同時保持清晰的安全邊界和隔離關注點。MCP 建立在 JSON-RPC 之上,它提供了一個有狀態的會話協議,主要關注客戶端和服務器之間的上下文交換和採樣協調。
3.1 核心組件
3.1.1 主機(Host)
主機進程充當容器和協調器:
-
創建並管理多個客戶端實例
-
控制客戶端連接權限和生命週期
-
執行安全策略和正式批准需求
-
處理用戶授權決策
-
協調 AI/LLM 的集成和採樣
-
管理跨客戶端的上下文聚合
3.1.2 客戶端(client)
每個客戶端由主機創建,並維護一個獨立的服務器連接:
-
爲每個服務器建立一個有狀態會話
-
處理協議協商和能力交換
-
支持雙向的路由協議消息
-
管理訂閱和通知
-
維護服務器之間的安全邊界
主機應用程序創建並管理多個客戶機,每個客戶機與特定服務器具有 1:1 的關係。
3.1.3 服務器(Server)
服務器提供專門的環境和功能:
-
通過 MCP 原語公開資源、工具和提示詞
-
獨立工作,責任明確
-
通過客戶端接口請求取樣
-
必須尊循安全約束
-
可以是本地進程或遠程服務
3.2 設計原則
MCP 建立在幾個關鍵設計原則的基礎上,這些原則爲其架構和實施提供了參考信息:
3.2.1 服務器應該非常容易構建
-
主機應用程序負責處理複雜的業務流程
-
服務器側重於特定的、定義良好的能力
-
簡單接口並最小化實現開銷
-
清晰的分離,支持可維護的代碼
3.2.2 服務器應該是高度可組合的
-
每個服務器提供獨立的重點功能
-
可以無縫地組合多個服務器
-
共享的協議支持互操作性
-
模塊化設計支持可擴展性
3.2.3 服務器不能夠讀取整個會話,也不能 “看到” 其他服務器
-
服務器只接收必要的上下文信息
-
完整的會話歷史保留在主機上
-
每個服務器連接保持隔離
-
跨服務器交互由主機控制
-
主機進程強制執行安全邊界
3.2.4 功能特性可以逐步添加到服務器和客戶端
-
核心協議提供了最低要求的功能
-
額外的能力可以根據需要進行協商
-
服務器和客戶機是獨立開發的
-
爲將來的可擴展性而設計的協議
-
保持後向兼容性
3.3 能力協商
模型上下文協議使用一個基於能力的協商系統,客戶端和服務器在初始化期間顯式地聲明它們支持的功能特性。能力決定哪些協議特性和原語在會話期間可用。
-
服務器聲明諸如資源訂閱、工具支持和提示模板等功能
-
客戶端聲明採樣支持和通知處理等功能
-
在整個會話過程中,雙方都必須遵循對方聲明的能力
-
額外的功能可以通過協議的擴展來協商
每個功能解鎖特定的協議特性,以便在會話期間使用。例如:
-
實現的服務器特性必須在服務器能力中公佈
-
發出資源訂閱通知需要服務器聲明其支持訂閱
-
工具調用要求服務器聲明其工具的能力
-
採樣要求客戶端在其功能中聲明支持
此能力協商確保客戶端和服務器在維護協議可擴展性的同時清楚地理解所支持的功能。
4. 基本協議
修訂於 2025 年 3 月 26 日
4.1 概覽
模型上下文協議由幾個協同工作的關鍵組成部分組成:
-
基本協議:核心 JSON-RPC 消息類型
-
生命週期管理: 連接初始化、能力協商和會話控制
-
服務器特性: 服務器公開的資源、提示詞和工具
-
客戶端特性: 客戶端提供的取樣和根目錄列表
-
實用程序: 橫切關注點,如日誌記錄和參數不全
所有的實現都必須支持基本協議和生命週期管理組件。其他組件可以根據應用程序的具體需要來實現。
這些協議層建立了清晰的關注點分離,同時實現了客戶端和服務器之間的豐富交互。模塊化設計允許實現完全支持它們需要的特性。
4.1.1 消息
MCP 客戶端和服務器之間的所有消息必須遵循 JSON-RPC 2.0 規範,該協議定義了以下類型的消息。
4.1.1.1 請求
請求從客戶端發送到服務器,反之亦然,以啓動一個操作。
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
-
請求必須包含一個字符串或整數 ID。
-
與基本 JSON-RPC 不同,ID 不能爲空。
-
請求 ID 必須以前沒有被請求者在同一個會話中使用過。
4.1.1.2 響應
響應是在回覆請求時發送的,包含操作的結果或錯誤信息。
{
jsonrpc: "2.0";
id: string | number;
result?: {
[key: string]: unknown;
}
error?: {
code: number;
message: string;
data?: unknown;
}
}
-
響應必須包含與其對應的請求相同的 ID。
-
響應進一步細分爲成功的結果或錯誤。必須設置結果或錯誤,一個響應不能同時設置成功和錯誤。
-
結果可以遵循任何 JSON 對象結構,而錯誤必須至少包含一個錯誤編碼和消息。
-
錯誤編碼碼必須是整數。 #### 通知
通知作爲單向消息從客戶機發送到服務器,反之亦然。接收者不能發送響應。
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
通知不能包含 ID。
4.1.1.3 批處理
JSON-RPC 還定義了一種方法來批處理多個請求和通知,將它們發送到一個數組中。MCP 實現可能支持發送端的 JSON-RPC 批處理,但必須支持接收端的 JSON-RPC 批處理。
4.1.2 授權
MCP 提供了一個用於 HTTP 的授權框架。使用基於 http 傳輸的實現應該符合這個規範,而使用 STDIO 傳輸的實現不應該遵循這個規範,而應該從環境中檢索憑證。
此外,客戶端和服務器可以協商自己的自定義身份驗證和授權策略。
欲瞭解更多關於 MCP 身份驗證機制發展的討論和貢獻,請加入 GitHub 討論,幫助塑造協議的未來!
4.1.3 Schema
協議的完整規範被定義爲 TypeScript 模式。這是所有協議消息和結構的真實來源。
還有一個 JSON Schema,它是從 TypeScript 可信真值源自動生成的,用於各種自動化工具。
4.2 生命週期
模型上下文協議 (Model Context Protocol,MCP) 爲客戶端 - 服務器連接定義了嚴格的生命週期,以確保適當的能力協商和狀態管理。
-
初始化: 能力協商和協議版本認同
-
操作: 正常協議通信
-
Shutdown: 連接的正常終止
4.2.1 生命週期階段
4.2.1.1 初始化
初始化階段必須是客戶端和服務器之間的第一次交互。在這個階段,客戶端和服務器:
-
建立協議版本兼容性
-
交換和協商能力
-
共享實現細節
客戶端必須通過發送包含以下內容的初始化請求來啓動此階段:
-
支持的協議版本
-
客戶端能力
-
客戶端的實現信息
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {}
},
"clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
}
}
}
初始化請求不能成爲 JSON-RPC 批處理的一部分,因爲在初始化完成之前,其他請求和通知是不可能發出的。這還允許向後兼容不顯式支持 JSON-RPC 批處理的以前協議版本。
服務器必須用自己的能力和信息進行響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "ExampleServer",
"version": "1.0.0"
},
"instructions": "Optional instructions for the client"
}
}
初始化成功後,客戶端必須發送一個初始化通知,表明它已準備好開始正常操作:
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
-
在服務器響應初始化請求之前,客戶端不應該發送 ping 以外的請求。
-
在接收到初始化通知之前,服務器不應該發送 ping 和日誌以外的請求。
4.2.1.2 版本協商
在初始化請求中,客戶端必須發送它支持的協議版本。這應該是客戶端支持的最新版本。
如果服務器支持請求的協議版本,它必須用相同的版本響應。否則,服務器必須使用其支持的另一個協議版本進行響應。這應該是服務器支持的最新版本。
如果客戶端不支持服務器響應中的版本,它應該斷開連接。
4.2.1.3 能力協商
客戶端和服務器功能確定在會話期間哪些可選協議的特性可用。
主要能力包括:
能力對象可以像這樣描述其子能力:
-
listChanged: 支持列表更改通知 (用於提示、資源和工具)
-
subscribe: 支持訂閱單個項目的更改 (僅限參考資料)
4.2.1.4 操作
在操作階段,客戶端和服務器根據協商的能力交換消息。
雙方應該:
-
遵循協議的版本
-
只使用成功協商的能力
4.2.1.5 shutdown
在關閉階段,一方 (通常是客戶端) 乾淨地終止協議連接。沒有定義特定的關閉消息ーー相反,應該使用底層傳輸機制來發送連接終止信號:
stdio
對於 stdio 傳輸,客戶端應該通過以下方式啓動關閉:
-
首先,關閉子進程 (服務器) 的輸入流
-
等待服務器退出,如果服務器沒有在合理的時間內退出,則發送 SIGTERM
-
如果服務器沒有在 SIGTERM 之後的合理時間內退出,則發送 SIGKILL
服務器可以通過關閉其到客戶端的輸出流並退出來啓動關閉。
HTTP
對於 HTTP 傳輸,通過關閉相關的 HTTP 連接來指示關閉。
4.2.1.6 超時
實現應該爲所有發送的請求建立超時,以防止掛起連接和資源耗盡。當請求在超時期間內沒有收到成功或錯誤響應時,發送方應該爲該請求發出取消通知,並停止等待響應。
SDK 和其他中間件應該允許根據每個請求配置這些超時。
實現可能在接收到相應請求的進度通知時選擇重置超時時鐘,這意味着工作實際上正在發生。但是,無論進度通知如何,實現都應該強制執行最大超時,以限制行爲不當的客戶端或服務器的影響。
4.2.1.7 錯誤處理
應該準備好實現來處理這些錯誤情況:
-
協議版本不匹配
-
未能就所需能力完成協商
-
請求超時
-
初始化的錯誤示例:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Unsupported protocol version",
"data": {
"supported": ["2024-11-05"],
"requested": "1.0.0"
}
}
}
4.3 傳輸
MCP 使用 JSON-RPC 編碼消息。 JSON-RPC 消息必須是 utf-8 編碼。
該協議目前定義了客戶端 - 服務器通信的兩種標準傳輸機制:
-
STDIO:標準輸入和標準輸出的通信
-
Streamable HTTP
客戶端應該儘可能支持 stdio。
客戶端和服務器也可以以可插拔的方式實現自定義傳輸。
4.3.1 STDIO
在 STDIO 的傳輸中:
-
客戶端將 MCP 服務器作爲子進程啓動。
-
服務器從其標準輸入 (stdin) 中讀取 JSON-RPC 消息,並將消息發送到其標準輸出 (stdout)。
-
消息可以是 JSON-RPC 請求、通知、響應ーー或包含一個或多個請求和 / 或通知的 JSON-RPC 批處理。
-
消息由換行符分隔,並且不能 (MUST NOT) 包含嵌入的換行符。
-
服務器可以將 utf-8 字符串寫入其標準錯誤 (stderr) ,以便記日誌。客戶端可以捕獲、轉發或忽略此日誌記錄。
-
服務器不能寫入任何非有效 MCP 消息的標準輸出。
-
客戶端不能向服務器的 stdin 寫入非有效 MCP 消息的內容。
4.3.2 Streamable HTTP
這取代了協議 2024-11-05 版本中的 HTTP + SSE 傳輸。
在 Streamable HTTP 傳輸中,服務器作爲獨立進程運行,可以處理多個客戶端連接。此傳輸使用 HTTP POST 和 GET 請求。服務器可以選擇性地使用 SSE 來流化多個服務器消息。這爲基本的 MCP 服務器和支持流的服務器提供了更多豐富的功能,並支持服務器到客戶端的通知和請求。
服務器必須提供一個同時支持 POST 和 GET 方法的 HTTP 端點路徑 (以下稱爲 MCP 端點)。例如,這可能是一個類似於 https://example.com/mcp 的 URL。
4.3.2.1 安全警告
實現流式 HTTP 傳輸時:
-
服務器必須在所有傳入連接上驗證初始的 HTTP 頭,以防止 DNS 重新綁定攻擊
-
在本地運行時,服務器應該只綁定到本地主機 (127.0.0.1) ,而不是綁定到網絡接口 (0.0.0.0)
-
服務器應該爲所有連接實現正確的身份驗證
如果沒有這些保護,攻擊者可以使用 DNS 重新綁定來與遠程站點的本地 MCP 服務器交互。
4.3.2.2 向服務器發送消息
從客戶端發送的每個 JSON-RPC 消息都必須是對 MCP 端點的新 HTTP POST 請求。
-
客戶端必須使用 HTTP POST 將 JSON-RPC 消息發送到 MCP 端點。
-
客戶機必須包含一個 Accept 頭,列出將 application/json 和 text/event-stream 作爲支持的內容類型。
-
POST 請求的正文 MUST 必須列情況之一:
-
單個 JSON-RPC 請求、通知或響應
-
批處理一個或多個請求和 / 或通知的數組
-
批處理一個或多個響應的數組
-
-
如果輸入僅由 (任意數量的) JSON-RPC 組成響應或者通知:
-
如果服務器接受輸入,則服務器必須返回 HTTP 狀態碼 202 Accepted,而不接受任何正文。
-
如果服務器不能接受輸入,它必須返回一個 HTTP 錯誤狀態碼 (例如,400 Bad Request)。HTTP 響應的正文可能包含一個沒有 id 的 JSON-RPC 錯誤響應。
-
-
如果輸入包含任意數量的 JSON-RPC 請求,服務器必須返回 Content-Type: text/event-stream 來初始化 SSE 流,或者返回 Content-Type: application/JSON 來返回一個 JSON 對象。客戶端必須同時支持這兩種情況。
-
如果服務器啓動 SSE 流:
-
斷開連接不應被解釋爲客戶端取消其請求。
-
若要取消其請求,客戶端應顯式發送 MCP CancelledNotification。
-
爲了避免由於斷開連接而導致的消息丟失,服務器可以恢復流傳輸。
-
SSE 流最終應該爲 POST 主體中發送的每個 JSON-RPC 請求包含一個 JSON-RPC 響應。這些響應可以是批處理形式。
-
在發送 JSON-RPC 響應之前,服務器可能會發送 JSON-RPC 請求和通知。這些消息應該與原始客戶端的請求相關。這些請求和通知可以被批處理。
-
服務器不應該在爲每個接收到的 JSON-RPC 請求發送一個 JSON-RPC 響應之前關閉 SSE 流,除非會話過期。
-
在發送了所有 JSON-RPC 響應之後,服務器應該關閉 SSE 流。 斷開連接可以發生在任何時間 (例如,由於網絡條件),因此:
-
4.3.2.3 偵聽來自服務器的消息
-
客戶端可以向 MCP 端點發出 HTTP GET 請求。這可以用來打開一個 SSE 流,允許服務器與客戶端通信,而不需要客戶機首先通過 HTTP POST 發送數據。
-
客戶端必須包含一個 Accept 頭,將 text/event-stream 列爲受支持的內容類型。
-
服務器必須返回 Content-Type: text/event-stream 來響應這個 HTTP GET,或者返回 HTTP 405 Method Not Allowed,表明服務器沒有在這個端點提供 SSE 流。
-
如果服務器啓動了 SSE 流:
-
服務器可以在流上發送 JSON-RPC 請求和通知。這些請求和通知可以被批處理。
-
這些消息應該與來自客戶端的任何併發運行的 JSON-RPC 請求無關。
-
服務器不能在流上發送 JSON-RPC 響應,除非恢復與以前的客戶端請求相關聯的流。
-
服務器可以在任何時候關閉 SSE 流。
-
客戶端可以在任何時候關閉 SSE 流。
-
4.3.2.4 多連接
-
客戶端可以同時保持與多個 SSE 流的連接。
-
服務器必須只在一個已連接的流上發送它的每個 JSON-RPC 消息;也就是說,它絕對不能跨多個流廣播相同的消息。
- 可以通過使流可恢復來降低消息丟失的風險。
4.3.2.5 可恢復性和重新發送
爲了支持恢復中斷的連接,並重新發送可能丟失的消息:
-
服務器可以附上一個 id 字段並添加到它們的 SSE 事件,像 SSE 標準描述的那樣:
- 如果存在該 ID ,則必須在該會話內的所有流之間是全局唯一的ーー或者在不使用會話管理的情況下在具有該特定客戶端的所有流之間是全局唯一的。
-
如果客戶端希望在斷開連接後恢復,則它應該向 MCP 端點發出一個 HTTP GET 請求, 並將使用 Last-Event-ID 頭來指示它接收的最後一個事件 ID。
-
服務器可以使用這個頭來重播在最後一個事件 ID 之後發送的消息,並在斷開連接的流上從該點恢復流。
-
服務器一定不能重播在不同流上傳遞的消息。
-
換句話說,服務器應該根據每個流分配這些事件 id,作爲該特定流中的遊標。
4.3.2.6 會話管理
一個 MCP “會話” 由客戶端和服務器之間邏輯上相關的交互組成,從初始化階段開始。未來支持希望建立有狀態會話的服務器:
-
使用流式 HTTP 傳輸的服務器可以在初始化時分配會話 ID,方法是將其 HTTP 響應頭 Mcp-Session-Id header 中包含 InitializeResult.
-
會話 ID 應該是全局唯一的,並且具有加密安全性 (例如,安全生成的 UUID、 JWT 或加密散列)。
-
會話 ID 必須只包含可見的 ASCII 字符 (範圍從 0x21 到 0x7e)。
-
-
如果服務器在初始化期間返回 Mcp-Session-Id ,客戶端使用流式 HTTP 傳輸時必須在所有後續 HTTP 請求頭中包含 Mcp-Session-Id 。
- 需要會話 ID 的服務器應該使用 HTTP 400 Bad Request 來響應沒有 Mcp-Session-Id 頭的請求 (初始化除外)。
-
服務器可以在任何時候終止會話,之後它必須用 HTTP 404 Not Found 響應包含該會話 ID 的請求。
-
當客戶端響應包含 Mcp-Session-Id 的請求而收到 HTTP 404 時,它必須通過發送一個沒有附加會話 ID 的新 InitializeRequest 來啓動一個新會話。
-
不再需要特定會話的客戶端 (例如,因爲用戶即將離開客戶端應用) 應該發送 HTTP DELETE 到 MCP 端點,並使用 Mcp-Session-Id 頭以顯式終止會話。
- 服務器可能用 HTTP 405 Method Not Allowed 響應此請求,表示服務器不允許客戶端終止會話。
4.3.2.7 向後兼容性
客戶端和服務器可以維護與 HTTP+ SSE 傳輸 (來自協議版本 2024-11-05) 的向後兼容性,如下所示:
希望支持老客戶端的服務器應該:
-
繼續承載舊傳輸的 SSE 和 POST 端點,以及爲 Streamable HTTP 傳輸定義的新 “MCP 端點”。
-
也可以組合舊的 POST 端點和新的 MCP 端點,但是這可能會引入不必要的複雜性。
希望支持舊服務器的客戶端應該:
-
接受來自用戶的 MCP 服務器 URL,該 URL 可以指向使用舊傳輸協議或新傳輸協議的服務器。
-
試圖 POST 一個 InitializeRequest 到服務器 URL,使用如上所述的 Accept 頭:
-
客戶端向服務器 URL 發出 GET 請求,期望這將打開一個 SSE 流並返回一個 endpoint 事件作爲第一個事件。
-
當 endpoint 事件到達時,客戶端可以假設這是一個運行舊 HTTP + SSE 傳輸的服務器,並且應該將該傳輸用於所有後續通信。
4.3.2.8 定製傳輸
-
如果成功,客戶端可以假設這是一個支持新的 Streamable HTTP 傳輸的服務器。
-
如果失敗,服務器使用了 HTTP 4xx 的狀態代碼 (例如,405 Method Not Allowed 或 404 Not Found) :
客戶短和服務器可以實現額外的自定義傳輸機制,以滿足它們的特定需求。該協議是傳輸無關的,可以在任何支持雙向消息交換的信道上完成實現。
選擇支持自定義傳輸的實現者必須確保它們保留由 MCP 定義的 JSON-RPC 消息格式和生命週期需求。自定義傳輸應該記錄其特定的連接建立和消息交換模式,以幫助實現互操作性。
4.4 鑑權
4.4.1. 簡介
4.4.1.1 目標及範圍
模型上下文協議在傳輸級別提供鑑權功能,使 MCP 客戶短能夠代表資源所有者向受限 MCP 服務器發出請求。本規範定義了基於 HTTP 傳輸的授權流程。
4.4.1.2 協議要求
對於 MCP 實現,鑑權是可選的。當支持鑑權時:
-
使用基於 HTTP 傳輸的實現應該符合此規範。
-
使用 STDIO 傳輸的實現不應該遵循此規範,而應該從環境中檢索憑據。
-
使用替代傳輸的實現必須遵循其協議的既定安全最佳實踐。
4.4.1.3 遵守標準
這種鑑權機制基於下列既定規範,但實現了其特性的一個選定子集,以確保安全性和互操作性,同時保持簡單:
-
OAuth 2.1 IETF DRAFT
-
OAuth 2.0 Authorization Server Metadata (RFC8414)
-
OAuth 2.0 Dynamic Client Registration Protocol (RFC7591)
4.4.2. 鑑權流程
4.4.2.1 概覽
-
MCP 鑑權實現必須實現 OAuth 2.1,併爲私密客戶端和公共客戶端提供適當的安全措施。
-
MCP auth 實現應該支持 OAuth 2.0 動態客戶端註冊協議 (RFC7591)。
-
MCP 服務器應該和 MCP 客戶端必須實現 OAuth 2.0 鑑權服務器元數據協議 (RFC8414)。不支持元數據協議的服務器必須遵循默認 URI Schema。
OAuth 授權類型
OAuth 指定不同的流或授權類型,這是獲得訪問令牌的不同方式。每個目標都有不同的用例和場景。
MCP 服務器應該支持 OAuth 授權類型,這種授權類型最適合目標用戶。例如:
-
鑑權碼: 當客戶短代表 (人類) 最終用戶行事時非常有用。
- 例如,Agent 調用由 SaaS 系統實現的 MCP 工具。
-
客戶端憑據: 客戶端是另一個應用程序 (不是人)
- 例如,Agent 調用一個安全 MCP 工具來檢查特定商店的庫存, 不需要模擬最終用戶。
4.4.2.2 示例: 鑑權碼授予
這裏演示了用於用戶身份驗證的鑑權碼授予類型的 OAuth 2.1 流。
注意: 下面的示例假定 MCP 服務器也作爲授權服務器運行。但是,可以將授權服務器部署爲其自己的特定服務。
人類用戶通過 web 瀏覽器完成 OAuth 流程,獲得一個訪問令牌,該令牌可以識別用戶,並允許客戶端代表用戶進行操作。
當需要鑑權且客戶端尚未證明授權時,服務器必須響應 HTTP 401 Unauthorized。
客戶端在收到 HTTP 401 Unauthorized 之後啓動 OAuth 2.1 IETF DRAFT 鑑權流程。
下圖展示了使用 PKCE 公共客戶端的基本 OAuth 2.1 流程。
4.4.2.3 服務器元數據發現
對於服務器能力發現而言:
-
MCP 客戶端必須遵循 RFC8414 中定義的 OAuth 2.0 Authorization Server Metadata 協議。
-
MCP 服務器應該遵循 OAuth 2.0 Authorization Server Metadata 協議。
-
不支持 OAuth 2.0 Authorization Server Metadata 協議的 MCP 服務器必須支持會退 URL。
發現流程如下:
4.4.2.3.1 服務器元數據發現的 HTTP 頭
MCP 客戶端應該在服務器元數據發現期間包含頭 MCP-protocol-version: ,以允許 MCP 服務器基於 MCP 的協議版本進行響應。
例如: MCP-Protocol-Version: 2024-11-05
4.4.2.3.2 鑑權的基 URL
通過丟棄任何當前的路徑元素,鑑權的基 URL 必須從 MCP 服務器 URL 中確定。例如:
如果 MCP 服務器 URL 是 https://api.example.com/v1/MCP ,那麼:
-
鑑權的基 URL 是 https://api.example.com
-
元數據端點必須在 https://api.example.com/.well-known/oauth-authorization-server
這確保鑑權端點始終位於承載 MCP 服務器的域名的根級別,而不管 MCP 服務器 URL 中的其他路徑元素如何。
4.4.2.3.3 服務器未支持元數據發現的的後備方案
對於沒有實現 OAuth 2.0 Authorization Server Metadata 協議的服務器,客戶端必須使用相對於鑑權的基 URL (在 2.3.2 節中定義) 的以下默認端點路徑:
例如,當 MCP 服務器託管在 https://api.example.com/v1/MCP 時,默認端點爲:
https://api.example.com/authorize
https://api.example.com/token
https://api.example.com/register
客戶端必須首先嚐試通過元數據文檔發現端點,然後再回到默認路徑。當使用默認路徑時,所有其他協議要求保持不變。
4.4.2.4 動態客戶端註冊
MCP 客戶端和服務器應該支持 OAuth 2.0 動態客戶端註冊協議,以允許 MCP 客戶端在沒有用戶交互的情況下獲得 OAuth 客戶端 ID。這爲客戶端自動向新服務器註冊提供了一種標準化的方法,對於 MCP 至關重要,因爲:
-
客戶端不能預先知道所有可能的服務器
-
手動註冊會給用戶帶來不便
-
客戶端支持與新服務器的無縫連接
-
服務器可以實現自己的註冊策略
任何不支持動態客戶端註冊的 MCP 服務器都需要提供獲取客戶端 ID 以及 (如果適用的話) 客戶端保密的替代方法。對於其中一臺服務器,MCP 客戶端必須滿足以下條件之一:
-
專門爲 MCP 服務器硬編碼客戶端 ID (如果適用,還有客戶端密鑰) ,或者
-
在註冊 OAuth 客戶端之後 ,爲用戶提供一個允許他們輸入這些細節的 UI(例如,通過服務器託管的配置接口)。
4.4.2.5 鑑權的流程步驟
完整的鑑權流程如下:
4.4.2.5.1 決策流程概述
4.4.2.6 訪問令牌的使用
4.4.2.6.1 令牌要求
訪問令牌的處理必須符合 OAuth 2.1 第 5 部分對資源請求的要求,特別是:
- MCP 客戶端必須使用 OAuth 2.1 中 5.1.1 節的鑑權請求頭字段:
Authorization: Bearer <access-token>
請注意,從客戶端到服務器的每個 HTTP 請求中都必須包含鑑權,即使它們是同一邏輯會話的一部分。
- 訪問令牌不能包含在 URI 的查詢字符串中 請求示例:
GET /v1/contexts HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
4.4.2.6.2 令牌處理
資源服務器必須驗證訪問令牌,如 OAuth 2.1 的第 5.2 節所述。如果驗證失敗,服務器必須根據 5.3 節的錯誤處理要求進行響應。無效或過期的令牌必須接收一個 HTTP 401 響應。
4.4.2.7 安全性考量
必須執行下列安全性要求:
-
客戶端必須按照 OAuth 2.0 最佳實踐安全地存儲令牌
-
服務器應該強制令牌過期和輪換
-
所有鑑權端點必須通過 HTTPS 提供服務
-
服務器必須驗證重定向的 URI 以防止打開重定向漏洞
-
重定向 URI 必須是本地主機 URL 或 HTTPS URL
4.4.2.8 錯誤處理
服務器必須爲鑑權錯誤返回適當的 HTTP 狀態碼:
4.4.2.9 實施規定
-
具體實現必須遵循 OAuth 2.1 安全最佳實踐
-
所有客戶端都需要 PKCE
-
爲了增強安全性,應該實現令牌輪換
-
令牌生存週期應該根據安全需求進行限制
4.4.2.10 第三方鑑權流程
4.4.2.10.1 概覽
MCP 服務器可以通過第三方鑑權服務器支持委託鑑權。在這個流程中,MCP 服務器既充當 OAuth 客戶端 (對於第三方身份驗證服務器) ,又充當 OAuth 鑑權服務器 (對於 MCP 客戶端)。
4.4.2.10.2 流程描述
第三方鑑權流程包括以下步驟:
-
MCP 客戶端與 MCP 服務器初始化標準 OAuth 流程
-
MCP 服務器將用戶請求重定向到第三方鑑權服務器
-
使用第三方服務器進行用戶授權
-
第三方服務器使用鑑權重定向回 MCP 服務器
-
MCP 服務器爲第三方訪問令牌交換鑑權碼
-
MCP 服務器生成自己綁定到第三方會話的訪問令牌
-
MCP 服務器使用 MCP 客戶端完成初始的 OAuth 流程
4.4.2.10.3 會話綁定要求
實現第三方授權的 MCP 服務器必須:
-
維護第三方令牌與已發佈 MCP 令牌之間的安全映射
-
在承認 MCP 令牌之前驗證第三方令牌的狀態
-
實現適當的令牌生命週期管理
-
處理第三方令牌的過期和更新
4.4.2.10.4 安全性考量
在實施第三方授權時,服務器必須:
-
驗證所有重定向 URI
-
安全地存儲第三方憑據
-
實現適當的會話超時處理
-
考慮令牌鏈的安全性影響
-
爲第三方身份鑑權失敗實現正確的錯誤處理
4.4.3 最佳實踐
4.4.3.1 本地客戶端作爲公共 OAuth 2.1 客戶端
我們強烈建議本地客戶端將 OAuth 2.1 作爲公共客戶端實現:
-
對鑑權請求使用 PKCE 以防止攔截攻擊
-
實現適合本地系統的安全令牌存儲
-
遵循令牌刷新的最佳實踐來維護會話
-
正確處理令牌的過期和更新
4.4.3.2 鑑權元數據的發現
我們強烈建議所有客戶端都實現元數據發現。這減少了用戶手動提供端點或客戶端回退到預定義默認值的需要。
4.4.3.3 動態客戶端註冊
由於客戶端事先不知道 MCP 服務器的集合,我們強烈建議實現動態客戶端註冊。這允許應用程序自動向 MCP 服務器註冊,並消除了用戶手動獲取客戶機 id 的需要。
4.5 實用程序
4.5.1 取消請求
模型上下文協議支持通過通知消息可選地取消正在進行的請求。任何一方都可以發送取消通知,表明以前發出的請求應該終止。
4.5.1.1 取消流程
當一方希望取消一個正在進行的請求時,它會發送一個 notifications/cancelled 通知,其中包括:
-
要取消的請求 ID
-
可以記錄或顯示可選的原因字符串
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
4.5.1.2 行爲要求
-
取消通知必須只有請求:
-
先前已向同一方向發出
-
確信仍在進行中
-
-
客戶端不能取消初始化請求
-
取消通知的接收方應該:
-
停止處理取消的請求
-
釋放相關資源
-
不爲取消的請求發送響應
-
-
接收方可以忽略取消通知,如果:
-
引用的請求未知
-
處理工作已經完成
-
請求無法取消
-
-
取消通知的發送方應該忽略對隨後到達請求的任何響應
4.5.1.3 時機的考量
由於網絡延遲,取消通知可能在請求處理完成之後到達,並且可能在響應已經發送之後到達。
雙方都必須妥善處理這些競爭條件:
4.5.1.4 實施說明
-
爲了調試,雙方都應該記錄請求取消原因
-
應用程序的 UI 應該指示何時請求取消 ####4.5.1.5 錯誤處理
無效的取消通知應該被忽略:
-
未知的請求 ID
-
已經處理完成的請求
-
格式錯誤的通知
這保持了通知的 “發送和忘記” 特性,同時允許異步通信中的競態條件。
4.5.2 Ping
模型上下文協議包含一個可選的 ping 機制,允許任何一方驗證對方是否仍然響應,以及連接是否存在。
4.5.2.1 概覽
Ping 功能是通過簡單的請求 / 響應模式實現的。客戶端或服務器都可以通過發送 ping 請求來初始化一個 ping。
4.5.2.2 消息格式
Ping 請求是一個沒有參數的標準 JSON-RPC 請求:
{
"jsonrpc": "2.0",
"id": "123",
"method": "ping"
}
4.5.2.3 行爲要求
接收方必須立即作出一個空響應:
{ "jsonrpc": "2.0", "id": "123", "result": {} }
如果在合理的超時期限內沒有收到響應,則發送方可以:
-
考慮連接是否過期
-
終止連接
-
嘗試重新連接
4.5.2.4 使用模式
4.5.2.5 實現的考量
-
實現應該週期性發出 ping 以檢測連接的健康狀況
-
Ping 的頻率應該是可配置的
-
超時應適用於網絡環境
-
應該避免過多的 ping 以減少網絡開銷
4.5.2.6 錯誤處理
-
超時應被視爲連接失敗
-
多個失敗的 ping 可能觸發連接復位
-
具體實現應該記錄診斷失敗的日誌
4.5.3 進度
模型上下文協議支持以通知消息對長時間運行的操作執行可選的進度跟蹤。任何一方都可以發送進度通知,以提供有關操作狀態的更新。
4.5.3.1 進度流程
當一方希望接收請求的進度更新時,它會在請求元數據中包含 progressToken。
-
進度令牌必須是字符串或整數值
-
發送方可以使用任何方法選擇進度令牌,但是在所有進行的請求中必須是唯一的。
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
然後,接收方可以發送進度通知,內容包括:
- 原始進度令牌
- 迄今爲止的當前進度值
- 一個可選的 “total” 值
- 一個可選的 “message” 值
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
-
進度值必須隨着每次通知而增加,即使總數是未知的。
-
進度值和總值可以是浮點數。
-
消息字段應該提供相關的人類可讀的進度信息。
4.5.3.2 行爲要求
進度通知必須只引用以下令牌:
-
在主動請求中提供
-
與正在進行的操作關聯
進度請求的接收方可以:
-
選擇不發送任何進度通知
-
以他們認爲合適的頻率發送通知
-
如果未知,則省略總值
4.5.3.3 實施指南
-
發送方和接收方應該跟蹤活動的進度令牌
-
雙方應實行限速,以防止通知氾濫
-
進度通知必須在完成後停止發送
5 客戶端特性
5.1 根目錄
模型上下文協議爲客戶端向服務器公開文件系統的 “根目錄” 提供了一種標準化的方法。Root 定義了服務器可以在文件系統中操作的邊界,允許服務器理解它們可以訪問哪些目錄和文件。服務器可以從支持的客戶端中請求根目錄的列表,並在該列表發生更改時接收通知。
5.1.1 用戶交互模型
MCP 中的根通常通過工作區或項目配置接口公開。
例如,實現可以提供一個工作區 / 項目選擇器,允許用戶選擇服務器應該訪問的目錄和文件。這可以與來自版本控制系統或項目文件的自動工作區檢測相結合。
然而,具體實現可以自由地通過任何符合其需要的接口模式來公開 “根”,協議本身並不要求任何特定的用戶交互模型。
5.1.2 能力
支持根目錄的客戶端必須在初始化期間聲明根目錄的能力:
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
listChanged 指示當根列表發生更改時,客戶端是否發出通知。
5.1.3 協議消息
5.1.3.1 Listing Roots
爲了檢索根目錄,服務器發送一個 roots/list 請求。
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
5.1.3.2 Root List 變更
當根發生變更時,支持 listChanged 的客戶端必須發送一個通知。
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
5.1.4 消息流程
5.1.5 數據類型
5.1.5.1 Root
根的定義包括:
URI: root 的唯一標識符,必須是當前規範中的文件://URI。
名稱:用於顯示目的的人類可讀名稱 (可選)。
不同用例的 root 示例:
項目目錄
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
多儲存庫
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
5.1.6 錯誤處理
對於常見的失敗情況,客戶端應該返回標準的 JSON-RPC 錯誤:
-
客戶端不支持 root:-32601 (未找到方法)
-
內部錯誤:-32603
錯誤示例:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
5.1.7 安全事宜
- 客戶端必須:
-
僅暴露具有適當權限的根
-
驗證所有 root URI 以防止路徑遍歷
-
實現正確的訪問控制
-
監控 root 的可訪問性
- 服務器應該:
-
處理根不可用的情況
-
在操作過程中遵守根的範圍邊界
-
根據提供的根驗證所有路徑
5.1.8 實施指南
客戶端應該:
-
在將 root 暴露給服務器之前提示用戶同意
-
爲 root 管理提供清晰的用戶界面
-
在暴露之前驗證 root 的可訪問性
-
監控 root 變更
服務器應該:
-
使用前請檢查 root 功能
-
優雅地處理根列表變更
-
在操作中遵守根的邊界
-
適當緩存根信息
5.2 採樣
模型上下文協議爲服務器通過客戶端從語言模型請求 LLM 採樣 (“補全” 或 “代替”) 提供了一種標準化的方法。此流程允許客戶端維護對模型訪問、選擇和權限的控制,同時允許服務器利用 AI 功能ーー不需要服務器 API 密鑰。服務器可以請求基於文本、音頻或圖像的交互,還可以在提示詞中包含來自 MCP 服務器的上下文。
5.2.1 用戶交互模型
MCP 中的採樣允許服務器實現智能體行爲,允許 LLM 調用嵌套在其他 MCP 服務器的功能。
具體實現可以自由地通過任何適合其需要的接口模式公開採樣,協議本身並不要求任何特定的用戶交互模型。
爲了信任、保密和安全性,應該總是有一個人工行爲在循環中有能力拒絕採樣請求。
應用應該:
-
提供用戶界面,使其更容易和直觀地審查採樣請求
-
允許用戶在發送之前查看和編輯提示詞
-
提供生成的響應,以便在交付前進行審查 ###5.2.2 能力
支持採樣的客戶端必須在初始化期間聲明採樣能力:
{
"capabilities": {
"sampling": {}
}
}
5.2.3 協議消息
5.2.3.1 創建消息
爲了請求語言模型的一個生成結果,服務器發送一個 sampling/createMessage 請求:
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"role": "assistant",
"content": {
"type": "text",
"text": "The capital of France is Paris."
},
"model": "claude-3-sonnet-20240307",
"stopReason": "endTurn"
}
}
5.2.4 消息流程
5.2.5 數據類型
5.2.5.1 消息
採樣信息可以包含:
文字內容
{
"type": "text",
"text": "The message content"
}
圖片內容
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/jpeg"
}
音頻內容
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
5.2.6 模型偏好設置
MCP 中的模型選擇需要仔細的抽象,因爲服務器和客戶端可能使用不同的 AI 提供者提供不同的模型。服務器不能簡單地通過名稱請求特定的模型,因爲客戶端可能無法訪問該確切的模型,或者可能更喜歡使用不同提供者的等價模型。
爲了解決這個問題,MCP 實現了一個偏好設置系統,將抽象的能力優先級與可選的模型引導結合起來。
5.2.6.1 能力優先級
服務器通過三個規範化的優先級值 (0-1) 來表達它們的需求:
-
成本優先: 最小化成本的重要程度? 更高的值傾向於更便宜的模型。
-
速度優先: 低延遲的重要程度? 更高的值傾向於更快的模型。
-
智能優先: 智能的程度? 更高的值傾向於更有能力的模型。
5.2.6.2 模型引導
雖然優先級有助於根據特徵選擇模型,但引導允許服務器建議特定的模型或模型家族:
-
引導被視爲可以靈活匹配模型名稱的子字符串
-
按偏好順序計算多個引導詞
-
客戶端可以將引導詞映射到來自不同提供者的等效模型
-
提示是建議性的ーー最終由客戶端選擇模型
例如:
{
"hints": [
{ "name": "claude-3-sonnet" }, // Prefer Sonnet-class models
{ "name": "claude" } // Fall back to any Claude model
],
"costPriority": 0.3, // Cost is less important
"speedPriority": 0.8, // Speed is very important
"intelligencePriority": 0.5 // Moderate capability needs
}
客戶端處理這些偏好項以從其可用選項中選擇適當的模型。例如,如果客戶端沒有訪問 Claude 模型,但有 Gemini,它可能會基於類似的功能將 sonnet 引導映射到 Gemini-1.5-pro。
5.2.7 錯誤處理
對於常見的故障情況,客戶端應該返回錯誤:
錯誤示例:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -1,
"message": "User rejected sampling request"
}
}
5.2.7 安全事宜
-
客戶端應實現用戶審批控制
-
雙方都應該驗證消息內容
-
客戶端應該遵循模型的偏好引導
-
客戶端應實施速率限制
-
雙方必須適當地處理敏感數據
6. 服務器特性
6.1 概覽
服務器提供了通過 MCP 向語言模型添加上下文的基本構建塊。這些原語支持客戶端、服務器和語言模型之間的豐富交互:
-
提示詞: 指導語言模型交互的預定義模板或指令
-
資源: 爲模型提供附加上下文的結構化數據或內容
-
工具: 允許模型執行操作或檢索信息的可執行函數
每個原語可以歸納爲以下的控制層次結構:
以下更詳細地探討這些關鍵原語:提示詞、資源和工具。
6.2 提示詞
模型上下文協議 (Model Context Protocol,MCP) 爲服務器向客戶機公開提示模板提供了一種標準化的方法。提示允許服務器提供與語言模型交互的結構化消息和指令。客戶機可以發現可用的提示,檢索它們的內容,並提供參數來定製它們。
6.2.1 用戶交互模型
提示詞被設計爲由用戶控制,這意味着它們從服務器公開給客戶端,用戶可以顯式地選擇它們來使用。
通常,提示詞將通過用戶界面中由用戶發起的命令觸發,這允許用戶自然地發現和調用可用的提示次。例如,作爲斜槓命令。
然而,實現者可以自由地通過任何適合他們需要的接口模式公開提示詞ーー協議本身並不要求任何特定的用戶交互模型。
6.2.2 能力
支持提示詞的服務器必須在初始化期間聲明提示詞功能:
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
listChanged 指示了當可用提示詞列表發生更改時,服務器是否發出通知。
6.2.3 協議消息
6.2.3.1 對提示詞進行檢索
爲了檢索可用的提示詞,客戶端發送一個 prompts/list 請求。此操作支持分頁。
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
6.2.3.2 獲得提示詞
爲了檢索特定的提示詞,客戶端發送一個 prompts/get 請求。參數可以通過完整的 API 自動完成。
請求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
響應:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
6.2.3.3 變更通知
當可用提示詞列表發生更改時,聲明 listChanged 能力的服務器應發送通知:
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
6.2.4 消息流
6.2.5 數據類型
6.2.5.1 提示詞
一個提示詞的定義包括:
-
名稱:提示詞的唯一標識符
-
說明:可選的人類可讀說明
-
參數:可選的自定義參數列表 ####6.2.5.2 提示詞消息
一個提示詞中的消息可以包含:
角色:指代說話者是 “用戶” 或 “助手”
內容:以下內容類型之一:
文字內容
文本內容表示純文本消息:
{
"type": "text",
"text": "The text content of the message"
}
這是用於自然語言交互的最常見內容類型。
圖片內容
圖像內容允許在消息中包含視覺信息:
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
圖像數據必須是 base64 編碼,並且包含有效的 MIME 類型。這使得多模態交互在視覺上下文很重要的地方成爲可能。
音頻內容
音頻內容允許在消息中包含音頻信息:
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
音頻數據必須是 base64 編碼,並且包含有效的 MIME 類型。這使得在音頻上下文很重要的情況下進行多模態交互成爲可能。
嵌入式資源
嵌入式資源允許在消息中直接引用服務器端資源:
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
資源可以包含文本或二進制 (blob) 數據,必須包括:
-
有效的資源 URI
-
適當的 MIME 類型
-
文本內容或 base64 編碼的 blob 數據
嵌入式資源允許提示詞將服務器管理的內容 (如文檔、代碼示例或其他參考資料) 無縫地直接合併到會話流中。
6.2.6 錯誤處理
對於常見的故障情況,服務器應該返回標準的 JSON-RPC 錯誤:
-
無效提示詞名稱:-32602 (Invalid params)
-
缺少所需參數: -32602 (Invalid params)
-
內部錯誤: -32603 (Internal error)
6.2.7 實施考慮
-
服務器在處理前驗證提示參數
-
客戶端應該處理大型提示詞列表的分頁
-
雙方應該遵循能力協商
6.2.8 安全性
具體實現必須仔細驗證所有提示詞的輸入和輸出,以防止注入攻擊或未經授權的資源訪問。
6.3 資源
模型上下文協議爲服務器向客戶端公開資源提供了一種標準化的方法。資源允許服務器共享爲語言模型提供上下文的數據,例如文件、數據庫模式或特定於應用程序的信息。每個資源都由一個 URI 唯一標識。
6.3.1 用戶交互模型
MCP 中的資源被設計爲由應用程序所驅動,由主機應用程序根據自己的需要確定如何合併上下文。
例如,應用程序可以:
-
在樹視圖或列表視圖中,通過 UI 元素公開資源以進行顯式選擇
-
允許用戶搜索和篩選可用資源
-
基於啓發式或人工智能模型的選擇。實現自動上下文包含
然而,具體實現可以通過任何適合其需要的接口模式自由地公開資源ーー協議本身並不強制任何特定的用戶交互模型。
6.3.3 能力
支持資源的服務器必須聲明資源能力:
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
該能力支持兩個可選特性:
-
Subscribe: 客戶端是否可以訂閱以獲得單個資源更改的通知。
-
listChanged: 當可用資源列表發生更改時,服務器是否發出通知。
Subscribe 和 listChanged 都是可選的ーー服務器可以不支持它們,也可以支持它們中的一個,或者兩者都支持:
{
"capabilities": {
"resources": {} // Neither feature supported
}
}
{
"capabilities": {
"resources": {
"subscribe": true // Only subscriptions supported
}
}
}
{
"capabilities": {
"resources": {
"listChanged": true // Only list change notifications supported
}
}
}
6.3.4 協議消息
6.3.4.1 資源的檢索
爲了發現可用的資源,客戶端發送一個 resources/list 請求。此操作支持分頁。
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
6.3.4.2 讀取資源
爲了檢索資源內容,客戶端發送一個 resources/read 請求。
請求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
響應:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
6.3.4.3 資源模板
資源模板允許服務器使用 URI 模板公開參數化的資源。參數可以通過 API 自動補全。
請求:
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list"
}
響應:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
]
}
}
6.3.4.4 名單更改通知
當可用資源列表發生更改時,聲明 listChanged 功能的服務器應發送通知。
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
6.3.4.5 訂閱
該協議支持對資源更改的可選訂閱。客戶端可以訂閱特定的資源,並在資源更改時接收通知。
訂閱請求:
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
更新通知:
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
6.3.5 消息流程
6.3.6 數據類型
6.3.6.1 資源
一個資源定義包括:
-
Uri: 資源的唯一標識符
-
名稱:人類可讀的名稱
-
描述: 可選的描述
-
mimeType: 可選的 MIME 類型
-
Size: 可選的大小 (字節) ####6.3.6.2 資源內容
資源可以包含文本數據或二進制數據:
文字內容
{
"uri": "file:///example.txt",
"mimeType": "text/plain",
"text": "Resource content"
}
二進制內容
{
"uri": "file:///example.png",
"mimeType": "image/png",
"blob": "base64-encoded-data"
}
6.3.6.3 常見的 URI 方案
該協議定義了幾個標準的 URI 模式。這個列表並不詳盡,具體實現總是可以自由地使用額外的、自定義的 URI 模式。
https://
用於表示 web 上可用的資源。
只有當客戶端能夠自己直接從 web 獲取和加載資源時,服務器才應該使用這種方案ーー也就是說,它不需要通過 MCP 服務器讀取資源。
對於其他用例,服務器應該優先使用另一個 URI 方案,或者定義一個自定義 URI 方案,即使服務器本身將通過 internet 下載資源內容。
file://
用於標識行爲類似於文件系統的資源。但是,資源不需要映射到實際的物理文件系統。
MCP 服務器可以使用 XDG MIME 類型標識 file:// 資源,比如 inode/directory,來表示沒有標準 MIME 類型的非常規文件 (比如目錄)。
git://
Git 版本控制集成。
6.3.7 錯誤處理
對於常見的故障情況,服務器應該返回標準的 JSON-RPC 錯誤:
-
未找到資源:-32002
-
內部錯誤:-32603
錯誤示例:
{
"jsonrpc": "2.0",
"id": 5,
"error": {
"code": -32002,
"message": "Resource not found",
"data": {
"uri": "file:///nonexistent.txt"
}
}
}
6.3.8 安全事宜
-
服務器必須驗證所有資源的 URI
-
應對敏感資源實施訪問控制
-
二進制數據必須正確編碼
-
操作前應檢查資源權限
6.4 工具
模型上下文協議允許服務器公開可由語言模型調用的工具。工具使模型能夠與外部系統交互,例如查詢數據庫、調用 api 或執行計算。每個工具都由名稱唯一標識,幷包含描述其模式的元數據。
6.4.1 用戶交互模型
MCP 中的工具被設計爲由模型控制,這意味着語言模型可以根據其上下文理解和用戶的提示詞自動發現和調用工具。
然而,具體實現可以通過任何適合其需要的接口模式自由地公開工具ーー協議本身並不強制要求任何特定的用戶交互模型。
爲了信任、保密和安全性,在循環中應該始終有一個人工操控有能力拒絕工具調用。
應用應該:
-
提供用戶界面,清楚地說明哪些工具將公開給 AI 模型
-
在調用工具時插入清晰的可視化指示詞
-
確認當前提示給用戶進行操作,以確保有人可以在操作循環中 ### 6.4.2 能力
支持工具的服務器必須聲明工具能力:
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
listChanged 指示當可用工具列表發生更改時,服務器是否發出通知。
6.4.3 協議消息
6.4.3.1 對工具的檢索
爲了發現可用的工具,客戶端發送一個 tools/list 請求。這個操作支持分頁。
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
}
],
"nextCursor": "next-page-cursor"
}
}
6.4.3.2 調用工具
要調用工具,客戶端發送一個 tools/call 請求:
請求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
響應:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
6.4.3.3 更改通知
當可用工具列表發生更改時,聲明 listChanged 功能的服務器應該發送一個通知:
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
6.4.4 消息流程
6.4.5 數據類型
6.4.5.1 工具
一個工具定義包括:
-
名字: 工具唯一標識符
-
描述: 人類可讀的功能描述
-
inputSchema: 定義預期參數的 json schema
-
註釋: 描述工具行爲的可選屬性
爲了信任、保密和安全性,客戶端必須認爲工具註釋是不可信的,除非它們來自受信任的服務器。
6.4.5.2 工具結果
工具結果可以包含不同類型的多個內容項:
文本內容
{
"type": "text",
"text": "Tool result text"
}
圖片內容
{
"type": "image",
"data": "base64-encoded-data",
"mimeType": "image/png"
}
音頻內容
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
嵌入式資源
可以將資源嵌入到 URI 後面,以提供額外的上下文或數據,客戶端以後可以訂閱或再次獲取這些 URI:
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
6.4.6 錯誤處理
工具使用兩種錯誤報告機制。
6.4.6.1 協議錯誤
協議錯誤是 標準的 JSON-RPC 錯誤,例如:
-
Unknown tools:未知工具
-
Invalid arguments:無效的參數
-
Server errors:服務器錯誤
協議錯誤示例:
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Unknown tool: invalid_tool_name"
}
}
6.4.6.2 工具執行錯誤
工具執行錯誤在工具結果中使用 isError: true 報告:
-
API failures:API 失敗
-
Invalid input data:無效的輸入數據
-
Business logic errors:業務邏輯錯誤
工具執行錯誤示例:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "Failed to fetch weather data: API rate limit exceeded"
}
],
"isError": true
}
}
6.4.7 安全事宜
1. 服務器必須:
-
驗證所有的工具輸入
-
實施適當的訪問控制
-
工具調用的速率限制
-
清理工具輸出
2 客戶端應該:
-
提示用戶確認敏感操作
-
在調用服務器之前向用戶顯示工具輸入,以避免惡意或意外的數據溢出
-
在傳遞給 LLM 之前驗證工具結果
-
實現工具調用的超時
-
爲審計目的記錄工具的使用情況
6.5 實用程序
6.5.1 補全
模型上下文協議爲服務器提供了一種標準化的方法,用於爲提示詞和資源 uri 提供參數的自動補全建議。這使得用戶可以在輸入參數值時接收上下文建議,從而獲得豐富的類 ide 體驗。
6.5.1.1 用戶交互模型
MCP 中的補全設計用於支持類似於 IDE 代碼補全的交互式用戶體驗。
例如,當用戶輸入時,應用程序可以在下拉菜單或彈出菜單中顯示補全建議,並具有從可用選項中進行篩選和選擇的能力。
然而,具體實現可以自由地通過任何適合其需要的接口模式公開補全的能力,協議本身並不要求任何特定的用戶交互模型。
6.5.1.2 能力
支持補全的服務器必須聲明補全的能力:
{
"capabilities": {
"completions": {}
}
}
6.5.1.3 協議消息
補全的請求
爲了獲得全建議,客戶端通過參考類型發送一個 completion/complete 請求,並指定正在完成的內容。
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
響應:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
參考類型
該協議支持兩種類型的補全:
完成結果
服務器返回一個按相關性排序的補全值的數組,其中包括:
-
每次回覆最多 100 個項
-
可選的可用匹配項總數
-
指示是否存在其他結果的布爾值
6.5.1.4 消息流程
6.5.1.5 數據類型
CompleteRequest
-
ref: 一個 PromptReference 或 ResourceReference
-
argument: 對象包含
-
Name: 參數名稱
-
Value: 當前值
-
CompleteResult
-
completion: 對象包含
-
values: 建議數組 (最大值 100)
-
total: 可選的匹配總數
-
hasMore: 附加結果標誌
-
6.5.1.6 錯誤處理
錯誤處理 對於常見的故障情況,服務器應該返回標準的 JSON-RPC 錯誤:
-
未找到方法:-32601 (Capability not supported)
-
無效提示詞名稱:-32602 (Invalid params)
-
缺少必需的參數:-32602 (Invalid params)
-
內部錯誤: -32603 (Internal error)-32603
6.5.1.7 實施考慮
- 服務器應該:
——按相關性排序返回建議
——在適當的地方實現模糊匹配
——補全請求速率限制
——驗證所有輸入
- 客戶端應該:
-
能夠快速取消補全請求
-
在適當的地方緩存補全結果
-
優雅地處理缺失或部分結果
6.5.1.8 安全性
具體實施必須:
-
驗證所有補全輸入
-
實施適當的速率限制
-
控制對敏感建議的訪問
-
防止基於補全的信息披露
6.5.2 日誌
模型上下文協議爲服務器向客戶端發送結構化日誌消息提供了一種標準化方法。客戶端可以通過設置最低日誌級別來控制日誌記錄的詳細程度,服務器發送包含嚴重級別、可選日誌名稱和任意可序列化 json 數據的通知。
6.5.2.1 用戶交互模型
具體實現可以自由地通過任何符合其需要的接口模式公開日誌記錄,協議本身並不要求任何特定的用戶交互模型。
6.5.2.2 能力
發出日誌消息通知的服務器必須聲明日誌記錄能力:
{
"capabilities": {
"logging": {}
}
}
6.5.2.3 日誌級別
該協議遵循 RFC 5424 規定的標準 syslog 的日誌嚴重級別:
6.5.2.4 協議消息
設置日誌級別
要配置最低日誌級別,客戶端可以發送一個 logging/setLevel 請求 。
請求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
日誌消息通知
服務器使用 notifications/message 發送日誌消息:
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
6.5.2.5 消息流程
6.5.2.6 錯誤處理
對於常見的故障情況,服務器應該返回標準的 JSON-RPC 錯誤:
-
無效日誌級別:-32602 (Invalid params)
-
配置錯誤:-32603 (Internal error) #### 6.5.2.7 實施考慮
1. 服務器應該:
-
日誌消息的速率限制
-
在數據字段中包含相關上下文
-
使用一致的日誌記錄名稱
-
刪除敏感信息
2. 客戶可以:
-
在 UI 中顯示日誌消息
-
實現日誌過濾 / 搜索
-
直觀地顯示嚴重程度
-
持久化日誌消息
6.5.2.8 安全性
1. 日誌消息不能包含:
-
證書或密鑰
-
個人身份信息
-
可能被攻擊的內部系統細節
2. 具體實現應該:
-
速率限制信息
-
驗證所有數據字段
-
控制日誌訪問
-
監視敏感內容
6.5.3 分頁
模型上下文協議支持可能返回大型結果集的分頁列表操作。分頁能夠允許服務器以更小的塊產生結果,而不是一次產生所有結果。
當通過互聯網連接到外部服務時,分頁尤其重要,而且對於本地集成也很有用,可以避免大型數據集的性能問題。
6.5.3.1 分頁模型
MCP 中的分頁使用不透明的基於遊標的方法,而不是編號頁。
-
遊標是不透明的字符串標記,表示結果集中的位置
-
頁面大小由服務器決定,客戶端不能採用固定的頁面大小 #### 6.5.3.2 響應格式
當服務器發送包含以下內容的響應時,開始分頁:
-
結果的當前頁
-
如果存在更多結果,則爲可選的 nextCursor 字段
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"resources": [...],
"nextCursor": "eyJwYWdlIjogM30="
}
}6.5.3.3 請求格式
接收到遊標後,客戶端可以通過發出包括該遊標在內的請求來繼續分頁:
{
"jsonrpc": "2.0",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
6.5.3.4 分頁流程
6.5.3.5 支持分頁的操作
下列 MCP 操作支持分頁:
-
Resources/List - 列出可用的資源
-
Resources/templates/List - 列出資源模板
-
prompts/list - 列出可用的提示詞
-
tools/list - 列出可用的工具
6.5.3.5 實施指引
1. 服務器應該:
-
提供穩定的遊標
-
優雅地處理無效遊標
2. 客戶應該
-
將缺少的 nextCursor 視爲結果的末尾
-
支持分頁和非分頁的流
3. 客戶端必須將遊標視爲不透明的令牌:
-
不要對遊標的格式做任何假設
-
不要嘗試解析或修改遊標
-
不要跨會話持久化遊標 #### 6.5.3.7 錯誤處理 無效的遊標應導致代碼 -32602 錯誤 (Invalid params).。
7. 資源
7.1 版本控制
模型上下文協議使用符合 YYYY-MM-DD 格式的基於字符串的版本標識符,以指示向後不兼容更改的最後日期。
協議版本不會在協議更新時增加,只需更改保持向後兼容。這允許在保持互操作性的同時進行增量改進。
7.1.1 修訂版
修訂內容可標示如下:
-
Draft: 進行中的規範,尚未準備好應用。
-
Current: 當前協議版本,已準備好使用,並可能繼續接收向後兼容的更改。
-
Final: 過去,完整的規範將不會改變。
Current 協議版本是 2025-03-26。
7.1.2 協商
版本協商發生在初始化過程中。客戶端和服務器可以同時支持多個協議版本,但是它們必須同意在會話中使用一個版本。
如果版本協商失敗,該協議提供適當的錯誤處理,允許客戶端在找不到與服務器兼容的版本時正常地終止連接。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/buugkrhgixlb4n1Smcb80w