From 77ddcd5d4a426e3943ade11f6f5b871baf747e98 Mon Sep 17 00:00:00 2001 From: Jah-yee Date: Thu, 12 Mar 2026 01:51:57 +0800 Subject: [PATCH] fix(auth): preserve existing refresh_token when server omits it Per RFC 6749 Section 6, issuing a new refresh token in the refresh response is optional. When the authorization server does not return a new refresh_token, the previously stored refresh_token is now preserved instead of being discarded. Fixes: #2270 --- src/mcp/client/auth/oauth2.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mcp/client/auth/oauth2.py b/src/mcp/client/auth/oauth2.py index 25075dec3..8e3d5acb9 100644 --- a/src/mcp/client/auth/oauth2.py +++ b/src/mcp/client/auth/oauth2.py @@ -458,6 +458,11 @@ async def _handle_refresh_response(self, response: httpx.Response) -> bool: # p content = await response.aread() token_response = OAuthToken.model_validate_json(content) + # Per RFC 6749 Section 6, the server may not return a new refresh_token. + # If the server omits it, preserve the existing refresh_token. + if not token_response.refresh_token and self.context.current_tokens: + token_response.refresh_token = self.context.current_tokens.refresh_token + self.context.current_tokens = token_response self.context.update_token_expiry(token_response) await self.context.storage.set_tokens(token_response)