MCP Specification · 2026-07-28 · zh-TW
多回合請求
Multi Round-Trip Requests (MRTR)
以 InputRequiredResult 與重試請求完成需要額外用戶端輸入的無狀態流程。
多回合請求(Multi Round-Trip Requests, MRTR)是在本版 MCP 規範新增的模式,用來取代先前由伺服器主動送出請求的方式。伺服器若需要執行 roots/list、sampling/createMessage 或 elicitation/create 等「伺服器向用戶端取得輸入」的互動,MUST(必須)使用 MRTR;舊的 server-initiated request 模式已不再支援。
為了簡潔,本頁部分 JSON 範例省略每次請求的 _meta 協定欄位。依 Base Protocol,io.modelcontextprotocol/protocolVersion 與 io.modelcontextprotocol/clientCapabilities MUST(必須)出現在每個請求;io.modelcontextprotocol/clientInfo 為選用欄位,但用戶端 SHOULD(應該)在未特別停用時提供。
多回合請求
MCP 中有些操作在處理過程中需要向使用者或用戶端取得額外資訊。MRTR 提供標準化的無狀態流程,不要求不同伺服器實例共用儲存,也不要求使用 stateful load balancing。
- 用戶端以執行操作所需的參數送出初始請求。
- 伺服器判斷資訊不足,回傳需要額外輸入的結果。
- 用戶端從使用者或其他來源取得所需資料,再重送原始請求,並附上額外輸入。
- 伺服器確認資訊足夠後,回傳最終結果。
每一回合都是彼此獨立的 JSON-RPC 請求。處理重試的伺服器不需要知道前一次請求的記憶體狀態;必要的狀態應由請求本身攜帶。
核心型別
InputRequests
InputRequests 是伺服器希望用戶端完成之請求的 map。key 是伺服器自行指定的字串識別碼;value 是請求物件,例如 ElicitRequest、CreateMessageRequest 或 ListRootsRequest。
{
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": { "name": { "type": "string" } },
"required": ["name"]
}
}
}
}
InputResponses
InputResponses 是用戶端對前述伺服器請求的回覆 map。key 對應 InputRequests 中的 key,value 則是各請求的結果,例如 ElicitResult、CreateMessageResult 或 ListRootsResult。
{
"github_login": {
"action": "accept",
"content": { "name": "octocat" }
}
}
InputRequiredResult
InputRequiredResult 是一種 Result,表示目前尚不能完成請求,仍需要額外輸入:
inputRequests(選用):伺服器希望用戶端完成的InputRequestsmap。requestState(選用):只有伺服器能理解的不透明字串。用戶端 MUST NOT(不得)檢查、解析、修改它,也不得對其內容作任何假設。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "input_required",
"inputRequests": {
"github_login": {
"method": "elicitation/create",
"params": { "mode": "form", "message": "Please provide your GitHub username" }
}
},
"requestState": "AEAD-protected blob"
}
}
支援的請求
伺服器 MAY(可以)在下列用戶端請求回傳 InputRequiredResult:
| 用戶端請求 | 可回傳 InputRequiredResult |
|---|---|
prompts/get | 是 |
resources/read | 是 |
tools/call | 是 |
伺服器 MUST NOT(不得)在其他用戶端請求中回傳 InputRequiredResult。
基本流程
以下以 tools/call 為例;相同模式也適用於前述其他支援的請求。
- 用戶端送出
tools/call。 - 伺服器需要更多資料,回傳包含
inputRequests與/或requestState的InputRequiredResult;初始請求到此即結束。 - 用戶端完成需要的 Elicitation/Sampling/Roots 輸入。
- 用戶端以新的 JSON-RPC
id重送原始tools/call,並附上inputResponses與原樣回傳的requestState。 - 伺服器只依新請求中的資料重建所需狀態並完成操作。
伺服器要求
- 伺服器 MAY(可以)對任何支援 MRTR 的用戶端請求回傳
InputRequiredResult。 inputRequests為選用;若存在,其 key 由伺服器指定,且在該請求範圍內 MUST(必須)唯一;value MUST(必須)是ElicitRequest、CreateMessageRequest或ListRootsRequest之一。requestState為選用,格式完全由伺服器決定,例如 base64 JSON、加密 JWT 或序列化二進位資料。- 當重試請求帶有
requestState時,伺服器 MUST(必須)把它視為攻擊者可控制的輸入。如果它會影響授權、資源存取或商業邏輯,伺服器 MUST(必須)保護其完整性(例如 HMAC 或 AEAD),並拒絕驗證失敗的狀態。只有在竄改最多只會導致請求失敗時,才 MAY(可以)省略完整性保護。 - 為限制 replay,伺服器 SHOULD(應該)把已驗證 principal、短效 TTL,以及原始請求識別資訊(例如 method 與重要參數摘要)放入受到完整性保護的
requestState,並在接收時逐一驗證。若業務要求狀態只能被消耗一次,則仍 MUST(必須)由伺服器端額外維護 single-use invariant。 - 每一個
InputRequiredResultMUST(必須)至少包含inputRequests或requestState其中之一。 - 伺服器 MUST NOT(不得)要求用戶端沒有在 capabilities 宣告支援的輸入。例如用戶端沒有宣告
elicitation時,不得在inputRequests放入elicitation/create。 - 伺服器 MUST NOT(不得)假設用戶端一定會完成
inputRequests或重試原請求。若應用希望持續向使用者詢問直到資訊足夠,伺服器 MAY(可以)在多次嘗試中重複回傳InputRequiredResult。
用戶端要求
- 若
InputRequiredResult含有inputRequests,用戶端在重試原始請求前 MUST(必須)建立所要求的輸入;若沒有inputRequests,則用戶端 MAY(可以)立刻重試。 - 若結果含有
requestState,用戶端重試時 MUST(必須)原封不動回傳相同值,並 MUST NOT(不得)檢查、解析、修改或猜測內容。若原結果沒有requestState,重試時也 MUST NOT(不得)自行加入。 - 初始請求與重試請求是兩個獨立 JSON-RPC 請求,因此
idMUST(必須)不同。 inputRequests與requestState只影響對原始請求的這次重試,MUST NOT(不得)套用到用戶端並行送出的其他請求。
錯誤處理
伺服器 SHOULD(應該)驗證用戶端提供的資料是否為合法的 InputResponses,且內容可以正確解析。格式不正確的 JSON、schema 錯誤或伺服器內部錯誤,SHOULD(應該)以適當的 JSON-RPC error code 與 message 回覆。
若 InputResponses 含有額外且未預期的欄位,伺服器 SHOULD(應該)忽略自己不認得或不需要的資料。若用戶端漏掉先前要求、而且完成請求確實需要的資訊,伺服器 SHOULD(應該)再次回傳新的 InputRequiredResult 要求缺少的資訊,而不是直接回傳錯誤。
安全考量
requestState 會經過用戶端,因此惡意或遭入侵的用戶端可能嘗試修改它,藉此改變伺服器行為、繞過授權檢查或破壞商業邏輯。伺服器 MUST(必須)依前述伺服器要求驗證並保護 requestState。