
    k7ic.                    Z   S SK Jr  S SKrS SKrS SKJr  S SKJr  S SKJ	r	  S SK
r
S SKrS SKJr  S SKJr  S SKJr  S S	KJrJr  S S
KJrJrJr  S SKJr  S SKJr  S SKJr  S SKJ r J!r!  S SK"J#r#  S SK$J%r%  S/r&\%" \'5      r( " S S\)5      r* S     SS jjr+ " S S\5      r, " S S\5      r-g)    )annotationsN)AsyncGenerator)Any)urlparse)PydanticAdapter)AsyncKeyValue)MemoryStore)OAuthClientProviderTokenStorage)OAuthClientInformationFullOAuthClientMetadata
OAuthToken)
AnyHttpUrl)override)Server)OAuthCallbackResultcreate_oauth_callback_server)find_available_port)
get_loggerOAuthc                      \ rS rSrSrSrg)ClientNotFoundError$   zARaised when OAuth client credentials are not found on the server. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       S/home/james-whalen/.local/lib/python3.13/site-packages/fastmcp/client/auth/oauth.pyr   r   $   s    Kr!   r   c                  #    [         R                  " S0 U=(       d    0 D6 ISh  vN n UR                  U SS9I Sh  vN nUR                  S;   a   SSS5      ISh  vN   gSUR                  ;   a   SSS5      ISh  vN   g SSS5      ISh  vN   g Ns N\ N= N N! [         R
                   a     SSS5      ISh  vN    gf = f! , ISh  vN  (       d  f       g= f7f)	z
Check if the MCP endpoint requires authentication by making a test request.

Returns:
    True if auth appears to be required, False otherwise
Ng      @)timeout)i  i  TzWWW-AuthenticateFr   )httpxAsyncClientgetstatus_codeheadersRequestError)mcp_urlhttpx_kwargsclientresponses       r"   check_if_auth_requiredr/   (   s        8L$6B88F	#ZZZ==H ##z1 988 "X%5%55 988  988 > 9  !! 	% 988 	! 988s   $C)BC)CB$B B$C) B!C)&B$7C)B C)	C)B"C)B$C) C)"C)$C8C9C)CC)CCC&CC&"C)c                      \ rS rSr% S\S'   S\S'   S\S'   S\S	'   SS
 jrSS jrSS jrSS jr\	SS j5       r
\	SS j5       r\	SS j5       r\	SS j5       rSrg)TokenStorageAdapterF   str_server_urlr   _key_value_storezPydanticAdapter[OAuthToken]_storage_oauth_tokenz+PydanticAdapter[OAuthClientInformationFull]_storage_client_infoc                    X l         Xl        [        [           " SU[        SS9U l        [        [
           " SU[
        SS9U l        g )Nzmcp-oauth-tokenT)default_collection	key_valuepydantic_modelraise_on_validation_errorzmcp-oauth-client-info)r4   r5   r   r   r6   r   r7   )selfasync_key_value
server_urls      r"   __init__TokenStorageAdapter.__init__L   sM    % /$3J$?0%%&*	%
! %44N$O6%5&*	%
!r!   c                     U R                    S3$ )Nz/tokensr4   r=   s    r"   _get_token_cache_key(TokenStorageAdapter._get_token_cache_key\   s    ""#7++r!   c                     U R                    S3$ )Nz/client_inforC   rD   s    r"   _get_client_info_cache_key.TokenStorageAdapter._get_client_info_cache_key_   s    ""#<00r!   c                   #    U R                   R                  U R                  5       S9I S h  vN   U R                  R                  U R	                  5       S9I S h  vN   g  N4 N7fN)key)r6   deleterE   r7   rH   rD   s    r"   clearTokenStorageAdapter.clearb   sZ     ''..43L3L3N.OOO''..43R3R3T.UUU 	PUs!   +A&A".A&A$A&$A&c                l   #    U R                   R                  U R                  5       S9I S h  vN $  N7frK   )r6   r'   rE   rD   s    r"   
get_tokensTokenStorageAdapter.get_tokensf   s.     ..22t7P7P7R2SSSS   +424c                   #    U R                   R                  U R                  5       UUR                  S9I S h  vN   g  N7fN)rL   valuettl)r6   putrE   
expires_in)r=   tokenss     r"   
set_tokensTokenStorageAdapter.set_tokensj   s@     ''++))+!! , 
 	
 	
s   7A?Ac                l   #    U R                   R                  U R                  5       S9I S h  vN $  N7frK   )r7   r'   rH   rD   s    r"   get_client_info#TokenStorageAdapter.get_client_infor   s9     ..22//1 3 
 
 	
 
rS   c                   #    S nUR                   (       a+  UR                   [        [        R                  " 5       5      -
  nU R                  R	                  U R                  5       UUS9I S h  vN   g  N7frU   )client_secret_expires_atinttimer7   rX   rH   )r=   client_inforW   s      r"   set_client_info#TokenStorageAdapter.set_client_infox   sc     //66TYY[9IIC''++//1 , 
 	
 	
s   A+A5-A3.A5)r5   r4   r7   r6   N)r>   r   r?   r3   )returnr3   rg   None)rg   zOAuthToken | None)rZ   r   rg   ri   )rg   z!OAuthClientInformationFull | None)rd   r   rg   ri   )r   r   r   r   __annotations__r@   rE   rH   rN   r   rQ   r[   r^   re   r    r   r!   r"   r1   r1   F   s    ##55EE
 ,1V T T 
 
 
 

 

 

r!   r1   c                     ^  \ rS rSrSr     S	           S
U 4S jjjrSU 4S jjrSS jrSS jr    SU 4S jjr	Sr
U =r$ )r      z
OAuth client provider for MCP servers with browser-based authentication.

This class provides OAuth authentication for FastMCP clients by opening
a browser for user authorization and running a local callback server.
c           	     P  > [        U5      nUR                   SUR                   3nU=(       d
    [        5       U l        SU R                   S3n	[        U[        5      (       a  SR                  U5      n
OUb  [        U5      n
OSn
[        SU[        U	5      /SS/S	/U
S
.U=(       d    0 D6nU=(       d
    [        5       n[        U[        5      (       a  SSKJn  U" SSS9  [        XHS9U l        Xl        ["        TU ]I  UUU R                  U R&                  U R(                  S9  g)a  
Initialize OAuth client provider for an MCP server.

Args:
    mcp_url: Full URL to the MCP endpoint (e.g. "http://host/mcp/sse/")
    scopes: OAuth scopes to request. Can be a
    space-separated string or a list of strings.
    client_name: Name for this client during registration
    token_storage: An AsyncKeyValue-compatible token store, tokens are stored in memory if not provided
    additional_client_metadata: Extra fields for OAuthClientMetadata
    callback_port: Fixed port for OAuth callback (default: random available port)
z://zhttp://localhost:z	/callback N authorization_coderefresh_tokencode)client_nameredirect_urisgrant_typesresponse_typesscoper   )warnzmUsing in-memory token storage is not recommended for production use -- tokens will be lost on server restart.   )message
stacklevel)r>   r?   )r?   client_metadatastorageredirect_handlercallback_handlerr   )r   schemenetlocr   redirect_port
isinstancelistjoinr3   r   r   r	   warningsrx   r1   token_storage_adapterserver_base_urlsuperr@   r~   r   )r=   r+   scopesrs   token_storageadditional_client_metadatacallback_port
parsed_urlr   redirect_uri
scopes_strr|   rx   	__class__s                r"   r@   OAuth.__init__   s@   * g&
'../s:3D3D2EF +C.A.C*4+=+=*>iH fd##&)JVJJ- 
#%l34-?"8
 */R
 &6m[11%; ;N);
"
  / 	&+..!22!22 	 	
r!   c                   >#    [         TU ]  5       I Sh  vN   U R                  R                  (       aV  U R                  R                  R                  (       a0  U R                  R                  U R                  R                  5        ggg Nv7f)zBLoad stored tokens and client info, properly setting token expiry.N)r   _initializecontextcurrent_tokensrY   update_token_expiry)r=   r   s    r"   r   OAuth._initialize   sd      g!### <<&&4<<+F+F+Q+QLL,,T\\-H-HI ,R& 	$s   BBA7Bc                  #    [         R                  " 5        ISh  vN nUR                  USS9I Sh  vN nUR                  S:X  a  [	        S5      eUR                  S;  a  [        SUR                   35      eSSS5      ISh  vN   [        R                  SU 35        [        R                  " U5        g N N N7! , ISh  vN  (       d  f       NL= f7f)	zIOpen browser for authorization, with pre-flight check for invalid client.NF)follow_redirectsi  z8OAuth client not found - cached credentials may be stale)   i.  i/  i3  i4  z#Unexpected authorization response: zOAuth authorization URL: )
r%   r&   r'   r(   r   RuntimeErrorloggerinfo
webbrowseropen)r=   authorization_urlr-   r.   s       r"   r~   OAuth.redirect_handler   s      $$&&&#ZZ(9EZRRH ##s*)N 
 ##+DD"9(:N:N9OP  '& 	/0A/BCD)*! 'R '&&&sU   CB;CCB=AC<CB?4C=C?CCC
CCc                  #    [        5       n[        R                  " 5       n[        U R                  U R
                  UUS9n[        R                  " 5        ISh  vN nUR                  UR                  5        [        R                  SU R                   35        Sn [        R                  " U5         UR                  5       I Sh  vN   UR                  (       a  UR                  eUR                  UR                  4sSSS5        SUl        [        R"                  " S5      I Sh  vN   UR$                  R'                  5         sSSS5      ISh  vN   $  GN N N5 N! , (       d  f       O%= f! [(         a  n[)        SU S35      UeSnAff = f SUl        [        R"                  " S5      I Sh  vN    UR$                  R'                  5         OE! SUl        [        R"                  " S5      I Sh  vN    UR$                  R'                  5         f = fSSS5      ISh  vN    O! , ISh  vN  (       d  f       O= f[+        S	5      e7f)
z4Handle OAuth callback and return (auth_code, state).)portr?   result_containerresult_readyNu7   🎧 OAuth callback server started on http://localhost:g     r@Tg?zOAuth callback timed out after z secondsz+OAuth callback handler could not be started)r   anyioEventr   r   r   create_task_group
start_soonserver   r   
fail_afterwaiterrorrr   stateshould_exitsleepcancel_scopecancelTimeoutErrorr   )r=   resultr   servertgTIMEOUTes          r"   r   OAuth.callback_handler   s     %&{{} 6##++#%	
 **,,MM&,,'KKI$J\J\I]^ G)%%g.&++---||$ll*!;;4	 /. &*"kk#&&&&&() -,, . '' - /.
   "5gYhG / &*"kk#&&&&&( &*"kk#&&&&&() -,,,,,, HIIs   AIEIA H2 E76E&
E 8E&	E7 H2,E"-H2IE$I E&"H2$I&
E4	0E73G4E77
FFFG H2:F=; H2!H<G?
= HH2 I+H.,I2I	8H;9I	Ic                 >#     [         TU ]  U5      nSn  UR                  U5      I Sh  vN nU7v nM!   N! [         a     gf = f! [         a    [
        R                  S5        SU l        U R                  R                  5       I Sh  vN    [         TU ]  U5      nSn  UR                  U5      I Sh  vN  nU7v nO! [         a      gf = fM4  f = f7f)zHTTPX auth flow with automatic retry on stale cached credentials.

If the OAuth flow fails due to invalid/stale client credentials,
clears the cache and retries once with fresh registration.
Nz@OAuth client not found on server, clearing cache and retrying...F)
r   async_auth_flowasendStopAsyncIterationr   r   debug_initializedr   rN   )r=   requestgenr.   yielded_requestr   s        r"   r   OAuth.async_auth_flow  s     	')'2CH,/IIh,?&?O%44H &?)  # 	LLR
 !&D,,22444')'2CH,/IIh,?&?&?O%44H) 	 	s   CA
 : 8	: A
 : 
AA
 CAA
 
ACBC&C:B=;
CC
CCCCCC)r   r   r   r   )NzFastMCP ClientNNN)r+   r3   r   zstr | list[str] | Noners   r3   r   zAsyncKeyValue | Noner   dict[str, Any] | Noner   z
int | Nonerh   )r   r3   rg   ri   )rg   ztuple[str, str | None])r   zhttpx.Requestrg   z-AsyncGenerator[httpx.Request, httpx.Response])r   r   r   r   r   r@   r   r~   r   r   r    __classcell__)r   s   @r"   r   r      s     *.+.2<@$(H
H
 'H
 	H

 ,H
 %:H
 "H
 H
TJ+*%JN#$#	6# #r!   )N)r+   r3   r,   r   rg   bool).
__future__r   rc   r   collections.abcr   typingr   urllib.parser   r   r%   key_value.aio.adapters.pydanticr   key_value.aio.protocolsr   key_value.aio.stores.memoryr	   mcp.client.authr
   r   mcp.shared.authr   r   r   pydanticr   typing_extensionsr   uvicorn.serverr   fastmcp.client.oauth_callbackr   r   fastmcp.utilities.httpr   fastmcp.utilities.loggingr   __all__r   r   	Exceptionr   r/   r1   r   r   r!   r"   <module>r      s    "   *  !   ; 1 3 = 
   & ! 7 0)	H	L) L
 9= 5	<=
, =
@z zr!   