协议修订: 2025-06-18

简介

目的和范围

模型上下文协议 (MCP) 在传输层提供授权能力,使 MCP 客户端能够代表资源所有者向受限制的 MCP 服务器发出请求。本规范定义了基于 HTTP 的传输的授权流程。

协议要求

授权对于 MCP 实现是**可选的 (OPTIONAL)**。当支持时:
  • 使用基于 HTTP 的传输的实现**应该 (SHOULD)** 符合本规范。
  • 使用 STDIO 传输的实现**不应 (SHOULD NOT)** 遵循本规范,而应从环境中检索凭证。
  • 使用其他传输方式的实现**必须 (MUST)** 遵循其协议已建立的安全最佳实践。

标准合规性

此授权机制基于下面列出的已建立规范,但仅实现了其特性的一个选定子集,以确保安全性和互操作性,同时保持简单性:

授权流程

角色

受保护的 *MCP 服务器* 充当 OAuth 2.1 资源服务器,能够使用访问令牌接受和响应受保护的资源请求。 *MCP 客户端* 充当 OAuth 2.1 客户端,代表资源所有者发出受保护的资源请求。 *授权服务器* 负责与用户进行交互(如果需要)并为在 MCP 服务器上使用的访问令牌颁发。授权服务器的实现细节超出了本规范的范围。它可以与资源服务器托管在一起,也可以是一个独立的实体。 授权服务器发现部分 指定了 MCP 服务器如何向客户端指示其对应的授权服务器的位置。

概述

  1. 授权服务器**必须 (MUST)** 实施 OAuth 2.1,并为机密客户端和公共客户端采取适当的安全措施。
  2. 授权服务器和 MCP 客户端**应该 (SHOULD)** 支持 OAuth 2.0 动态客户端注册协议 (RFC7591)。
  3. MCP 服务器**必须 (MUST)** 实施 OAuth 2.0 受保护资源元数据 (RFC9728)。MCP 客户端**必须 (MUST)** 使用 OAuth 2.0 受保护资源元数据进行授权服务器发现。
  4. 授权服务器**必须 (MUST)** 提供 OAuth 2.0 授权服务器元数据 (RFC8414)。MCP 客户端**必须 (MUST)** 使用 OAuth 2.0 授权服务器元数据。

授权服务器发现

本节描述了 MCP 服务器向 MCP 客户端宣告其关联的授权服务器的机制,以及 MCP 客户端可以确定授权服务器端点和支持的功能的发现过程。

授权服务器位置

MCP 服务器**必须 (MUST)** 实施 OAuth 2.0 受保护资源元数据 (RFC9728) 规范来指示授权服务器的位置。MCP 服务器返回的受保护资源元数据文档**必须 (MUST)** 包含 `authorization_servers` 字段,该字段至少包含一个授权服务器。 `authorization_servers` 的具体使用超出了本规范的范围;实现者应查阅 OAuth 2.0 受保护资源元数据 (RFC9728) 获取实现细节的指导。 实现者应注意,受保护资源元数据文档可以定义多个授权服务器。选择使用哪个授权服务器的责任在于 MCP 客户端,遵循 RFC9728 第 7.6 节“授权服务器”中指定的指导方针。 MCP 服务器在返回 *401 Unauthorized* 时**必须 (MUST)** 使用 HTTP 头 `WWW-Authenticate` 来指示资源服务器元数据 URL 的位置,如 RFC9728 第 5.1 节“WWW-Authenticate 响应”中所述。 MCP 客户端**必须 (MUST)** 能够解析 `WWW-Authenticate` 头,并对来自 MCP 服务器的 `HTTP 401 Unauthorized` 响应作出适当的响应。

服务器元数据发现

MCP 客户端**必须 (MUST)** 遵循 OAuth 2.0 授权服务器元数据 RFC8414 规范,以获取与授权服务器交互所需的信息。

时序图

下图概述了一个示例流程:

动态客户端注册

MCP 客户端和授权服务器**应该 (SHOULD)** 支持 OAuth 2.0 动态客户端注册协议 RFC7591,以允许 MCP 客户端在无需用户交互的情况下获取 OAuth 客户端 ID。这为客户端提供了一种标准化的方式来自动注册新的授权服务器,这对 MCP 至关重要,因为:
  • 客户端可能无法预先知道所有可能的 MCP 服务器及其授权服务器。
  • 手动注册会给用户带来不便。
  • 它实现了与新 MCP 服务器及其授权服务器的无缝连接。
  • 授权服务器可以实施自己的注册策略。
任何*不支持*动态客户端注册的授权服务器需要提供获取客户端 ID(以及适用的客户端凭据)的替代方法。对于这些授权服务器之一,MCP 客户端将不得不:
  1. 硬编码一个客户端 ID(以及适用的客户端凭据),专门供 MCP 客户端在与该授权服务器交互时使用,或者
  2. 向用户呈现一个 UI,允许他们输入这些详细信息,前提是他们自己已经注册了一个 OAuth 客户端(例如,通过服务器托管的配置界面)。

授权流程步骤

完整的授权流程如下:

资源参数实现

MCP 客户端**必须 (MUST)** 实施 RFC 8707 中定义的 OAuth 2.0 资源指示符,以明确指定请求令牌的目标资源。`resource` 参数:
  1. **必须 (MUST)** 包含在授权请求和令牌请求中。
  2. **必须 (MUST)** 标识客户端打算使用该令牌的 MCP 服务器。
  3. **必须 (MUST)** 使用 RFC 8707 第 2 节中定义的 MCP 服务器的规范 URI。
规范服务器 URI
就本规范而言,MCP 服务器的规范 URI 定义为 RFC 8707 第 2 节中指定的资源标识符,并与 RFC 9728 中的 `resource` 参数保持一致。 MCP 客户端**应该 (SHOULD)** 提供他们打算访问的 MCP 服务器最具体的 URI,遵循 RFC 8707 中的指导。虽然规范形式使用小写的 scheme 和 host 组件,但为了稳健性和互操作性,实现**应该 (SHOULD)** 接受大写的 scheme 和 host 组件。 有效的规范 URI 示例:
  • https://mcp.example.com/mcp
  • https://mcp.example.com
  • https://mcp.example.com:8443
  • https://mcp.example.com/server/mcp (当需要路径组件来标识单个 MCP 服务器时)
无效的规范 URI 示例:
  • mcp.example.com (缺少 scheme)
  • https://mcp.example.com#fragment (包含 fragment)
**注意:** 虽然 `https://mcp.example.com/` (带尾部斜杠) 和 `https://mcp.example.com` (不带尾部斜杠) 根据 RFC 3986 都是技术上有效的绝对 URI,但实现**应该 (SHOULD)** 一致地使用不带尾部斜杠的形式,以获得更好的互操作性,除非尾部斜杠对于特定资源具有语义上的重要性。
例如,如果访问位于 `https://mcp.example.com` 的 MCP 服务器,授权请求将包含:
&resource=https%3A%2F%2Fmcp.example.com
MCP 客户端**必须 (MUST)** 发送此参数,无论授权服务器是否支持它。

访问令牌使用

令牌要求

在向 MCP 服务器发出请求时,访问令牌的处理**必须 (MUST)** 符合 OAuth 2.1 第 5 节“资源请求”中定义的要求。具体来说:
  1. MCP 客户端**必须 (MUST)** 使用 OAuth 2.1 第 5.1.1 节中定义的 Authorization 请求头字段。
Authorization: Bearer <access-token>
请注意,从客户端到服务器的每个 HTTP 请求都**必须 (MUST)** 包含授权信息,即使它们属于同一个逻辑会话。
  1. 访问令牌**不得 (MUST NOT)** 包含在 URI 查询字符串中。
请求示例
GET /mcp HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

令牌处理

MCP 服务器,在其作为 OAuth 2.1 资源服务器的角色中,**必须 (MUST)** 按照 OAuth 2.1 第 5.2 节的描述验证访问令牌。MCP 服务器**必须 (MUST)** 根据 RFC 8707 第 2 节验证访问令牌是否是专门为其作为预期受众而颁发的。如果验证失败,服务器**必须 (MUST)** 按照 OAuth 2.1 第 5.3 节的错误处理要求进行响应。对于无效或过期的令牌,**必须 (MUST)** 响应 HTTP 401。 MCP 客户端**不得 (MUST NOT)** 向 MCP 服务器发送非 MCP 服务器授权服务器颁发的令牌。 授权服务器**必须 (MUST)** 只接受对其自身资源有效的令牌。 MCP 服务器**不得 (MUST NOT)** 接受或传递任何其他令牌。

错误处理

服务器**必须 (MUST)** 为授权错误返回适当的 HTTP 状态码:
状态码描述用途
401未授权需要授权或令牌无效
403禁止访问作用域无效或权限不足
400错误请求格式错误的授权请求

安全注意事项

实现**必须 (MUST)** 遵循 OAuth 2.1 第 7 节“安全注意事项”中规定的 OAuth 2.1 安全最佳实践。

令牌受众绑定和验证

RFC 8707 资源指示符通过将令牌绑定到其预期的受众,提供了关键的安全优势,**前提是授权服务器支持此功能**。为了实现当前和未来的采用:
  • MCP 客户端**必须 (MUST)** 在授权和令牌请求中包含 `resource` 参数,如资源参数实现部分所述。
  • MCP 服务器**必须 (MUST)** 验证提交给它们的令牌是专门为其使用而颁发的。
安全最佳实践文档概述了为什么令牌受众验证至关重要,以及为什么明确禁止令牌传递。

令牌盗窃

攻击者如果获取了客户端存储的令牌,或服务器上缓存或记录的令牌,就可以通过对资源服务器看似合法的请求来访问受保护的资源。 客户端和服务器**必须 (MUST)** 实施安全的令牌存储并遵循 OAuth 最佳实践,如 OAuth 2.1 第 7.1 节中所述。 授权服务器**应该 (SHOULD)** 颁发短生命周期的访问令牌,以减少泄露令牌的影响。对于公共客户端,授权服务器**必须 (MUST)** 轮换刷新令牌,如 OAuth 2.1 第 4.3.1 节“令牌端点扩展”中所述。

通信安全

实现**必须 (MUST)** 遵循 OAuth 2.1 第 1.5 节“通信安全” 具体来说:
  1. 所有授权服务器端点**必须 (MUST)** 通过 HTTPS 提供服务。
  2. 所有重定向 URI **必须 (MUST)** 要么是 `localhost`,要么使用 HTTPS。

授权码保护

已获取授权响应中授权码的攻击者可以尝试用该授权码兑换访问令牌或以其他方式利用该授权码。(在 OAuth 2.1 第 7.5 节中有进一步描述) 为了缓解这种情况,MCP 客户端**必须 (MUST)** 根据 OAuth 2.1 第 7.5.2 节实施 PKCE。PKCE 通过要求客户端创建秘密的验证器-挑战对,有助于防止授权码拦截和注入攻击,确保只有原始请求者才能用授权码交换令牌。

开放重定向

攻击者可能构造恶意的重定向 URI 将用户引导至钓鱼网站。 MCP 客户端**必须 (MUST)** 将重定向 URI 注册到授权服务器。 授权服务器**必须 (MUST)** 对照预先注册的值验证精确的重定向 URI,以防止重定向攻击。 MCP 客户端**应该 (SHOULD)** 在授权码流程中使用并验证 state 参数,并丢弃任何不包含或与原始 state 不匹配的结果。 授权服务器**必须 (MUST)** 采取预防措施,防止将用户代理重定向到不受信任的 URI,遵循 OAuth 2.1 第 7.12.2 节中提出的建议。 授权服务器**应该 (SHOULD)** 仅在信任重定向 URI 的情况下自动重定向用户代理。如果 URI 不受信任,授权服务器可以通知用户,并依赖用户做出正确的决定。

困惑的代理问题

攻击者可以利用充当第三方 API 中介的 MCP 服务器,导致困惑的代理漏洞。通过使用窃取的授权码,他们可以在未经用户同意的情况下获取访问令牌。 使用静态客户端 ID 的 MCP 代理服务器**必须 (MUST)** 在转发到第三方授权服务器之前,为每个动态注册的客户端获取用户同意(这可能需要额外的同意)。

访问令牌权限限制

如果 MCP 服务器接受为其他资源颁发的令牌,攻击者可能会获得未经授权的访问或以其他方式危及该服务器。 这个漏洞有两个关键维度:
  1. **受众验证失败。** 当 MCP 服务器不验证令牌是否专门为其所用(例如,通过受众声明,如 RFC9068 中所述),它可能会接受最初为其他服务颁发的令牌。这打破了 OAuth 的一个基本安全边界,允许攻击者在不同于预期的服务之间重复使用合法令牌。
  2. **令牌传递。** 如果 MCP 服务器不仅接受具有不正确受众的令牌,还将其未经修改地转发到下游服务,这可能会导致“困惑的代理”问题,下游 API 可能会错误地信任该令牌,就像它来自 MCP 服务器一样,或者假定该令牌已由上游 API 验证。更多详情请参阅《安全最佳实践指南》中的令牌传递部分
MCP 服务器**必须 (MUST)** 在处理请求前验证访问令牌,确保访问令牌是专门为该 MCP 服务器颁发的,并采取一切必要措施确保没有数据返回给未经授权的方。 MCP 服务器**必须 (MUST)** 遵循 OAuth 2.1 - 第 5.2 节中的指导方针来验证入站令牌。 MCP 服务器**必须 (MUST)** 只接受专门针对自己的令牌,并且**必须 (MUST)** 拒绝不包含它们在受众声明中或以其他方式验证它们是令牌预期接收者的令牌。详情请参阅安全最佳实践令牌传递部分 如果 MCP 服务器向上游 API 发出请求,它可以作为它们的 OAuth 客户端。在上游 API 使用的访问令牌是另一个由上游授权服务器颁发的独立令牌。MCP 服务器**不得 (MUST NOT)** 传递它从 MCP 客户端收到的令牌。 MCP 客户端**必须 (MUST)** 实施并使用 RFC 8707 - OAuth 2.0 资源指示符中定义的 `resource` 参数,以明确指定请求令牌的目标资源。此要求与 RFC 9728 第 7.4 节中的建议一致。这确保了访问令牌与其预定资源绑定,不能在不同服务间被滥用。