+
    lHàjyp  ã                   ó~  a € RC t?0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
HtHt ^ RIHt ^ RIHtHtHt ^ RIHt ]P*                  ! R4      tRDtRER R lltR	 R
 ltR R ltR R lt ! R R]4      t ! R R]4      tRFt R R lt!R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' lt+R( R) lt,R* R+ lt-R,R-R.].! 4       /R/ R0 llt/RGt0]Pb                  ! R14      t2^t3]03R2 R3 llt4R4t5R5 R6 lt6R7 R8 lt7R9 R: lt8R; R< lt9Rs:] ^ k R= R> lt;R? R@ lt<RHt=] ^k RA RB lt>R# )Ia  MCP connection/transport error classification: URL validation, TLS client certs, identity
headers, redirect header stripping, exception-group unwrapping, auth/session-expired/
method-not-found detection and connect-error formatting. Split from tools/mcp_tool.py.N)ÚAnyÚListÚOptional)Úurlparse)Ú_exc_strÚ_sanitize_errorÚ_core)ÚNodeAbiMismatchErrorztools.mcp_toolc                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )é   ÚexcÚcodesÚmarkersÚreturn)ÚBaseExceptionÚtupleÚbool)Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/tools/mcp_tool_errors.pyÚ__annotate__r      s/   € ÷ Rñ Rœ-ð R´ð RÄð RÔUYñ Ró    c                óÔ   a € \        \        S RR4      RR4      ;'       g    TpW19   ;'       g;    \        ;QJ d    V 3R lV 4       F  '       g   K   R# 	  R# ! V 3R lV 4       4      # )z×Structural ``MCPError.error.code`` (or *code*) in *codes*, else any *marker* in ``str(exc).lower()``. Never
``isinstance`` on SDK exception types: they arrive wrapped in ExceptionGroups and drift across generations.ÚerrorNÚcodec              3   óZ   <"  € T F   q\        S4      P                  4       9   x € K"  	  R # 5i©N)ÚstrÚlower)Ú.0Úmarkerr   s   & €r   Ú	<genexpr>Ú#_jsonrpc_matches.<locals>.<genexpr>   s   øé € ÐQÉ¸v¬#¨c«(¯.©.Ó*:Ö :Ëùs   ƒ(+TF)ÚgetattrÚany)r   r   r   r   s   f&&&r   Ú_jsonrpc_matchesr$      sW   ø€ ô ”7˜3 ¨Ó.°¸Ó=×EÐEÀ€DØ‰=×QÐQŸC›CÔQÉÓQŸCœCÐQšCÐQ˜CÔQÉÓQÓQÐQr   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r   r   ©r   r   )r   s   "r   r   r      s   € ÷ Lñ L¤}ð L¼ñ Lr   c           
     ó¢   € \        V \        \        P                  3R\	        \        4      3\        V RR4      R7      ;'       g    \        V 4      # )zOTrue when a failed ``initialize`` signals a stateless-only (2026-07-28) server.zunsupported protocol versionr   N)r   )r$   Ú%_JSONRPC_UNSUPPORTED_PROTOCOL_VERSIONr   Ú_JSONRPC_METHOD_NOT_FOUNDr   r"   Ú_is_method_not_found_error©r   s   &r   Ú_handshake_rejected_as_modernr-      sR   € äØÔ3´U×5TÑ5TÐUØ	'¬Ô-RÓ)SÐTÜ�S˜& $Ó'ô)÷ Lð Lô -GÀsÓ,KðLr   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r'   )r   s   "r   r   r   &   s   € ÷ gñ g´mð gÌñ gr   c                óL   € R\        \        V 4      4      P                  4       9   # )u'  True when ``initialize`` SUCCEEDED on the wire (HTTP 200, a valid InitializeResult) but the SDK
refused the ``protocolVersion`` the server named â€” its ``RuntimeError("Unsupported protocol version
from the server: ...")``. Distinct from a JSON-RPC -32022 rejection, where the server refused us.z,unsupported protocol version from the server)r   Ú_unwrap_exception_groupr   r,   s   &r   Ú,_handshake_answered_with_unsupported_versionr1   &   s$   € ð :¼SÔAXÐY\ÓA]Ó=^×=dÑ=dÓ=fÑfÐfr   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r'   )r   s   "r   r   r   -   s   € ÷ iñ i¤Mð i´dñ ir   c                óp   € \        V \        P                  3\        \        P                  4      RRR34      # )u+  True if *exc* is a JSON-RPC ``method not found`` (-32601; ``ping`` is optional in MCP). The
substring fallback includes "Unknown method: <name>" â€” without it the pingâ†’list_tools keepalive
fallback never latches and reconnect-loops.

The substring fallback matters when a server reports method-not-found without a structural ``-32601``
code (e.g. surfaced as a plain exception string). Besides the canonical "method not found", many
JSON-RPC implementations phrase it as "Unknown method: <name>" â€” agentmemory's MCP server is one such
case (#50028).
zmethod not foundzunknown methodznot found: ping)r$   r   r*   r   r,   s   &r   r+   r+   -   s;   € ô ØŒe×-Ñ-Ð/Ü	ŒU×,Ñ,Ó	-Ð/AÐCSÐUfÐgóið ir   c                   ó   € ] tR t^<tRtRtR# )ÚInvalidMcpUrlErroru  A remote MCP server's ``url`` is not parseable http(s):// â€” validated once at startup to fail fast.

Validated once at startup so we fail fast with a clear message instead of burning through the
reconnect-backoff loop on every attempt. (Ported from anomalyco/opencode#25019.)
© N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r6   r   r   r5   r5   <   s   † õr   r5   c                   ó   € ] tR t^DtRtRtR# )ÚNonMcpEndpointErrorzïAn HTTP MCP URL served a non-MCP 2xx (e.g. ``text/html``). Non-retryable: every attempt gets
the same page, so backoff is skipped and the server fails immediately. Subclasses ConnectionError
so broad catches still see a connection problem.r6   Nr7   r6   r   r   r?   r?   D   s   † õ8r   r?   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r'   )r   s   "r   r   r   O   s   € ÷ Wñ W¤}ð W¼ñ Wr   c                óà   € \        V 4      p\        \        VRR4      RR4      \        9   d   R# \        \        VRR4      RR4      pVR8H  ;'       d    R\        V4      P	                  4       9   # )	uÏ  True when a Streamable-HTTP connect failure looks like a transport mismatch rather than a
broken server: a 400-family rejection of the initialize POST, or the SDK's opaque INTERNAL_ERROR
(-32603 ``Server returned an error response``) it maps such rejections to on mcp >= 2.0 (error
class per PR #104363, @RohithPariki). Timeouts and auth errors never qualify â€” neither carries
these markers â€” so a slow or 401ing server is not retried on the wrong transport.
ÚresponseNÚstatus_codeTr   r   ú!server returned an error responseé¥€ÿÿ)r0   r"   Ú_STREAMABLE_REJECT_STATUSESr   r   )r   Úrootr   s   &  r   Ú_is_streamable_http_rejectionrH   O   sf   € ô # 3Ó'€DÜŒw�t˜Z¨Ó.°¸tÓDÔHcÔcÙÜ”7˜4 ¨$Ó/°¸Ó>€DØ�6‰>×VÐVÐAÄSÈÃYÇ_Á_ÓEVÑVÐVr   i,  c                ó$   € V ^8„  d   QhR\         /# )r   Úsink)Údict)r   s   "r   r   r   `   s   € ÷ ñ ¬ñ r   c                ó   a € V 3R lpV# )u  httpx response hook for the owned Streamable HTTP client: remembers the last 4xx/5xx the server
sent (status, method, URL, head of the body). mcp >= 2.0 folds a non-2xx whose body it cannot
parse as a JSON-RPC error into the opaque ``-32603 Server returned an error response`` â€” the
status and the server's own words (e.g. ``400 {"code":-32020,"message":"Unsupported
MCP-Protocol-Version"}``) never reach the exception, so this is the only place they can be
observed. SSE bodies are never read (a stream would block the hook).c              “   ód  <"  € V P                   R 8  d   R# RpV P                  P                  RR4      P                  R4      ^ ,          P	                  4       P                  4       R8w  dW    V P                  4       G Rj  x€L
 pRP                  VR\        ^,           P                  RR4      P                  4       4      pSP                  V P                   V P                  P                  \        V P                  P                  4      VR\         R	7       R#  Lš  \         d    Rp Lji ; i5i)
é�  NÚ úcontent-typeÚ;útext/event-streamÚ zutf-8Úreplace)ÚstatusÚmethodÚurlÚbody)rC   ÚheadersÚgetÚsplitÚstripr   ÚareadÚjoinÚ_HTTP_REJECTION_BODY_CHARSÚdecodeÚ	ExceptionÚupdateÚrequestrV   r   rW   )rB   rX   ÚrawrJ   s   &  €r   Ú_recordÚ._make_http_rejection_recorder.<locals>._recordh   s  øé € Ø×Ñ #Ô%ÙØˆØ×Ñ×Ñ °Ó3×9Ñ9¸#Ó>¸qÕA×GÑGÓI×OÑOÓQÐUhÔhðØ$ŸN™NÓ,×,�Ø—x‘x Ð$CÔ%?À!Õ%CÐ D× KÑ KÈGÐU^Ó _× eÑ eÓ gÓh�ð 	�‰˜8×/Ñ/¸×8HÑ8H×8OÑ8OÜ˜H×,Ñ,×0Ñ0Ó1¸Ð=XÔ>XÐ8Yð 	ö 	[ñ	 -øäô Ø’ðüs>   ƒA)D0Á-D Â DÂAD ÃAD0ÄD ÄD-Ä*D0Ä,D-Ä-D0r6   )rJ   re   s   f r   Ú_make_http_rejection_recorderrg   `   s   ø€ õ[ð €Nr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r   Ú	rejectionr   )r   rK   r   )r   s   "r   r   r   x   s!   € ÷  ñ  ¤ð  ¼$ð  Ä3ñ  r   c                óR  € \        V 4      p\        V4      p\        \        VRR4      RR4      R8H  ;'       d    RVP                  4       9   pV'       d	   V'       g   V# RVR,           RVR,           R	VR
,           2pVR,          '       d   VRVR,           2,          pV RV R2# )a  ``str(root cause)`` of a Streamable HTTP connect failure; when that root is the SDK's opaque
``-32603 Server returned an error response`` and the recorder saw the rejection, the HTTP status,
request URL and body head are appended so the message names what the server actually said.r   Nr   rD   zHTTP rU   z from rV   rS   rW   rX   ú: ú (Ú)rE   )r0   r   r"   r   )r   ri   rG   ÚtextÚopaqueÚdetails   &&    r   Ú_describe_http_failurerq   x   sº   € ô # 3Ó'€DÜˆt‹9€DÜ”g˜d G¨TÓ2°F¸DÓAÀVÑK÷ Fð FØ5¸¿¹»ÑEð ç—yØˆØ�Y˜xÕ(Ð)¨°	¸(Õ0CÐ/DÀAÀiÐPUÕFVÐEWÐX€FØ�×ÔØ�B�y Õ(Ð)Ð*Õ*ˆØˆV�2�f�X˜QÐÐr   c                ó0   € V ^8„  d   QhR\         R\         /# r&   )r   )r   s   "r   r   r   ˆ   s   € ÷ ñ ¤ð ´=ñ r   c                ó€  € \        V \        4      '       d¨   V P                  '       d–   V P                  \        \
        34      ^ ,          pVe@   \        V\        4      '       d(   VP                  '       d   VP                  ^ ,          pK=  Vh\        R V P                   4       V P                  ^ ,          4      p K½  V # )a"  Root-cause leaf of anyio ``(Base)ExceptionGroup`` wrappers (group ``str()`` is opaque). A
``KeyboardInterrupt``/``SystemExit`` leaf anywhere is re-raised, never flattened into a loggable
error; a non-cancellation leaf is preferred over the ``CancelledError`` noise anyio sprays on siblings.c              3   óL   "  € T F  p\        V4      '       d   K  Vx € K  	  R # 5ir   ©Ú_contains_only_cancellation©r   Úsubs   & r   r    Ú*_unwrap_exception_group.<locals>.<genexpr>’   s   é € ÐZ¡>˜CÔ9TÐUX×9Y—C’C£>ùs   ‚$š
$)Ú
isinstanceÚBaseExceptionGroupÚ
exceptionsr[   ÚKeyboardInterruptÚ
SystemExitÚnext)r   Úleafs   & r   r0   r0   ˆ   sŠ   € ô �SÔ,×
-Ò
-°#·.·.°.Ø!Ÿi™iÔ):¼JÐ(GÓHÈÕKˆØÒÜ˜TÔ#5×6Ò6¸4¿?¿?¸?Ø—‘ qÕ)’ØˆJÜÑZ 3§>¢>ÓZÐ\_×\jÑ\jÐklÕ\mÓnŠØ€Jr   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r'   )r   s   "r   r   r   –   s   € ÷ 3ñ 3¤]ð 3´tñ 3r   c                óò   € \        V \        4      '       dI   \        ;QJ d&    R V P                   4       F  '       d   K   R# 	  R# ! R V P                   4       4      # \        V \        P
                  4      # )z?True if ``exc`` is (or a group containing only) CancelledError.c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5ir   ru   rw   s   & r   r    Ú._contains_only_cancellation.<locals>.<genexpr>™   s   é € ÐN¹~¸Ô.¨s×3Ð3»~ùs   ‚FT)rz   r{   Úallr|   ÚasyncioÚCancelledErrorr,   s   &r   rv   rv   –   sT   € ä�#Ô)×*Ò*ß‹sÑN¸s¿~º~ÓN�sŒsÐNŠsÐNˆsÑN¸s¿~º~ÓNÓNÐNÜ�cœ7×1Ñ1Ó2Ð2r   c                ó0   € V ^8„  d   QhR\         R\        /# r&   ©r   r   )r   s   "r   r   r   �   s   € ÷ 
7ñ 
7œMð 
7¬cñ 
7r   c                óÒ   €  ^ RI Hp \        T 4      p\	        Y!4      '       d   \        T4      P                  4       MRpT'       d   R\        T4       2# R#   \         d     R# i ; i)a  `` <guidance>`` when *exc* (or its group root) is the SDK's ``OAuthRegistrationError``, else ``""``. The DCR
guard in ``HermesMCPOAuthProvider`` raises one naming the next step (pre-register an OAuth client), and the
generic needs-reauth text alone would hide it from the model (#78190).)ÚOAuthRegistrationErrorrO   rS   )Úmcp.client.authr‹   ÚImportErrorr0   rz   r   r\   r   )r   r‹   rG   rn   s   &   r   Ú_auth_error_detailrŽ   �   s`   € ðÝ:ô # 3Ó'€DÜ *¨4× HÒ HŒ3ˆt‹9�?‰?ÔÈb€Dß*.ˆQŒ˜tÓ$Ð%Ð&Ð6°BÐ6øô	 ô Úðús   ‚A ÁA&Á%A&c                ó0   € V ^8„  d   QhR\         R\        /# r&   r‰   )r   s   "r   r   r   ª   s   € ÷ Xñ X¤-ð X´Cñ Xr   c                ór   € \        V 4      p\        R\        V4      P                   R\	        V4       24      # )z·Generic tool-error text naming the group root cause: the transport's TaskGroup wrapper ``str()`` is
"unhandled errors in a TaskGroup (1 sub-exception)", which tells the model nothing.zMCP call failed: rk   )r0   r   Útyper8   r   )r   rG   s   & r   Ú_mcp_call_failed_messager’   ª   s7   € ô # 3Ó'€DÜÐ.¬t°D«z×/BÑ/BÐ.CÀ2ÄhÈtÃnÐEUÐVÓWÐWr   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r‰   )r   s   "r   r   r   ±   s   € ÷ 
5ñ 
5œ}ð 
5´ñ 
5r   c                óX  € \        V 4      p\        V4      ;'       g‚    \        V\        \        \
        \        34      ;'       gZ    \        V\        4      ;'       d'    \        VRR4      \        P                  8H  ;'       g    \        \        VRR4      RR4      R9   pV'       d   R# R# )zÜ``'permanent'`` (``run()`` parks instead of burning the retry ladder: auth 401/403,
NonMcpEndpointError, InvalidMcpUrlError, missing stdio command, native addon built for another
Node) or ``'transient'`` (backoff retry).ÚerrnoNrB   rC   Ú	permanentÚ	transient)é‘  i“  )r0   Ú_is_auth_errorrz   r?   r5   ÚFileNotFoundErrorr	   ÚOSErrorr"   r•   ÚENOENT)r   rG   r–   s   &  r   Ú_classify_mcp_failurer�   ±   s©   € ô # 3Ó'€DÜ Ó%÷ `ð `Ü˜tÔ&9Ô;MÔO`ÔbvÐ%wÓx÷`ð `ä ¤gÓ.×_Ð_´7¸4ÀÈ$Ó3OÔSX×S_ÑS_Ñ3_÷`ð `ô œG D¨*°dÓ;¸]ÈDÓQÐU_Ñ_ð	 ÷
 $ˆ;Ð4¨Ð4r   c                ó<   € V ^8„  d   QhR\         R\        R\         /# )r   Úserver_namerW   r   )r   r   )r   s   "r   r   r   ¾   s!   € ÷ ñ ¬#ð ´Cð ¼Cñ r   c                ó  a € R V 3R llp\        V\        4      '       g   V! R\        V4      P                   24      hVP	                  4       pV'       g	   V! R4      h \        V4      pTP                  P                  4       R9  d   T! RTP                  : RT: R24      hTP                  '       g   T! R	T: R24      hTP                  '       g   T! R
T: R24      hT#   \         d   pT! T: RT R24      ThRp?ii ; i)uœ   The stripped URL if valid http(s); else InvalidMcpUrlError naming the server (non-string, other scheme â€”
stdio servers use ``command`` â€” or empty host).c                ó0   € V ^8„  d   QhR\         R\        /# )r   rp   r   )r   r5   )r   s   "r   r   Ú._validate_remote_mcp_url.<locals>.__annotate__Á   s   € ÷ Tñ T”Sð TÔ/ñ Tr   c                 ó&   <€ \        R S RV  24      # )zInvalid MCP URL for 'ú': )r5   )rp   rŸ   s   &€r   Ú_badÚ&_validate_remote_mcp_url.<locals>._badÁ   s   ø€ Ü!Ð$9¸+¸ÀcÈ&ÈÐ"RÓSÐSr   zexpected a string, got z	empty urlrl   rm   Nz"scheme must be http or https, got zmissing host (zmissing hostname (>   ÚhttpÚhttps)rz   r   r‘   r8   r\   r   ra   Úschemer   ÚnetlocÚhostname)rŸ   rW   r¥   ÚstrippedÚparsedr   s   f&    r   Ú_validate_remote_mcp_urlr®   ¾   s  ø€ ÷Tð Tä�cœ3×ÒÙÐ,¬T°#«Y×-?Ñ-?Ð,@ÐAÓBÐBØ�y‰y‹{€HßÙ�;ÓÐð5Ü˜(Ó#ˆð ‡}�}×ÑÓÐ$5Ô5ÙÐ7¸¿¹Ñ7HÈÈ8É,ÐVWÐXÓYÐYØ�=�=ˆ=Ù�^ H¡<¨qÐ1Ó2Ð2Ø�?�?ˆ?ÙÐ'¨¡|°1Ð5Ó6Ð6Ø€Oøô ô 5Ù�h‘\  C 5¨Ð*Ó+°Ð4ûð5ús   Á C% Ã%DÃ0D Ä Dc                ó0   € V ^8„  d   QhR\         R\        /# ©r   rŸ   Úconfig©r   rK   )r   s   "r   r   r   Õ   s   € ÷  ñ  ¤cð  ´4ñ  r   c                ó2  a€ VP                  R4      pVP                  R4      pVf   Vf   R# RV  R2oR V3R llp\        V\        \        34      '       g   V! VR4      pVe   WT! VR4      3# T# Ve   \	        S R24      h\        V4      R9  d   \	        S R	\        V4       R
24      hV! V^ ,          R4      V! V^,          R4      3p\        V4      ^8X  d   V# \        V^,          \        4      '       g   \	        S R24      h. VOV^,          N5# )zø``client_cert`` / ``client_key`` in httpx's ``cert=`` shape: None, a combined-PEM path,
``(cert, key)`` or ``(cert, key, password)``. ``~`` is expanded; missing files raise a
server-scoped FileNotFoundError instead of an opaque TLS handshake error.Úclient_certÚ
client_keyNzMCP server 'r¤   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   ÚpathÚlabelr   )r   r   )r   s   "r   r   Ú*_resolve_client_cert.<locals>.__annotate__ß   s!   € ÷ ñ ”cð ¤#ð ¬#ñ r   c                 óv  <€ \        V \        4      '       d   V P                  4       '       g'   \        S V R \	        V 4      P
                   R24      h\        P                  P                  V P                  4       4      p\        P                  P                  V4      '       g   \        S V RV: 24      hV# )z& must be a non-empty string path (got rm   z not found at )rz   r   r\   Ú
ValueErrorr‘   r8   Úosr·   Ú
expanduserÚisfilerš   )r·   r¸   ÚexpandedÚprefixs   && €r   Ú_expandÚ%_resolve_client_cert.<locals>._expandß   s’   ø€ Ü˜$¤×$Ò$¨D¯J©J¯LªLÜ ˜x¨ wÐ.TÔUYÐZ^ÓU_×UhÑUhÐTiÐijÐkÓlÐlÜ—7‘7×%Ñ% d§j¡j£lÓ3ˆÜ�w‰w�~‰~˜h×'Ò'Ü# v h¨u¨g°^ÀHÁ<Ð$PÓQÐQØˆr   zVspecify either client_cert as a list [cert, key] OR client_cert + client_key, not bothz5client_cert list form must have 2 or 3 elements (got rm   zclient_cert[0]zclient_cert[1]z0client_cert[2] (key passphrase) must be a string)r   é   )rZ   rz   Úlistr   r»   Úlenr   )rŸ   r±   Úraw_certÚraw_keyrÁ   Ú	cert_pathÚpairrÀ   s   &&     @r   Ú_resolve_client_certrÊ   Õ   s4  ø€ ð �z‰z˜-Ó(€HØ�j‰j˜Ó&€GØÒ˜GšOÙØ˜K˜=¨Ð,€F÷ð ô �h¤¤u ×.Ò.Ù˜H mÓ4ˆ	Ø>EÒ>Q�	˜7 7¨LÓ9Ð:Ð`ÐW`Ð`ØÒÜ˜F˜8Ð#yÐzÓ{Ð{Ü
ˆ8ƒ}˜FÔ"Ü˜F˜8Ð#XÔY\Ð]eÓYfÐXgÐghÐiÓjÐjÙ�H˜Q•KÐ!1Ó2±G¸HÀQ½KÐIYÓ4ZÐ[€DÜ
ˆ8ƒ}˜ÔØˆÜ�h˜q•k¤3×'Ò'Ü˜F˜8Ð#SÐTÓUÐUØˆTÐ�8˜A•;ÑÐr   c                ó0   € V ^8„  d   QhR\         R\        /# r°   r²   )r   s   "r   r   r   õ   s   € ÷ !ñ !¬#ð !´tñ !r   c                ó¶  a € VP                  R4      pVf   R# R V 3R llp\        V\        4      '       g   V! R\        V4      P                  4      # VP                  R4      p\        V\
        4      '       d   VP                  4       '       g	   V! R4      # VP                  R4      ;'       g    R	P                  4       P                  4       pVR
8X  d   ^ RIH	p VP                  4       V! 4       3# VR	8w  d
   V! RV4      # VP                  R4      p\        V\
        4      '       d   VP                  4       '       g	   V! R4      # VP                  4       V3# )uì   ``identity_header`` ``{name, value_from: "static"|"profile", value}`` â†’ ``(name, value)`` or
None. Invalid configs warn and are ignored â€” an identity header must never break the connection.
``profile`` resolves once at connect time.Úidentity_headerNc                ó$   € V ^8„  d   QhR\         /# )r   rp   ©r   )r   s   "r   r   Ú._resolve_identity_header.<locals>.__annotate__ý   s   € ÷ kñ kœñ kr   c                 óV   <€ \         P                  ! R V ,           R,           S.VO5!   R# )z!MCP server '%s': identity_header u    â€” ignoringN)ÚloggerÚwarning)rp   ÚargsrŸ   s   &*€r   Ú_ignoreÚ)_resolve_identity_header.<locals>._ignoreý   s#   ø€ Ü�ŠÐ:¸VÕCÀoÕUÐWbÐjÐeiÖjr   zDmust be a mapping with 'name' and 'value'/'value_from' keys (got %s)Únamezrequires a non-empty 'name'Ú
value_fromÚstaticÚprofile)Úget_active_profile_namez1value_from must be 'static' or 'profile' (got %r)Úvaluez;with value_from: static requires a non-empty string 'value')
rZ   rz   rK   r‘   r8   r   r\   r   Úhermes_cli.profilesrÛ   )rŸ   r±   rd   rÕ   r×   rØ   rÛ   rÜ   s   f&      r   Ú_resolve_identity_headerrÞ   õ   s   ø€ ð �*‰*Ð&Ó
'€CØ
‚{Ù÷kð kä�cœ4× Ò ÙÐ]Ô_cÐdgÓ_h×_qÑ_qÓrÐrØ�7‰7�6‹?€DÜ�dœC× Ò ¨¯
©
¯ªÙÐ4Ó5Ð5Ø—'‘'˜,Ó'×3Ð3¨8×:Ñ:Ó<×BÑBÓD€JØ�YÔÝ?Ø—
‘
“Ñ5Ó7Ð8Ð8Ø�XÔÙÐJÈJÓWÐWØ�G‰G�GÓ€EÜ�eœS×!Ò!¨¯©¯ªÙÐTÓUÐUØ�J‰J‹L˜%Ð Ð r   c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   rŸ   r±   rY   r   r²   )r   s   "r   r   r     s(   € ÷ ñ ¬ð ´Tð ÄDð ÌTñ r   c                óþ   a€ \        W4      ;'       g    Rw  opSf   V# \        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       d   \        P                  RV S4       V# W2S&   V# )u’   Merge the identity header into ``headers`` in place; an explicit entry of the same name (any
casing) wins â€” never silently override user config.c              3   ód   <"  € T F%  qP                  4       SP                  4       8H  x € K'  	  R # 5ir   )r   )r   Úkeyr×   s   & €r   r    Ú)_apply_identity_header.<locals>.<genexpr>  s    øé € Ð
:±'¨3�9‰9‹;˜$Ÿ*™*›,Ö&³'ùs   ƒ-0TFul   MCP server '%s': identity_header '%s' already set via explicit headers config â€” keeping the explicit value)NN)rÞ   r#   rÒ   Údebug)rŸ   r±   rY   rÜ   r×   s   &&& @r   Ú_apply_identity_headerrå     st   ø€ ô +¨;Ó?×OÐOÀ<�K€Dˆ%Ø‚|Øˆß
ƒsÔ
:±'Ó
:‡s‡s‚sÔ
:±'Ó
:×:Ò:Ü�‰ð EØFQÐSWô	Yð €Nð �‰Ø€Nr   ÚstrictFÚconfigured_header_namesc                ór   € V ^8„  d   QhR\         R\        \        ,          \        \        ,          ,          /# )r   ræ   rç   )r   Úsetr   Ú	frozenset)r   s   "r   r   r     s)   € ÷ $ñ $Ätð $Ü<?Ä½HÄyÔQTÅ~Õ<Uñ$r   c               óf   a aaa€ VP                   VP                  VP                  3oVV VV3R lpV# )u;  Client factory enforcing the redirect credential boundary: on a cross-origin redirect
follow-up it strips ``Authorization``; with *strict* (Agent Plugins v1 ``strict_redirect_headers``)
every configured header (lowercase names in *configured_header_names*) is stripped too â€” v1 forbids
forwarding them cross-origin.

The factory builds ``httpx_mod.AsyncClient(**kwargs)`` â€” resolved at call time, so the proxy
``mounts=`` / ``transport=`` the caller passes reach the SDK's real client class (and anything a
caller swapped in for it) unchanged â€” and installs the boundary on that instance's
``_build_redirect_request``. This MUST live on ``_build_redirect_request``: ``response.next_request``
is unset when response event hooks fire (httpx populates it later in the redirect loop), so a
response hook can never mutate the follow-up; and a *request* hook would fire on non-redirect traffic
too â€” the OAuth auth flow yields token/metadata/registration requests through the same client, often
to a different-origin authorization server whose own credentials must NOT be stripped.c                  ó~   <aa€ SP                   ! R/ V B o\        \        S4      R R4      oVVVVV3R lpVSn        S# )Ú_build_redirect_requestNc                 ó  <€ S! SW4      pVP                   pVP                  VP                  VP                  3S	8w  dN   VP                  pVP                  R R4       VP                  RR4       S
'       d   SMR F  pWT9   g   K  WE K  	  V# )ÚauthorizationNÚAuthorizationr6   )rW   r©   ÚhostÚportrY   Úpop)rc   rB   Únext_requestÚtargetrY   Ú_nameÚ
base_buildÚclientrç   Úoriginræ   s   &&    €€€€€r   rí   ÚV_make_redirect_header_stripper.<locals>._build_client.<locals>._build_redirect_request3  s‚   ø€ Ù% f¨gÓ@ˆLØ!×%Ñ%ˆFØ—‘˜vŸ{™{¨F¯K©KÐ8¸FÔBØ&×.Ñ.�Ø—‘˜O¨TÔ2Ø—‘˜O¨TÔ2ß8>Ñ4ÀBÒF�EØÖ*Ø#šNñ Gð  Ðr   r6   )ÚAsyncClientr"   r‘   rí   )Úkwargsrí   r÷   rø   rç   Ú	httpx_modrù   ræ   s   , @@€€€€r   Ú_build_clientÚ5_make_redirect_header_stripper.<locals>._build_client/  sC   ú€ Ø×&Ò&Ñ0¨Ñ0ˆÜœT &›\Ð+DÀdÓKˆ
÷
	 ñ 
	 ð *AˆÔ&Øˆr   )r©   rñ   rò   )rý   Úoriginal_urlræ   rç   rþ   rù   s   f&dd @r   Ú_make_redirect_header_stripperr    s5   û€ ð ×!Ñ! <×#4Ñ#4°l×6GÑ6GÐH€F÷ð ð& Ðr   s   (?:\r\n|\r(?!\n)|\n){2}c                ó$   € V ^8„  d   QhR\         /# )r   Úlimit)Úint)r   s   "r   r   r   U  s   € ÷ ;.ñ ;.ÄCñ ;.r   c                ó~   a aa€  ! V V3R lRS P                   4      o ! VV V3R lRS P                  4      pV! V4      # )zºWrap ``inner_transport`` so every response body is size-capped. ``httpx_mod`` must be the SDK's
own httpx module (``sdk_httpx()``): the transport is handed to that SDK's ``AsyncClient``.c                   ó`   <a € ] tR tRt o V 3R lR ltV 3R lVV3R lltV3R ltR tRtV t	R	# )
Ú3_make_mcp_body_cap_transport.<locals>._CappedStreamiY  c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úis_sserW   )r   r   )r   Ú__classdict__s   "€r   r   Ú@_make_mcp_body_cap_transport.<locals>._CappedStream.__annotate__Z  s   ø€ ÷ 	Fñ 	F©$ð 	F±Sñ 	Fr   c                ó0   € WVuV n         V n        V n        R # r   ©Ú_innerÚ_is_sseÚ_url)ÚselfÚinnerr	  rW   s   &&&&r   Ú__init__Ú<_make_mcp_body_cap_transport.<locals>._CappedStream.__init__Z  s   € Ø38À#Ð0ˆDŒK˜œ t¦yr   c                ó    <€ V ^8„  d   QhRS[ /# )r   ÚkindrÏ   )r   r
  s   "€r   r   r  ]  s   ø€ ÷ 	_ñ 	_¡ñ 	_r   c           	     óN   <€ SP                  R V RS RV P                   R24      # )zMCP z	 exceeds z bytes (from rm   )Ú	ReadErrorr  )r  r  rý   r  s   &&€€r   Ú_rejectÚ;_make_mcp_body_cap_transport.<locals>._CappedStream._reject]  s2   ø€ Ø×&Ñ&¨¨d¨V°9¸U¸GÀ=ÐQU×QZÑQZÐP[Ð[\Ð']Ó^Ð^r   c           	    óz  <"  € ^ pRpV P                     Rj  x€L
  pV P                  '       d»   W#,           p^ p\        P                  V4       F`  pVP	                  4       pV\        V4      8:  d   K%  W,           \        V\        V4      4      ,
          S8”  d   V P                  R4      h^ TrQKb  	  V\        V4      \        V\        V4      4      ,
          ,          pV\        ) R pMV\        V4      ,          pVS8”  d*   T P                  V P                  '       d   R4      hR4      hV5x € EK    ELEDR# 5i)é    r   Nz	SSE eventzHTTP response)	r  r  Ú_SSE_BOUNDARY_REÚfinditerÚendrÅ   Úmaxr  Ú_SSE_BOUNDARY_CARRY)	r  ÚcountedÚtailÚchunkÚwindowÚposÚmatchr  r  s	   &       €r   Ú	__aiter__Ú=_make_mcp_body_cap_transport.<locals>._CappedStream.__aiter__`  s  øé € ØˆGØˆDØ#Ÿ{š{÷ ð �eØ—<—<�<ð
 "�\�FØ�CÜ!1×!:Ñ!:¸6Ö!B˜Ø#Ÿi™i›k˜Ø¤# d£)Ô+Ù$Ø"�=¬3¨s´C¸³IÓ+>Õ>ÀÔFØ"&§,¡,¨{Ó";Ð;Ø'(¨#¢ñ "Cð œs 6›{¬S°´c¸$³iÓ-@Õ@Õ@�GØ!Ô#6Ð"6Ð"7Ð8‘Dàœs 5›zÕ)�GØ˜U”?ØŸ,™,°d·l·l°l {ÓXÐXÈÓXÐXØ–ò+›{ùs,   ƒD;”D7˜D4™D7œDD;Ä D;Ä4D7Ä7D;c              “  óV   "  € V P                   P                  4       G R j  x€L
  R #  L5ir   ©r  Úaclose©r  s   &r   r,  Ú:_make_mcp_body_cap_transport.<locals>._CappedStream.aclosez  ó   é € Ø—+‘+×$Ñ$Ó&×&Ô&ùó   ‚) '¡)r  N)
r8   r9   r:   r;   r  r  r(  r,  r=   Ú__classdictcell__)r
  rý   r  s   @€€r   Ú_CappedStreamr  Y  s,   ù‡ € ÷	Fð 	F÷	_ô 	_õ	÷4	'ð 	'r   r2  c                   ó>   <a € ] tR tRt o R tVVV3R ltR tRtV tR# )Ú7_make_mcp_body_cap_transport.<locals>._BodyCapTransporti}  c                ó   € Wn         R # r   ©r  )r  r  s   &&r   r  Ú@_make_mcp_body_cap_transport.<locals>._BodyCapTransport.__init__~  s   € ØŽKr   c              “  ód  <"  € V P                   P                  V4      G R j  x€L
 pVP                  P                  R4      p\        P
                  ! \        4      ;_uu_ 4        VeN   \        V4      S8”  d>   VP                  4       G R j  x€L
  SP                  RV RS RVP                   R24      hR R R 4       RVP                  P                  RR4      P                  4       9   pS! VP                  V\        VP                  4      4      Vn        V#  Lö LŽ  + '       g   i     Lo; i5i)	Nzcontent-lengthz*MCP HTTP response declares Content-Length z > z bytes cap (from rm   rR   rP   rO   )r  Úhandle_async_requestrY   rZ   Ú
contextlibÚsuppressr»   r  r,  r  rW   r   Ústreamr   )r  rc   rB   Údeclaredr	  r2  rý   r  s   &&   €€€r   r9  ÚL_make_mcp_body_cap_transport.<locals>._BodyCapTransport.handle_async_request�  s  øé € Ø!Ÿ[™[×=Ñ=¸gÓF×FˆHØ×'Ñ'×+Ñ+Ð,<Ó=ˆHÜ×$Ò$¤Z×0Õ0ØÒ'¬C°«M¸EÔ,AØ"Ÿ/™/Ó+×+Ð+Ø#×-Ñ-Ð0ZÐ[cÐZdÐdgÐhmÐgnð oAØAHÇÁÀÈQð/Pó Qð Q÷ 1ð
 )¨H×,<Ñ,<×,@Ñ,@ÀÐQSÓ,T×,ZÑ,ZÓ,\Ñ\ˆFÙ+¨H¯O©O¸VÄSÈÏÉÓEUÓVˆHŒOØˆOñ Gñ ,÷ 1×0üs;   ƒD0¢D£AD0Á$(DÂDÂ)DÂ6A$D0ÄDÄD-	Ä(D0c              “  óV   "  € V P                   P                  4       G R j  x€L
  R #  L5ir   r+  r-  s   &r   r,  Ú>_make_mcp_body_cap_transport.<locals>._BodyCapTransport.aclose�  r/  r0  r6  N)	r8   r9   r:   r;   r  r9  r,  r=   r1  )r
  r2  rý   r  s   @€€€r   Ú_BodyCapTransportr4  }  s   ù‡ € ò	 ÷
	÷	'ð 	'r   rA  )ÚAsyncByteStreamÚAsyncBaseTransport)rý   Úinner_transportr  rA  r2  s   f&f @r   Ú_make_mcp_body_cap_transportrE  U  s?   ú€ ÷"'ð "'˜	×1Ñ1ô "'÷H'ñ '˜I×8Ñ8ô 'ñ& ˜_Ó-Ð-r   i'  c                óF   € V ^8„  d   QhR\         R\        \         ,          /# r&   ©r   rÄ   )r   s   "r   r   r   ˜  s#   € ÷ eñ e”}ð e¬¬mÕ)<ñ er   c                óv   € \        V RR4      ;'       g    Rp. VOR V P                  V P                  3 4       O# )uÞ   A group's sub-exceptions (if any) followed by ``__cause__``/``__context__`` when they are exceptions â€” a
group raised inside an ``except`` block carries the caught error as ``__context__``, so the chain is never
skipped.r|   Nc              3   óV   "  € T F  p\        V\        4      '       g   K  Vx € K!  	  R # 5ir   )rz   r   )r   Úcs   & r   r    Ú _exc_children.<locals>.<genexpr>�  s   é € ÐcÑ"B˜QÄjÐQRÔTa×Fb—q’qÓ"Bùó   ‚)Ÿ
)r6   )r"   Ú	__cause__Ú__context__)r   Únesteds   & r   Ú_exc_childrenrP  ˜  s=   € ô �S˜,¨Ó-×3Ð3°€FØdˆVÐdÑc 3§=¡=°#·/±/Ñ"BÓcÐdÐdr   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# r&   rG  )r   s   "r   r   r      s   € ÷ ñ œ}ð ´´mÕ1Dñ r   c                ó@  € V .p\        4       p. pV'       d‡   \        V4      \        8  ds   VP                  4       p\	        V4      V9   d   K>  VP                  \	        V4      4       VP                  V4       VP                  \        \        V4      4      4       KŽ  V# )a¬  Pre-order, left-to-right walk of an exception tree/chain, each node once. ``__cause__``/``__context__``
can point back at an ancestor (a raised-and-caught pair does this routinely, e.g. the same OAuth error
raised on the Streamable-HTTP attempt and again on the SSE fallback), so a naive recursive walk dies with
RecursionError and hides the real connect error; the visited set breaks cycles, the budget bounds acyclic
blow-ups.)
ré   rÅ   Ú_EXC_TRAVERSAL_MAX_NODESró   ÚidÚaddÚappendÚextendÚreversedrP  )r   ÚstackÚseenÚorderedÚcurrents   &    r   Ú_iter_exception_nodesr]     sw   € ð ˆE€EÜ“U€DØ#%€Gß
”C˜“LÔ#;Ô;Ø—)‘)“+ˆÜˆg‹;˜$ÔÙØ�‰”�G“ÔØ�‰�wÔØ�‰”Xœm¨GÓ4Ó5Ö6Ø€Nr   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r‰   )r   s   "r   r   r   ³  s   € ÷ $$ñ $$œ}ð $$´ñ $$r   c           
     ó¶  a a€ \        S 4      oR V3R llpR V V3R llp\        R S 4       R4      pVe   \        \        V4      4      # V! 4       pV'       gC   \        RP	                  \        \        P                  V! 4       4      4      R,          4      4      # R	V R
2p\        P                  P                  V4      R9   d
   VR,          p\        V4      # )zERender nested MCP connection errors into an actionable short message.c                ó:   € V ^8„  d   QhR\         \        ,          /# ©r   r   )r   r   )r   s   "r   r   Ú+_format_connect_error.<locals>.__annotate__·  s   € ÷ ñ œ8¤C�=ñ r   c                  ó  <€ S F€  p \        V \        4      '       g   K  \        V R R4      '       d   \        V P                  4      u # \
        P                  ! R\        V 4      4      pV'       g   Ko  VP                  ^4      u # 	  R# )ÚfilenameNz$No such file or directory: '([^']+)')rz   rš   r"   r   rd  ÚreÚsearchÚgroup)r\  r'  Únodess     €r   Ú_find_missingÚ,_format_connect_error.<locals>._find_missing·  sh   ø€ ÛˆGÜ˜'Ô#4×5Ô5Ü˜7 J°×5Ò5Ü˜w×/Ñ/Ó0Ò0ÜŸ	š	Ð"IÌ3ÈwË<ÓX�ß‘5Ø Ÿ;™; q›>Ò)ñ ñ r   c                ó:   € V ^8„  d   QhR\         \        ,          /# ra  )rÄ   r   )r   s   "r   r   rb  Á  s   € ÷ 	4ñ 	4œt¤C�yñ 	4r   c                  ó^  <€ . p S F„  p\        VR R4      '       d   RM\        V4      P                  4       pV'       d   V P                  V4       KL  \	        V4      '       d   K_  V P                  VP
                  P                  4       K†  	  T ;'       g    SP
                  P                  .# )r|   NrO   )r"   r   r\   rV  rP  Ú	__class__r8   )Úmessagesr\  rn   r   rh  s      €€r   Ú_flatten_messagesÚ0_format_connect_error.<locals>._flatten_messagesÁ  sƒ   ø€ Ø ˆÛˆGä  ¨,¸×=Ò=‘2Ä3ÀwÃ<×CUÑCUÓCWˆDßØ—‘ Ö%Ü" 7×+Ô+Ø—‘ × 1Ñ 1× :Ñ :Ö;ñ ð ×3Ð3˜CŸM™M×2Ñ2Ð3Ð3r   c              3   óV   "  € T F  p\        V\        4      '       g   K  Vx € K!  	  R # 5ir   )rz   r	   )r   Únodes   & r   r    Ú(_format_connect_error.<locals>.<genexpr>Ì  s   é € ÐQ¡˜¬*°TÔ;O×*P—’£ùrL  Nz; :NrÃ   Nzmissing executable 'Ú'z³ (ensure Node.js is installed and PATH includes its bin directory, or set mcp_servers.<name>.command to an absolute path and include that directory in mcp_servers.<name>.env.PATH)>   ÚnpmÚnpxrr  )r]  r   r   r   r^   rÄ   rK   Úfromkeysr¼   r·   Úbasename)r   ri  ro  ÚabiÚmissingÚmessagerh  s   f     @r   Ú_format_connect_errorr|  ³  sÄ   ù€ ä! #Ó&€E÷ð ÷	4ñ 	4ô ÑQ¡ÓQÐSWÓ
X€CØ
‚Üœs 3›xÓ(Ð(Ù‹o€GßÜ˜tŸy™y¬¬d¯m©mÑ<MÓ<OÓ.PÓ)QÐRTÕ)UÓVÓWÐWØ$ W I¨QÐ/€GÜ	‡w�w×Ñ˜Ó Ð$:Ô:Øð Eõ 	Fˆô ˜7Ó#Ð#r   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   ÚmoduleÚnamesr   )r   rÄ   )r   s   "r   r   r   Ú  s!   € ÷ ñ œCð ¬ð ´ñ r   c                ó¢   €  \         P                  ! V 4      pV Uu. uF  p\        W#4      NK  	  up# u upi   \        \        3 d    . u # i ; i)zJ``[module.name, ...]`` or ``[]`` when the module/attribute is unavailable.)Ú	importlibÚimport_moduler"   r�   ÚAttributeError)r~  r  Úmodr×   s   &*  r   Ú_optional_typesr…  Ú  sM   € ðÜ×%Ò% fÓ-ˆÙ/4Ó5©u t”˜Ö"©uÑ5Ð5ùÒ5øÜœÐ(ô ØŠ	ðús   ‚8 œ3°8 ³8 ¸AÁAc                ó$   € V ^8„  d   QhR\         /# ra  )r   )r   s   "r   r   r   ç  s   € ÷ ñ œuñ r   c            	     óP  € \         '       d   \         ^ ,          '       gƒ   \        P                  ! 4       p \        \        P                  V e   V P                  .M. \        RR4      ,           4      4      p. \        RRR4      O\        RR4      O\        RR4      OVO5pW!3s \         # )	u�  Cached ``(auth_types, http_status_types)``: SDK ``OAuthFlowError``/``OAuthTokenError`` (+ legacy
``UnauthorizedError``), our ``OAuthNonInteractiveError``, and ``HTTPStatusError`` from both httpx
flavours â€” a 401 may come from the SDK's own stack (``httpx2`` on mcp >= 2.0) or Hermes' pinned
``httpx``; the classes are unrelated and still need the 401 check in :func:`_is_auth_error`.ÚhttpxÚHTTPStatusErrorzmcp.client.authÚOAuthFlowErrorÚOAuthTokenErrorÚUnauthorizedErrorztools.mcp_oauthÚOAuthNonInteractiveError)Ú_AUTH_ERROR_TYPESr   Ú	sdk_httpxr   rK   rw  r‰  r…  )Úsdk_modÚ
http_typesÚ
auth_typess      r   Ú_get_auth_error_typesr“  ç  s³   € ÷ ÓÔ"3°A×"6Ô"6Ü—/’/Ó#ˆÜœ4Ÿ=™=Ø*1Ò*=ˆg×%Ñ%Ñ&À2ÌÐY`ÐbsÓItÕtóvó wˆ
ðd”Ð'8Ð:JÐL]Ó^ð dÜ&Ð'8Ð:MÓNðdä&Ð'8Ð:TÓUðdàXbñdˆ
ð (Ð4ÐÜÐr   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r'   )r   s   "r   r   r   ø  s   € ÷ fñ fœð f¬$ñ fr   c                óš   € \        4       w  r\        W4      '       g   R# \        W4      '       d   \        V P                  RR4      R8H  # R# )z`True if ``exc`` indicates an MCP OAuth failure; ``HTTPStatusError`` counts only with status 401.FrC   Nr˜   T)r“  rz   r"   rB   )r   r’  r‘  s   &  r   r™   r™   ø  sC   € ä2Ó4Ñ€JÜ�c×&Ò&ÙÜ@JÈ3×@[Ò@[Œ7�3—<‘< °Ó5¸Ñ<ÐeÐaeÐer   c                ó0   € V ^8„  d   QhR\         R\        /# r&   r'   )r   s   "r   r   r   	  s   € ÷ ñ ¤=ð ´Tñ r   c                ó€  a€ \        \        RRRR4      4      pRp\        V 4       F”  p\        V\        4      '       d    R# \        V4      P                  4       oT;'       gV    \        W14      ;'       gC    \        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      pK–  	  V# )uÎ  True if ``exc`` looks like a transport session expiry (Streamable-HTTP servers GC session state on idle TTL /
restart / pod rotation while the OAuth token stays valid) â€” the fix is a transport reconnect, not an OAuth
refresh. Every node ``_iter_exception_nodes`` reaches is inspected so an InterruptedError anywhere overrides
transport markers; the chain walk matters because SDK wrappers raise a generic RuntimeError *from* a
message-less ClosedResourceError.ÚanyioÚBrokenResourceErrorÚClosedResourceErrorÚEndOfStreamFc              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir   r6   )r   ÚmÚmsgs   & €r   r    Ú,_is_session_expired_error.<locals>.<genexpr>  s   øé € ÐJvÑ]uÐXYÐPSÎ8Ó]uùs   ƒT)	r   r…  r]  rz   ÚInterruptedErrorr   r   r#   Ú_SESSION_EXPIRED_MARKERS)r   Útransport_error_typesÚfoundr\  rž  s   &   @r   Ú_is_session_expired_errorr¤  	  s“   ø€ ô "¤/°'Ð;PÐRgÐivÓ"wÓxÐØ€EÜ(¨Ö-ˆÜ�gÔ/×0Ò0Úä�'‹l× Ñ Ó"ˆØ×vÐvœ GÓC×vÐvÇsÃsÔJvÕ]uÓJvÇsÇsÂsÔJvÕ]uÓJvÓGvŠñ .ð €Lr   c                ó~   € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   ^\         9   d
   \        ;R&   # )r   rŽ  r¡  )Ú__conditional_annotations__r   r   )r   s   "r   r   r      sC   € ÷ Zñ Z÷F *Ò )”8œE•?Ñ )ñGZ÷DNò Nœ%ñ NòEZr   iê‚ÿÿr   )rN   i•  i–  i›  i    )zinvalid or expired sessionzexpired sessionzsession expiredzsession not foundzunknown sessionzsession terminatedÚclosedresourceerrorzclosed resourceztransport is closedzconnection closedzbroken pipezend of file)@r¦  r<   r†   r:  r•   r�  Úloggingr¼   re  Útypingr   r   r   Úurllib.parser   Útools.mcp_tool_commonr   r   r   Útools.mcp_tool_node_abir	   Ú	getLoggerrÒ   r)   r$   r-   r1   r+   r»   r5   ÚConnectionErrorr?   rF   rH   r_   rg   rq   r0   rv   rŽ   r’   r�   r®   rÊ   rÞ   rå   rê   r  Ú_MCP_HTTP_MAX_BODY_BYTESÚcompiler  r!  rE  rS  rP  r]  r|  r…  rŽ  r“  r™   r¡  r¤  r   )r¦  s   @r   Ú<module>r±     sZ  øðöZó Û Û Û Û Û 	Û 	ß &Ñ &Ý !ß BÑ BÝ 8à	×	Ò	Ð+Ó	,€ð )/Ð %÷RõLõgõiô˜ô ô8˜/ô 8ð 3Ð õWð !Ð õõ0 õ õ3õ
7õXõ
5õõ. õ@!õ6ð$Èeð $ÙXaÓXc÷$ð\ ,Ð ð
 —:’:Ð9Ó:Ð ØÐ ð Kc÷ ;.ð@ "Ð õeõõ&$$õNð &*Ð Ó )õõ"fð#NÐ ó N÷r   