Skip to content

Commit 86cc5a3

Browse files
committed
Merge branch 'main' into 307_redirect
2 parents f1bcba0 + 0a4e8d4 commit 86cc5a3

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/mcp/client/auth.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ async def _register_client(self) -> httpx.Request | None:
308308
async def _handle_registration_response(self, response: httpx.Response) -> None:
309309
"""Handle registration response."""
310310
if response.status_code not in (200, 201):
311+
await response.aread()
311312
raise OAuthRegistrationError(f"Registration failed: {response.status_code} {response.text}")
312313

313314
try:

src/mcp/server/fastmcp/utilities/func_metadata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def pre_parse_json(self, data: dict[str, Any]) -> dict[str, Any]:
130130
for field_name in self.arg_model.model_fields.keys():
131131
if field_name not in data.keys():
132132
continue
133-
if isinstance(data[field_name], str):
133+
if isinstance(data[field_name], str) and self.arg_model.model_fields[field_name].annotation is not str:
134134
try:
135135
pre_parsed = json.loads(data[field_name])
136136
except json.JSONDecodeError:

tests/client/test_auth.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,42 @@ async def test_resource_param_included_with_protected_resource_metadata(self, oa
516516
assert "resource=" in content
517517

518518

519+
class TestRegistrationResponse:
520+
"""Test client registration response handling."""
521+
522+
@pytest.mark.anyio
523+
async def test_handle_registration_response_reads_before_accessing_text(self, oauth_provider):
524+
"""Test that response.aread() is called before accessing response.text."""
525+
526+
# Track if aread() was called
527+
class MockResponse:
528+
def __init__(self):
529+
self.status_code = 400
530+
self._aread_called = False
531+
self._text = "Registration failed with error"
532+
533+
async def aread(self):
534+
self._aread_called = True
535+
return b"test content"
536+
537+
@property
538+
def text(self):
539+
if not self._aread_called:
540+
raise RuntimeError("Response.text accessed before response.aread()")
541+
return self._text
542+
543+
mock_response = MockResponse()
544+
545+
# This should call aread() before accessing text
546+
with pytest.raises(Exception) as exc_info:
547+
await oauth_provider._handle_registration_response(mock_response)
548+
549+
# Verify aread() was called
550+
assert mock_response._aread_called
551+
# Verify the error message includes the response text
552+
assert "Registration failed: 400" in str(exc_info.value)
553+
554+
519555
class TestAuthFlow:
520556
"""Test the auth flow in httpx."""
521557

0 commit comments

Comments
 (0)