Skip to content

Commit f33add0

Browse files
committed
fix: add typed Protocol for Authlib client to satisfy pyright strict mode
Define _AsyncOAuth2ClientProtocol as a minimal structural interface for AsyncOAuth2Client's members used by AuthlibOAuthAdapter (token, scope, code_challenge_method, fetch_token, create_authorization_url, ensure_active_token). Annotate self._client with the Protocol and suppress the assignment from the untyped library with # type: ignore[assignment]. This eliminates all reportUnknownMemberType / reportUnknownVariableType / reportUnknownArgumentType errors in pyright strict mode without requiring upstream type stubs or a proliferation of per-line ignores.
1 parent b5f36e9 commit f33add0

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

src/mcp/client/auth/authlib_adapter.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import secrets
3535
import string
3636
from collections.abc import AsyncGenerator, Awaitable, Callable
37-
from typing import Any
37+
from typing import Any, Protocol
3838

3939
import anyio
4040
import httpx
@@ -47,6 +47,30 @@
4747

4848
logger = logging.getLogger(__name__)
4949

50+
51+
# ---------------------------------------------------------------------------
52+
# Internal protocol — typed interface for untyped Authlib client
53+
# ---------------------------------------------------------------------------
54+
55+
56+
class _AsyncOAuth2ClientProtocol(Protocol):
57+
"""Minimal typed interface for authlib.integrations.httpx_client.AsyncOAuth2Client.
58+
59+
Defined as a Protocol so that pyright strict mode can type-check all member
60+
accesses on the Authlib client without requiring upstream type stubs.
61+
"""
62+
63+
token: dict[str, Any] | None
64+
scope: str | None
65+
code_challenge_method: str
66+
67+
async def fetch_token(self, url: str, **kwargs: Any) -> dict[str, Any]: ...
68+
69+
def create_authorization_url(self, url: str, **kwargs: Any) -> tuple[str, str]: ...
70+
71+
async def ensure_active_token(self, token: dict[str, Any]) -> None: ...
72+
73+
5074
# ---------------------------------------------------------------------------
5175
# Configuration
5276
# ---------------------------------------------------------------------------
@@ -128,7 +152,7 @@ def __init__(
128152
self._initialized: bool = False
129153

130154
scope_str = " ".join(config.scopes) if config.scopes else None
131-
self._client: AsyncOAuth2Client = AsyncOAuth2Client(
155+
self._client: _AsyncOAuth2ClientProtocol = AsyncOAuth2Client( # type: ignore[assignment]
132156
client_id=config.client_id,
133157
client_secret=config.client_secret,
134158
scope=scope_str,

0 commit comments

Comments
 (0)