@@ -170,6 +170,7 @@ def _resolve_token(
170170 Returns ``(token, AuthCache)``. The cache is empty when the caller supplied
171171 an explicit token.
172172 """
173+ url = _normalize_url (url )
173174 if explicit_token is not None :
174175 return explicit_token , AuthCache ()
175176
@@ -211,6 +212,7 @@ def _handle_token_expired(url: str, cache: AuthCache) -> str | None:
211212 On success writes the new token to cache and returns it.
212213 Returns ``None`` if the cache lacks a refresh token or the refresh fails.
213214 """
215+ url = _normalize_url (url )
214216 if not (cache .refresh_token and cache .client_id ):
215217 return None
216218 try :
@@ -230,7 +232,7 @@ def _handle_token_expired(url: str, cache: AuthCache) -> str | None:
230232 return None
231233
232234
233- def with_auth (fn : " Callable[..., Awaitable[Any]]" ) -> " Callable[..., Awaitable[Any]]" :
235+ def with_auth (fn : Callable [..., Awaitable [Any ]]) -> Callable [..., Awaitable [Any ]]:
234236 """Decorator: resolve bearer token (explicit → cache → OAuth) and retry once on 401.
235237
236238 The wrapped function's ``token`` kwarg is replaced with the resolved token
@@ -290,6 +292,17 @@ async def wrapper(*args: Any, **kwargs: Any) -> Any:
290292)
291293
292294
295+ def _normalize_url (url : str ) -> str :
296+ """Canonicalize *url* so it is always usable as an unambiguous cache key.
297+
298+ * Prepends ``https://`` when no scheme is present.
299+ * Strips a trailing ``/`` to avoid ``/mcp`` vs ``/mcp/`` mismatches.
300+ """
301+ if url and not url .startswith (("http://" , "https://" )):
302+ url = f"https://{ url } "
303+ return url .rstrip ("/" )
304+
305+
293306def get_oauth_config (url : str ) -> OAuthMetadata :
294307 u = urlparse (url )
295308 u = u ._replace (path = "/.well-known/oauth-authorization-server" )
@@ -345,6 +358,7 @@ def check_auth(
345358 str , Option (help = "Path for OAuth redirect (e.g. /Callback)" )
346359 ] = "/" ,
347360) -> OAuth2Redirect :
361+ url = _normalize_url (url or "http://127.0.0.1:8000/mcp" )
348362 md = get_oauth_config (url )
349363 oauth = get_oauth2_tokens (
350364 client_id ,
@@ -353,7 +367,7 @@ def check_auth(
353367 redirect_port ,
354368 redirect_path ,
355369 )
356- if url and oauth .access_token :
370+ if oauth .access_token :
357371 cache_update (
358372 url = url ,
359373 token = oauth .access_token ,
@@ -546,6 +560,7 @@ def cache_update(
546560 --refresh-token rrt_... \\
547561 --client-id my-client-id
548562 """
563+ url = _normalize_url (url )
549564 _write_auth_cache (
550565 url ,
551566 AuthCache (token = token , refresh_token = refresh_token , client_id = client_id ),
@@ -560,6 +575,8 @@ def cache_show(
560575 ] = None ,
561576):
562577 """Display the current auth cache contents (tokens are redacted)."""
578+ if url :
579+ url = _normalize_url (url )
563580 store = _read_auth_store ()
564581 if not store .root :
565582 pp ("[dim]Auth cache is empty.[/dim]" )
@@ -632,6 +649,12 @@ async def list_tools(
632649 client_id : Annotated [
633650 Optional [str ], Option (help = "OAuth client ID (used when no --token or cached token)" )
634651 ] = None ,
652+ redirect_port : Annotated [
653+ int , Option ("--redirect-port" , help = "Local port for OAuth redirect listener" )
654+ ] = 8976 ,
655+ redirect_path : Annotated [
656+ str , Option ("--redirect-path" , help = "Path for OAuth redirect (e.g. /Callback)" )
657+ ] = "/" ,
635658):
636659 async with mcp_client_session (url , token ) as session :
637660 result = await session .list_tools ()
@@ -659,6 +682,12 @@ async def call_tool(
659682 client_id : Annotated [
660683 Optional [str ], Option (help = "OAuth client ID (used when no --token or cached token)" )
661684 ] = None ,
685+ redirect_port : Annotated [
686+ int , Option ("--redirect-port" , help = "Local port for OAuth redirect listener" )
687+ ] = 8976 ,
688+ redirect_path : Annotated [
689+ str , Option ("--redirect-path" , help = "Path for OAuth redirect (e.g. /Callback)" )
690+ ] = "/" ,
662691 args : Annotated [
663692 Optional [str ], Option (help = "The arguments to pass to the tool as a JSON" )
664693 ] = None ,
0 commit comments