授權

協議版本: 草案

1. 介紹

1.1 目的和範圍

模型上下文協議在傳輸層提供授權功能,使 MCP 客戶端能夠代表資源所有者向受限的 MCP 服務器發出請求。本規範定義了 HTTP+SSE 傳輸的授權流程。

1.2 協議要求

授權對 MCP 實現是可選的。當支持時:

  • 使用 HTTP+SSE 傳輸的實現應該遵守本規範。
  • 使用 STDIO 傳輸的實現不應該遵循本規範,而應從環境中檢索憑據。
  • 使用其他傳輸的實現必須遵循其協議的既定安全最佳實踐。

1.3 標準合規性

此授權機制基於下面列出的既定規範,但實現了其特性的選定子集,以確保安全性和互操作性,同時保持簡單性:

2. 授權流程

2.1 概述

  1. MCP 授權實現必須實現 OAuth 2.1,併為機密和公共客戶端提供適當的安全措施。

  2. MCP 授權實現應該支持 OAuth 2.0 動態客戶端註冊協議 (RFC7591)。

  3. MCP 服務器應該和 MCP 客戶端必須實現 OAuth 2.0 授權服務器元數據 (RFC8414)。不支持授權服務器元數據的服務器必須遵循默認 URI 模式。

2.2 基本 OAuth 2.1 授權

當需要授權且客戶端尚未證明時,服務器必須響應 HTTP 401 未授權

客戶端在收到 HTTP 401 未授權 後啟動 OAuth 2.1 IETF 草案 授權流程。

以下演示了使用 PKCE 的公共客戶端的基本 OAuth 2.1。

  sequenceDiagram
    participant B as 用戶代理(瀏覽器)
    participant C as 客戶端
    participant M as MCP 服務器

    C->>M: MCP 請求
    M->>C: HTTP 401 未授權
    Note over C: 生成 code_verifier 和 code_challenge
    C->>B: 打開帶有授權 URL + code_challenge 的瀏覽器
    B->>M: GET /authorize
    Note over M: 用戶登錄並授權
    M->>B: 重定向到回調 URL 並帶有授權碼
    B->>C: 帶有授權碼的回調
    C->>M: 帶有 code + code_verifier 的令牌請求
    M->>C: 訪問令牌(+ 刷新令牌)
    C->>M: 帶有訪問令牌的 MCP 請求
    Note over C,M: 開始標準 MCP 消息交換

2.3 服務器元數據發現

對於服務器能力發現:

  • MCP 客戶端_必須_遵循 RFC8414 中定義的 OAuth 2.0 授權服務器元數據協議。
  • MCP 服務器_應該_遵循 OAuth 2.0 授權服務器元數據協議。
  • 不支持 OAuth 2.0 授權服務器元數據協議的 MCP 服務器_必須_支持回退 URL。

發現流程如下所示:

  sequenceDiagram
    participant C as 客戶端
    participant S as 服務器

    C->>S: GET /.well-known/oauth-authorization-server
    alt 發現成功
        S->>C: 200 OK + 元數據文檔
        Note over C: 使用元數據中的端點
    else 發現失敗
        S->>C: 404 未找到
        Note over C: 回退到默認端點
    end
    Note over C: 繼續授權流程

2.3.1 服務器元數據發現標頭

MCP 客戶端_應該_在服務器元數據發現期間包含標頭 MCP-Protocol-Version: <protocol-version>,以允許 MCP 服務器根據 MCP 協議版本進行響應。

例如:MCP-Protocol-Version: 2024-11-05

2.3.2 授權基礎 URL

授權基礎 URL 必須通過丟棄 SSE 端點 URL 的任何現有 path 組件來確定。例如:

如果 SSE 端點是 https://api.example.com/v1/sse,那麼:

  • 授權基礎 URL 是 https://api.example.com
  • 元數據端點必須位於 https://api.example.com/.well-known/oauth-authorization-server

這確保授權端點始終位於提供 SSE 端點的域的根級別,無論 SSE 端點 URL 中的任何路徑組件如何。

2.3.3 沒有元數據發現的服務器的回退

對於不實現 OAuth 2.0 授權服務器元數據的服務器,客戶端必須使用以下相對於授權基礎 URL 的默認端點路徑(如 第 2.3.2 節 中所定義):

端點默認路徑描述
授權端點/authorize用於授權請求
令牌端點/token用於令牌交換和刷新
註冊端點/register用於動態客戶端註冊

例如,對於 SSE 端點 https://api.example.com/v1/sse,默認端點將是:

  • https://api.example.com/authorize
  • https://api.example.com/token
  • https://api.example.com/register

客戶端必須首先嚐試通過元數據文檔發現端點,然後再回退到默認路徑。使用默認路徑時,所有其他協議要求保持不變。

2.3 動態客戶端註冊

MCP 客戶端和服務器應該支持 OAuth 2.0 動態客戶端註冊協議,以允許 MCP 客戶端無需用戶交互即可獲取 OAuth 客戶端 ID。這為客戶端提供了一種標準化的方式來自動註冊新服務器,這對 MCP 至關重要,因為:

  • 客戶端無法提前知道所有可能的服務器
  • 手動註冊會給用戶帶來摩擦
  • 它使無縫連接到新服務器成為可能
  • 服務器可以實現自己的註冊策略

任何_不_支持動態客戶端註冊的 MCP 服務器需要提供獲取客戶端 ID(以及適用的情況下,客戶端密鑰)的替代方式。對於這些服務器,MCP 客戶端必須:

  1. 專門為該 MCP 服務器硬編碼客戶端 ID(以及適用的情況下,客戶端密鑰),或
  2. 向用戶呈現一個 UI,允許他們在自己註冊 OAuth 客戶端後輸入這些詳細信息(例如,通過服務器託管的配置界面)。

2.4 授權流程步驟

完整的授權流程如下所示:

  sequenceDiagram
    participant B as 用戶代理(瀏覽器)
    participant C as 客戶端
    participant M as MCP 服務器

    C->>M: GET /.well-known/oauth-authorization-server
    alt 服務器支持發現
        M->>C: 授權服務器元數據
    else 無發現
        M->>C: 404(使用默認端點)
    end

    alt 動態客戶端註冊
        C->>M: POST /register
        M->>C: 客戶端憑據
    end

    Note over C: 生成 PKCE 參數
    C->>B: 打開帶有授權 URL + code_challenge 的瀏覽器
    B->>M: 授權請求
    Note over M: 用戶授權
    M->>B: 重定向到回調,帶有授權碼
    B->>C: 授權碼回調
    C->>M: 令牌請求 + code_verifier
    M->>C: 訪問令牌(+ 刷新令牌)
    C->>M: 帶有訪問令牌的 API 請求

2.4.1 決策流程概述

  flowchart TD
    A[開始授權流程] --> B{檢查元數據發現}
    B -->|可用| C[使用元數據端點]
    B -->|不可用| D[使用默認端點]

    C --> G{檢查註冊端點}
    D --> G

    G -->|可用| H[執行動態註冊]
    G -->|不可用| I[需要替代註冊]

    H --> J[開始 OAuth 流程]
    I --> J

    J --> K[生成 PKCE 參數]
    K --> L[請求授權]
    L --> M[用戶授權]
    M --> N[用碼交換令牌]
    N --> O[使用訪問令牌]

2.5 訪問令牌使用

2.5.1 令牌要求

訪問令牌處理必須符合 OAuth 2.1 第 5 節 對資源請求的要求。具體來說:

  1. MCP 客戶端必須使用授權請求頭字段 第 5.1.1 節
Authorization: Bearer <access-token>
  1. 訪問令牌不得包含在 URI 查詢字符串中

請求示例:

GET /v1/contexts HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

2.5.2 令牌處理

資源服務器必須按照 第 5.2 節 中所述驗證訪問令牌。如果驗證失敗,服務器必須根據 第 5.3 節 錯誤處理要求進行響應。無效或過期的令牌必須收到 HTTP 401 響應。

2.6 安全考慮

必須實施以下安全要求:

  1. 客戶端必須按照 OAuth 2.0 最佳實踐安全存儲令牌
  2. 服務器應該強制令牌過期和輪換
  3. 所有授權端點必須通過 HTTPS 提供服務
  4. 服務器必須驗證重定向 URI,以防止開放重定向漏洞
  5. 重定向 URI 必須是 localhost URL 或 HTTPS URL

2.7 錯誤處理

服務器必須為授權錯誤返回適當的 HTTP 狀態碼:

狀態碼描述用途
401未授權需要授權或令牌無效
403禁止無效範圍或權限不足
400錯誤請求授權請求格式錯誤

2.8 實施要求

  1. 實現必須遵循 OAuth 2.1 安全最佳實踐
  2. 所有客戶端需要使用 PKCE
  3. 應該實施令牌輪換以增強安全性
  4. 令牌生命週期應該根據安全要求限制

2.9 第三方授權流程

2.9.1 概述

MCP 服務器可以通過第三方授權服務器支持委託授權。在此流程中,MCP 服務器同時充當 OAuth 客戶端(對第三方授權服務器)和 OAuth 授權服務器(對 MCP 客戶端)。

2.9.2 流程描述

第三方授權流程包括以下步驟:

  1. MCP 客戶端啟動與 MCP 服務器的標準 OAuth 流程
  2. MCP 服務器將用戶重定向到第三方授權服務器
  3. 用戶在第三方服務器上授權
  4. 第三方服務器帶著授權碼重定向回 MCP 服務器
  5. MCP 服務器用授權碼交換第三方訪問令牌
  6. MCP 服務器生成綁定到第三方會話的自己的訪問令牌
  7. MCP 服務器完成與 MCP 客戶端的原始 OAuth 流程
  sequenceDiagram
    participant B as 用戶代理(瀏覽器)
    participant C as MCP 客戶端
    participant M as MCP 服務器
    participant T as 第三方授權服務器

    C->>M: 初始 OAuth 請求
    M->>B: 重定向到第三方 /authorize
    B->>T: 授權請求
    Note over T: 用戶授權
    T->>B: 重定向到 MCP 服務器回調
    B->>M: 授權碼
    M->>T: 用碼交換令牌
    T->>M: 第三方訪問令牌
    Note over M: 生成綁定的 MCP 令牌
    M->>B: 重定向到 MCP 客戶端回調
    B->>C: MCP 授權碼
    C->>M: 用碼交換令牌
    M->>C: MCP 訪問令牌

2.9.3 會話綁定要求

實現第三方授權的 MCP 服務器必須

  1. 維護第三方令牌和已發行 MCP 令牌之間的安全映射
  2. 在認可 MCP 令牌之前驗證第三方令牌狀態
  3. 實施適當的令牌生命週期管理
  4. 處理第三方令牌過期和更新

2.9.4 安全考慮

實施第三方授權時,服務器必須

  1. 驗證所有重定向 URI
  2. 安全存儲第三方憑據
  3. 實施適當的會話超時處理
  4. 考慮令牌鏈接的安全影響
  5. 為第三方授權失敗實施適當的錯誤處理

3. 最佳實踐

3.1 作為公共 OAuth 2.1 客戶端的本地客戶端

我們強烈建議本地客戶端作為公共客戶端實現 OAuth 2.1:

  1. 利用代碼挑戰 (PKCE) 進行授權請求,以防止攔截攻擊
  2. 實施適合本地系統的安全令牌存儲
  3. 遵循令牌刷新最佳實踐以維護會話
  4. 正確處理令牌過期和更新

3.2 授權元數據發現

我們強烈建議所有客戶端實施元數據發現。這減少了用戶手動提供端點或客戶端回退到定義的默認值的需要。

3.3 動態客戶端註冊

由於客戶端無法提前知道 MCP 服務器集,我們強烈建議實施動態客戶端註冊。這允許應用程序自動向 MCP 服務器註冊,並消除了用戶手動獲取客戶端 ID 的需要。