From 5aa4e0b42413e07f201cef1cadc56fdfdfe1bcab Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:14:35 -0400 Subject: [PATCH 1/2] Ensure the response is read before accessing response.text --- src/mcp/client/auth.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mcp/client/auth.py b/src/mcp/client/auth.py index 6238d69518..8bafe18eb3 100644 --- a/src/mcp/client/auth.py +++ b/src/mcp/client/auth.py @@ -308,6 +308,7 @@ async def _register_client(self) -> httpx.Request | None: async def _handle_registration_response(self, response: httpx.Response) -> None: """Handle registration response.""" if response.status_code not in (200, 201): + await response.aread() raise OAuthRegistrationError(f"Registration failed: {response.status_code} {response.text}") try: From a24d3d1d1acaa223dc3a370e7edd2c80785ba8d5 Mon Sep 17 00:00:00 2001 From: ihrpr Date: Thu, 10 Jul 2025 21:51:39 +0100 Subject: [PATCH 2/2] add test --- tests/client/test_auth.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/client/test_auth.py b/tests/client/test_auth.py index 8e6b4f54d5..affcaa2764 100644 --- a/tests/client/test_auth.py +++ b/tests/client/test_auth.py @@ -516,6 +516,42 @@ async def test_resource_param_included_with_protected_resource_metadata(self, oa assert "resource=" in content +class TestRegistrationResponse: + """Test client registration response handling.""" + + @pytest.mark.anyio + async def test_handle_registration_response_reads_before_accessing_text(self, oauth_provider): + """Test that response.aread() is called before accessing response.text.""" + + # Track if aread() was called + class MockResponse: + def __init__(self): + self.status_code = 400 + self._aread_called = False + self._text = "Registration failed with error" + + async def aread(self): + self._aread_called = True + return b"test content" + + @property + def text(self): + if not self._aread_called: + raise RuntimeError("Response.text accessed before response.aread()") + return self._text + + mock_response = MockResponse() + + # This should call aread() before accessing text + with pytest.raises(Exception) as exc_info: + await oauth_provider._handle_registration_response(mock_response) + + # Verify aread() was called + assert mock_response._aread_called + # Verify the error message includes the response text + assert "Registration failed: 400" in str(exc_info.value) + + class TestAuthFlow: """Test the auth flow in httpx."""