MCP 授权规范的深入审查(2025-03-26 版)
深入分析 MCP 授权规范,考察 MCP 服务器作为授权和资源服务器的双重角色、动态客户端注册机制,以及在现实场景中实施此协议的实际考虑。
MCP (模型上下文协议) 是一个开放标准,允许 AI 模型与外部工具和服务进行交互。它在行业中被广泛采用。由于 MCP 支持基于 HTTP 的传输方法,远程 MCP 服务器将在 MCP 生态系统中扮演日益重要的角色。
与允许每个用户运行自己的服务器实例的本地 MCP 服务器不同,远程 MCP 服务器要求所有用户共享同一个 MCP 服务器服务。这引出了 MCP 授权规范 要解决的核心问题:如何允许 MCP 服务器代表用户访问用户资源。
本文将深入分析 MCP 授权规范。这将帮助你理解 MCP 授权规范的设计原则以及实施 MCP 授权的一些方向。由于此规范仍在演变中,我将分享一些基于我在实施身份验证器中的个人经验的想法,包括:
- 作为授权框架的 OAuth 2.1 的优势和局限性
- MCP 服务器作为授权服务器和资源服务器的双重角色的挑战
- 实现完整授权服务器的实际复杂性
- 适合于委托第三方授权的场景分析
- 动态客户端注册的实际权衡
- 明确定义 MCP 服务器的资源边界的重要性
MCP 授权规范概述
MCP 授权规范 定义了 MCP 服务器(远程)和 MCP 客户端之间的认证过程。
我认为以 OAuth 2.1 作为此规范的基础是非常合理的选择。作为授权协议框架的 OAuth 解决了如何允许用户授权第三方应用程序代表他们访问用户资源的问题。 如果你不熟悉 OAuth,你可以查看 AuthWiki-OAuth 以获取更多信息。
在 MCP 客户端和 MCP 服务器的场景中,这是关于“用户授权 MCP 客户端访问 MCP 服务器上的用户资源”。目前,“MCP 服务器上的用户资源”主要指 MCP 服务器提供的工具或 MCP 服务器的后端服务提供的资源。
要实现 OAuth 2.1 认证过程,该协议要求 MCP 服务器提供以下接口,与 MCP 客户端合作完成 OAuth 2.1 认证过程:
/.well-known/oauth-authorization-server
: OAuth 服务器元数据/authorize
: 授权端点,用于授权请求/token
: 令牌端点,用于令牌交换与刷新/register
: 客户端注册端点,用于动态客户端注册
认证过程如下所示:
该规范还规定了 MCP 服务器如何通过第三方授权服务器支持委托授权。
规范中的示例流程如下(摘自规范内容):
在这种情况下,虽然 MCP 服务器将授权委托给第三方授权服务器,但 MCP 服务器仍然作为 MCP 客户端的授权服务器。这是因为 MCP 服务器需要向 MCP 客户端颁发自己的访问令牌。
在我看来,这种场景似乎更适合处理 MCP 服务器代理 MCP 客户端(用户)访问第三方资源(如 Github 仓库)的情况,而不是 MCP 服务器代理 MCP 客户端(用户)访问 MCP 服务器自己的资源。
总之,根据协议,MCP 服务器在 OAuth 中同时担任授权服务器和资源服务器的角色。
接下来,让我们讨论 MCP 服务器作为授权服务器和资源服务器的责任。
作为授权服务的 MCP 服务器
当 MCP 服务器充当授权服务器时,意味着 MCP 客户端的最终用户在 MCP 服务器上有自己的身份。MCP 服务器负责对该最终用户进行身份验证,并向其颁发访问令牌以访问 MCP 服务器资源。
上述 MCP 授权规范中要求的与授权相关的接口意味着 MCP 服务器必须提供授权服务器的实现。
然而,在 MCP 服务器上实现授权服务器功能对开发人员是一个重大挑战。一方面,大多数开发人员可能不熟悉 OAuth 相关概念。另一方面,实现授权服务器时需要考虑许多细节。如果开发人员不是来自相关领域,他们可能在实现过程中引入安全问题等。
然而,协议本身并没有限制 MCP 服务器仅自己实现授权服务器功能。开发人员可以完全重定向或代理这些与授权相关的端点到其他授权服务器。对于 MCP 客户端而言,这与 MCP 服务器自己实现授权服务器功能没什么区别。
你可能会想,这种方法是否应该使用上面提到的委托第三方授权方法?
在我看来,这主要取决于你所依赖的第三方授权服务的用户是否与 MCP 服务器的最终用户相同。这意味着第三方授权服务颁发给你的访问令牌将直接由你的 MCP 服务器消耗。
-
如果是,那么你可以完全将 MCP 服务器中的 Auth 相关接口转发到第三方授权服务。
-
如果不是,那么你应该使用规范中指定的委托第三方授权方法。你需要在 MCP 服务器中维护 MCP 服务器本身颁发的访问令牌与第三方授权服务颁发的访问令牌之间的映射关系。
我认为协议中指定的委托第三方授权方法在实际应用场景中有些模糊。协议似乎是让第三方帮助 MCP 服务器完成授权过程,但仍然要求 MCP 服务器颁发自己的访问令牌,实际上意味着 MCP 服务器仍然承担着作为授权服务器颁发访问令牌的责任,这对开发人员来说并不是方便得多。我认为这可能是因为协议的作者考虑到直接向 MCP 客户端返回第三方访问令牌会带来一些安全问题(例如泄露/滥用等)。
从我的经验来看,协议中指定的委托第三方授权方法最适合的场景应该是“用户授权 MCP 服务器访问第三方资源”的场景。例如,MCP 服务器需要访问用户的 Github 仓库并将仓库的代码部署到代码部署平台。在这种情况下,用户需要授权 MCP 服务器访问其 Github 仓库以及访问代码部署平台。
在这种情况下,MCP 服务器是 MCP 客户端的授权服务器,因为最终用户在 MCP 服务器中有自己的身份。MCP 服务器是第三方资源(在这种情况下是 Github)的第三方客户端。它需要获得用户授权以访问 Github 上的用户资源。在 MCP 客户端与 MCP 服务器之间,以及 MCP 服务器与第三方资源之间,用户身份 是分隔的。这使得在 MCP 服务器中维护 MCP 服务器本身颁发的访问令牌与第三方授权服务颁发的访问令牌之间的映射关系显得有意义。
因此,协议中的委托第三方授权协议应该解决“如何授权 MCP 服务器访问第三方资源服务器上的用户资源”的问题。
作为资源服务器的 MCP 服务器
当 MCP 服务器充当资源服务器时,MCP 服务器需要验证 MCP 客户端的请求是否携带有效的访问令牌。MCP 服务器将根据访问令牌的范围决定是否允许 MCP 客户端访问特定资源。
根据 MCP 的定义,MCP 服务器提供的资源应供 MCP 客户端使用。在这个场景中,MCP 服务器只需决定是否为用户提供对某些工具的访问。
但在实际场景中,MCP 服务器提供的这些工具还需要与 MCP 服务器服务提供商自身的资源服务器进行交互。此时,MCP 服务器从客户端请求获取的访问令牌需要用于访问它自己的资源服务器。在大多数情况下,MCP 服务器和工具背后的资源服务器是同一开发人员。MCP 服务器只是自己后台资源为 MCP 客户端提供的一个接口。此时,MCP 服务器可以与后台资源共享同一个由一个授权服务器颁发的访问令牌。
在这种情况下,与其说 MCP 服务器是一个资源服务器,提供工具和其自身服务的资源,不如说通过为 MCP 客户端提供调用工具,现有的资源服务器成为了一个 MCP 服务器。
将自己资源服务器提供的资源纳入 MCP 服务器提供的资源更多是从实际场景考虑的。但我个人仍然倾向于让 MCP 服务器提供的资源仅限于供 MCP 客户端使用的工具 ,而工具依赖的资源应该是 MCP 服务器从其他资源服务器(包括第一方和第三方)获取的资源。这样可以覆盖所有实际场景。
MCP 授权的工作机制
在了解了 MCP 服务器作为授权服务器和资源服务器的职责之后,我们可以知道 MCP 授权具体是如何工作的:
动态客户端注册
该规范还定义了授权服务器如何识别客户端。OAuth 2.1 提供了动态客户端注册协议,允许 MCP 客户端自动获取 OAuth 客户端 ID 而无需人工干预。
根据该规范,MCP 服务器应支持 OAuth 2.0 的动态客户端注册协议。这样,MCP 客户端可以自动注册新服务器以获得 OAuth 客户端 ID。在 MCP 场景中推荐这种方法的原因主要是:
- MCP 客户端无法提前知道所有可能的服务器
- 手动注册会给用户带来麻烦
- 使与新服务器的连接变得无缝
- 服务器可以实施自己的注册策略
然而,从实际角度来看,我对 MCP 场景中动态客户端注册的应用有一些看法:
- 在实际 OAuth 服务实践中,客户端通常与特定业务应用一一对应。动态创建客户端可能不利于在 OAuth 服务中有效管理相关资源(用户、应用等)。OAuth 服务提供商通常希望对已连接的客户端有明确的控制,而不是任由任何客户端随意注册。
- 许多 OAuth 服务不建议或不允许用户动态创建客户端,因为这可能导致服务滥用。大多数成熟的 OAuth 服务提供商(如 Github、Google 等)要求开发人员通过其开发者控制台手动注册客户端,可能还需要提供有关应用程序的详细信息、回调 URL 等。
- 手动注册 OAuth 客户端实际上是开发过程中一次性的工作,不是每个终端用户都需要做的事情,这不会对开发者造成很大的负担。
- 对于公共客户端(如原生应用程序、单页应用程序等),我们有更安全的方法来实现 OAuth 流程,而无需动态注册。客户端 ID 结 合 PKCE(证明密钥代码交换)可以为公共客户端提供足够安全的 OAuth 流程,而无需动态创建客户端。
- 尽管协议指出使用动态客户端注册可以避免客户端需要提前得知客户端 ID,但实际上,MCP 客户端始终需要提前知道远程 MCP 服务器的地址。如果是这样,指定客户端 ID 在传入远 MCP 服务器地址时不会带来太多额外麻烦。或者,我们也可以为 MCP 客户端创建一个向 MCP 服务器索要客户端 ID 的约定,这不是一件困难的事情。
虽然动态客户端注册在理论上为 MCP 生态系统提供了灵活性,但在实际实施中,我们可能需要考虑是否真的需要这种动态注册机制。对于大多数服务提供商,手动创建和管理 OAuth 客户端可能是更易于控制和更安全的方法。
总结
本文深入分析了 MCP 授权规格的设计理念和实现挑战。作为基于 OAuth 2.1 的授权框架,该规范旨在解决远程 MCP 服务器如何代表用户访问用户资源的关键问题。
通过详细讨论 MCP 服务器作为授权服务器和资源服务器的双重角色,以及动态客户端注册和第三方授权委托等机制的利弊,本文提出了从实施身份验证器的个人经验中得出的思考和建议。
值得注意的是,MCP 授权规范仍在不断演变中。作为 Logto 团队的成员,我们将继续关注此规范的最新动态,并在实践中不断优化我们的实现方案,以促进 AI 模型与外部服务之间的安全交互。