
    "<i0                    f   d dl mZ d dlZd dlZd dlmZ d dlmZ d dlZd dl	Z	d dl
mZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZmZmZ d dlmZ d dlmZ d dlmZ d dlm Z m!Z! d dl"m#Z# d dl$m%Z% dgZ& e%e'          Z( G d de)          Z*	 dddZ+ G d de          Z, G d de          Z-dS )     )annotationsN)AsyncGenerator)Any)PydanticAdapter)AsyncKeyValue)MemoryStore)OAuthClientProviderTokenStorage)McpHttpClientFactory)OAuthClientInformationFullOAuthClientMetadata
OAuthToken)
AnyHttpUrl)override)Server)OAuthCallbackResultcreate_oauth_callback_server)find_available_port)
get_loggerOAuthc                      e Zd ZdZdS )ClientNotFoundErrorzARaised when OAuth client credentials are not found on the server.N)__name__
__module____qualname____doc__     /Users/kimhansen/Desktop/03 Workspace/ceo-agents/chl-effectiveness/mcp-servers/whoop/.venv/lib/python3.11/site-packages/fastmcp/client/auth/oauth.pyr   r   $   s        KKKKr   r   mcp_urlstrhttpx_kwargsdict[str, Any] | Nonereturnboolc                  K   t          j        di |pi 4 d{V }	 |                    | d           d{V }|j        dv r	 ddd          d{V  dS d|j        v r	 ddd          d{V  dS 	 ddd          d{V  dS # t           j        $ r Y ddd          d{V  dS w xY w# 1 d{V swxY w Y   dS )	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)r    r"   clientresponses       r   check_if_auth_requiredr0   (   s+       88L$6B88       F	#ZZZ========H #z11              "X%555                             ! 	 	 	%              	!               s4   B0&B		B		B-B0,B--B00
B:=B:c                      e Zd ZU ded<   ded<   ded<   ded<   ddZddZddZddZedd            Z	ed d            Z
ed!d            Zed"d            ZdS )#TokenStorageAdapterr!   _server_urlr   _key_value_storezPydanticAdapter[OAuthToken]_storage_oauth_tokenz+PydanticAdapter[OAuthClientInformationFull]_storage_client_infoasync_key_value
server_urlc                    || _         || _        t          t                   d|t          d          | _        t          t
                   d|t
          d          | _        d S )Nzmcp-oauth-tokenT)default_collection	key_valuepydantic_modelraise_on_validation_errorzmcp-oauth-client-info)r3   r4   r   r   r5   r   r6   )selfr7   r8   s      r   __init__zTokenStorageAdapter.__init__L   sk    % /$3J$?0%%&*	%
 %
 %
! %44N$O6%5&*	%
 %
 %
!!!r   r$   c                    | j          dS )Nz/tokensr3   r>   s    r   _get_token_cache_keyz(TokenStorageAdapter._get_token_cache_key\   s    "++++r   c                    | j          dS )Nz/client_inforA   rB   s    r   _get_client_info_cache_keyz.TokenStorageAdapter._get_client_info_cache_key_   s    "0000r   Nonec                   K   | j                             |                                            d {V  | j                            |                                            d {V  d S N)key)r5   deleterC   r6   rE   rB   s    r   clearzTokenStorageAdapter.clearb   s|      '..43L3L3N3N.OOOOOOOOO'..43R3R3T3T.UUUUUUUUUUUr   OAuthToken | Nonec                l   K   | j                             |                                            d {V S rH   )r5   r*   rC   rB   s    r   
get_tokenszTokenStorageAdapter.get_tokensf   s>      .22t7P7P7R7R2SSSSSSSSSr   tokensr   c                ~   K   | j                             |                                 ||j                   d {V  d S N)rI   valuettl)r5   putrC   
expires_in)r>   rO   s     r   
set_tokenszTokenStorageAdapter.set_tokensj   sf      '++))++! , 
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
r   !OAuthClientInformationFull | Nonec                l   K   | j                             |                                            d {V S rH   )r6   r*   rE   rB   s    r   get_client_infoz#TokenStorageAdapter.get_client_infor   sS      .22//11 3 
 
 
 
 
 
 
 
 	
r   client_infor   c                   K   d }|j         r(|j         t          t          j                              z
  }| j                            |                                 ||           d {V  d S rQ   )client_secret_expires_atinttimer6   rT   rE   )r>   rZ   rS   s      r   set_client_infoz#TokenStorageAdapter.set_client_infox   s      / 	J6TY[[9I9IIC'++//11 , 
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
r   N)r7   r   r8   r!   )r$   r!   r$   rF   )r$   rL   )rO   r   r$   rF   )r$   rW   )rZ   r   r$   rF   )r   r   r   __annotations__r?   rC   rE   rK   r   rN   rV   rY   r_   r   r   r   r2   r2   F   s        ####5555EEEE
 
 
 
 , , , ,1 1 1 1V V V V T T T XT 
 
 
 X
 
 
 
 X

 

 

 

 X

 

 

r   r2   c                  Z     e Zd ZdZ	 	 	 	 	 	 dd fdZd fdZd dZd!dZd" fdZ xZ	S )#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.
    NFastMCP Clientr    r!   scopesstr | list[str] | Noneclient_nametoken_storageAsyncKeyValue | Noneadditional_client_metadatar#   callback_port
int | Nonehttpx_client_factoryMcpHttpClientFactory | Nonec           	     t   |                     d          }|pt          j        | _        |pt	                      | _        d| j         d}t          |t                    rd                    |          }	n|t          |          }	nd}	t          d|t          |          gddgd	g|	d
|pi }
|pt                      }t          |t                    rddlm}  |dd           t          ||          | _        || _        t%                                          ||
| j        | j        | j                   dS )al  
        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http://localhost:z	/callback N authorization_coderefresh_tokencode)rf   redirect_urisgrant_typesresponse_typesscoper   )warnzUsing in-memory token storage -- tokens will be lost when the client restarts. For persistent storage across multiple MCP servers, provide an encrypted AsyncKeyValue backend. See https://gofastmcp.com/clients/auth/oauth#token-storage for details.   )message
stacklevel)r7   r8   )r8   client_metadatastorageredirect_handlercallback_handlerr   )rstripr(   r)   rl   r   redirect_port
isinstancelistjoinr!   r   r   r   warningsry   r2   token_storage_adapterr    superr?   r   r   )r>   r    rd   rf   rg   ri   rj   rl   redirect_uri
scopes_strr}   ry   	__class__s               r   r?   zOAuth.__init__   s   . ..%% %9$ME<M!*C.A.C.CH4+=HHH fd## 	&))JJVJJJ- 
#%l334-?"8
 
 */R
 
 &6m[11 	%%%%%%D\ 	    ;N)g;
 ;
 ;
"
  	+.!2!2 	 	
 	
 	
 	
 	
r   r$   rF   c                   K   t                                                       d{V  | j        j        r7| j        j        j        r(| j                            | j        j                   dS dS dS )zBLoad stored tokens and client info, properly setting token expiry.N)r   _initializecontextcurrent_tokensrU   update_token_expiry)r>   r   s    r   r   zOAuth._initialize   s       gg!!######### <& 	J4<+F+Q 	JL,,T\-HIIIII	J 	J 	J 	Jr   authorization_urlc                  K   |                                  4 d{V }|                    |d           d{V }|j        dk    rt          d          |j        dvrt	          d|j                   	 ddd          d{V  n# 1 d{V swxY w Y   t
                              d|            t          j        |           dS )	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: )	rl   r*   r+   r   RuntimeErrorloggerinfo
webbrowseropen)r>   r   r.   r/   s       r   r   zOAuth.redirect_handler   s~      ,,.. 	 	 	 	 	 	 	&#ZZ(9EZRRRRRRRRH #s**)N  
 #+DDD"P(:NPP   	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	C0ACCDDD)*****s   AB
BBtuple[str, str | None]c                :  K   t                      }t          j                    }t          | j        | j        ||          }t          j                    4 d{V }|                    |j                   t          
                    d| j                    d}	 t          j        |          5  |                                 d{V  |j        r|j        |j        |j        fcddd           d|_        t          j        d           d{V  |j                                         cddd          d{V  S # 1 swxY w Y   n&# t(          $ r}t)          d| d          |d}~ww xY w	 d|_        t          j        d           d{V  |j                                         n?# d|_        t          j        d           d{V  |j                                         w xY w	 ddd          d{V  n# 1 d{V swxY w Y   t+          d	          )
z4Handle OAuth callback and return (auth_code, state).)portr8   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errorrt   stateshould_exitsleepcancel_scopecancelTimeoutErrorr   )r>   resultr   servertgTIMEOUTes          r   r   zOAuth.callback_handler   s`      %&&{}} 6#|#%	
 
 
 *,, 	) 	) 	) 	) 	) 	) 	)MM&,'''KK^$J\^^   G)%g.. 5 5&++---------| +$l*!;4	5 5 5 5 5 5 5 &*"k#&&&&&&&&&&&((()	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)5 5 5 5 5 5 5 5 5
     "GgGGG 5 &*"k#&&&&&&&&&&&(((( &*"k#&&&&&&&&&&&((((()	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	), HIIIsr   ?G=E	.6D=$E	0:G==E	E	E	E	F+	
E,E''E,,F+0;G=+<G''G==
H
Hrequesthttpx.Request-AsyncGenerator[httpx.Request, httpx.Response]c                 K   	 t                                          |          }d}	 	 |                    |           d{V }|W V }n# t          $ r Y dS w xY w4# t          $ r t
                              d           d| _        | j        	                                 d{V  t                                          |          }d}	 	 |                    |           d{V }|W V }n# t          $ r Y Y dS w xY w5w xY w)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.
        NTz@OAuth client not found on server, clearing cache and retrying...F)
r   async_auth_flowasendStopAsyncIterationr   r   debug_initializedr   rK   )r>   r   genr/   yielded_requestr   s        r   r   zOAuth.async_auth_flow!  sw     	''))'22CH,/IIh,?,?&?&?&?&?&?&?O%4444HH)   EE # 	 	 	LLR   !&D,22444444444 ''))'22CH,/IIh,?,?&?&?&?&?&?&?O%4444HH)   EEE		sS   $A  A 
A 
AA AA A.D C-,D-
C<7D;C<<D)Nrc   NNNN)r    r!   rd   re   rf   r!   rg   rh   ri   r#   rj   rk   rl   rm   r`   )r   r!   r$   rF   )r$   r   )r   r   r$   r   )
r   r   r   r   r?   r   r   r   r   __classcell__)r   s   @r   r   r      s          *.+.2<@$(<@L
 L
 L
 L
 L
 L
 L
\J J J J J J+ + + +*%J %J %J %JN$ $ $ $ $ $ $ $ $ $r   )N)r    r!   r"   r#   r$   r%   ).
__future__r   r^   r   collections.abcr   typingr   r   r(   key_value.aio.adapters.pydanticr   key_value.aio.protocolsr   key_value.aio.stores.memoryr   mcp.client.authr	   r
   mcp.shared._httpx_utilsr   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   r0   r2   r   r   r   r   <module>r      sJ   " " " " " "      * * * * * *         ; ; ; ; ; ; 1 1 1 1 1 1 3 3 3 3 3 3 = = = = = = = = 8 8 8 8 8 8         
        & & & & & & ! ! ! ! ! !        7 6 6 6 6 6 0 0 0 0 0 0)	H		L L L L L) L L L
 9=    <=
 =
 =
 =
 =
, =
 =
 =
@         r   