授权
协议版本:2025-03-26
简介
目的和范围
模型上下文协议在传输层提供授权能力,使 MCP 客户端能够代表资源所有者向受限的 MCP 服务器发出请求。本规范定义了基于 HTTP 传输的授权流程。
协议要求
授权对于 MCP 实现是可选的。当支持时:
- 使用基于 HTTP 的传输的实现应该遵循此规范。
- 使用 STDIO 传输的实现不应该遵循此规范,而应从环境中检索凭据。
- 使用替代传输的实现必须遵循其协议的既定安全最佳实践。
标准合规性
此授权机制基于以下列出的既定规范,但实现了其功能的选定子集,以确保安全性和互操作性,同时保持简洁性:
- OAuth 2.1 IETF DRAFT
- OAuth 2.0 授权服务器元数据 (RFC8414)
- OAuth 2.0 动态客户端注册协议 (RFC7591)
授权流程
概述
MCP 授权实现必须实现 OAuth 2.1,并为机密客户端和公共客户端采取适当的安全措施。
MCP 授权实现应该支持 OAuth 2.0 动态客户端注册协议 (RFC7591)。
MCP 服务器应该实现 OAuth 2.0 授权服务器元数据 (RFC8414),MCP 客户端必须实现 OAuth 2.0 授权服务器元数据。不支持授权服务器元数据的服务器必须遵循默认 URI 架构。
OAuth 授权类型
OAuth 指定了不同的流程或授权类型,这是获取访问令牌的不同方式。每种方式针对不同的用例和场景。
MCP 服务器应该支持与预期受众最一致的 OAuth 授权类型。例如:
- 授权代码:当客户端代表(人类)最终用户时很有用。
- 例如,代理调用由 SaaS 系统实现的 MCP 工具。
- 客户端凭据:客户端是另一个应用程序(不是人类)
- 例如,代理调用安全的 MCP 工具来检查特定商店的库存。无需模拟最终用户。
示例:授权代码授权
这演示了用于用户授权的授权代码授权类型的 OAuth 2.1 流程。
注意:以下示例假设 MCP 服务器也充当授权服务器。但是,授权服务器可以部署为自己的独立服务。
人类用户通过 Web 浏览器完成 OAuth 流程,获得识别其个人的访问令牌,并允许客户端代表其行事。
当需要授权且客户端尚未证明时,服务器必须响应 HTTP 401 Unauthorized。
客户端在收到 HTTP 401 Unauthorized 后启动 OAuth 2.1 IETF DRAFT 授权流程。
以下演示了使用 PKCE 的公共客户端的基本 OAuth 2.1。
sequenceDiagram
participant B as 用户代理(浏览器)
participant C as 客户端
participant M as MCP 服务器
C->>M: MCP 请求
M->>C: HTTP 401 Unauthorized
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_verifier 的令牌请求
M->>C: 访问令牌(+ 刷新令牌)
C->>M: 带有访问令牌的 MCP 请求
Note over C,M: 开始标准 MCP 消息交换
服务器元数据发现
对于服务器功能发现:
- 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 Not Found
Note over C: 回退到默认端点
end
Note over C: 继续授权流程
服务器元数据发现头
MCP 客户端应该在服务器元数据发现期间包含头 MCP-Protocol-Version: <protocol-version>,以允许 MCP 服务器根据 MCP 协议版本进行响应。
例如:MCP-Protocol-Version: 2024-11-05
授权基础 URL
授权基础 URL 必须通过丢弃任何现有的 path 组件从 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 中的任何路径组件如何。
不支持元数据发现的服务器的回退
对于未实现 OAuth 2.0 授权服务器元数据的服务器,客户端必须使用相对于授权基础 URL的以下默认端点路径:
| 端点 | 默认路径 | 描述 |
|---|---|---|
| 授权端点 | /authorize | 用于授权请求 |
| 令牌端点 | /token | 用于令牌交换和刷新 |
| 注册端点 | /register | 用于动态客户端注册 |
例如,对于托管在 https://api.example.com/v1/mcp 的 MCP 服务器,默认端点将是:
https://api.example.com/authorizehttps://api.example.com/tokenhttps://api.example.com/register
客户端必须首先尝试通过元数据文档发现端点,然后再回退到默认路径。使用默认路径时,所有其他协议要求保持不变。
动态客户端注册
MCP 客户端和服务器应该支持 OAuth 2.0 动态客户端注册协议,以允许 MCP 客户端在无需用户交互的情况下获取 OAuth 客户端 ID。这为客户端自动注册新服务器提供了标准化的方式,这对于 MCP 至关重要,因为:
- 客户端无法提前知道所有可能的服务器
- 手动注册会给用户带来摩擦
- 它实现了与新服务器的无缝连接
- 服务器可以实现自己的注册策略
任何不支持动态客户端注册的 MCP 服务器都需要提供获取客户端 ID 的替代方法(以及适用的客户端密钥)。对于这些服务器之一,MCP 客户端将不得不:
- 硬编码专门为该 MCP 服务器使用的客户端 ID(以及适用的客户端密钥),或
- 向用户呈现 UI,允许他们输入这些详细信息,在他们自己注册 OAuth 客户端之后(例如,通过服务器托管的配置界面)。
授权流程步骤
完整的授权流程进行如下:
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 请求
决策流程概述
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[使用访问令牌]
访问令牌使用
令牌要求
访问令牌处理必须符合 OAuth 2.1 第 5 节的资源请求要求。具体来说:
- MCP 客户端必须使用授权请求头字段 第 5.1.1 节:
Authorization: Bearer <access-token>请注意,授权必须包含在从客户端到服务器的每个 HTTP 请求中,即使它们属于同一个逻辑会话。
- 访问令牌绝不能包含在 URI 查询字符串中
示例请求:
GET /v1/contexts HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...令牌处理
资源服务器必须按照 第 5.2 节中的描述验证访问令牌。如果验证失败,服务器必须按照 第 5.3 节错误处理要求进行响应。无效或过期的令牌必须收到 HTTP 401 响应。
安全注意事项
必须实现以下安全要求:
- 客户端必须遵循 OAuth 2.0 最佳实践安全地存储令牌
- 服务器应该强制执行令牌过期和轮换
- 所有授权端点必须通过 HTTPS 提供
- 服务器必须验证重定向 URI 以防止开放重定向漏洞
- 重定向 URI 必须是 localhost URL 或 HTTPS URL
错误处理
服务器必须为授权错误返回适当的 HTTP 状态代码:
| 状态代码 | 描述 | 用法 |
|---|---|---|
| 401 | Unauthorized | 需要授权或令牌无效 |
| 403 | Forbidden | 无效作用域或权限不足 |
| 400 | Bad Request | 格式错误的授权请求 |
实现要求
- 实现必须遵循 OAuth 2.1 安全最佳实践
- 所有客户端都需要 PKCE
- 应该实现令牌轮换以增强安全性
- 应该根据安全要求限制令牌生命周期
第三方授权流程
概述
MCP 服务器可以通过第三方授权服务器支持委派授权。在此流程中,MCP 服务器既是 OAuth 客户端(对第三方授权服务器),又是 OAuth 授权服务器(对 MCP 客户端)。
流程描述
第三方授权流程包括以下步骤:
- MCP 客户端启动与 MCP 服务器的标准 OAuth 流程
- MCP 服务器将用户重定向到第三方授权服务器
- 用户授权第三方服务器
- 第三方服务器使用授权代码重定向回 MCP 服务器
- MCP 服务器交换代码以获取第三方访问令牌
- MCP 服务器生成自己的绑定到第三方会话的访问令牌
- 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 访问令牌
会话绑定要求
实现第三方授权的 MCP 服务器必须:
- 维护第三方令牌和颁发的 MCP 令牌之间的安全映射
- 在兑现 MCP 令牌之前验证第三方令牌状态
- 实施适当的令牌生命周期管理
- 处理第三方令牌过期和续订
安全注意事项
实现第三方授权时,服务器必须:
- 验证所有重定向 URI
- 安全地存储第三方凭据
- 实施适当的会话超时处理
- 考虑令牌链的安全影响
- 为第三方授权失败实施适当的错误处理
最佳实践
本地客户端作为公共 OAuth 2.1 客户端
我们强烈建议本地客户端实现为公共 OAuth 2.1 客户端:
- 利用代码质询(PKCE)进行授权请求以防止拦截攻击
- 实施适合本地系统的安全令牌存储
- 遵循令牌刷新最佳实践以维护会话
- 正确处理令牌过期和续订
授权元数据发现
我们强烈建议所有客户端实施元数据发现。这减少了用户手动提供端点或客户端回退到定义的默认值的需要。
动态客户端注册
由于客户端提前不知道 MCP 服务器集,我们强烈建议实施动态客户端注册。这允许应用程序自动注册到 MCP 服务器,并消除了用户手动获取客户端 ID 的需要。