|
1 | | -from collections.abc import AsyncIterator |
| 1 | +from __future__ import annotations |
| 2 | + |
| 3 | +from collections.abc import AsyncIterator, Callable |
2 | 4 | from contextlib import asynccontextmanager |
| 5 | +from pathlib import Path |
| 6 | +from types import ModuleType |
| 7 | +from typing import Protocol, cast |
3 | 8 |
|
4 | 9 | import anyio |
5 | 10 | import pytest |
6 | 11 | from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream |
| 12 | + |
7 | 13 | from mcp.client.auth import OAuthClientProvider |
8 | 14 | from mcp.shared.message import SessionMessage |
9 | 15 |
|
10 | | -from mcp_simple_auth_client import main as client_module |
11 | | -from mcp_simple_auth_client.main import SimpleAuthClient |
| 16 | +CLIENT_ROOT = Path(__file__).parents[3] / "examples" / "clients" / "simple-auth-client" |
| 17 | + |
| 18 | + |
| 19 | +class SimpleAuthClient(Protocol): |
| 20 | + def __init__( |
| 21 | + self, |
| 22 | + server_url: str, |
| 23 | + transport_type: str = "streamable-http", |
| 24 | + client_metadata_url: str | None = None, |
| 25 | + ) -> None: ... |
| 26 | + |
| 27 | + async def connect(self) -> None: ... |
| 28 | + |
| 29 | + |
| 30 | +class ClientModule(Protocol): |
| 31 | + SimpleAuthClient: type[SimpleAuthClient] |
12 | 32 |
|
13 | 33 |
|
14 | 34 | @pytest.mark.anyio |
15 | | -async def test_oauth_client_preserves_the_complete_connection_url(monkeypatch: pytest.MonkeyPatch) -> None: |
| 35 | +async def test_oauth_client_preserves_the_complete_connection_url( |
| 36 | + monkeypatch: pytest.MonkeyPatch, |
| 37 | + load_example_module: Callable[[Path, str], ModuleType], |
| 38 | +) -> None: |
16 | 39 | """The example passes the opaque MCP endpoint unchanged to its OAuth provider.""" |
| 40 | + client_module = cast(ClientModule, load_example_module(CLIENT_ROOT, "mcp_simple_auth_client.main")) |
17 | 41 | resource_url = "https://mcp.example.com/prefix/mcp?tenant=mcp" |
18 | 42 | providers: list[OAuthClientProvider] = [] |
19 | 43 | sessions = 0 |
@@ -49,9 +73,9 @@ async def record_session( |
49 | 73 |
|
50 | 74 | monkeypatch.setattr(client_module, "CallbackServer", FakeCallbackServer) |
51 | 75 | monkeypatch.setattr(client_module, "sse_client", fake_sse_client) |
52 | | - monkeypatch.setattr(SimpleAuthClient, "_run_session", record_session) |
| 76 | + monkeypatch.setattr(client_module.SimpleAuthClient, "_run_session", record_session) |
53 | 77 |
|
54 | | - await SimpleAuthClient(resource_url, transport_type="sse").connect() |
| 78 | + await client_module.SimpleAuthClient(resource_url, transport_type="sse").connect() |
55 | 79 |
|
56 | 80 | assert sessions == 1 |
57 | 81 | assert [str(provider.context.server_url) for provider in providers] == [resource_url] |
0 commit comments