OAuth scope selection falls back to the authorization server's scopes_supported, which the spec does not allow

オープン 初心者向け
#3,781 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
79/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python

調査の方向性

src/mcp/client/auth/utils.py の get_client_metadata_scopes から始め、issueで引用されている仕様の動作と照らし合わせながら、scope選択の分岐を追ってください。challenge scopeがない場合とPRM scopes_supported を対象とするテストを確認するか追加してください。これらのケースで、PRM scopesがあればそれを選択し、なければscopeを省略し、authorization server scopesを使わないことが完了条件です。

索引モデルが issue の本文から書いたものです。

説明

bug v1 v2
Initial Checks
Description

When the 401 carries no scope and the Protected Resource Metadata (PRM) has no scopes_supported, get_client_metadata_scopes (src/mcp/client/auth/utils.py) requests every scope the authorization server lists:

# MCP spec scope selection priority:
#   1. WWW-Authenticate header scope
#   2. PRM scopes_supported
#   3. AS scopes_supported (SDK fallback)
#   4. Omit scope parameter
...
elif authorization_server_metadata is not None and authorization_server_metadata.scopes_supported is not None:
    selected_scope = " ".join(authorization_server_metadata.scopes_supported)

The spec has two steps, and the second one ends in omitting scope (2026-07-28, Authorization → Scope Selection Strategy):

  1. Use scope parameter from the initial WWW-Authenticate header in the 401 response, if provided
  2. If scope is not available, use all scopes defined in scopes_supported from the Protected Resource Metadata document, omitting the scope parameter if scopes_supported is undefined.

The same section says clients SHOULD request "only the scopes necessary for their intended operations."

An authorization server's scopes_supported describes the whole authorization server, not this resource. Often that's a shared IdP serving many APIs (openid, profile, email, org-admin and write scopes for unrelated services). Tier 3 therefore turns "the resource didn't say" into "ask for everything the IdP has". The results:

  • an over-privileged token for an MCP server that needed none of it;
  • a broad consent screen for the user;
  • a login failure when the authorization server refuses to issue some of the listed scopes to a public or dynamically registered client (invalid_scope), where omitting scope would have succeeded with the authorization server's default.
Example Code

The selection function on its own (works on 1.26.0, 1.30.0 and 2.3.0):

from mcp.client.auth.utils import get_client_metadata_scopes
from mcp.shared.auth import OAuthMetadata, ProtectedResourceMetadata

prm = ProtectedResourceMetadata(
    resource="https://mcp.example.com/mcp",
    authorization_servers=["https://auth.example.com"],
)  # no scopes_supported
asm = OAuthMetadata(
    issuer="https://auth.example.com",
    authorization_endpoint="https://auth.example.com/authorize",
    token_endpoint="https://auth.example.com/token",
    scopes_supported=["openid", "profile", "email", "admin:org", "repo:write"],
)
print(get_client_metadata_scopes(None, prm, asm))
# 'openid profile email admin:org repo:write'   — expected: None (omit scope)

In the real flow, OAuthClientProvider.async_auth_flow assigns this result to client_metadata.scope on every 401. So a client can't avoid it by configuring a narrower scope: that is #2317, which has several production reports.

Expected behaviour

Follow the spec: (1) the challenge scope, (2) PRM scopes_supported, otherwise omit scope. If a fallback beyond the spec is wanted, make it something a client turns on, not the default.

Relation to existing issues
  • #2317: a configured client_metadata.scope is overwritten. This issue is separate: even with no configured scope, the SDK should omit scope rather than take the authorization server's list. Fixing #2317 alone would leave clients that don't configure a scope on tier 3.
  • #3172 (closed): put the configured scope after tier 3. That doesn't help here, because the AS-wide list still wins whenever the authorization server advertises any scopes.
Python & MCP Python SDK
  • MCP Python SDK: reproduced on 1.26.0, 1.30.0, 2.3.0. The same code is on main at d7845c0.
  • Python 3.12
主要言語
Python
スター
24.7k
フォーク
4.1k
平均マージ
18時間 27分
マージ済み PR(30日)
15

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

modelcontextprotocol/python-sdk のほかの issue

modelcontextprotocol/python-sdk の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。