OAuth: 403 responses without insufficient_scope incorrectly retry with same token

当 MCP Python SDK 的 OAuth 客户端收到 403 响应、但 WWW-Authenticate 中的 error 不是 insufficient_scope(例如 invalid_token,或没有 error 字段)时,客户端仍会带上同一 token 再重试一次,导致没有意义的请

快速结论:当 MCP Python SDK 的 OAuth 客户端收到 403 响应、但 WWW-Authenticate 中的 error 不是 insufficient_scope(例如 invalid_token,或没有 error 字段)时,客户端仍会带上同一 token 再重试一次,导致没有意义的请求往返。优先确认你使用的 SDK 是否已包含 main 分支上的修复。

适用环境:Issue 指向 MCP Python SDK 的 OAuth 客户端实现,文件路径为 src/mcp/client/auth/oauth2.py(第 662-681 行附近)。Issue 未提供操作系统、Python 版本、CUDA、显卡或依赖版本等信息。

最快修复方案:Issue 评论确认已在 main 修复:OAuth 流程现在只在 401,或 403 且 error 为 insufficient_scope 时重新认证,其他 403 会原样返回。可升级到包含该修复的版本。

注意事项:Issue 中没有给出具体修复版本号或 commit,需要自行确认所用版本是否包含该修复;若未升级,只能通过修改本地 OAuth 逻辑规避,且这只是 Issue 正文中的建议方向,不一定已被验证。

问题场景

在使用 MCP Python SDK 连接需要 OAuth 鉴权的 MCP 服务端时,客户端发起请求并收到 HTTP 403。如果 403 的原因不是 insufficient_scope,OAuth 客户端仍会执行重试逻辑:重新添加 Authorization 头并再次发送同一个请求,结果通常因为同样的原因再次失败,只是多消耗了一次请求往返,并延后错误反馈。

报错原文

OAuth: 403 responses without insufficient_scope incorrectly retry with same token

相关的行为差异(来自 Issue 正文的对照表):

403 with insufficient_scope        → Get new tokens → retry (Correct)
403 with different error (invalid_token) → Retries once with same token, then fails
403 with no error field            → Retries once with same token, then fails

原因分析

在 src/mcp/client/auth/oauth2.py 中处理 403 的分支里,只有 error == “insufficient_scope” 时才会执行 scope 升权并重新获取 token,但紧随其后的重试代码(添加鉴权头并 yield 请求)被放在了 if 块之外,因此无论是否拿到新 token 都会执行。结果是:非 insufficient_scope 的 403(含没有 error 字段的 403)也会用旧 token 重试一次,属于必然失败的重试。这也与 MCP 授权规范中 scope 挑战处理的描述不一致——规范只暗示 insufficient_scope 才应触发重试。

环境排查

  • 确认所使用的 modelcontextprotocol/python-sdk 版本,判断是否已包含 main 上的修复。
  • 确认问题是否出现在 mcp/client/auth/oauth2.py 的 OAuth 客户端流程中,而不是服务端返回的 403 本身。
  • 抓取或查看 403 响应中的 WWW-Authenticate 头,确认 error 字段的具体取值(insufficient_scope / invalid_token / 缺失)。
  • Issue 未提供 Python、CUDA、PyTorch、显卡或节点版本信息,这些不构成本问题的必要排查项。

解决步骤

  1. 先确认当前 403 的错误类型:读取响应 WWW-Authenticate 头中的 error 字段。如果是 insufficient_scope,旧行为本身是可用的;如果不是,则属于本 Issue 描述的缺陷场景。
  2. 升级 MCP Python SDK 到包含该修复的版本(评论确认修复已在 main:401,或 403 且 error 为 insufficient_scope 时才重新认证,其他 403 原样返回)。
  3. 如果暂时无法升级,可优先尝试按 Issue 正文的建议修改本地代码逻辑:把重试(self._add_auth_header(request); yield request)移入 if error == “insufficient_scope”: 分支内,并让其他 403 直接抛出错误(例如 OAuthFlowError),而不是继续重试。该修改是 Issue 提出的方向,Issue 中未给出对本地补丁的验证结论,需自行测试。
  4. 修改后重新发起原本失败的请求,观察行为是否变为立即报错,而不是多一次注定失败的重试。

验证方法

构造或复现一次非 insufficient_scope 的 403(例如 error 为 invalid_token,或不带 error 字段),确认客户端不再用同一 token 重发请求,而是直接返回/抛出鉴权错误;对于 insufficient_scope 的 403,仍应看到先获取新 token 再用新 token 重试的正常升权流程。同时可通过日志或抓包核对,非 scope 类 403 的请求次数由两次变为一次。

参考来源

modelcontextprotocol/python-sdk #1602

Issue 内引用的相关规范:RFC 6750 Section 3.1、MCP Authorization Spec(scope challenge handling)。

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 29189

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注