Deprecate constructing the pre-provisioned OAuth clients without an issuer (#3435)

This commit is contained in:
Max 2026-09-04 15:53:21 +01:00 • committed by GitHub
commit 979208c115
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -7,6 +7,7 @@ Provides OAuth providers for machine-to-machine authentication flows:
"""
import time
import warnings
from collections.abc import Awaitable, Callable
from typing import Any, Literal
from urllib.parse import urlparse
@ -20,10 +21,20 @@ from mcp.client.auth import OAuthClientProvider, OAuthFlowError, TokenStorage
from mcp.client.auth.oauth2 import OAuthContext
from mcp.client.auth.utils import issuers_match
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata
from mcp.shared.exceptions import MCPDeprecationWarning
def _checked_issuer(issuer: str | None) -> str | None:
if issuer is not None and urlparse(issuer).scheme not in ("http", "https"):
if issuer is None:
warnings.warn(
"Omitting `issuer` is deprecated and it will be required in 3.0. Without it, the MCP server "
"decides which authorization server receives this client's credentials; pass "
"issuer=<your authorization server's issuer URL> so they are only ever sent there.",
MCPDeprecationWarning,
stacklevel=3,
)
return None
if urlparse(issuer).scheme not in ("http", "https"):
raise ValueError(f"issuer must be the authorization server's http(s) issuer URL, got {issuer!r}")
return issuer
@ -97,7 +108,8 @@ class ClientCredentialsOAuthProvider(OAuthClientProvider):
issuer: The issuer identifier of the authorization server that issued
`client_id` and `client_secret`. When set, token requests are only built from
discovered authorization server metadata whose `issuer` is exactly this string;
otherwise the flow stops with `OAuthFlowError`. When omitted, whichever
otherwise the flow stops with `OAuthFlowError`. Omitting it is deprecated
(`MCPDeprecationWarning`) and it will be required in 3.0; until then, whichever
authorization server discovery yields is used.
"""
# Build minimal client_metadata for the base class
@ -168,6 +180,7 @@ def static_assertion_provider(token: str) -> Callable[[str], Awaitable[str]]:
storage=my_token_storage,
client_id="my-client-id",
assertion_provider=static_assertion_provider(my_prebuilt_jwt),
issuer="https://auth.example.com",
)
```
@ -202,6 +215,7 @@ class SignedJWTParameters(BaseModel):
storage=my_token_storage,
client_id="my-client-id",
assertion_provider=jwt_params.create_assertion_provider(),
issuer="https://auth.example.com",
)
```
"""
@ -267,6 +281,7 @@ class PrivateKeyJWTOAuthProvider(OAuthClientProvider):
storage=my_token_storage,
client_id="my-client-id",
assertion_provider=get_workload_identity_token,
issuer="https://auth.example.com",
)
```
@ -280,6 +295,7 @@ class PrivateKeyJWTOAuthProvider(OAuthClientProvider):
storage=my_token_storage,
client_id="my-client-id",
assertion_provider=static_assertion_provider(my_prebuilt_jwt),
issuer="https://auth.example.com",
)
```
@ -298,6 +314,7 @@ class PrivateKeyJWTOAuthProvider(OAuthClientProvider):
storage=my_token_storage,
client_id="my-client-id",
assertion_provider=jwt_params.create_assertion_provider(),
issuer="https://auth.example.com",
)
```
"""
@ -327,7 +344,8 @@ class PrivateKeyJWTOAuthProvider(OAuthClientProvider):
registered with. When set, an assertion is only minted, and token requests
are only built, once authorization server metadata whose `issuer` is exactly this
string has been discovered; otherwise the flow stops with `OAuthFlowError`.
When omitted, whichever authorization server discovery yields is used.
Omitting it is deprecated (`MCPDeprecationWarning`) and it will be required in
3.0; until then, whichever authorization server discovery yields is used.
"""
# Build minimal client_metadata for the base class
client_metadata = OAuthClientMetadata(