@@ -259,6 +259,56 @@ async def test_token_exchange_request(self, oauth_provider):
259259 assert "code_verifier=test_verifier" in content
260260 assert "client_id=test_client" in content
261261 assert "client_secret=test_secret" in content
262+ # Resource parameter should be included per RFC 8707
263+ assert "resource=https%3A%2F%2Fapi.example.com%2Fv1%2Fmcp" in content
264+
265+ @pytest .mark .anyio
266+ async def test_authorization_url_request (self , oauth_provider ):
267+ """Test authorization URL construction with resource parameter."""
268+ from unittest .mock import patch
269+
270+ # Set up required context
271+ oauth_provider .context .client_info = OAuthClientInformationFull (
272+ client_id = "test_client" ,
273+ client_secret = "test_secret" ,
274+ redirect_uris = [AnyUrl ("http://localhost:3030/callback" )],
275+ )
276+
277+ # Mock the redirect handler to capture the URL
278+ captured_url = None
279+
280+ async def mock_redirect_handler (url : str ):
281+ nonlocal captured_url
282+ captured_url = url
283+
284+ oauth_provider .context .redirect_handler = mock_redirect_handler
285+
286+ # Mock callback handler
287+ async def mock_callback_handler ():
288+ return "test_auth_code" , "test_state"
289+
290+ oauth_provider .context .callback_handler = mock_callback_handler
291+
292+ # Mock pkce and state generation for predictable testing
293+ with (
294+ patch ("mcp.client.auth.PKCEParameters.generate" ) as mock_pkce ,
295+ patch ("mcp.client.auth.secrets.token_urlsafe" ) as mock_state ,
296+ ):
297+ mock_pkce .return_value .code_verifier = "test_verifier"
298+ mock_pkce .return_value .code_challenge = "test_challenge"
299+ mock_state .return_value = "test_state"
300+
301+ # Mock compare_digest to return True
302+ with patch ("mcp.client.auth.secrets.compare_digest" , return_value = True ):
303+ await oauth_provider ._perform_authorization ()
304+
305+ # Verify the captured URL contains resource parameter
306+ assert captured_url is not None
307+ assert "resource=https%3A%2F%2Fapi.example.com%2Fv1%2Fmcp" in captured_url
308+ assert "client_id=test_client" in captured_url
309+ assert "response_type=code" in captured_url
310+ assert "code_challenge=test_challenge" in captured_url
311+ assert "code_challenge_method=S256" in captured_url
262312
263313 @pytest .mark .anyio
264314 async def test_refresh_token_request (self , oauth_provider , valid_tokens ):
@@ -283,6 +333,8 @@ async def test_refresh_token_request(self, oauth_provider, valid_tokens):
283333 assert "refresh_token=test_refresh_token" in content
284334 assert "client_id=test_client" in content
285335 assert "client_secret=test_secret" in content
336+ # Resource parameter should be included per RFC 8707
337+ assert "resource=https%3A%2F%2Fapi.example.com%2Fv1%2Fmcp" in content
286338
287339
288340class TestAuthFlow :
0 commit comments