+
    wi%/                     j   ^ RI t ^ RIt^ RIHtHt ^ RIHtHt ^ RIH	t	H
t
 ^ RIHtHt ^ RIHt ^ RIHtHtHtHtHt ^ RIHt ] P0                  ! ]4      tR	 R
 ltR R ltR R ltR R ltR'R R lltR R lt R R lt!R R lt"R R lt#R R lt$R R lt%R R  lt&R! R" lt'R'R# R$ llt(R% R& lt)R# )(    N)urljoinurlparse)RequestResponse)AnyUrlValidationError)OAuthRegistrationErrorOAuthTokenError)MCP_PROTOCOL_VERSION)OAuthClientInformationFullOAuthClientMetadataOAuthMetadata
OAuthTokenProtectedResourceMetadata)LATEST_PROTOCOL_VERSIONc                J    V ^8  d   QhR\         R\        R\        R,          /# )   response
field_namereturnNr   str)formats   "I/home/ubuntu/.local/lib/python3.14/site-packages/mcp/client/auth/utils.py__annotate__r      s%      (  d
     c                    V P                   P                  R4      pV'       g   R# V R2p\        P                  ! W24      pV'       d+   VP	                  ^4      ;'       g    VP	                  ^4      # R# )z{
Extract field from WWW-Authenticate header.

Returns:
    Field value if found in WWW-Authenticate header, None otherwise
zWWW-AuthenticateNz=(?:"([^"]+)"|([^\s,]+)))headersgetresearchgroup)r   r   www_auth_headerpatternmatchs   &&   r   extract_field_from_www_authr&      sb     &&**+=>O 56GIIg/E{{1~//Q/r   c                >    V ^8  d   QhR\         R\        R,          /# r   r   r   Nr   )r   s   "r   r   r   ,   s     : :( :sTz :r   c                    \        V R4      # )z
Extract scope parameter from WWW-Authenticate header as per RFC6750.

Returns:
    Scope string if found in WWW-Authenticate header, None otherwise
scope)r&   r   s   &r   extract_scope_from_www_authr,   ,   s     'x99r   c                >    V ^8  d   QhR\         R\        R,          /# r(   r   )r   s   "r   r   r   6   s"     
F 
Fh 
F3: 
Fr   c                P    V '       d   V P                   R8w  d   R# \        V R4      # )z
Extract protected resource metadata URL from WWW-Authenticate header as per RFC9728.

Returns:
    Resource metadata URL if found in WWW-Authenticate header, None otherwise
i  Nresource_metadata)status_coder&   r+   s   &r   'extract_resource_metadata_from_www_authr1   6   s%     x++s2&x1DEEr   c                `    V ^8  d   QhR\         R,          R\         R\        \         ,          /# )r   www_auth_urlN
server_urlr   r   list)r   s   "r   r   r   C   s-     # #3: #[^ #cghkcl #r   c                \   . pV '       d   VP                  V 4       \        V4      pVP                   RVP                   2pVP                  '       d<   VP                  R8w  d+   \        VRVP                   24      pVP                  V4       \        VR4      pVP                  V4       V# )a  
Build ordered list of URLs to try for protected resource metadata discovery.

Per SEP-985, the client MUST:
1. Try resource_metadata from WWW-Authenticate header (if present)
2. Fall back to path-based well-known URI: /.well-known/oauth-protected-resource/{path}
3. Fall back to root-based well-known URI: /.well-known/oauth-protected-resource

Args:
    www_auth_url: optional resource_metadata url extracted from the WWW-Authenticate header
    server_url: server url

Returns:
    Ordered list of URLs to try for discovery
:///z%/.well-known/oauth-protected-resource)appendr   schemenetlocpathr   )r3   r4   urlsparsedbase_urlpath_based_urlroot_based_urls   &&     r   0build_protected_resource_metadata_discovery_urlsrC   C   s      D L! j!F--FMM?3H {{{v{{c) -RSYS^S^R_+`aN# X'NONKKKr   c          	          V ^8  d   QhR\         R,          R\        R,          R\        R,          R\         R,          /# )r   www_authenticate_scopeNprotected_resource_metadataauthorization_server_metadatar   )r   r   r   )r   s   "r   r   r   i   sB      $J!:T!A $14#7 	4Z	r   c                    V e   V # Ve*   VP                   e   RP                  VP                   4      # Ve*   VP                   e   RP                  VP                   4      # R# )zLSelect scopes as outlined in the 'Scope Selection Strategy' in the MCP spec.N )scopes_supportedjoin)rE   rF   rG   s   &&&r   get_client_metadata_scopesrL   i   se     )%%	$	05P5a5a5mxx3DDEE	&	27T7e7e7qxx5FFGG r   c                `    V ^8  d   QhR\         R,          R\         R\        \         ,          /# )r   auth_server_urlNr4   r   r5   )r   s   "r   r   r      s.     ) )cTXj )fi )nrsvnw )r   c                   V '       g)   \        V4      pVP                   RVP                   R2.# . p\        V 4      pVP                   RVP                   2pVP                  '       d   VP                  R8w  d   RVP                  P	                  R4       2pVP                  \        WE4      4       RVP                  P	                  R4       2pVP                  \        WF4      4       VP                  P	                  R4       R2pVP                  \        WF4      4       V# VP                  \        VR4      4       VP                  \        VR4      4       V# )z
Generate ordered list of (url, type) tuples for discovery attempts.

Args:
    auth_server_url: URL for the OAuth Authorization Metadata URL if found, otherwise None
    server_url: URL for the MCP server, used as a fallback if auth_server_url is None
r8   z'/.well-known/oauth-authorization-serverr9   z!/.well-known/openid-configuration)r   r;   r<   r=   rstripr:   r   )rN   r4   r?   r>   r@   
oauth_path	oidc_paths   &&     r   8build_oauth_authorization_server_metadata_discovery_urlsrS      s2     *%==/V]]O3Z[\\Do&F--FMM?3H {{{v{{c)>v{{?Q?QRU?V>WX
GH12 88J8J38O7PQ	GH01 {{))#.//PQ	GH01 	KK"KLM 	KK"EFGKr   c                >    V ^8  d   QhR\         R\        R,          /# r(   )r   r   )r   s   "r   r   r      s!      %r   c                   "   V P                   ^8X  d2    V P                  4       G Rj  xL
 p\        P                  ! V4      pV# R#  L  \         d     R# i ; i5i)z
Handle protected resource metadata discovery response.

Per SEP-985, supports fallback when discovery fails at one URL.

Returns:
    True if metadata was successfully discovered, False if we should try next URL
N)r0   areadr   model_validate_jsonr   )r   contentmetadatas   &  r   "handle_protected_resource_responserZ      s[      s"	$NN,,G0DDWMHO  -  		s8   AA	 AA	 AA	 	AAAAc                `    V ^8  d   QhR\         R\        \        \        R,          3,          /# r(   )r   tupleboolr   )r   s   "r   r   r      s*     
 
( 
uT=[_K_E_?` 
r   c                   "   V P                   ^8X  d4    V P                  4       G Rj  xL
 p\        P                  ! V4      pRV3# V P                   R8  g   V P                   R8  d   R# R#  LD  \         d    Ru # i ; i5i)   NTi  i  )TN)FN)r0   rV   r   rW   r   )r   rX   asms   &  r   handle_auth_metadata_responsera      s     s"	$NN,,G33G<C9 
			#x';';s'B -  		s8   BA/ A-A/ 'B-A/ /A?<B>A??Bc                0    V ^8  d   QhR\         R\        /# )r   urlr   )r   r   )r   s   "r   r   r      s     X Xs Xw Xr   c                 2    \        R V \        \        /R7      # )GET)r   )r   r   r   )rc   s   &r   create_oauth_metadata_requestrf      s    5#(<>U'VWWr   c                V    V ^8  d   QhR\         R,          R\        R\        R\        /# )r   auth_server_metadataNclient_metadataauth_base_urlr   )r   r   r   r   )r   s   "r   r   r      s7     s s'$.sATsehssr   c                    V '       d)   V P                   '       d   \        V P                   4      pM\        VR4      pVP                  RRRR7      p\	        RW4RR/R7      # )	z9Build registration request or skip if already registered.z	/registerTjson)by_aliasmodeexclude_nonePOSTzContent-Typezapplication/json)rl   r   )registration_endpointr   r   
model_dumpr   )rh   ri   rj   registration_urlregistration_datas   &&&  r   "create_client_registration_requestru      sa    
  4 J J J3IIJ"=+>'22Dv\`2a6+n^pMqrrr   c                0    V ^8  d   QhR\         R\        /# r   r   r   )r   r   )r   s   "r   r   r      s     L L L>X Lr   c                R  "   V P                   R9  d>   V P                  4       G Rj  xL
  \        RV P                    RV P                   24      h V P                  4       G Rj  xL
 p\        P
                  ! V4      pV#  LZ L  \         d   p\        RT 24      hRp?ii ; i5i)zHandle registration response.NzRegistration failed: rI   zInvalid registration response: )r_      )r0   rV   r	   textr   rW   r   )r   rX   client_infoes   &   r   handle_registration_responser}      s     :-nn$'<X=Q=Q<RRST\TaTaSb%cddL ((0DDWM 	 )
  L$'Fqc%JKKLsE   %B'B)B'B %B&B B'B B$BB$$B'c                >    V ^8  d   QhR\         R,          R\        /# )r   rc   Nr   )r   r]   )r   s   "r   r   r      s      cDj T r   c                    V '       g   R#  \        V 4      pVP                  R8H  ;'       d    VP                  R9  #   \         d     R# i ; i)zValidate that a URL is suitable for use as a client_id (CIMD).

The URL must be HTTPS with a non-root pathname.

Args:
    url: The URL to validate

Returns:
    True if the URL is a valid HTTPS URL with a non-root pathname
Fhttps) r9   )r   r;   r=   	Exception)rc   r?   s   & r   is_valid_client_metadata_urlr      sJ     #}}'HHFKKy,HH s    = = AAc                X    V ^8  d   QhR\         R,          R\        R,          R\        /# )r   oauth_metadataNclient_metadata_urlr   )r   r   r]   )r   s   "r   r   r   
  s4     H H!D(HtH 
Hr   c                F    V'       g   R# V '       g   R# V P                   RJ # )a  Determine if URL-based client ID (CIMD) should be used instead of DCR.

URL-based client IDs should be used when:
1. The server advertises client_id_metadata_document_supported=true
2. The client has a valid client_metadata_url configured

Args:
    oauth_metadata: OAuth authorization server metadata
    client_metadata_url: URL-based client ID (already validated)

Returns:
    True if CIMD should be used, False if DCR should be used
FT)%client_id_metadata_document_supported)r   r   s   &&r   should_use_client_metadata_urlr   
  s!    " ??4GGr   c                `    V ^8  d   QhR\         R\        \        ,          R,          R\        /# )r   r   redirect_urisNr   )r   r6   r   r   )r   s   "r   r   r   $  s-      -1&\D-@r   c                    \        V RVR7      # )a  Create client information using a URL-based client ID (CIMD).

When using URL-based client IDs, the URL itself becomes the client_id
and no client_secret is used (token_endpoint_auth_method="none").

Args:
    client_metadata_url: The URL to use as the client_id
    redirect_uris: The redirect URIs from the client metadata (passed through for
        compatibility with OAuthClientInformationFull which inherits from OAuthClientMetadata)

Returns:
    OAuthClientInformationFull with the URL as client_id
none)	client_idtoken_endpoint_auth_methodr   )r   )r   r   s   &&r   $create_client_info_from_metadata_urlr   $  s      &%#)# r   c                0    V ^8  d   QhR\         R\        /# rw   )r   r   )r   s   "r   r   r   ;  s     > >>>r   c                   "    V P                  4       G Rj  xL
 p\        P                  ! V4      pV#  L  \         d   p\	        RT 24      hRp?ii ; i5i)aV  Parse and validate token response with optional scope validation.

Parses token response JSON. Callers should check response.status_code before calling.

Args:
    response: HTTP response from token endpoint (status already checked by caller)

Returns:
    Validated OAuthToken model

Raises:
    OAuthTokenError: If response JSON is invalid
NzInvalid token response: )rV   r   rW   r   r
   )r   rX   token_responser|   s   &   r   handle_token_response_scopesr   ;  sX      > ((#77@ )  > 8<==>s1   A6 46 A6 AAAA)N)*loggingr    urllib.parser   r   httpxr   r   pydanticr   r   mcp.client.authr	   r
   mcp.client.streamable_httpr   mcp.shared.authr   r   r   r   r   	mcp.typesr   	getLogger__name__loggerr&   r,   r1   rC   rL   rS   rZ   ra   rf   ru   r}   r   r   r   r    r   r   <module>r      s     	 * # , C ;  .			8	$,:
F#L0)X2
XsL (H4.>r   