Skip to content

Commit 6b3f869

Browse files
authored
Merge pull request #24 from sacha-development-stuff/codex/resolve-github-merge-conflicts-for-oauth-support
Resolve upstream merge conflicts while preserving OAuth extensions
2 parents cd87f36 + 1999135 commit 6b3f869

File tree

5 files changed

+13
-57
lines changed

5 files changed

+13
-57
lines changed

src/mcp/client/auth/oauth2.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -461,16 +461,12 @@ def _get_token_endpoint(self) -> str:
461461
token_url = urljoin(auth_base_url, "/token")
462462
return token_url
463463

464-
<<<<<<< HEAD:src/mcp/client/auth.py
465-
token_data = {
466-
"grant_type": "authorization_code",
467-
"code": auth_code,
468-
"redirect_uri": str(self.context.client_metadata.redirect_uris[0]),
469-
"code_verifier": code_verifier,
470-
}
471-
=======
472464
async def _exchange_token_authorization_code(
473-
self, auth_code: str, code_verifier: str, *, token_data: dict[str, Any] | None = {}
465+
self,
466+
auth_code: str,
467+
code_verifier: str,
468+
*,
469+
token_data: dict[str, Any] | None = None,
474470
) -> httpx.Request:
475471
"""Build token exchange request for authorization_code flow."""
476472
if self.context.client_metadata.redirect_uris is None:
@@ -489,7 +485,6 @@ async def _exchange_token_authorization_code(
489485
"code_verifier": code_verifier,
490486
}
491487
)
492-
>>>>>>> upstream/main:src/mcp/client/auth/oauth2.py
493488

494489
# Only include resource param if conditions are met
495490
if self.context.should_include_resource_param(self.context.protocol_version):
@@ -671,7 +666,6 @@ async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.
671666
logger.exception("OAuth flow error")
672667
raise
673668

674-
<<<<<<< HEAD:src/mcp/client/auth.py
675669
# Retry with new tokens
676670
self._add_auth_header(request)
677671
yield request
@@ -950,8 +944,3 @@ async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.
950944
response = yield request
951945
if response.status_code == 401:
952946
self._current_tokens = None
953-
=======
954-
# Retry with new tokens
955-
self._add_auth_header(request)
956-
yield request
957-
>>>>>>> upstream/main:src/mcp/client/auth/oauth2.py

src/mcp/shared/auth.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,21 @@ class OAuthClientMetadata(BaseModel):
4242
for the full specification.
4343
"""
4444

45-
<<<<<<< HEAD
46-
redirect_uris: list[AnyUrl] = Field(..., min_length=1)
47-
# token_endpoint_auth_method: this implementation only supports none &
48-
# client_secret_post;
49-
# ie: we do not support client_secret_basic
50-
token_endpoint_auth_method: Literal["none", "client_secret_post"] = "client_secret_post"
45+
redirect_uris: list[AnyUrl] | None = Field(default=None, min_length=1)
46+
# supported auth methods for the token endpoint
47+
token_endpoint_auth_method: Literal["none", "client_secret_post", "private_key_jwt"] = "client_secret_post"
5148
# grant_types: this implementation supports authorization_code, refresh_token, client_credentials, token_exchange,
52-
# and allows additional grant types provided by the client (e.g. device code)
49+
# and allows additional grant types provided by the client (e.g. device code or JWT bearer)
5350
grant_types: list[
5451
Literal[
5552
"authorization_code",
5653
"refresh_token",
5754
"client_credentials",
5855
"token_exchange",
5956
"device_code",
57+
"urn:ietf:params:oauth:grant-type:jwt-bearer",
6058
]
61-
=======
62-
redirect_uris: list[AnyUrl] | None = Field(..., min_length=1)
63-
# supported auth methods for the token endpoint
64-
token_endpoint_auth_method: Literal["none", "client_secret_post", "private_key_jwt"] = "client_secret_post"
65-
# supported grant_types of this implementation
66-
grant_types: list[
67-
Literal["authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:jwt-bearer"] | str
68-
>>>>>>> upstream/main
59+
| str
6960
] = [
7061
"authorization_code",
7162
"refresh_token",

tests/client/test_auth.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -478,13 +478,9 @@ async def test_oauth_discovery_fallback_conditions(self, oauth_provider: OAuthCl
478478
)
479479

480480
# Mock the authorization process to minimize unnecessary state in this test
481-
<<<<<<< HEAD
482-
oauth_provider._perform_authorization = AsyncMock(return_value=("test_auth_code", "test_code_verifier"))
483-
=======
484-
oauth_provider._perform_authorization_code_grant = mock.AsyncMock(
481+
oauth_provider._perform_authorization_code_grant = AsyncMock(
485482
return_value=("test_auth_code", "test_code_verifier")
486483
)
487-
>>>>>>> upstream/main
488484

489485
# Next request should fall back to legacy behavior: register then obtain token
490486
registration_request = await auth_flow.asend(oauth_metadata_response_3)
@@ -881,13 +877,9 @@ async def test_auth_flow_with_no_tokens(self, oauth_provider: OAuthClientProvide
881877
)
882878

883879
# Mock the authorization process
884-
<<<<<<< HEAD
885-
oauth_provider._perform_authorization = AsyncMock(return_value=("test_auth_code", "test_code_verifier"))
886-
=======
887-
oauth_provider._perform_authorization_code_grant = mock.AsyncMock(
880+
oauth_provider._perform_authorization_code_grant = AsyncMock(
888881
return_value=("test_auth_code", "test_code_verifier")
889882
)
890-
>>>>>>> upstream/main
891883

892884
# Next request should be to exchange token
893885
token_request = await auth_flow.asend(registration_response)

tests/issues/test_88_random_error.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,8 @@ async def client(
8383
write_stream: MemoryObjectSendStream[SessionMessage],
8484
scope: anyio.CancelScope,
8585
):
86-
<<<<<<< HEAD
87-
# Use a timeout that's:
88-
# - Long enough for fast operations (>10ms)
89-
# - Short enough for slow operations (<200ms)
90-
# - Not too short to avoid flakiness
91-
async with ClientSession(
92-
read_stream,
93-
write_stream,
94-
# Increased to 150ms to avoid flakiness on slower platforms
95-
read_timeout_seconds=timedelta(milliseconds=150),
96-
) as session:
97-
=======
9886
# No session-level timeout to avoid race conditions with fast operations
9987
async with ClientSession(read_stream, write_stream) as session:
100-
>>>>>>> upstream/main
10188
await session.initialize()
10289

10390
# First call should work (fast operation, no timeout)

tests/shared/test_streamable_http.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@
77
import json
88
import multiprocessing
99
import socket
10-
<<<<<<< HEAD
1110
import sys
1211
import time
13-
=======
14-
>>>>>>> upstream/main
1512
from collections.abc import Generator
1613
from typing import Any
1714

0 commit comments

Comments
 (0)