1. 引言
1.1 目的与范围
模型上下文协议(Model Context Protocol, MCP)在传输层提供授权能力,使MCP客户端能够代表资源所有者向受限制的MCP服务器发起请求。本规范定义了基于HTTP的传输协议的授权流程。
1.2 协议要求
授权功能在MCP实现中为可选项。若实现授权功能时:
- 使用基于HTTP传输的实现应遵循本规范;
- 使用STDIO传输的实现不应遵循本规范,而应从环境变量中获取凭据;
- 使用其他传输方式的实现必须遵循其协议领域已确立的安全最佳实践。
1.3 标准合规性
本授权机制基于以下已确立的规范实现,但选择性地实现了其功能子集,在确保安全性、互操作性的同时保持协议简洁性:
- OAuth 2.1 IETF草案
- OAuth 2.0授权服务器元数据(RFC8414)
- OAuth 2.0动态客户端注册协议(RFC7591)
2. 授权流程
2.1 概述
- MCP授权实现必须实现OAuth 2.1,并为机密客户端和公共客户端采取适当的安全措施。
- MCP授权实现应支持OAuth 2.0动态客户端注册协议(RFC7591)。
- MCP服务器应且MCP客户端必须实现OAuth 2.0授权服务器元数据(RFC8414)。不支持授权服务器元数据的服务器必须遵循默认URI架构。
2.1.1 OAuth授权类型
OAuth规范定义了多种授权流程或授权类型(grant types),即获取访问令牌的不同方式,每种类型针对不同的使用场景:
MCP服务器应根据目标用户群体支持最合适的OAuth授权类型,例如:
- 授权码模式(Authorization Code)
- 适用场景:客户端代表终端用户进行操作
- 示例:代理程序调用由SaaS系统实现的MCP工具时使用
- 客户端凭证模式(Client Credentials)
- 适用场景:客户端是应用程序(非人类用户)
- 示例:代理程序调用安全的MCP工具查询特定商店库存时,无需模拟终端用户身份
2.2 示例:授权码模式
本示例展示了用于用户认证的OAuth 2.1授权码模式流程。
注:以下示例假设MCP服务器同时作为授权服务器运行,但授权服务器也可以作为独立服务部署。
人类用户通过网页浏览器完成OAuth流程,获取标识其个人身份的访问令牌,该令牌允许客户端代表用户进行操作。
当需要授权但客户端尚未提供有效凭证时,服务器必须返回HTTP 401 Unauthorized响应。
客户端在收到HTTP 401 Unauthorized后,应启动OAuth 2.1 IETF草案授权流程。
以下示例展示了使用PKCE的公共客户端基本OAuth 2.1流程。
2.3 服务器元数据发现
关于服务器能力发现:
- MCP客户端必须遵循RFC8414定义的OAuth 2.0授权服务器元数据协议。
- MCP服务器应当遵循OAuth 2.0授权服务器元数据协议。
- 不支持OAuth 2.0授权服务器元数据协议的MCP服务器必须支持备用URL。
发现流程如下所示:
2.3.1 服务器元数据发现头部
MCP客户端在进行服务器元数据发现时,应当包含 MCP-Protocol-Version: <协议版本>头部,以便MCP服务器能够根据MCP协议版本进行响应。
例如:MCP-Protocol-Version: 2024-11-05
2.3.2 授权基础URL
授权基础URL必须通过去除MCP服务器URL中所有现有路径组件来确定。例如:
当MCP服务器URL为 api.example.com/v1/mcp 时:
- 授权基础URL应为 api.example.com
- 元数据端点必须位于 api.example.com/.well-known…
此规范确保无论MCP服务器URL包含何种路径组件,授权端点始终位于托管MCP服务器的域名根目录级别。
2.3.3 不支持元数据发现的服务器的回退方案
对于未实现OAuth 2.0授权服务器元数据的服务器,客户端必须使用以下相对于授权基础URL(如2.3.2节所定义)的默认端点路径:
| 端点类型 | 默认路径 | 描述 |
|---|---|---|
| 授权端点 | /authorize | 用于授权请求 |
| 令牌端点 | /token | 用于令牌交换和刷新 |
| 注册端点 | /register | 用于动态客户端注册 |
例如,当MCP服务器托管在api.example.com/v1/mcp时,默认端…
客户端必须首先尝试通过元数据文档发现端点,仅在失败时才回退到默认路径。当使用默认路径时,所有其他协议要求保持不变。
2.4 动态客户端注册
MCP客户端和服务器应当支持OAuth 2.0动态客户端注册协议,使MCP客户端无需用户交互即可获取OAuth客户端ID。这对MCP至关重要,因为:
- 客户端无法预先知道所有可能的服务器
- 手动注册会给用户带来不便
- 可实现与新服务器的无缝连接
- 服务器可以自行制定注册策略
对于不支持动态客户端注册的MCP服务器,必须提供其他获取客户端ID(及必要时客户端密钥)的方式。在此情况下,MCP客户端需要采取以下任一方案:
- 硬编码特定配置: 为特定MCP服务器预先硬编码客户端ID(及必要时客户端密钥)
- 提供用户配置界面:通过用户界面引导用户手动输入这些凭证(例如通过服务器托管的配置界面),要求用户自行注册OAuth客户端后获取凭证。
2.5 授权流程步骤
完整的授权流程如下:
2.5.1 决策流程概述

2.6 访问令牌(Access Token)使用
2.6.1 令牌要求
访问令牌的处理必须符合 OAuth 2.1 第 5 节对资源请求的要求,具体如下:
- MCP 客户端必须使用 Authorization 请求头字段(第 5.1.1 节):
Authorization: Bearer <access-token>
注意:授权信息必须包含在客户端到服务器的每个 HTTP 请求中,即使它们属于同一逻辑会话。
- 访问令牌不得包含在 URI 查询字符串中
示例请求:
GET /v1/contexts HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
2.6.2 令牌处理
资源服务器必须按照第5.2节所述验证访问令牌。如果验证失败,服务器必须根据第5.3节的错误处理要求进行响应。对于无效或过期的令牌,必须返回HTTP 401响应。
2.7 安全注意事项
必须实施以下安全要求:
- 客户端必须按照OAuth 2.0最佳实践安全存储令牌
- 服务器应当强制实施令牌过期和轮换机制
- 所有授权端点必须通过HTTPS提供服务
- 服务器必须验证重定向URI以防止开放重定向漏洞
- 重定向URI必须是
localhost URL或HTTPS URL
2.8 错误处理
服务器必须针对授权错误返回适当的HTTP状态码:
| Status Code | Description | Usage |
|---|---|---|
| 401 | Unauthorized | Authorization required or token invalid |
| 403 | Forbidden | Invalid scopes or insufficient permissions |
| 400 | Bad Request | Malformed authorization request |
2.9 实现要求
- 实现必须遵循OAuth 2.1安全最佳实践
- 所有客户端必须使用PKCE(Proof Key for Code Exchange)
- 建议实现令牌轮换以增强安全性
- 应根据安全要求限制令牌有效期
2.10 第三方授权流程
2.10.1 概述
MCP服务器可选择支持通过第三方授权服务器进行委托授权。在此流程中,MCP服务器既充当OAuth客户端(对第三方授权服务器而言),又充当OAuth授权服务器(对MCP客户端而言)。
2.10.2 流程说明
第三方授权流程包含以下步骤:
- MCP客户端与MCP服务器发起标准OAuth流程
- MCP服务器将用户重定向至第三方授权服务器
- 用户在第三方服务器完成授权
- 第三方服务器携带授权码重定向回MCP服务器
- MCP服务器用授权码换取第三方访问令牌
- MCP服务器生成与第三方会话绑定的自有访问令牌
- MCP服务器与MCP客户端完成原始OAuth流程
2.10.3 会话绑定要求
实现第三方授权的MCP服务器必须:
- 维护第三方令牌与已颁发MCP令牌之间的安全映射关系
- 在使用MCP令牌前验证第三方令牌状态
- 实施适当的令牌生命周期管理
- 处理第三方令牌过期和续期
2.10.4 安全注意事项
实施第三方授权时,服务器必须:
- 验证所有重定向URI
- 安全存储第三方凭证
- 实施适当的会话超时处理
- 考虑令牌链的安全影响
- 为第三方授权失败实施正确的错误处理
3. 最佳实践
3.1 本地客户端作为公共OAuth 2.1客户端
我们强烈建议本地客户端作为公共客户端实现OAuth 2.1:
- 在授权请求中使用代码挑战(PKCE)防止拦截攻击
- 根据本地系统特点实施安全的令牌存储方案
- 遵循令牌刷新最佳实践以维持会话
- 正确处理令牌过期和续期
3.2 授权元数据发现
我们强烈建议所有客户端实现元数据发现功能。这可以减少用户手动提供端点的需求,也避免了客户端回退到默认设置的情况。
3.3 动态客户端注册
由于客户端无法预先知道所有MCP服务器,我们强烈建议实现动态客户端注册功能。这使得应用程序能够自动向MCP服务器注册,无需用户手动获取客户端ID。