Skip to content

Commit ffef4a6

Browse files
author
冯基魁
committed
fix: request JSON token responses
1 parent a527142 commit ffef4a6

5 files changed

Lines changed: 19 additions & 7 deletions

File tree

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from pydantic import BaseModel, Field
1919

2020
from mcp.client.auth import OAuthClientProvider, OAuthFlowError, OAuthTokenError, TokenStorage
21+
from mcp.client.auth.utils import create_token_request_headers
2122
from mcp.shared.auth import AuthorizationCodeResult, OAuthClientInformationFull, OAuthClientMetadata
2223

2324

@@ -92,7 +93,7 @@ async def _exchange_token_client_credentials(self) -> httpx.Request:
9293
"grant_type": "client_credentials",
9394
}
9495

95-
headers: dict[str, str] = {"Content-Type": "application/x-www-form-urlencoded"}
96+
headers = create_token_request_headers()
9697

9798
# Use standard auth methods (client_secret_basic, client_secret_post, none)
9899
token_data, headers = self.context.prepare_token_auth(token_data, headers)
@@ -320,7 +321,7 @@ async def _exchange_token_client_credentials(self) -> httpx.Request:
320321
"grant_type": "client_credentials",
321322
}
322323

323-
headers: dict[str, str] = {"Content-Type": "application/x-www-form-urlencoded"}
324+
headers = create_token_request_headers()
324325

325326
# Add JWT client authentication (RFC 7523 Section 2.2)
326327
await self._add_client_authentication_jwt(token_data=token_data)
@@ -480,6 +481,4 @@ async def _exchange_token_jwt_bearer(self) -> httpx.Request:
480481
token_data["scope"] = self.context.client_metadata.scope
481482

482483
token_url = self._get_token_endpoint()
483-
return httpx.Request(
484-
"POST", token_url, data=token_data, headers={"Content-Type": "application/x-www-form-urlencoded"}
485-
)
484+
return httpx.Request("POST", token_url, data=token_data, headers=create_token_request_headers())

src/mcp/client/auth/oauth2.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
create_client_info_from_metadata_url,
2626
create_client_registration_request,
2727
create_oauth_metadata_request,
28+
create_token_request_headers,
2829
credentials_match_issuer,
2930
extract_field_from_www_auth,
3031
extract_resource_metadata_from_www_auth,
@@ -409,7 +410,7 @@ async def _exchange_token_authorization_code(
409410
token_data["resource"] = self.context.get_resource_url() # RFC 8707
410411

411412
# Prepare authentication based on preferred method
412-
headers = {"Content-Type": "application/x-www-form-urlencoded"}
413+
headers = create_token_request_headers()
413414
token_data, headers = self.context.prepare_token_auth(token_data, headers)
414415

415416
return httpx.Request("POST", token_url, data=token_data, headers=headers)
@@ -461,7 +462,7 @@ async def _refresh_token(self) -> httpx.Request:
461462
refresh_data["resource"] = self.context.get_resource_url() # RFC 8707
462463

463464
# Prepare authentication based on preferred method
464-
headers = {"Content-Type": "application/x-www-form-urlencoded"}
465+
headers = create_token_request_headers()
465466
refresh_data, headers = self.context.prepare_token_auth(refresh_data, headers)
466467

467468
return httpx.Request("POST", token_url, data=refresh_data, headers=headers)

src/mcp/client/auth/utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
from mcp.types import LATEST_PROTOCOL_VERSION
1717

1818

19+
def create_token_request_headers() -> dict[str, str]:
20+
return {
21+
"Accept": "application/json",
22+
"Content-Type": "application/x-www-form-urlencoded",
23+
}
24+
25+
1926
def extract_field_from_www_auth(response: Response, field_name: str) -> str | None:
2027
"""Extract field from WWW-Authenticate header.
2128

tests/client/auth/extensions/test_client_credentials.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ async def test_token_exchange_request_jwt_predefined(self, rfc7523_oauth_provide
108108

109109
assert request.method == "POST"
110110
assert str(request.url) == "https://api.example.com/token"
111+
assert request.headers["Accept"] == "application/json"
111112
assert request.headers["Content-Type"] == "application/x-www-form-urlencoded"
112113

113114
# Check form data
@@ -252,6 +253,7 @@ async def test_exchange_token_client_credentials(self, mock_storage: MockTokenSt
252253

253254
assert request.method == "POST"
254255
assert str(request.url) == "https://api.example.com/token"
256+
assert request.headers["Accept"] == "application/json"
255257

256258
content = urllib.parse.unquote_plus(request.content.decode())
257259
assert "grant_type=client_credentials" in content
@@ -398,6 +400,7 @@ async def mock_assertion_provider(audience: str) -> str:
398400

399401
assert request.method == "POST"
400402
assert str(request.url) == "https://auth.example.com/token"
403+
assert request.headers["Accept"] == "application/json"
401404

402405
content = urllib.parse.unquote_plus(request.content.decode())
403406
assert "grant_type=client_credentials" in content

tests/client/test_auth.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ async def test_token_exchange_request_authorization_code(self, oauth_provider: O
602602

603603
assert request.method == "POST"
604604
assert str(request.url) == "https://api.example.com/token"
605+
assert request.headers["Accept"] == "application/json"
605606
assert request.headers["Content-Type"] == "application/x-www-form-urlencoded"
606607

607608
# Check form data
@@ -628,6 +629,7 @@ async def test_refresh_token_request(self, oauth_provider: OAuthClientProvider,
628629

629630
assert request.method == "POST"
630631
assert str(request.url) == "https://api.example.com/token"
632+
assert request.headers["Accept"] == "application/json"
631633
assert request.headers["Content-Type"] == "application/x-www-form-urlencoded"
632634

633635
# Check form data

0 commit comments

Comments
 (0)