Skip to content

Commit 1aec562

Browse files
committed
Remove the unused timeout parameter from OAuthClientProvider
OAuthContext.timeout was assigned in the constructor but never read anywhere, so the parameter has never bounded anything since the OAuth client was added. Drop it from OAuthClientProvider, the deprecated RFC7523OAuthClientProvider, and OAuthContext rather than keep a knob that silently does nothing.
1 parent 1963af5 commit 1aec562

6 files changed

Lines changed: 25 additions & 13 deletions

File tree

docs/client/oauth-clients.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ The first time `Client` sends a request, the server answers `401`. The provider
8383

8484
After that it is quiet. Tokens come out of storage, an expired access token is refreshed with the refresh token, and only when none of that works does it run the flow again.
8585

86-
You wrote none of it. Three keyword arguments remain (`timeout`, `client_metadata_url` and `validate_resource_url`), and this file needs none of them. `client_metadata_url` is the one worth knowing about; it gets its own section below.
86+
You wrote none of it. Two keyword arguments remain (`client_metadata_url` and `validate_resource_url`), and this file needs neither. `client_metadata_url` is the one worth knowing about; it gets its own section below.
8787

8888
### Try it
8989

docs/migration.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,24 @@ ClientCredentialsOAuthProvider(..., scopes="read write")
19911991
ClientCredentialsOAuthProvider(..., scope="read write")
19921992
```
19931993

1994+
### `timeout` parameter removed from `OAuthClientProvider`
1995+
1996+
`OAuthClientProvider` (and the deprecated `RFC7523OAuthClientProvider`) no longer accept a `timeout` argument, and `OAuthContext.timeout` is gone. The value was stored but never read, so it never bounded anything — removing it changes nothing at runtime.
1997+
1998+
**Before (v1):**
1999+
2000+
```python
2001+
provider = OAuthClientProvider(server_url, client_metadata, storage, timeout=120.0)
2002+
```
2003+
2004+
**After (v2):**
2005+
2006+
```python
2007+
provider = OAuthClientProvider(server_url, client_metadata, storage)
2008+
```
2009+
2010+
If you passed `timeout` to bound how long you wait for the user to complete authorization, apply that bound where you actually wait — inside your `redirect_handler`/`callback_handler`, e.g. `with anyio.fail_after(120): ...`.
2011+
19942012
### Client rejects authorization server metadata with a mismatched `issuer`
19952013

19962014
During OAuth discovery, `OAuthClientProvider` now validates that the authorization server

src/mcp/client/auth/extensions/client_credentials.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def __init__(
6666
token_endpoint_auth_method=token_endpoint_auth_method,
6767
scope=scope,
6868
)
69-
super().__init__(server_url, client_metadata, storage, None, None, 300.0)
69+
super().__init__(server_url, client_metadata, storage, None, None)
7070
# Store client_info to be set during _initialize - no dynamic registration needed
7171
self._fixed_client_info = OAuthClientInformationFull(
7272
redirect_uris=None,
@@ -280,7 +280,7 @@ def __init__(
280280
token_endpoint_auth_method="private_key_jwt",
281281
scope=scope,
282282
)
283-
super().__init__(server_url, client_metadata, storage, None, None, 300.0)
283+
super().__init__(server_url, client_metadata, storage, None, None)
284284
self._assertion_provider = assertion_provider
285285
# Store client_info to be set during _initialize - no dynamic registration needed
286286
self._fixed_client_info = OAuthClientInformationFull(
@@ -407,7 +407,6 @@ def __init__(
407407
storage: TokenStorage,
408408
redirect_handler: Callable[[str], Awaitable[None]] | None = None,
409409
callback_handler: Callable[[], Awaitable[AuthorizationCodeResult]] | None = None,
410-
timeout: float = 300.0,
411410
jwt_parameters: JWTParameters | None = None,
412411
) -> None:
413412
warnings.warn(
@@ -416,7 +415,7 @@ def __init__(
416415
MCPDeprecationWarning,
417416
stacklevel=2,
418417
)
419-
super().__init__(server_url, client_metadata, storage, redirect_handler, callback_handler, timeout)
418+
super().__init__(server_url, client_metadata, storage, redirect_handler, callback_handler)
420419
self.jwt_parameters = jwt_parameters
421420

422421
async def _exchange_token_authorization_code(

src/mcp/client/auth/oauth2.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ class OAuthContext:
103103
storage: TokenStorage
104104
redirect_handler: Callable[[str], Awaitable[None]] | None
105105
callback_handler: Callable[[], Awaitable[AuthorizationCodeResult]] | None
106-
timeout: float = 300.0
107106
client_metadata_url: str | None = None
108107

109108
# Discovered metadata
@@ -233,7 +232,6 @@ def __init__(
233232
storage: TokenStorage,
234233
redirect_handler: Callable[[str], Awaitable[None]] | None = None,
235234
callback_handler: Callable[[], Awaitable[AuthorizationCodeResult]] | None = None,
236-
timeout: float = 300.0,
237235
client_metadata_url: str | None = None,
238236
validate_resource_url: Callable[[str, str | None], Awaitable[None]] | None = None,
239237
):
@@ -245,7 +243,6 @@ def __init__(
245243
storage: Token storage implementation.
246244
redirect_handler: Handler for authorization redirects.
247245
callback_handler: Handler for authorization callbacks.
248-
timeout: Timeout for the OAuth flow.
249246
client_metadata_url: URL-based client ID. When provided and the server
250247
advertises client_id_metadata_document_supported=True, this URL will be
251248
used as the client_id instead of performing dynamic client registration.
@@ -271,7 +268,6 @@ def __init__(
271268
storage=storage,
272269
redirect_handler=redirect_handler,
273270
callback_handler=callback_handler,
274-
timeout=timeout,
275271
client_metadata_url=client_metadata_url,
276272
)
277273
self._validate_resource_url_callback = validate_resource_url

tests/client/test_auth.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ async def test_oauth_provider_initialization(
192192
assert oauth_provider.context.server_url == "https://api.example.com/v1/mcp"
193193
assert oauth_provider.context.client_metadata == client_metadata
194194
assert oauth_provider.context.storage == mock_storage
195-
assert oauth_provider.context.timeout == 300.0
196195
assert oauth_provider.context is not None
197196

198197
def test_context_url_parsing(self, oauth_provider: OAuthClientProvider):

tests/docs_src/test_oauth_clients.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ async def test_client_credentials_provider_builds_its_own_metadata() -> None:
8282
assert metadata.scope == "user"
8383

8484

85-
async def test_the_three_remaining_keyword_arguments_have_defaults() -> None:
86-
"""The page names `timeout`, `client_metadata_url` and `validate_resource_url` as the remainder."""
85+
async def test_the_two_remaining_keyword_arguments_have_defaults() -> None:
86+
"""The page names `client_metadata_url` and `validate_resource_url` as the remainder."""
8787
parameters = inspect.signature(OAuthClientProvider.__init__).parameters
8888
supplied = ["server_url", "client_metadata", "storage", "redirect_handler", "callback_handler"]
89-
remainder = ["timeout", "client_metadata_url", "validate_resource_url"]
89+
remainder = ["client_metadata_url", "validate_resource_url"]
9090
assert list(parameters) == ["self", *supplied, *remainder]
9191
assert all(parameters[name].default is not inspect.Parameter.empty for name in remainder)
9292

0 commit comments

Comments
 (0)