Allow `OAuthClientProvider` to accept a pre-configured auth server URL
@pcarleton ya está trabajando en esto.
Desde el 5/3/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
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_urlat 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 features —
client_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
OAuthClientProvider—mcp/client/auth/oauth2.pyline 217OAuthContext.auth_server_url— already exists as a field (line ~107), just populated from PRM todayasync_auth_flow— the 401 branch starts at line ~504- MCP spec — Authorization
- RFC 9728 — Protected Resource Metadata
- RFC 8414 — OAuth Authorization Server Metadata
- Lenguaje dominante
- Python
- Estrellas
- 24.3k
- Forks
- 4k
- Merge medio
- 1 d 1 h
- PR fusionados (30 d)
- 31
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/python-sdk
-
Streamable HTTP client logs a WARNING for valid 202 Accepted on session termination (DELETE) Abiertov1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
modelcontextprotocol/python-sdk#3546 · 4 comentarios ·
-
v1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
modelcontextprotocol/python-sdk#3545 · 1 comentario ·
-
v1 v2
Dificultad 1/5 Menos de una hora Aptitud para principiantes 91/100
modelcontextprotocol/python-sdk#3508 · 2 comentarios ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
modelcontextprotocol/python-sdk#3504 ·
-
v1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
modelcontextprotocol/python-sdk#3492 · 1 comentario ·
Todos los issues de modelcontextprotocol/python-sdk
Issues similares
-
🐛 Bug 🔔 Pending processing
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
jumpserver/jumpserver#17584 ·
-
link-check link-check:sphinx-theme
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
qgis/QGIS-Documentation#11275 ·
-
bug priority:normal ready-for-dev
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
OpenHands/extensions#626 · 1 comentario ·
-
Change observation tooltip text Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 90/100
CSCfi/sd-search-api#39 ·