modelcontextprotocol / modelcontextprotocol/python-sdk

Allow `OAuthClientProvider` to accept a pre-configured auth server URL

Đang mở
#2,121 0 bình luận 0 reaction 1 người được giao Xem trên GitHub

@pcarleton đang làm issue này rồi.

Từ ngày 5/3/2026.

auth enhancement needs confirmation
Ngôn ngữ chính
Python
Star
24.3k
Fork
4k
Merge trung bình
1 ngày 1 giờ
Pull request đã merge (30 ngày)
31

Mô tả

Description

Problem

OAuthClientProvider.async_auth_flow in mcp/client/auth/oauth2.py only triggers OAuth discovery when it receives a 401 response. There's no way to tell the client "I already know where the auth server is — skip straight to OASM discovery and token exchange."

This forces an unnecessary round-trip in environments where the authorization server URL is already known (config file, env var, service registry, etc.).

Current behavior

In OAuthClientProvider.__init__:

OAuthClientProvider(
    server_url="http://mcp-server:3002/mcp",
    client_metadata=OAuthClientMetadata(...),
    storage=my_storage,
    redirect_handler=...,
    callback_handler=...,
)

Then inside async_auth_flow (line ~500):

response = yield request  # unauthenticated

if response.status_code == 401:
    # Only NOW does it start discovery:
    # 1. Extract WWW-Authenticate
    # 2. Discover PRM (/.well-known/oauth-protected-resource)
    # 3. Set self.context.auth_server_url from PRM
    # 4. Discover OASM (/.well-known/oauth-authorization-server)
    # 5. Register client (DCR or CIMD)
    # 6. Authorization code + PKCE
    # 7. Retry with token

Steps 1–3 exist purely to resolve auth_server_url. When the caller already has that URL, they're wasted work.

Proposed change

Add an optional authorization_server_url parameter to OAuthClientProvider.__init__:

OAuthClientProvider(
    server_url="http://mcp-server:3002/mcp",
    client_metadata=OAuthClientMetadata(...),
    storage=my_storage,
    redirect_handler=...,
    callback_handler=...,
    authorization_server_url="http://auth-server:9000",  # NEW
)

When provided:

  • Set self.context.auth_server_url at init time
  • In async_auth_flow, skip the initial unauthenticated request and jump directly to OASM fetch → client registration → token exchange → send authenticated request

When omitted, behavior stays identical to today.

Rough implementation sketch

In OAuthContext:

@dataclass
class OAuthContext:
    # ... existing fields ...
    auth_server_url: str | None = None  # already exists, just needs to be settable at init

In OAuthClientProvider.__init__:

def __init__(self, ..., authorization_server_url: str | None = None):
    self.context = OAuthContext(...)
    if authorization_server_url:
        self.context.auth_server_url = authorization_server_url

In async_auth_flow, before response = yield request:

if self.context.auth_server_url and not self.context.is_token_valid():
    # Auth server already known — go straight to OASM + token exchange
    # (skip sending unauthenticated request and waiting for 401)
    ...

Why this matters

  • Latency — One fewer round-trip before the client can do real work.
  • Controlled environments — Enterprise setups always know their auth server. Discovery via 401 adds no value there.
  • Complements existing featuresclient_metadata_url (CIMD) already lets you skip DCR. This is the same idea applied one step earlier in the chain.

Alternatives considered

Approach Limitation
CIMD (client_metadata_url) Skips DCR (step 5), but the 401 trigger + PRM discovery still happens
Pre-populating TokenStorage We don't necessarily manage the TokenStorage
Using httpx.Auth with a static Bearer token Works, but loses the full OAuth lifecycle (refresh, re-auth, etc.)
References
  • OAuthClientProvidermcp/client/auth/oauth2.py line 217
  • OAuthContext.auth_server_url — already exists as a field (line ~107), just populated from PRM today
  • async_auth_flow — the 401 branch starts at line ~504
  • MCP spec — Authorization
  • RFC 9728 — Protected Resource Metadata
  • RFC 8414 — OAuth Authorization Server Metadata

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.