Ë
    tPêj†q ã                   ób  — U d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZmZmZmZ ddlmZ ddlmZmZmZmZ ddlZddlmZmZ ddlmZmZ ddlmZ dd	lm Z  dd
l!m"Z"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l0m1Z1m2Z2 ddl3m4Z4 ddl5m6Z6m7Z7 ddl8m9Z9m:Z:m;Z; ddl<m=Z= ddl>m?Z?m@Z@mAZAmBZB ddlCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZN ddlOmPZPmQZQmRZR ddlSmTZT ddlUmVZVmWZW ddlXmYZYmZZZ ddl[m\Z\m]Z] ddl^m_Z_m`Z` ddlambZbmcZcmdZd erddlemfZg ddlhmiZi i Zjeekelememf   elemdz  enf   f      eod<   d Zpeeod!<   d"Zqeeod#<   d$Zreeod%<   d&Zseeod'<   d"Zteeod(<   d)Zueeod*<   d+emd,emd-dfd.„Zvd+emd,emd/emdz  d-dfd0„Zwd1Zxeyeod2<   	 ddlzZzdd3l{m|Z|m}Z} dd4l~mZ dd5l€m�Z� ddlemfZg dd6l‚mƒZƒm„Z„m…Z…m†Z†m‡Z‡  ez�j                  «       Z‰d7eod8<    e�j                  d;d¬<«      ZŽee�j                  d=      eod><   d:a� e�j                   «       Z‘eeod?<   d@ekememf   dz  d-emdz  fdA„Z’dBemd-eyfdC„Z“dDe”d-ekememf   dz  fdE„Z•dFekememf   dz  d-e”fdG„Z–dHe”d-dfdI„Z—dJe$d-dfdK„Z˜dDe”d-e”fdL„Z™dMe”d-e”fdN„ZšdHe”d-dfdO„Z›dPePd-efdQ„Zœex�rådd4l~mZ ddRl�mžZžmŸZŸ ddSl m¡Z¡ ddTl¢m£Z£ 	 ddUl¤m¥Z¥ ddVl‚m¦Z¦m§Z§m¨Z¨m©Z© ddWl‚m‡Zª ddXl«m¬Z¬ ddYl­m®Z®m¯Z¯m°Z°m±Z±m²Z²m³Z³ ddZl´mµZµm¶Z¶m·Z·m¸Z¸m¹Z¹mºZº dd[l»m¼Z¼m½Z½m¾Z¾ dd\l¿mÀZÀ dd]lÁmÂZÂ dd^lCmÃZÃmÄZÄmÅZÅmÆZÆmÇZÇ dd_lXmÈZÈmÉZÉ  G d`„ daeª«      ZÊdbeËd-eËe�   fdc„ZÌ	 	 �ddde¡dz  deekemekeme”f   f   dz  d-e£fdf„ZÍ eeEeF¬g«      ZÎee   eodh<    e�jž                  eÍeÎ«      eÎ_Ð         eÀdi«      ZÑeeÀ   eodj<    e¥eÎdd:d1¬k«      ZÒeeodl<    e¥eÎdd:d:¬k«      ZÓeeodm<   i ZÔeekeme¬f      eodn<   i ZÕeekemenf      eodo<   i ZÖeekememf      eodp<   i Z×eekeme�j                   f      eodq<   i ZØeekemeÙf      eodr<    G ds„ dte«      ZÚ G du„ dve«      ZÛd-eÛfdw„ZÜdxemd-dfdy„ZÝeÒZÞeeodz<    e¥eÎdd:d1¬k«      Zßeeod{<   daàdaádaâdaãe�jÈ                  dz  eod|<   	 �d	d}endz  d-dfd~„Zådemd-eyfd€„Zæ�d
d�„Zçd‚„ Zèdƒ„ Zée�jÔ                  d-ed   fd„„«       ZëeÎ�jÙ                  «       �dd…„«       Zíd-edz  fd†„Zî	 	 �dd‡emdˆekeme”f   d‰eRd@eememf   dz  dŠemdz  d-e,dz  fd‹„Zï	 	 	 	 	 �dd‡emdˆekeme”f   dz  d‰eRdz  dŠemdz  dŒeËem   dz  d�emdz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-e¦dz  fd�„ZðeÎ�jã                  «       d‡emdˆekeme”f   dz  d-e¦fd‘„«       ZòeÎ�jç                  «       d-eËe¨   fd’„«       ZóeÎ�jé                  «       d‡emdˆekememf   dz  d-e„fd“„«       ZôeÎ�jë                  «       d-eËe}   fd”„«       ZõeÎ�jí                  «       d-eËe…   fd•„«       ZöeÎ�jï                  «       d–ed-eËe�   fd—„«       Z÷dŒeËem   dz  d˜eËe]   d-eËe]   fd™„Zødšemd›eËem   dœe]d-eyfd�„ZùdžeËeª   dœe]d-eËeª   fdŸ„ZúdžeËeª   dœe]d-eËeª   fd „Zûd-emdz  fd¡„Zü	 �d	d‰eRdz  dŒeËem   dz  dŠemdz  d-eËe]   fd¢„Zýdhe]dŽekemekememf   f   dz  d-eyfd£„Zþdhe]d�ekememf   dz  dŽekemekememf   f   dz  d-eyfd¤„Zÿ	 �d	dhe]d‰eRdz  d¥d¦d-ekememf   dz  fd§„�Z d‰eRdz  d-ekemd¨f   fd©„�Z	 	 �ddhe]dŽekemekememf   f   dz  d�emdz  d�ekememf   dz  d@ekememf   dz  d‰eRdz  dªeËe]   dz  d-elekememf   emz  dz  ekememf   dz  f   fd«„�Zd˜eËe]   d-emdz  fd¬„�Ze�jÔ                  	 �dd‰eRdz  dŒeËem   dz  dŠemdz  d­eyd-ed   f
d®„«       �Zdhe]d-emfd¯„�Z	 	 	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d°eyd±emdz  d²emdz  d³eËem   dz  dŠemdz  d-e¯fd´„�Z	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-eËe¨   fdµ„�Z	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-eËe}   fd¶„�Z	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-eËe…   fd·„�Z	džeËeª   d,emd‰eRdz  d-eËeª   fd¸„�Z
	 	 	 	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d°eyd±emdz  dŠemdz  d-e¯fd¹„�Z	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-eËe¨   fdº„�Z	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-eËe}   fd»„�Z	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-eËe…   fd¼„�Zd‡emd˜eËe]   d-emfd½„�Zdœe]d‰eRdz  d-emdz  fd¾„�Zdœe]d‰eRdz  d-dfd¿„�Z	 	 	 	 	 	 �dd‡emdˆekeme”f   d˜eËe]   dÀed‰eRdz  d�emdz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  dÁedz  dÂed-e¦fdÃ„�ZdÄe¦dÅe,dz  d‰eRdz  dÆeeme”f   d-e¦f
dÇ„�Z �eh dÈ£«      �ZeeodÉ<   	 	 �ddÊe,dÄe¦dÀedËed‰eRdz  dÆeeme”f   dz  d-e¦fdÌ„�Zec	 	 	 	 	 	 	 �dd‡emdˆekeme”f   dz  d‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  dÂed-e¦fdÍ„«       �Z	 	 	 	 	 	 	 �dd‡emdˆekeme”f   dz  d‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-e„fdÎ„�Z	 	 	 	 	 	 �dd–ed‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  d-e|fdÏ„�Z	 �d	d‡emdˆekeme”f   dÐemdz  dxemdz  d-e`f
dÑ„�Z	 	 	 	 	 	 	 �ddÐemd‡emdˆekeme”f   d‰eRdz  d�emdz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  dÅe,dz  dÁedz  d-e¦fdÒ„�Zd‡emdˆekeme”f   d-e¦fdÓ„�ZdÔemd-eËem   dz  fdÕ„�ZdÖ„ �ZdJe$d-emdz  fd×„�Z	 	 �dd‰eRdz  d�ekememf   dz  dŠemdz  d-emfdØ„�Z dÙ�e!d-eyfdÚ„�Z"dÛe#d-eleËe"   �e!f   fdÜ„�Z#dJe$dÛe#dÝe%dÞdßd-eyf
dà„�Z$d‰eRdáemd-eRfdâ„�Z%	 �d	dJe$dŒeËem   dz  d�ekememf   dz  dŽekemekememf   f   dz  d‰eRdz  dŠemdz  dã�e&em   dz  d-dfdä„�Z'dJe$d-emdz  fdå„�Z(dJe$d-eyfdæ„�Z)dJe$d-emdz  fdç„�Z*dhe]d-eyfdè„�Z+	 �dd–emdéemdêend-eleÙemdz  f   fdë„�Z,dJe$d‰eRdz  dŒeËem   dz  dŠemdz  d-df
dì„�Z-dJe$dÛe#dÝe%d-dfdí„�Z.dJe$dÛe#dÝe%d-dfdî„�Z/ eeEeDeFeë¬ï«      �Z0�e0�jc                  dðdñ¬ò«      d-ekemeyf   fdó„«       �Z2�e0�jg                  dô�e.«       �e0�jg                  dõ�e.«       �e0�jg                  dö�e.«       �e0�jg                  d÷�e/«       �e0�ji                  ež«       	 	 	 	 	 	 �ddøe¬d‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  dŠemdz  d-dfdù„�Z5	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  dŠemdz  d-e¬fdú„�Z6	 	 	 	 	 	 	 	 	 �dd‰eRdz  d�emdz  dŒeËem   dz  dŽekemekememf   f   dz  d�ekememf   dz  d@ekememf   dz  dŠemdz  dxemdz  dûeydüeyd-e¬fdý„�Z7	 �d	dÝe%døe¬dþemdÿeemgdf   dz  d-e%f
�d „�Z8d-eleRdz  emdz  eËem   dz  ekemekememf   f   dz  ekememf   dz  ekememf   dz  emdz  f   f�d„�Z9�d„ �Z:�d„ �Z;d-e¬dz  f�d„�Z<d-eleRdz  emdz  eËem   dz  ekemekememf   f   dz  ekememf   dz  ekememf   dz  emdz  f   f�d„�Z=d-egdz  f�d„�Z>d-e¬dz  f�d„�Z?y e«       �Z0y# eŠ$ r1Z‹ e'�j                  d9e‹«       d:ZxdZƒdZ„dZ�dZ|dZ}dZ…dZdZ†Y dZ‹[‹�ŒÑdZ‹[‹ww xY w# eŠ$ r dZ¥Y �Œw xY w(  z
LiteLLM MCP Server Routes
é    N)ÚAsyncIteratorÚCallableÚMappingÚSequence)Údatetime)ÚTYPE_CHECKINGÚAnyÚFinalÚProtocol)ÚFastAPIÚHTTPException)ÚAnyUrlÚ
ConfigDict)ÚRequest©ÚJSONResponse)ÚMessageÚReceiveÚScopeÚSend)Úverbose_logger)ÚMAXIMUM_TRACEBACK_LINES_TO_LOG)ÚLogging)Úget_async_httpx_clientÚhttpxSpecialProvider)ÚMCPRequestHandlerÚ_is_mcp_admitted_user_subject)Úget_request_base_url)ÚMCPToolResultErrorÚMCPUpstreamAuthError)Ú_mcp_active_toolset_idÚ$_mcp_gateway_initialize_instructionsÚ_mcp_gateway_server_name)ÚMCPDebug)Ú_redact_mcp_resource_urlÚ get_passthrough_www_authenticateÚget_route_relative_request_pathÚwell_known_root_suffix)ÚLITELLM_MCP_SERVER_DESCRIPTIONÚLITELLM_MCP_SERVER_NAMEÚLITELLM_MCP_SERVER_VERSIONÚMCPMissingUserEnvVarsErrorÚadd_server_prefix_to_nameÚbuild_synthetic_mcp_requestÚ%extract_mcp_tool_result_error_messageÚget_server_prefixÚiter_known_server_prefixesÚlogging_safe_mcp_headersÚmatch_known_tool_name)ÚProxyExceptionÚSpecialMCPServerNamesÚUserAPIKeyAuth)ÚIPAddressUtils)ÚLiteLLMProxyRequestSetupÚget_chain_id_from_headers)ÚMCPAuthÚMCPSpecVersion)ÚMCPInfoÚ	MCPServer)Ú	CallTypesÚStandardLoggingMCPToolCall)ÚRulesÚclientÚfunction_setup)ÚServerSession)ÚOAuthCredentialPayloadÚ_byok_cred_cacheé<   Ú_BYOK_CRED_CACHE_TTLi   Ú_BYOK_CRED_CACHE_MAX_SIZEi  Ú&_STATEFUL_SESSION_IDLE_TIMEOUT_SECONDSéd   Ú _MAX_STATEFUL_SESSIONS_PER_OWNERÚ_MCP_ROUTING_PEEK_MAX_BYTESÚlitellm_otel_transport_spanÚ_MCP_TRANSPORT_SPAN_SCOPE_KEYÚuser_idÚ	server_idÚreturnc                 ó4   — t         j                  | |fd«       y)zÍRemove a (user_id, server_id) entry from the BYOK credential cache.

    Call this after storing or deleting a credential so subsequent calls
    see the fresh value rather than a stale cached result.
    N)rE   Úpop)rO   rP   s     úr/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/_experimental/mcp_server/server.pyÚ_invalidate_byok_cred_cacherU   s   s   € ô ×Ñ˜' 9Ð-¨tÕ4ó    Ú
credentialc                 ó–   — t        t        «      t        k\  rt        j                  «        |t	        j
                  «       ft        | |f<   y)zKWrite a credential value to the cache, evicting all entries if at capacity.N)ÚlenrE   rH   ÚclearÚtimeÚ	monotonic)rO   rP   rW   s      rT   Ú_write_byok_cred_cacher]   |   s9   € ä
ÔÓÔ 9Ò9Ü×ÑÔ Ø.8¼$¿.¹.Ó:JÐ-KÔ�g˜yÐ)Ò*rV   TÚMCP_AVAILABLE)ÚReadResourceResultÚResource)ÚServer)ÚReadResourceContents)ÚBlobResourceContentsÚGetPromptResultÚResourceTemplateÚTextResourceContentsÚToolz7weakref.WeakKeyDictionary[object, MCPAuthenticatedUser]Ú_session_obj_auth_storagezMCP module not found: %sFÚactive_mcp_session©Údefaultz_McpServerSession | NoneÚactive_mcp_session_varÚ_INITIALIZATION_LOCKÚraw_headersc                 ó’   — | sy| j                  «       D ]1  \  }}t        |t        «      sŒ|j                  «       dk(  sŒ+|xs dc S  y)z–The ``mcp-session-id`` of a stateful MCP session, read case-insensitively
    from the request headers. ``None`` for stateless calls (no such header).Nzmcp-session-id)ÚitemsÚ
isinstanceÚstrÚlower)rn   ÚkeyÚvalues      rT   Ú_mcp_session_id_from_headersrv   ²   sM   € ñ
 ØØ!×'Ñ'Ó)ò !‰
ˆˆUÜ�cœ3Õ C§I¡I£KÐ3CÓ$CØ’=˜DÒ ð!ð rV   Útextc                 óÜ  — d}d}d}g }d}d}g }| D ]Ù  }|rE|rd}n?|dk(  rd}n7|dk(  rd}|r.|dk(  r)dj                  |«      dk(  r y|r|j                  |«       ŒJ|dk(  rd}|xr |dk\  xr |d	   }g }d}Œf|d
k(  s|dk(  r|dz  }|j                  |d
k(  «       |d
k(  }Œ�|dk(  s|dk(  r!|r|j                  «        |dz  }|dk  r yd}Œº|dk(  rt        |«      xr |d	   }ŒÒ|dk(  sŒØd}ŒÛ y)a  Whether a (possibly truncated) JSON-RPC envelope has a ``method`` key at
    the root object's top level.

    Used to tell a request/notification (carries ``method``) apart from a
    response (carries ``result``/``error`` and no top-level ``method``). A
    response payload can itself nest a ``method`` field, so only keys at the
    root object's depth are inspected rather than searching the whole string.
    Returns ``True`` only when a top-level ``method`` key is positively found;
    truncation that hides it yields ``False``.
    r   Fú\Tú"é   Ú Úmethodéÿÿÿÿú{ú[ú}ú]ú,ú:)ÚjoinÚappendrS   Úbool)	rw   ÚdepthÚ	in_stringÚescapedÚ	in_objectÚreading_keyÚ
expect_keyÚ	key_charsÚchs	            rT   Ú"_jsonrpc_text_has_top_level_methodr�   ¿   sK  € ð €EØ€IØ€GØ#%€IØ€KØ€JØ€IØò  ˆÙÙØ‘Ø�t’Ø‘Ø�s’Ø!�	Ù 5¨A¢:°"·'±'¸)Ó2DÈÒ2PÙÙØ× Ñ  Ô$ØØ�Š9ØˆIØ$ÒE¨°!©ÒE¸	À"¹ˆKØˆIØ‰JØ�3ŠY˜" š)Ø�Q‰JˆEØ×Ñ˜R 3™YÔ'Ø˜s™‰JØ�3ŠY˜" š)ÙØ—‘”Ø�Q‰JˆEØ˜ŠzØð ð ‰JØ�3ŠYÜ˜i›Ò:¨Y°r©]‰JØ�3‹YØ‰JðA ðB rV   Úreq_ctxc                 óÔ   — t        | dd«      }t        |dd«      }t        |t        «      sydD �ci c](  }t        |j                  |«      t        «      sŒ#|||   “Œ* }}|xs dS c c}w )uª  The W3C trace context (``traceparent``/``tracestate``) the MCP client
    propagated in the request's ``params._meta`` (SEP-414), or ``None``.

    When present, the MCP span records this propagated context as a span *link*,
    never the parent â€” a remote parent would root the span in a trace whose root
    never reaches the gateway's tracing backend. The span itself nests under the
    transport span of the request carrying this specific message, so a
    streamable-HTTP session that multiplexes many messages still does not glue
    every message under the session's first request;
    see ``resolve_mcp_span_context``. The client's W3C Baggage is
    deliberately excluded: it is caller-controlled, and the otel baggage processor
    stamps allowlisted baggage keys (``litellm.team.id``, ``litellm.metadata.*``,
    ...) onto the span, so honoring remote baggage would let a client spoof a
    span's identity attribution.
    ÚmetaNÚmodel_extra)ÚtraceparentÚ
tracestate)Úgetattrrq   ÚdictÚgetrr   )r‘   r“   Úextrart   Úcarriers        rT   Ú_mcp_meta_trace_carrierrœ   õ   sp   € ô  ˜' 6¨4Ó0€DÜ˜4 °Ó5€EÜ�eœTÔ"ØØ1NÖr¨#ÔR\Ð]b×]fÑ]fÐgjÓ]kÔmpÕRq�c˜5 ™:‘oÐr€GÐrØŠ?�dÐùò ss   °$A%ÁA%r›   c                 ó>   — 	 ddl m}  || «      S # t        $ r Y yw xY w)z´Stash ``carrier`` for the otel_v2 MCP span and return a reset token, or
    ``None`` when otel_v2 is unavailable. Lazily imported so opentelemetry stays an
    optional dependency.r   )Úset_mcp_message_trace_carrierN)Ú*litellm.integrations.otel.plumbing.contextrž   ÚImportError)r›   rž   s     rT   Ú_otel_set_mcp_trace_carrierr¡     s+   € ðõ	
ñ -¨WÓ5Ð5øÜò Ùðús   ‚ �	›Útokenc                 óF   — | €y	 ddl m}  || «       y# t        $ r Y yw xY w)z”Clear the per-message trace carrier so it never leaks to the next message on
    the same session task. Paired with ``_otel_set_mcp_trace_carrier``.Nr   )Úreset_mcp_message_trace_carrier)rŸ   r¤   r    )r¢   r¤   s     rT   Ú_otel_reset_mcp_trace_carrierr¥     s2   € ð €}Øðõ	
ñ 	(¨Õ.øÜò Ùðúó   … ”	 Ÿ Úscopec                 óV   — 	 ddl m}  |«       }|�
|| t        <   yy# t        $ r Y yw xY w)uª  Record this request's tracing span on its own ASGI scope.

    Resolved on the ASGI request task, where the proxy's server span is anchored,
    and read back by the MCP message handler through ``req_ctx.request`` â€” the
    ``Request`` the transport attaches to each message. A stateful streamable-HTTP
    session handles every message on the task spawned by its ``initialize`` POST, so
    the handler's own task cannot see later requests' spans.

    The scope, not the shared session auth context: a JSON-RPC *response* POST
    deliberately skips the per-session lock (it can arrive while the tool call that
    awaits it is still in flight), so a field on that shared object would be
    overwritten mid-call and the tool call would attribute itself to the response's
    request. A scope belongs to exactly one request and dies with it, which also
    keeps a finished span from being retained by an idle session.

    The live span, not just its context: a failed tool call stamps ``error.*`` on it,
    which needs a span still open for writes. Lazily imported so opentelemetry stays
    an optional dependency; a no-op when otel_v2 is unavailable or no request span is
    anchored.r   )Úrequest_root_spanN)rŸ   r©   r    rN   )r§   r©   Úspans      rT   Ú%_otel_publish_transport_span_on_scoper«   *  sB   € ð(õ	
ñ (Ó)ˆð ÐØ/3ˆÔ+Ò,ð øô ò Ùðús   ‚ œ	(§(c                 ó‚   — t        | dd«      }t        |dd«      }t        |t        «      sy|j                  t        «      S )ax  The tracing span of the HTTP request that carried this MCP message.

    Read off that request's ASGI scope, reached through the ``Request`` the
    streamable-HTTP transport attaches to each message, so it is this message's
    transport and not whichever request happens to have touched the session last.
    Returns whatever the scope holds; the otel plumbing validates it.ÚrequestNr§   )r—   rq   r   r™   rN   )r‘   r­   r§   s      rT   Ú!_otel_transport_span_from_messager®   J  s=   € ô ˜W i°Ó6€GÜ˜7 G¨TÓ2€EÜ�eœWÔ%ØØ�9‰9Ô2Ó3Ð3rV   rª   c                 óD   — | €y	 ddl m}  || «      S # t        $ r Y yw xY w)zÈPublish the current message's transport span, which the otel_v2 MCP span
    attaches to and a failed tool call stamps its error on. Returns a reset token,
    or ``None`` when otel_v2 is unavailable.Nr   )Úset_mcp_message_transport_span)rŸ   r°   r    )rª   r°   s     rT   Ú_otel_set_mcp_transport_spanr±   X  s5   € ð €|Øðõ	
ñ .¨dÓ3Ð3øÜò Ùðús   … “	žc                 óF   — | €y	 ddl m}  || «       y# t        $ r Y yw xY w)z-Paired with ``_otel_set_mcp_transport_span``.Nr   )Ú reset_mcp_message_transport_span)rŸ   r³   r    )r¢   r³   s     rT   Ú_otel_reset_mcp_transport_spanr´   h  s0   € à€}Øðõ	
ñ 	)¨Õ/øÜò Ùðúr¦   Úexcc                 ó¨   — 	 t        | j                  «      }t	        || j
                  | j                  xs d¬«      S # t        t        f$ r d}Y Œ9w xY w)uB  Map a ``ProxyException`` to an ``HTTPException`` that preserves its real
    status code and headers.

    ``user_api_key_auth`` raises ``ProxyException`` (not ``HTTPException``) on
    auth failures. The MCP ASGI handlers re-raise ``HTTPException`` to keep the
    status and any ``WWW-Authenticate`` challenge, but a ``ProxyException`` would
    otherwise fall through to their generic handler and be flattened to a 500 â€”
    dropping the 401 + challenge an OAuth client needs to re-authenticate, so the
    tool call surfaces as a cancelled/terminated session instead.
    iô  N©Ústatus_codeÚdetailÚheaders)ÚintÚcodeÚ	TypeErrorÚ
ValueErrorr   Úmessagerº   )rµ   r¸   s     rT   Ú"_proxy_exception_to_http_exceptionrÀ   v  sT   € ðÜ˜#Ÿ(™(“mˆô ØØ�{‰{Ø—‘Ò#˜tôð øô ”zÐ"ò ØŠðús   ‚= ½AÁA)ÚAuthContextMiddlewareÚauth_context_var)ÚNotificationOptions)ÚInitializationOptions)ÚStreamableHTTPSessionManager)ÚCallToolResultÚListToolsResultÚPromptÚTextContent©rg   )ÚMCPAuthenticatedUser)ÚSERVER_OUTCOMES_META_KEYÚAggregateToolListingÚServerListOkÚServerOutcomeÚclassify_list_exceptionÚoutcome_wire_value)ÚMCPServerManagerÚ_caller_authorization_fans_outÚ'_client_forwarded_authorization_headersÚ_resolve_openapi_tool_authÚ"_should_strip_caller_authorizationÚglobal_mcp_server_manager)Ú_request_auth_headerÚ_request_extra_headersÚ_request_resolved_auth_headers)ÚSseServerTransport)Úglobal_mcp_tool_registry)ÚMCP_TOOL_PREFIX_SEPARATORÚis_tool_name_prefixedÚnormalize_server_nameÚsplit_server_prefix_from_nameÚstrip_known_server_prefix)ÚDEFAULT_CREDENTIAL_HEADERÚwithout_headerc                   ó8   — e Zd ZU dZdZedz  ed<    ed¬«      Zy)Ú!ListMCPToolsRestAPIResponseObjectzD
        Object returned by the /tools/list REST API route.
        NÚmcp_infoT)Úarbitrary_types_allowed)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__ræ   r<   Ú__annotations__r   Úmodel_config© rV   rT   rå   rå   Í  s!   … ñ	ð $(ˆ�'˜D‘.Ó'Ù!¸$Ô?‰rV   rå   Úcontentsc                 ó¾  — g }| D ]Õ  }t        |dd«      }|€@t        |d«      r4|j                  «       }|j                  d«      }|€|j                  d«      }t	        |t
        «      r2|j                  t        |j                  |j                  |¬«      «       Œ”t	        |t        «      sŒ¥|j                  t        |j                  |j                  |¬«      «       Œ× |S )zRNormalize ResourceContents to ReadResourceContents, preserving meta (MCP 1.26.0+).r“   NÚ
model_dumpÚ_meta)ÚcontentÚ	mime_typer“   )r—   Úhasattrrñ   r™   rq   rf   r†   rb   rw   ÚmimeTyperc   Úblob)rï   Ú
normalizedró   r“   Úds        rT   Ú_normalize_resource_contentsrú   Õ  sÑ   € à8:ˆ
Øò 	ˆGÜ˜7 F¨DÓ1ˆDØˆ|¤¨°Ô >Ø×&Ñ&Ó(�Ø—u‘u˜V“}�Ø�<ØŸ5™5 ›>�DÜ˜'Ô#7Ô8Ø×!Ñ!Ü(Ø '§¡Ø")×"2Ñ"2Ø!ôõô ˜GÔ%9Õ:Ø×!Ñ!Ü(Ø '§¡Ø")×"2Ñ"2Ø!ôõð!	ð. ÐrV   Únotification_optionsÚexperimental_capabilitiesc                 óÖ   — t        j                  | ||xs i ¬«      }i }t        j                  «       }|�||d<   t	        j                  «       }|�||d<   |r|j                  |¬«      S |S )N)rû   rü   ÚinstructionsÚserver_name©Úupdate)ra   Úcreate_initialization_optionsr"   r™   r#   Ú
model_copy)Úselfrû   rü   ÚoptsÚupdatesÚmergedÚscoped_server_names          rT   Ú&_gateway_create_initialization_optionsr	  ñ  s~   € ô
 ×:Ñ:ØØ!5Ø&?Ò&EÀ2ô
ˆð
 *,ˆÜ<×@Ñ@ÓBˆØÐØ&,ˆG�NÑ#Ü$<×$@Ñ$@Ó$BÐØÐ)Ø%7ˆG�MÑ"Ù29ˆt�‰ gˆÓ.ÐC¸tÐCrV   ©ÚnameÚversionÚserverz/mcp/sse/messagesÚsse)ÚappÚevent_storeÚjson_responseÚ	statelessÚsession_manager_statelessÚsession_manager_statefulÚ_stateful_session_auth_contextsÚ(_stateful_session_auth_context_last_seenÚ_stateful_session_ownersÚ_stateful_session_locksÚ'_stateful_session_active_request_countsc                   ó   — e Zd Zdd„Zy)Ú_TerminableTransportNc              ƒ   ó   K  — y ­w©Nrî   )r  s    rT   Ú	terminatez_TerminableTransport.terminate-  s   è ø� ùs   ‚©rQ   N)rè   ré   rê   r  rî   rV   rT   r  r  ,  s   „ Ü.rV   r  c                   ó0   — e Zd Zdedefd„Zdeddddfd„Zy)Ú_TransportRegistryÚ
session_idrQ   c                 ó   — y r  rî   )r  r"  s     rT   Ú__contains__z_TransportRegistry.__contains__0  ó   � rV   rk   Nz_TerminableTransport | Nonec                 ó   — y r  rî   )r  r"  rk   s      rT   rS   z_TransportRegistry.pop2  r%  rV   )rè   ré   rê   Úobjectr‡   r$  rr   rS   rî   rV   rT   r!  r!  /  s"   „ ØB¨6ÐB¸ÓBà^ #Ð^°Ð^Ð<YÔ^rV   r!  c                  ó$   — t        t        di «      S )NÚ_server_instances)r—   r  rî   rV   rT   Ú_stateful_server_instancesr*  4  s   € ÜÔ/Ð1DÀbÓIÐIrV   r"  c                 óà   — t         j                  | d «       t        j                  | d «       t        j                  | d «       t        j                  | d «       t
        j                  | d «       y r  )r  rS   r  r  r  r  )r"  s    rT   Ú!_remove_stateful_session_trackingr,  7  sR   € Ü'×+Ñ+¨J¸Ô=Ü0×4Ñ4°ZÀÔFÜ ×$Ñ$ Z°Ô6Ü×#Ñ# J°Ô5Ü/×3Ñ3°JÀÕErV   Úsession_managerÚsse_session_managerÚ#_stateful_auth_context_cleanup_taskÚnowc              ƒ   ó  K  — | €t        j                  «       n| } t        «       }g }t        j	                  «       D ]A  \  }}t
        j                  |d«      dkD  rŒ | |z
  t        k\  s||vsŒ1|j                  |«       ŒC |D ]S  }t
        j                  |d«      dkD  rŒ|j                  |d«      }|�|j                  «       ƒ d{  –—†  t        |«       ŒU t        t        «      D ]  }|t        vsŒt        |«       Œ y7 Œ:­w)zATerminate expired stateful sessions and drop their auth contexts.Nr   )r[   r\   r*  r  rp   r  r™   rI   r†   rS   r  r,  Úlistr  )r0  Úserver_instancesÚexpired_session_idsr"  Ú	last_seenÚ	transports         rT   Ú-_purge_expired_stateful_session_auth_contextsr7  O  s  è ø€ ð #& +Œd�n‰nÔ°3ˆÜ"<Ó">ÐØ02ÐÜ%M×%SÑ%SÓ%Uò 	7Ñ!ˆJ˜	Ü6×:Ñ:¸:ÀqÓIÈAÒMØØ�Y‰Ô"HÒHÈJÐ^nÒLnØ#×*Ñ*¨:Õ6ð		7ð .ò 	:ˆJô 7×:Ñ:¸:ÀqÓIÈAÒMØð )×,Ñ,¨Z¸Ó>ˆIØÐ$Ø×)Ñ)Ó+×+Ð+Ü-¨jÕ9ð!	:ô$ ÔGÓHò 	>ˆJØÔ!@Ò@Ü1°*Õ=ñ	>ð ,ús   ‚A)DÁ,ADÃD Ã+DÃ2DÚownerc              ƒ   óª  ‡ ‡K  — t        «       Šdt        t           fˆ ˆfd„} |«       }t        |«      t        k  ryt        |d„ ¬«      D ]l  }t         |«       «      t        k  r nSt        j                  |d«      dkD  rŒ6‰j                  |d«      }|�|j                  «       ƒ d{  –—†  t        |«       Œn t         |«       «      t        k  S 7 Œ(­w)a)  
        Bound the number of concurrent stateful sessions a single caller holds
        before routing a new ``initialize`` to the stateful manager.

        Evicts the caller's *own* oldest idle sessions (no in-flight requests)
        to make room, so a busy-but-legitimate client keeps its newest sessions
        and other callers are never affected. Returns ``True`` if the new
        session may proceed, or ``False`` when the caller is already at the cap
        with every session in flight (the new ``initialize`` should be rejected).
        rQ   c                  óp   •— t         j                  «       D � �cg c]  \  } }|‰k(  r| ‰v r| ‘Œ c}} S c c}} w r  )r  rp   )r"  Úsession_ownerr8  r3  s     €€rT   Ú_owned_live_session_idszH_enforce_stateful_session_cap_for_owner.<locals>._owned_live_session_ids  sC   ø€ ô 2J×1OÑ1OÓ1Q÷á-�J Ø  EÒ)¨jÐ<LÑ.Lò óð ùó s   ™2Tc                 ó.   — t         j                  | d«      S )Ng        )r  r™   )Úsids    rT   ú<lambda>z9_enforce_stateful_session_cap_for_owner.<locals>.<lambda>Œ  s   € ÔD×HÑHÈÈcÓR€ rV   )rt   r   N)r*  r2  rr   rY   rK   Úsortedr  r™   rS   r  r,  )r8  r<  Úownedr"  r6  r3  s   `    @rT   Ú'_enforce_stateful_session_cap_for_ownerrB  r  sÓ   ùè ø€ ô #=Ó">Ðð	¬¬c©ö 	ñ /Ó0ˆÜˆu‹:Ô8Ò8Øä ØÙRô
ò 	:ˆJô Ñ*Ó,Ó-Ô0PÒPÙÜ6×:Ñ:¸:ÀqÓIÈAÒMØØ(×,Ñ,¨Z¸Ó>ˆIØÐ$Ø×)Ñ)Ó+×+Ð+Ü-¨jÕ9ð	:ô Ñ*Ó,Ó-Ô0PÑPÐPð ,ús   „B$CÂ(CÂ))Cc               ƒ   óÖ   K  — 	 t        j                  t        «      ƒ d {  –—†  	 t        «       ƒ d {  –—†  Œ57 Œ7 Œ# t        $ r } t        j                  d| «       Y d } ~ Œ)d } ~ ww xY w­w)Nz3Error cleaning up expired MCP stateful sessions: %s)ÚasyncioÚsleeprI   r7  Ú	Exceptionr   Ú	exception©Úes    rT   Ú/_cleanup_expired_stateful_session_auth_contextsrJ  ™  s`   è ø€ ØÜ—-‘-Ô FÓG×GÐGðcÜCÓE×EÐEð ØGøàEùÜò cÜ×(Ñ(Ð)^Ð`a×bÑbûðcüs@   ‚A) 9¡A)¦= ³;´= ¸A)»= ½	A&ÁA!ÁA)Á!A&Á&A)c               ƒ   óp  K  — t         4 ƒd{  –—†  t        r	 ddd«      ƒd{  –—†  yt        j                  d«       t        j                  «       at        j                  «       at        j                  «       a
t        j                  «       ƒ d{  –—†  t        j                  «       ƒ d{  –—†  t        j                  «       ƒ d{  –—†  t        j                  t        «       «      adat        j                  d«       ddd«      ƒd{  –—†  y7 �Œ7 Œò7 Œ†7 Œl7 ŒR7 Œ# 1 ƒd{  –—†7  sw Y   yxY w­w)zFInitialize the session managers. Can be called from main app lifespan.Nz$Initializing MCP session managers...Tz@MCP Server started with StreamableHTTP and SSE session managers!)rm   Ú_SESSION_MANAGERS_INITIALIZEDr   Úinfor  ÚrunÚ_session_manager_cmr  Ú_session_manager_stateful_cmr.  Ú_sse_session_manager_cmÚ
__aenter__rD  Úcreate_taskrJ  r/  rî   rV   rT   Úinitialize_session_managersrT  ¡  s  è ø€ ô (÷ 	dñ 	dÝ,Ø÷	d÷ 	dð 	dô ×ÑÐ FÔGô #<×"?Ñ"?Ó"AÐÜ+C×+GÑ+GÓ+IÐ(Ü&9×&=Ñ&=Ó&?Ð#ô &×0Ñ0Ó2×2Ð2Ü.×9Ñ9Ó;×;Ð;Ü)×4Ñ4Ó6×6Ð6Ü29×2EÑ2EÔFuÓFwÓ2xÐ/à,0Ð)Ü×ÑÐ bÔc÷%	d÷ 	dñ 	dùð 	døð 3øØ;øØ6øð	dø÷ 	d÷ 	dñ 	düs•   ‚D6�DŽD6‘D!™D6¤D¥D6ªA(D!ÂDÂD!Â.DÂ/D!Ã
DÃ8D!ÄD6ÄDÄD6ÄD6ÄD!ÄD!ÄD!ÄD6Ä!D3Ä'D*Ä(D3Ä/D6c               ƒ   ó`  K  — t         rät        j                  d«       	 t        rNt        j	                  «        t        j                  t        j                  «      5  t        ƒ d{  –—†  ddd«       t        rt        j                  ddd«      ƒ d{  –—†  t        rt        j                  ddd«      ƒ d{  –—†  t        rt        j                  ddd«      ƒ d{  –—†  da	dadadada yy7 Œ‡# 1 sw Y   Œ†xY w7 Œh7 ŒE7 Œ"# t        $ r } t        j                  d| «       Y d} ~ ŒDd} ~ ww xY w­w)zShutdown the session managers.z%Shutting down MCP session managers...Nz)Error during session manager shutdown: %sF)rL  r   rM  r/  ÚcancelÚ
contextlibÚsuppressrD  ÚCancelledErrorrO  Ú	__aexit__rP  rQ  rF  rG  rH  s    rT   Úshutdown_session_managersr[  ¿  s  è ø€ õ )Ü×ÑÐ GÔHðYÝ6Ü7×>Ñ>Ô@Ü#×,Ñ,¬W×-CÑ-CÓDñ BÜA×AÐA÷Bå&Ü-×7Ñ7¸¸dÀDÓI×IÐIÝ/Ü6×@Ñ@ÀÀtÈTÓR×RÐRÝ*Ü1×;Ñ;¸DÀ$ÈÓM×MÐMð #'ÐØ+/Ð(Ø&*Ð#Ø26Ð/Ø,1Ñ)ð+ )ð Bø÷Bð Búð JøàRøàMùÜò YÜ×(Ñ(Ð)TÐVW×XÑXûðYüsˆ   ‚D.Ÿ=D Á
C0Á&C.Á'C0Á+(D ÂC<Â$D Â8C>Â9$D ÃD ÃD Ã"D.Ã.C0Ã0C9Ã5D Ã>D Ä D Ä	D+ÄD&Ä!D.Ä&D+Ä+D.c                ó˜   K  — t        «       ƒ d{  –—†  	 d­–— t        «       ƒ d{  –—†  y7 Œ7 Œ# t        «       ƒ d{  –—†7   w xY w­w)z%Application lifespan context manager.N)rT  r[  )r  s    rT   Úlifespanr]  ß  s@   è ø€ ô *Ó+×+Ð+ð	.Üä+Ó-×-Ñ-ð	 	,øð .ùÔ+Ó-×-Ò-üs<   ‚A
�.‘A
–2 ›A
¨0©A
°A
²AÁ AÁAÁA
c            
   ƒ   óL  K  — ddl m}  | j                  d«      }d}|rt        j	                  |j
                  «      }d}d}	 t        t        |«      «      }t        t        |«      «      }t        «       ƒ d{  –—† \  }}}}}	}
}t        j                  d|«       t        j                  d|«       t        j                  d|rt        |j                  «       «      nd«       t        t        |dd«      dd	«      r_dd
lm} ddlm}  |«       D �cg c]  } |j(                  |«      ‘Œ c}t+        |«       t-        |«       |�t        j/                  |«       S S t        j                  d«       t1        |||||	|
dd¬«      ƒ d{  –—† }t        j2                  dt5        |j6                  «      «       |j8                  s:|j6                  t+        |«       t-        |«       |�t        j/                  |«       S S t:        |j8                  j=                  «       D ��ci c]  \  }}|t?        |«      “Œ c}}i}tA        j(                  |j6                  |dœ«      t+        |«       t-        |«       |�t        j/                  |«       S S 7 �Œc c}w 7 �Œ	c c}}w # tB        $ rP}t        jD                  d|«       g cY d}~t+        |«       t-        |«       |�t        j/                  |«       S S d}~ww xY w# t+        |«       t-        |«       |�t        j/                  |«       w w xY w­w)aÛ  
        List all available tools, with each server's listing outcome attached to the result's
        ``_meta`` (SERVER_OUTCOMES_META_KEY) so a broken upstream is distinguishable from a healthy
        server with no tools. Returning a ListToolsResult (rather than a bare list) makes the MCP SDK
        pass the result through unwrapped, which is what lets the ``_meta`` survive to the client.
        Also captures the active session for propagation to callbacks.
        r   ©Úrequest_ctxNz3MCP list_tools - User API Key Auth from context: %sz-MCP list_tools - MCP servers from context: %sz,MCP list_tools - MCP server auth headers: %sÚobject_permissionÚmcp_tool_search_enabledFrÊ   )Úget_virtual_tool_definitionsz(MCP list_tools - Calling _list_mcp_toolsTÚmcp_protocol)Úuser_api_key_authÚmcp_auth_headerÚmcp_serversÚmcp_server_auth_headersÚoauth2_headersrn   Úlog_list_tools_to_spendlogsÚlist_tools_log_sourcez/MCP list_tools - Successfully returned %s tools)Útoolsrò   z Error in list_tools endpoint: %s)#Úmcp.server.lowlevel.serverr`  r™   rl   ÚsetÚsessionr¡   rœ   r±   r®   Úget_or_extract_auth_contextr   Údebugr2  Úkeysr—   Ú	mcp.typesrg   Ú2litellm.proxy._experimental.mcp_server.tool_searchrc  Úmodel_validater´   r¥   ÚresetÚ_list_mcp_toolsrM  rY   rl  ÚoutcomesrÌ   rp   rÑ   rÇ   rF  rG  )r`  r‘   Ú_session_reset_tokenÚ_trace_tokenÚ_transport_tokenre  rf  rg  rh  ri  rn   Ú
_client_iprg   rc  rù   Úlistingrt   ÚoutcomeÚoutcome_metarI  s                       rT   Úhandle_list_toolsr€  ì  s  è ø€ õ 	;à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ØˆØÐð>	CÜ6Ô7NÈwÓ7WÓXˆLÜ;Ô<]Ð^eÓ<fÓgÐô 2Ó3×3ñØ!ØØØ'ØØØä× Ñ Ð!VÐXiÔjÜ× Ñ Ð!PÐR]Ô^Ü× Ñ Ø>Ù8O”Ð,×1Ñ1Ó3Ô4ÐUYôô ÜÐ)Ð+>ÀÓEØ)Øôõ
 +õñ 9UÓ8VÖW°1Ð+˜×+Ñ+¨AÕ.ÒWô: +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ô9 × Ñ Ð!KÔLÜ#2Ø"3Ø /Ø'Ø(?Ø-Ø'Ø,0Ø&4ô	$÷ 	ˆGô ×ÑÐ QÔSVÐW^×WdÑWdÓSeÔfØ×#Ò#Ø—}‘}ô +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ô )ØIP×IYÑIY×I_ÑI_ÓIa÷+Ù9E¸¸g�CÔ+¨GÓ4Ñ4ó+ð#ˆLô
 #×1Ñ1¸G¿M¹MÐT`Ñ2aÓbô +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ðc 4ûò$ Xð	ûó+øô
 ò 	Ü×$Ñ$Ð%GÈÔKð ŒIä*Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûð	ûô +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0üs£   ‚?L$Á5J Á7JÁ8BJ ÄJÄ'J Ä)/L$Å+J ÆJÆAJ Ç/L$Ç7"J ÈJÈ/&J É/L$ÊJ ÊJ ÊJ Ê	K.ÊK)Ê5K.Ê6K1 Ê:/L$Ë)K.Ë.K1 Ë10L!Ì!L$c                 óž  ‡‡— 	 | j                   }|rt	        |d«      r|j
                  syt        |j
                  dd«      Š‰�t	        |d«      r|j                  sy|j                  Šdt        dt        dz  fˆˆfd„}t        j                  d	t        ‰«      dd
 «       |S # t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)z–Return a progress-forwarding callback bound to the host MCP session.

        Returns ``None`` when the host did not supply a progress token.
        z+Could not capture host progress context: %sNr“   ÚprogressTokenro  ÚprogressÚtotalc              “   óÒ   •K  — 	 ‰j                  ‰| |¬«      ƒ d{  –—†  t        j                  d| |«       y7 Œ# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)z8Forward progress notifications from external MCP to Host)Úprogress_tokenrƒ  r„  Nz Forwarded progress %s/%s to Hostz&Failed to forward progress to Host: %s)Úsend_progress_notificationr   rq  rF  Úerror)rƒ  r„  rI  Úhost_sessionÚ
host_tokens      €€rT   Úforward_progressz9_capture_host_progress_callback.<locals>.forward_progressP  su   øè ø€ ðRØ"×=Ñ=Ø#-Ø%Øð >ó ÷ ð ô
 ×$Ñ$Ð%GÈÐSXÕYðùô ò RÜ×$Ñ$Ð%MÈq×QÑQûðRüs7   ƒA'…; œ9�; ¸A'¹; »	A$ÁAÁA'ÁA$Á$A'z"Host progressToken captured: %s...é   )Úrequest_contextrF  r   Úwarningrõ   r“   r—   ro  Úfloatrq  rr   )Úhost_serverÚhost_ctxrI  r‹  r‰  rŠ  s       @@rT   Ú_capture_host_progress_callbackr’  >  sÈ   ù€ ð
	Ø)×9Ñ9ˆHñ
 œW X¨vÔ6¸8¿=º=ØÜ# H§M¡M°?ÀDÓIˆ
ØÐ¤g¨h¸	Ô&BÀx×GWÒGWØØ&×.Ñ.ˆð
	R¬Uð 
	R¼5À4¹<ö 
	Rô 	×ÑÐAÄ3ÀzÃ?ÐSUÐTUÐCVÔWØÐøô1 ò 	Ü×"Ñ"Ð#PÐRSÔTÜûð	ús   „B# Â#	CÂ,CÃCr  Ú	argumentsre  Ú	client_ipc              ƒ   óÖ   K  — ddl m} ddlm}m}m} t        d||¬«      }	 || |dœ¬«      j                  |	||t        j                  j                  ||¬«      ƒ d	{  –—† \  }
}|S 7 Œ	­w)
z‰Run the pre-call pipeline (guardrails + logging setup) for a virtual
        mcp_tool_call so the SSE path spend-logs like the REST path.r   )ÚProxyBaseLLMRequestProcessing)Úgeneral_settingsÚproxy_configÚproxy_logging_objú/mcp/tools/call©Úpathrn   r”  ©r  r“  )Údata)r­   Úuser_api_key_dictr˜  Ú
route_typer™  r—  N)Ú'litellm.proxy.common_request_processingr–  Úlitellm.proxy.proxy_serverr—  r˜  r™  r.   Ú common_processing_pre_call_logicr>   Úcall_mcp_toolru   )r  r“  re  rn   r”  r–  r—  r˜  r™  r­   Ú_Úvirtual_logging_objs               rT   Ú_build_virtual_call_logging_objr§  _  s…   è ø€ õ	
÷	
ñ 	
ô 5Ø"Ø#Øô
ˆñ
 (EØ¨YÑ7ô(
ç
*Ñ
*ØØ/Ø%Ü ×.Ñ.×4Ñ4Ø/Ø-ð +ó 
÷	"
ÑˆÐð #Ð"ð	"
ús   ‚AA)ÁA'Á
A)rg  rf  rh  ri  c	              ƒ   óŽ  K  — ddl m}	m}
m}m}m}m}m}m} | |vryt        t        |dd«      dd«      st        t        dd| › d	�¬
«      gd¬«      S |xs i }| |k(  r? ||j                  dd«       ||j                  dd«      «      |||||||¬«	      ƒ d{  –—† S |€J ‚| |	k(  rD |t        |j                  dd«      «       ||j                  d|
«      |
¬«      |¬«      ƒ d{  –—† S t        | ||||¬«      ƒ d{  –—† } ||j                  dd«      |j                  d«      xs i ||||||||¬«
      ƒ d{  –—† S 7 Œ¦7 Œ[7 ŒE7 Œ
­w)zÏHandle the mcp_tool_search / mcp_tool_call virtual tools.

        Returns a CallToolResult when ``name`` is a virtual tool, else ``None`` so
        the caller falls through to normal tool routing.
        r   )ÚAGENT_SEARCH_TOOL_NAMEÚDEFAULT_AGENT_SEARCH_TOP_KÚMCP_TOOL_SEARCH_TOOL_NAMEÚVIRTUAL_TOOL_NAMESÚcoerce_top_kÚhandle_agent_searchÚhandle_mcp_tool_callÚhandle_mcp_tool_searchNra  rb  Frw   zTool z, requires mcp_tool_search_enabled on the key)Útyperw   T©ró   ÚisErrorÚqueryr|   Útop_ké   )	r´  rµ  rŸ  r”  rg  rf  rh  ri  rn   rj   )r´  rµ  rŸ  )r  r“  re  rn   r”  Ú	tool_namer“  )
r·  r“  rŸ  r”  rg  rf  rh  ri  rn   Úlitellm_logging_obj)rt  r©  rª  r«  r¬  r­  r®  r¯  r°  r—   rÆ   rÉ   r™   rr   r§  )r  r“  re  r”  rg  rf  rh  ri  rn   r©  rª  r«  r¬  r­  r®  r¯  r°  Úargsr¦  s                      rT   Ú_dispatch_virtual_mcp_toolrº  ‚  s¦  è ø€ ÷ 		
÷ 		
ó 		
ð Ð)Ñ)ØäÜÐ%Ð':¸DÓAØ%Øô
ô
 "äØ#Ø$ T FÐ*VÐWôðð ôð ð  ’o 2ˆØÐ,Ò,Ù/Ø—h‘h˜w¨Ó+Ù" 4§8¡8¨G°QÓ#7Ó8Ø"3Ø#Ø'Ø /Ø(?Ø-Ø'ô
÷ 
ð 
ð !Ð,Ð,Ð,ØÐ)Ò)Ù,Ü˜$Ÿ(™( 7¨BÓ/Ó0Ù" 4§8¡8¨GÐ5OÓ#PÐZtÔuØ"3ô÷ ð ô
 ,KØØØ/Ø#Øô,
÷ &
Ðñ *Ø—h‘h˜{¨BÓ/Ø—h‘h˜{Ó+Ò1¨rØ/ØØ#Ø+Ø$;Ø)Ø#Ø 3ô
÷ 
ð 	
ð5
øðøð
&
øð
úsI   ‚BEÂD=ÂAEÃ#D?Ã$EÃ;EÃ<<EÄ8EÄ9EÄ?EÅEÅEc              ƒ   óÔ	  K  — ddl m} ddlm} ddlm}m} ddlm} ddl	m
} |j                  d«      }d}	|rt        j                  |j                  «      }	d}
d}	 t        t!        |«      «      }
t#        t%        |«      «      }t'        «       ƒ d{  –—† \  }}}}}}}t)        j*                  d|t-        |d	d
«      «       t)        j*                  d|«       	 t/        | ||||||||¬«	      ƒ d{  –—† }|�0|t1        |«       t3        |
«       |	�t        j5                  |	«       S S t7        t8        «      }| |dœ}t;        |«      }|r
||d<   ||d<   t=        d||¬«      }|�2 |||t?        j@                  || ¬«      ƒ d{  –—† |¬«      ƒ d{  –—† }n|}tC        d$|||||||dœ|¤Žƒ d{  –—† }|t1        |«       t3        |
«       |	�t        j5                  |	«       S S 7 �ŒN7 Œó7 Œe7 ŒY7 Œ=# tD        $ r‚}t)        jF                  d|jH                  |jJ                  «        |tM        tO        |«      d¬«      gd¬«      cY d}~t1        |«       t3        |
«       |	�t        j5                  |	«       S S d}~w|$ rg}t)        jP                  d|«        |tM        d|› �d¬«      gd¬«      cY d}~t1        |«       t3        |
«       |	�t        j5                  |	«       S S d}~w|$ rg}t)        jP                  d|«        |tM        d|› �d¬«      gd¬«      cY d}~t1        |«       t3        |
«       |	�t        j5                  |	«       S S d}~wtR        $ rq}t)        jP                  d|«        |tM        d|jT                  › �d¬«      gd¬«      cY d}~t1        |«       t3        |
«       |	�t        j5                  |	«       S S d}~wtV        $ r|}t)        jF                  d |jX                  «        |tM        d!|jX                  › d"�d¬«      gd¬«      cY d}~t1        |«       t3        |
«       |	�t        j5                  |	«       S S d}~wtZ        $ rg}t)        j\                  d#|«        |tM        d|› �d¬«      gd¬«      cY d}~t1        |«       t3        |
«       |	�t        j5                  |	«       S S d}~ww xY w# t1        |«       t3        |
«       |	�t        j5                  |	«       w w xY w­w)%a—  
        Call a specific tool with the provided arguments
        Args:
            name (str): Name of the tool to call
            arguments (Dict[str, Any] | None): Arguments to pass to the tool
        Returns:
            List[Union[MCPTextContent, MCPImageContent, MCPEmbeddedResource]]: Tool execution results
        Raises:
            HTTPException: If tool not found or arguments missing
        r   r_  )rÆ   )ÚBlockedPiiEntityErrorÚGuardrailRaisedException)Úadd_litellm_data_to_request)r˜  Nz=MCP mcp_server_tool_call - user_api_key_auth=%s, user_role=%sÚ	user_rolezN/Aú=MCP mcp_server_tool_call - User API Key Auth from context: %s)	r  r“  re  r”  rg  rf  rh  ri  rn   r�  Úlitellm_trace_idÚlitellm_session_idrš  r›  )r·  )rž  r­   rŸ  r˜  )re  rf  rg  rh  ri  rn   Úhost_progress_callbackzKMCP mcp_server_tool_call missing per-user env vars: server_id=%s missing=%srw   ©rw   r±  Tr²  z*BlockedPiiEntityError in MCP tool call: %sz%Error: Blocked PII entity detected - z-GuardrailRaisedException in MCP tool call: %szError: Guardrail violation - z"HTTPException in MCP tool call: %súError: z/Upstream auth failure calling MCP tool: HTTP %sz.Error: upstream authentication required (HTTP ú)z$MCP mcp_server_tool_call - error: %srî   )/rm  r`  rs  rÆ   Úlitellm.exceptionsr¼  r½  Ú$litellm.proxy.litellm_pre_call_utilsr¾  r¢  r˜  r™   rl   rn  ro  r¡   rœ   r±   r®   rp  r   rq  r—   rº  r´   r¥   rv  r’  r  r9   r.   r   Úbilling_auth_for_tool_callr¤  r,   rM  rP   ÚmissingrÉ   rr   rˆ  r   r¹   r    r¸   rF  rG  )r  r“  r`  rÆ   r¼  r½  r¾  r˜  r‘   ry  rz  r{  re  rf  rg  rh  ri  rn   r|  Úvirtual_tool_resultrÃ  Ú	body_dataÚchain_idr­   rž  ÚresponserI  s                              rT   Úmcp_server_tool_callrÏ  Ø  sV  è ø€ õ 	;Ý,çVÝTÝ;à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ØˆØÐðO	CÜ6Ô7NÈwÓ7WÓXˆLÜ;Ô<]Ð^eÓ<fÓgÐô 2Ó3×3ñØ!ØØØ'ØØØä× Ñ ØOØ!ÜÐ)¨;¸Ó>ôô × Ñ Ð!`ÐbsÔtðsô 4NØØ'Ø&7Ø(Ø +Ø$3Ø,CØ#1Ø +ô
4÷ 
.Ð#ð 'Ð2Ø.ôP +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ôQ 1PÔPVÓ0WÐ&à,0¸yÑ#I�	ä";¸KÓ"H�ÙØ4<�IÐ0Ñ1Ø6>�IÐ2Ñ3ä!<Ø*Ø +Ø(ô"�ð
 %Ð0Ù!<Ø&Ø 'ô 1B×0\Ñ0\Ø-¸ô1÷ +ð &2ô"÷ ‘Dð" %�Dä(5ð 	)Ø&7Ø$3Ø +Ø,CØ#1Ø +Ø+Añ	)ð ñ	)÷ 	#�ðD ä*Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ðE 4ùð
.øðP+øðøð&	#ùô .ò 	Ü×#Ñ#ØaØ—K‘KØ—I‘Iôñ
 &Ü(¬c°!«f¸6ÔBÐCØ ôô ôh +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûðe )ò 
Ü×$Ñ$Ð%QÐSTÔUÙ%ä#Ø#HÈÈÐ!LØ!'ôðð !ôô ô\ +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûðO ,ò Ü×$Ñ$Ð%TÐVWÔXÙ%Ü(Ð0MÈaÈSÐ.QÐX^Ô_Ð`Ø ôô ôF +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûôC !ò Ü×$Ñ$Ð%IÈ1ÔMÙ%Ü(°¸¿¹°zÐ.BÈÔPÐQØ ôô ô: +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûô7 (ò ô ×#Ñ#Ð$UÐWX×WdÑWdÔeÙ%ä#Ø#QÐRS×R_ÑR_ÐQ`Ð`aÐ!bØ!'ôðð !ôô ô$ +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûô ò Ü×(Ñ(Ð)OÐQRÔSÙ%Ü(°¸°s¨mÀ&ÔIÐJØ ôô ô +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0ûðûô +Ð+;Ô<Ü)¨,Ô7Ø#Ð/Ü&×,Ñ,Ð-AÕBð 0üsT  ‚AS(Á5R5 ÂGÂAR5 ÃG* Ã.G"Ã/G* Ã6/S(Ä%AG* Å>G$Å?G* ÆG&ÆG* Æ*G(Æ+G* Æ/R5 Æ0/S(ÇR5 Ç"G* Ç$G* Ç&G* Ç(G* Ç*	R2Ç3A	I0È<R2È=R5 É/S(É0R2É8.KÊ&R2Ê'R5 Ê+/S(ËR2Ë".MÌR2ÌR5 Ì/S(ÍR2Í8N<ÎR2Î	R5 Î/S(Î<R2ÏAP?ÐR2ÐR5 Ð/S(Ð?R2Ñ.R-Ñ9R2Ñ:R5 Ñ>/S(Ò-R2Ò2R5 Ò50S%Ó%S(c               ƒ   ó
  K  — ddl m}  | j                  d«      }d}|rt        j	                  |j
                  «      }	 t        «       ƒ d{  –—† \  }}}}}}}	t        j                  d|«       t        j                  d|«       t        j                  d|rt        |j                  «       «      nd«       t        j                  d«       t        ||||||¬«      ƒ d{  –—† }
t        j                  d	t        |
«      «       |
|�t        j                  |«       S S 7 ŒÐ7 Œ?# t        $ r:}t        j                   d
|«       g cY d}~|�t        j                  |«       S S d}~ww xY w# |�t        j                  |«       w w xY w­w)z,
        List all available prompts
        r   r_  Nz5MCP list_prompts - User API Key Auth from context: %sz/MCP list_prompts - MCP servers from context: %sz.MCP list_prompts - MCP server auth headers: %sz(MCP list_prompts - Calling _list_prompts©re  rf  rg  rh  ri  rn   z3MCP list_prompts - Successfully returned %s promptsz"Error in list_prompts endpoint: %s)rm  r`  r™   rl   rn  ro  rp  r   rq  r2  rr  Ú_list_mcp_promptsrM  rY   rv  rF  rG  )r`  r‘   ry  re  rf  rg  rh  ri  rn   r|  ÚpromptsrI  s               rT   Úlist_promptsrÔ  ƒ  s„  è ø€ õ
 	;à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ð$	Cô 2Ó3×3ñØ!ØØØ'ØØØä× Ñ Ð!XÐZkÔlÜ× Ñ Ð!RÐT_Ô`Ü× Ñ Ø@Ù8O”Ð,×1Ñ1Ó3Ô4ÐUYôô
 × Ñ Ð!KÔLÜ#4Ø"3Ø /Ø'Ø(?Ø-Ø'ô$÷ ˆGô ×ÑÐ UÔWZÐ[bÓWcÔdØð $Ð/Ü&×,Ñ,Ð-AÕBð 0ð3 4øðùô ò 	Ü×$Ñ$Ð%IÈ1ÔMð ŒIà#Ð/Ü&×,Ñ,Ð-AÕBð 0ûð	ûð $Ð/Ü&×,Ñ,Ð-AÕBð 0üsk   ‚;F¾D  ÁDÁBD  ÃDÃ$D  ÄFÄD  ÄD  Ä 	E#Ä)EÅ E#ÅE& ÅFÅE#Å#E& Å&F Æ Fc           
   ƒ   óˆ  K  — ddl m} |j                  d«      }d}|rt        j	                  |j
                  «      }	 t        «       ƒ d{  –—† \  }}}}}	}
}t        j                  d|«       t        | ||||||	|
¬«      ƒ d{  –—† |�t        j                  |«       S S 7 ŒU7 Œ# |�t        j                  |«       w w xY w­w)a#  
        Get a specific prompt with the provided arguments

        Args:
            name (str): Name of the prompt to get
            arguments (Dict[str, Any] | None): Arguments to pass to the prompt

        Returns:
            GetPromptResult: Getting prompt execution results
        r   r_  NrÀ  )r  r“  re  rf  rg  rh  ri  rn   )rm  r`  r™   rl   rn  ro  rp  r   rq  Úmcp_get_promptrv  )r  r“  r`  r‘   ry  re  rf  rg  rh  ri  rn   r|  s               rT   Ú
get_promptr×  µ  sß   è ø€ õ 	;à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ð	Cô 2Ó3×3ñØ!ØØØ'ØØØô × Ñ Ð!`ÐbsÔtÜ'ØØ#Ø"3Ø /Ø'Ø(?Ø-Ø'ô	÷ 	ð $Ð/Ü&×,Ñ,Ð-AÕBð 0ð 4øð	ùð $Ð/Ü&×,Ñ,Ð-AÕBð 0üs@   ‚;C¾B% ÁB!Á8B% ÂB#ÂB% ÂCÂ!B% Â#B% Â%B?Â?Cc               ƒ   óà  K  — ddl m}  | j                  d«      }d}|rt        j	                  |j
                  «      }	 t        «       ƒ d{  –—† \  }}}}}}}	t        j                  d|«       t        j                  d|«       t        j                  d|rt        |j                  «       «      nd«       t        ||||||¬«      ƒ d{  –—† }
t        j                  dt        |
«      «       |
|�t        j                  |«       S S 7 Œ»7 Œ?# t        $ r:}t        j                   d	|«       g cY d}~|�t        j                  |«       S S d}~ww xY w# |�t        j                  |«       w w xY w­w)
zList all available resources.r   r_  Nz7MCP list_resources - User API Key Auth from context: %sz1MCP list_resources - MCP servers from context: %sz0MCP list_resources - MCP server auth headers: %srÑ  z7MCP list_resources - Successfully returned %s resourcesz$Error in list_resources endpoint: %s)rm  r`  r™   rl   rn  ro  rp  r   rq  r2  rr  Ú_list_mcp_resourcesrM  rY   rv  rF  rG  )r`  r‘   ry  re  rf  rg  rh  ri  rn   r|  Ú	resourcesrI  s               rT   Úlist_resourcesrÛ  ä  ss  è ø€ õ 	;à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ð 	Cô 2Ó3×3ñØ!ØØØ'ØØØä× Ñ Ð!ZÐ\mÔnÜ× Ñ Ð!TÐVaÔbÜ× Ñ ØBÙ8O”Ð,×1Ñ1Ó3Ô4ÐUYôô
 &9Ø"3Ø /Ø'Ø(?Ø-Ø'ô&÷  ˆIô ×ÑÐ YÔ[^Ð_hÓ[iÔjØð
 $Ð/Ü&×,Ñ,Ð-AÕBð 0ð- 4øð ùô ò 	Ü×$Ñ$Ð%KÈQÔOØŒIà#Ð/Ü&×,Ñ,Ð-AÕBð 0ûð		ûð $Ð/Ü&×,Ñ,Ð-AÕBð 0üók   ‚;E.¾D ÁDÁA=D Ã	D	Ã
$D Ã.E.ÄD Ä	D Ä	EÄE	Ä+EÄ,E Ä0E.Å	EÅE ÅE+Å+E.c               ƒ   óà  K  — ddl m}  | j                  d«      }d}|rt        j	                  |j
                  «      }	 t        «       ƒ d{  –—† \  }}}}}}}	t        j                  d|«       t        j                  d|«       t        j                  d|rt        |j                  «       «      nd«       t        ||||||¬«      ƒ d{  –—† }
t        j                  dt        |
«      «       |
|�t        j                  |«       S S 7 Œ»7 Œ?# t        $ r:}t        j                   d	|«       g cY d}~|�t        j                  |«       S S d}~ww xY w# |�t        j                  |«       w w xY w­w)
z&List all available resource templates.r   r_  Nz@MCP list_resource_templates - User API Key Auth from context: %sz:MCP list_resource_templates - MCP servers from context: %sz9MCP list_resource_templates - MCP server auth headers: %srÑ  zIMCP list_resource_templates - Successfully returned %s resource templatesz-Error in list_resource_templates endpoint: %s)rm  r`  r™   rl   rn  ro  rp  r   rq  r2  rr  Ú_list_mcp_resource_templatesrM  rY   rv  rF  rG  )r`  r‘   ry  re  rf  rg  rh  ri  rn   r|  Úresource_templatesrI  s               rT   Úlist_resource_templatesrà    sz  è ø€ õ 	;à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ð"	Cô 2Ó3×3ñØ!ØØØ'ØØØä× Ñ Ð!cÐevÔwÜ× Ñ Ð!]Ð_jÔkÜ× Ñ ØKÙ8O”Ð,×1Ñ1Ó3Ô4ÐUYôô
 /KØ"3Ø /Ø'Ø(?Ø-Ø'ô/÷ )Ðô ×ÑØ[Ô]`ÐasÓ]tôð &ð
 $Ð/Ü&×,Ñ,Ð-AÕBð 0ð1 4øð)ùô ò 	Ü×$Ñ$Ð%TÐVWÔXØŒIà#Ð/Ü&×,Ñ,Ð-AÕBð 0ûð		ûð $Ð/Ü&×,Ñ,Ð-AÕBð 0ürÜ  Úurlc           	   ƒ   ó„  K  — ddl m} |j                  d «      }d }|rt        j	                  |j
                  «      }	 t        «       ƒ d {  –—† \  }}}}}}	}
t        | ||||||	¬«      ƒ d {  –—† }t        |j                  «      |�t        j                  |«       S S 7 ŒS7 Œ3# |�t        j                  |«       w w xY w­w)Nr   r_  )rá  re  rf  rg  rh  ri  rn   )rm  r`  r™   rl   rn  ro  rp  Úmcp_read_resourcerú   rï   rv  )rá  r`  r‘   ry  re  rf  rg  rh  ri  rn   r|  Úread_resource_results               rT   Úread_resourcerå  >  sÛ   è ø€ å:à$Ÿ™¨Ó.ˆØ#ÐÙÜ#9×#=Ñ#=¸g¿o¹oÓ#NÐ ð	Cô 2Ó3×3ñØ!ØØØ'ØØØô 1BØØ"3Ø /Ø'Ø(?Ø-Ø'ô1÷ +Ð ô 0Ð0D×0MÑ0MÓNà#Ð/Ü&×,Ñ,Ð-AÕBð 0ð 4øð+ùð $Ð/Ü&×,Ñ,Ð-AÕBð 0üs@   ‚;C ¾B# ÁBÁ!B# Á-B!Á.B# ÂC ÂB# Â!B# Â#B=Â=C Úallowed_mcp_serversc              ƒ   óJ  K  — i }| �°| D ]«  }d}|D ]S  }|sŒt        |«      D �cg c]  }|sŒ|j                  «       ‘Œ }}|j                  «       |v sŒB|||j                  <   d} n |rŒ`	 t        j                  |g«      ƒ d{  –—† }|D ](  }	|D ]!  }|	|j                  k(  sŒ|||j                  <   Œ# Œ* Œ­ |rt        |j                  «       «      S | �t        j                  d| «       g S |S c c}w 7 Œo# t
        $ r"}
t        j                  d||
«       Y d}
~
�Œd}
~
ww xY w­w)añ  
        Get the filtered MCP servers from the MCP server names.

        Fails closed when ``mcp_servers`` is explicitly provided (path- or
        header-derived) but none of the names resolve to a server alias or
        access group the caller can access. The previous behavior returned
        the full ``allowed_mcp_servers`` set, which silently widened scope
        when a client targeted ``/mcp/<unknown>/`` and made URL/header
        namespacing appear to work when it did not.
        NFTz*Could not resolve '%s' as access group: %szcMCP scope filter resolved to no servers for requested names %s; returning empty list (fail-closed).)
r1   rs   rP   r   Ú#_get_mcp_servers_from_access_groupsrF  r   rq  r2  Úvalues)rg  ræ  Úfiltered_serverÚserver_or_groupÚserver_name_matchedr  ÚsÚ
match_listÚaccess_group_server_idsrP   rI  s              rT   Ú._get_allowed_mcp_servers_from_mcp_server_namesrð  i  sk  è ø€ ð 8:ˆàÐ"Ø#.ò o�Ø&+Ð#à1ò "�FÚÜ9SÐTZÓ9[Ö%a°AÒ_` a§g¡g¥iÐ%a˜
Ð%aà*×0Ñ0Ó2°jÒ@Ø@F˜O¨F×,<Ñ,<Ñ=Ø26Ð/Ù!ð"ò +ð
oÜ8I×8mÑ8mØ,Ð-ó9÷ 3Ð/ð *Aò O˜IØ*=ò O Ø#,°×0@Ñ0@Ó#@ØHN O°F×4DÑ4DÒ$EñOñOð%oñ2 Ü˜×.Ñ.Ó0Ó1Ð1àÐ"ô × Ñ ØuØôð ˆIà"Ð"ùòC &bð3ùô %ò oÜ&×,Ñ,Ð-YÐ[jÐlm×nÒnûðoüsa   ‚D#–D#£C.«C.½D#ÁD#Á*C5ÂC3ÂC5Â"C5Â5>D#Ã3C5Ã5	D Ã>DÄD#ÄD Ä D#r·  Úfilter_listÚ
mcp_serverc                 ó8   — t        | |«      }t        |||«      duS )ak  
        Check if a tool name matches any name in the filter list.

        Reads the same owner the server-level permission checks use, so discovery hides
        exactly what dispatch refuses. ``mcp_server`` is required: guessing the boundary
        at the first separator mismatches every tool on a server whose prefix contains
        the separator.
        N)rá   r3   )r·  rñ  rò  Ú	bare_names       rT   Ú_tool_name_matchesrõ  £  s%   € ô 5°YÀ
ÓKˆ	Ü$ Y°
¸KÓHÐPTÐTÐTrV   rl  c                 ó0  — ddl m} | } ||«      r?|j                  sg S | D �cg c]&  }t        |j                  |j                  |«      sŒ%|‘Œ( }}|j
                  r0|D �cg c]%  }t        |j                  |j
                  |«      s|‘Œ' }}|S c c}w c c}w )aç  
        Filter tools by allowed/disallowed tools configuration.

        If allowed_tools is set, only tools in that list are returned.
        If disallowed_tools is set, tools in that list are excluded.
        Tool names are matched with and without server prefixes for flexibility.

        Args:
            tools: List of tools to filter
            mcp_server: Server configuration with allowed_tools/disallowed_tools

        Returns:
            Filtered list of tools
        r   )Úserver_applies_tool_allowlist)Ú,litellm.proxy._experimental.mcp_server.utilsr÷  Úallowed_toolsrõ  r  Údisallowed_tools)rl  rò  r÷  Útools_to_returnÚtools        rT   Úfilter_tools_by_allowed_toolsrý  ¯  sª   € õ$	
ð  ˆñ )¨Ô4Ø×+Ò+Ø�	à!&öØÔ*<¸T¿Y¹YÈ
×H`ÑH`ÐblÕ*m’ðˆOð ð
 ×&Ò&ð ,öàÜ)¨$¯)©)°Z×5PÑ5PÐR\Ô]ò ðˆOð ð Ðùòùòs   £&BÁ
BÁ *Bc                 óæ   — |j                   xs i }|j                  xs i }|s|s| S | D ]E  }t        |j                  |«      }|xs |j                  }||v r
||   |_        ||v sŒ<||   |_        ŒG | S )z¾Apply admin-configured display name/description overrides to tools.

        Overrides are keyed by the unprefixed tool name, same convention as
        allowed_tools configuration.
        )Útool_name_to_display_nameÚtool_name_to_descriptionrá   r  Údescription)rl  rò  Údisplay_name_mapÚdescription_maprü  Ú
unprefixedÚ
lookup_keys          rT   Úapply_tool_overridesr  Ù  s�   € ð #-×"FÑ"FÒ"LÈ"ÐØ!+×!DÑ!DÒ!JÈˆÙ©ØˆLàò 	?ˆDÜ2°4·9±9¸jÓIˆJØ#Ò0 t§y¡yˆJØÐ-Ñ-Ø,¨ZÑ8�”	Ø˜_Ò,Ø#2°:Ñ#>�Õ ð	?ð ˆrV   c                  óˆ   — 	 t        j                  «       } | rt        | t        «      r| j                  S y# t
        $ r Y yw xY w)z�
        Extract client_ip from auth context.
        Returns None if context not set (caller should handle this as "no IP filtering").
        N)rÂ   r™   rq   rË   r”  rF  ©Ú	auth_users    rT   Ú_get_client_ip_from_contextr
  ð  sJ   € ð
	Ü/×3Ñ3Ó5ˆIÙœZ¨	Ô3GÔHØ ×*Ñ*Ð*ð øô ò 	ØØð	ús   ‚15 µ	AÁ Ac              ƒ   óê  K  — |€!t        «       }|€t        j                  d«       t        j                  | «      ƒ d{  –—† }t        j
                  ||«      \  }}t        j                  d||«       |dkD  rt        j                  d||«       g }|D ]@  }t        j                  |«      }|€Œt        j                  |«      }|j                  |«       ŒB |�t        ||¬«      ƒ d{  –—† }|S 7 Œ°7 Œ­w)a‚  Return allowed MCP servers for a request after applying filters.

        Args:
            user_api_key_auth: The authenticated user's API key info.
            mcp_servers: Optional list of server names to filter to.
            client_ip: Client IP for IP-based access control. If None, falls back to
                      auth context. Pass explicitly from request handlers for safety.
        Note: If client_ip is None and auth context is not set, IP filtering is skipped.
              This is intentional for internal callers but may indicate a bug if called
              from a request handler without proper context setup.
        Nz�MCP _get_allowed_mcp_servers called without client_ip and no auth context. IP filtering will be skipped. This is expected for internal calls.z2MCP IP filter: client_ip=%s, allowed_server_ids=%sr   a  MCP IP filtering: %d server(s) are not accessible from client IP %s because they are restricted to internal networks. No tools from those servers will be returned. To expose a server externally, set 'available_on_public_internet: true' in its configuration.©rg  ræ  )r
  r   rq  r×   Úget_allowed_mcp_serversÚ!filter_server_ids_by_ip_with_infoÚget_mcp_server_by_idrÒ   Úresolve_oauth2_flow_for_requestr†   rð  )re  rg  r”  Úallowed_mcp_server_idsÚ_ip_blockedræ  Úallowed_mcp_server_idrò  s           rT   Ú_get_allowed_mcp_serversr  ý  s"  è ø€ ð" ÐÜ3Ó5ˆIØÐ Ü×$Ñ$ðYôô
 (A×'XÑ'XÐYjÓ'k×!kÐô &×GÑGÐH^Ð`iÓjñ	
Ø"Øä×ÑØ@ØØ"ô	
ð
 ˜Š?Ü× Ñ ð(ð
 Øôð 02ÐØ%;ò 	7Ð!Ü2×GÑGÐH]Ó^ˆJØÑ%ä-×MÑMÈjÓY�
Ø#×*Ñ*¨:Õ6ð	7ð Ð"Ü(VØ'Ø$7ô)÷ #Ðð
 #Ð"ðE "løð:#ús(   ‚<C3¾C/¿A.C3Â.:C3Ã(C1Ã)C3Ã1C3c                 óê   — |syddl m}  ||| j                  | j                  ¬«      }t	        |t
        «      rt        |j                  «       «      S t	        |t        «      rt        d„ |D «       «      S y)a�  True if the request carries a per-server ``x-mcp-{alias}-authorization``
        header for this server. This is the multi-server binding: it names one
        upstream, so it is unambiguously the caller's upstream token regardless of
        auth mode (never the LiteLLM admission credential).

        Resolves through the same ``lookup_mcp_server_auth_in_headers`` egress uses, so
        the connect gate and egress agree on which per-server header names match: a
        dashboard client sends ``x-mcp-{sanitize_mcp_alias_for_header(alias)}-authorization``,
        and matching only the raw alias here would 401 a token egress would forward.
        Fr   ©Ú!lookup_mcp_server_auth_in_headers©Úaliasrÿ   c              3   óf   K  — | ])  }t        |t        «      xr |j                  «       d k(  –— Œ+ y­w)ÚauthorizationN)rq   rr   rs   )Ú.0Úhks     rT   ú	<genexpr>z5_client_has_per_server_auth_header.<locals>.<genexpr>T  s+   è ø€ ÒfÐQS”z "¤cÓ*ÒL¨r¯x©x«z¸_Ñ/LÓLÑfùs   ‚/1)
rø  r  r  rÿ   rq   rr   r‡   Ústripr˜   Úany)r  rh  r  Úserver_headerss       rT   Ú"_client_has_per_server_auth_headerr"  :  sl   € ñ 'Øõ	
ñ !BØ#¨6¯<©<ÀV×EWÑEWô!
ˆô �n¤cÔ*Ü˜×,Ñ,Ó.Ó/Ð/Ü�n¤dÔ+ÜÑfÐWeÔfÓfÐfØrV   c                 óV   — |r|D ]  }|j                  «       dk(  sŒ y t        | |«      S )a«  True if the incoming request already carries an ``Authorization``
        header the gateway will forward to this pass-through server.

        The client may supply the bearer as either the top-level
        ``Authorization`` header (surfaced via ``oauth2_headers``) or a
        per-server ``x-mcp-auth-<alias>`` style header (surfaced via
        ``mcp_server_auth_headers``). Either form skips the pre-emptive 401.
        r  T)rs   r"  )r  ri  rh  Úks       rT   Ú%_client_has_passthrough_authorizationr%  W  s7   € ñ Ø#ò  �Ø—7‘7“9 Ó/Ùð ô 2°&Ð:QÓRÐRrV   Úprefetched_credsz-Mapping[str, "OAuthCredentialPayload"] | Nonec              ƒ   óª   K  — | j                   t        j                  k7  s|€yddlm}  |t        |dd«      | |«      ƒ d{  –—† }|rdd|› �iS dS 7 Œ­w)a  Stored OAuth2 token for (user, server) as an ``Authorization: Bearer`` header, or None.

        Thin wrapper over ``resolve_user_oauth_access_token`` (Redis cache, else DB + refresh);
        ``prefetched_creds`` skips the per-server Redis/DB lookups for the batch path.
        Nr   )Úresolve_user_oauth_access_tokenrO   ÚAuthorizationzBearer )Ú	auth_typer:   Úoauth2Ú)litellm.proxy._experimental.mcp_server.dbr(  r—   )r  re  r&  r(  r¢   s        rT   Ú%_get_user_oauth_extra_headers_from_dbr-  j  sk   è ø€ ð ×ÑœwŸ~™~Ò-Ð1BÐ1JØõ	
ñ =ÜÐ% y°$Ó7¸ÐAQó
÷ 
ˆñ 8=� 7¨5¨'Ð!2Ð3ÐFÀ$ÐFð
ús   ‚?AÁAÁArD   c              ƒ   ó  K  — | rt        | dd«      nd}|si S 	 ddlm} ddlm}  |d«      } |||«      ƒ d{  –—† }|D �ci c]  }d|v sŒ|d   |“Œ c}S 7 Œc c}w # t
        $ r#}t        j                  d||«       i cY d}~S d}~ww xY w­w)	zœFetch all OAuth2 credentials for the user in one DB query.

        Returns a dict keyed by server_id to avoid N+1 queries in asyncio.gather loops.
        rO   Nr   )Úlist_user_oauth_credentials)Úget_prisma_client_or_throwzCDatabase not connected. Connect a database to use OAuth2 MCP tools.rP   zB_prefetch_oauth_creds_for_user: failed to prefetch for user=%s: %s)r—   r,  r/  Úlitellm.proxy.utilsr0  rF  r   rŽ  )re  rO   r/  r0  Úprisma_clientÚcredsÚcrI  s           rT   Ú_prefetch_oauth_creds_for_userr5    s§   è ø€ ñ Uf¤WÐ->À	È4Ô%PÐkoˆÙØˆIð	õõ Gá#=ØUó$ˆMñ "=¸]ÈGÓ!T×TˆEØ/4ÖI¨!¸ÀqÒ8H�A�k‘N AÑ%ÒIÐIð UúÚIøÜò 	Ü×"Ñ"Ð#gÐipÐrsÔtØ�Iûð	üs\   ‚B™ A ¹AºA Á	AÁAÁA ÁBÁA ÁA Á	B
Á'BÁ?B
Â BÂB
Â
BÚscope_serversc                 óP  — d}|r%ddl m}  ||| j                  | j                  ¬«      }d}	| j                  }
|
xr t        | |«      }| j                  t        j                  k(  rD| j                  rd}	nH|r|j                  «       nd}	|	r2t        | ||¬«      r$t        |	t        «      }	n|
r|st        | |||¬«      }	| j                  rÀ|r¾|	€i }	|j!                  «       D ��ci c]0  \  }}t#        |t$        «      sŒt%        |«      j'                  «       |“Œ2 }}}t        | ||¬«      }| j                  D ]R  }t#        |t$        «      sŒ|j'                  «       dk(  r|s|rŒ,|j)                  |j'                  «       «      }|€ŒN||	|<   ŒT |	�t+        |	«      dk(  rd}	|€|}||	fS c c}}w )u  Build auth and extra headers for a server.

        ``scope_servers`` is the full server list a fan-out handler iterates. Passing it lets the
        client-forwarded token modes withhold the caller's request-wide ``Authorization`` when
        another server in the scope would also receive it (``_caller_authorization_fans_out``);
        explicitly-addressed operations leave it None. Per-server ``x-mcp-{alias}-authorization``
        headers are unaffected â€” they bind one token to one server and are the multi-server shape.
        Nr   r  r  )rò  rn   re  )rò  ri  rn   re  r  )rø  r  r  rÿ   Úis_client_forwarded_tokenrÓ   r*  r:   r+  Úhas_client_credentialsÚcopyrÖ   rã   râ   rÔ   Úextra_headersrp   rq   rr   rs   r™   rY   )r  rh  rf  ri  rn   re  r6  Úserver_auth_headerr  r;  Úis_client_forwarded_modeÚ withhold_forwarded_authorizationr$  ÚvÚnormalized_raw_headersÚstrip_caller_authorizationÚheaderÚheader_values                     rT   Ú_prepare_mcp_server_headersrD  ˜  sá  € ð" ;?ÐÙ"õñ "CØ'Ø—l‘lØ"×.Ñ.ô"Ðð 04ˆØ*0×*JÑ*JÐ ð 3Kò 3
ÔOmØ�MóP
Ð(ð ×ÑœwŸ~™~Ò-ð ×,Ò,Ø $‘ñ :H × 3Ñ 3Ô 5ÈT�ñ
 !Ô%GØ%Ø +Ø&7õ&ô
 %3°=ÔB[Ó$\‘MÙ%Ù3Ü GØ%Ø#1Ø +Ø&7ô	!�ð ×Ò¡KØÐ$Ø "�àKV×K\ÑK\ÓK^×,uÁ4À1ÀaÔblÐmnÔpsÕbt¬S°«V¯\©\«^¸QÑ->Ð,uÐ"Ñ,uô 1SØ!Ø'Ø"3ô1Ð&ð !×.Ñ.ò 
5�Ü! &¬#Ô.ØØ—<‘<“> _Ò4Ù.Ñ2RàØ5×9Ñ9¸&¿,¹,».ÓI�ØÐ'ØØ(4�˜fÒ%ð
5ð Ð$¬¨]Ó);¸qÒ)@Ø ˆMàÐ%Ø!0Ðà! =Ð0Ð0ùó? -vs   Ã!F"Ã:F"c                 ój  — | syg }| D ]ù  }|j                   xs, |j                  xs |j                  xs |j                  xs d}|j                  rF|j                  j                  «       r,|j                  ||j                  j                  «       f«       Œ�|j                  rŒœt        j                  j                  |j                  «      }|sŒÈ|j                  «       sŒÙ|j                  ||j                  «       f«       Œû |syt        |«      dk(  r|d   d   S dj                  d„ |D «       «      S )zhYAML/DB override, else upstream text (prefetch on init, or list_tools / health_check / call_tool cache).NÚmcpr{   r   z

---

c              3   ó2   K  — | ]  \  }}d |› d|› �–— Œ y­w)r€   z]
Nrî   )r  ÚlblÚtxts      rT   r  z9_merge_gateway_initialize_instructions.<locals>.<genexpr>  s!   è ø€ Ò!J¹¸¸S A c U¨#¨c¨UÔ"3Ñ!Jùs   ‚)r  rÿ   r  rP   rþ   r  r†   Ú	spec_pathr×   Ú._upstream_initialize_instructions_by_server_idr™   rY   r…   )ræ  Útextsr  ÚlabelÚcacheds        rT   Ú&_merge_gateway_initialize_instructionsrO     s  € ñ #Øà.0ˆØ)ò 		6ˆFØ—L‘LÒb F×$6Ñ$6Òb¸&¿+¹+ÒbÈ×IYÑIYÒbÐ]bˆEØ×"Ò" v×':Ñ':×'@Ñ'@Ô'BØ—‘˜e V×%8Ñ%8×%>Ñ%>Ó%@ÐAÔBØØ×ÒØÜ.×]Ñ]×aÑaÐbh×brÑbrÓsˆFÚ˜&Ÿ,™,�.Ø—‘˜e V§\¡\£^Ð4Õ5ð		6ñ ØÜˆu‹:˜Š?Ø˜‘8˜A‘;ÐØ×!Ñ!Ñ!JÀEÔ!JÓJÐJrV   Úscoped_server_endpointc                ó’  K  — t        | ||¬«      ƒ d {  –—† }|r@t        j                  |D �cg c]  }|�t        j                  |«      ‘Œ c}ddiŽƒ d {  –—†  t        |¬«      }d }|rIt        |«      dk(  r;|d   }|j                  xs( |j                  xs |j                  xs |j                  }t        j                  |«      }	t        j                  |«      }
	 d ­–— t        j                  |	«       t        j                  |
«       y 7 Œúc c}w 7 Œ¿# t        j                  |	«       t        j                  |
«       w xY w­w)N©re  rg  r”  Úreturn_exceptionsT)ræ  r{   r   )r  rD  Úgatherr×   Ú/_ensure_upstream_initialize_instructions_cachedrO  rY   r  rÿ   r  rP   r"   rn  r#   rv  )re  rg  r”  rP  Úallowedrí  r  r  Úscoped_serverÚinstructions_tokenÚserver_name_tokens              rT   Ú._gateway_initialize_instructions_request_scoperZ    sF  è ø€ ô  8Ø/Ø#Øô 
÷ 
ˆñ
 ô —.‘.ð %öàØ�}ô .×]Ñ]Ð^_Õ`òðð #'ñ÷ ð ô ?ÐSZÔ[ˆØ!ÐÙ!¤c¨'£l°aÒ&7Ø#*¨1¡:ˆMà×#Ñ#Òq }×'@Ñ'@ÒqÀM×DVÑDVÒqÐZg×ZqÑZqð ô %I×$LÑ$LÈVÓ$TÐÜ#;×#?Ñ#?Ð@RÓ#SÐð	>Üä0×6Ñ6Ð7IÔJÜ$×*Ñ*Ð+<Õ=ð=
úòðùô( 1×6Ñ6Ð7IÔJÜ$×*Ñ*Ð+<Õ=üsE   ‚E”D•E®DÁ
EÁDÁBEÃD Ã$,EÄEÄ,EÅEc                 ó    — t        | «      xs dS )an  The client-visible key for a server in listing outcomes and spend metadata: the same
        display prefix (alias, or the short prefix when that mode is enabled) the caller already
        sees on the tool names. Canonical internal server names never key a caller-readable
        surface; when the display naming deliberately hides them, the outcome keys must too.Úunknown)r0   ©r  s    rT   Ú_aggregate_server_keyr^  @  s   € ô
 ! Ó(Ò5¨IÐ5rV   rj  rk  rÁ  Úrequest_tagsc           	   ƒ   ó2	  ‡ ‡‡‡‡‡)‡*K  — t         st        g i ¬«      S t        j                  «       }d}i }|�rt	        «       }t        t        j                  «       «      }|xs t        ‰«      }ddi}t        |t
        «      r||d<   t        |t        «      r||d<   dt        j                  j                  |||t        ‰«      dœ|	rd	|	ini ¥d
d|dœdœgdœ}‰ �;t        j                   |‰ d¬«       t#        ‰ dd«      xs t#        ‰ dd«      }|r||d<   	 t%        d,d||dœ|¤Ž\  }}|r&t        j                  j                  |_        d|_        	 t1        ‰ ||
¬«      ƒ d{  –—† Š*t3        d„ ‰*D «       «      }|rt5        ‰ «      ƒ d{  –—† ni Š)dt6        ddfˆ)ˆ*ˆˆˆˆˆ fd„}‰*D �cg c]
  } ||«      ‘Œ }}t9        j:                  |Ž ƒ d{  –—† }|D ���cg c]  \  }}|D ]  }|‘Œ Œ }}}}t=        ‰*|«      D ���ci c]  \  }\  }}|�t?        |«      |“Œ }}}}|�r=t=        ‰*|«      D ���ci c]  \  }\  }}|�t?        |«      tA        |«      “Œ! } }}}|jB                  jE                  d«      }!t        |!tF        «      ry|!jE                  d«      }"t        |"tF        «      si }"|"|!d<   tA        ‰*«      |"d<   tA        |«      |"d<   | |"d<   |jI                  «       D �#�ci c]  \  }#}|#tK        |«      “Œ c}}#|"d <   t        j                  «       }$	 |jM                  |D �cg c]&  }t        |tN        «      r|jQ                  d!¬"«      n|‘Œ( c}||$¬#«      ƒ d{  –—†  t-        jT                  d%tA        |«      «       t        ||¬«      S # t*        $ r#}t-        j.                  d|«       d}Y d}~�Œbd}~ww xY w7 �ŒX7 �Œ4c c}w 7 �Œ÷c c}}}w c c}}}w c c}}}w c c}}#w c c}w 7 Œ�# t*        $ r }%t-        jR                  d$|%«       Y d}%~%Œ¯d}%~%ww xY w# t*        $ ru}&|rm‰ �k	 d&d'l+m,}' |'r=t[        j\                  t^        ¬(«      }(|'ja                  |xs i |&‰ d)|(¬*«      ƒ d{  –—†7   ‚ # t*        $ r t-        j.                  d+«       Y ‚ w xY w‚ d}&~&ww xY w­w)-ay  
        Helper method to fetch tools from MCP servers based on server filtering criteria.

        Args:
            user_api_key_auth: User authentication info for access control
            mcp_auth_header: Optional auth header for MCP server (deprecated)
            mcp_servers: Optional list of server names/aliases to filter by
            mcp_server_auth_headers: Optional dict of server-specific auth headers
            oauth2_headers: Optional dict of oauth2 headers

        Returns:
            AggregateToolListing: Combined tools from filtered servers plus each server's
            classified listing outcome
        ©rl  rx  NÚmcp_operationÚ
list_toolsÚsourceÚrequested_mcp_serverszMCP: list_tools)Úspend_logs_metadatarº   ÚtagsÚsystem)rb  re  )Úroleró   )ÚmodelÚ	call_typeÚlitellm_call_idrÁ  ÚmetadataÚinputrm  )rž  rŸ  Ú_metadata_variable_nameÚend_user_idrO   ÚuserÚlist_mcp_tools)Úoriginal_functionÚ	rules_objÚ
start_timez3Failed to initialize logging for MCP list_tools: %srR  c              3   óX   K  — | ]"  }t        |d d«      t        j                  k(  –— Œ$ y­w)r*  N)r—   r:   r+  )r  rí  s     rT   r  z._get_tools_from_mcp_servers.<locals>.<genexpr>²  s#   è ø€ Ò$rÐYZ¤W¨Q°¸TÓ%BÄgÇnÁnÕ%TÑ$rùs   ‚(*r  rQ   z#tuple[list[MCPTool], ServerOutcome]c           	   “   ó^  •K  — | €g t        d¬«      fS t        | ‰‰‰‰‰‰
¬«      \  }}ddlm}  || «      du}|sG| j                  t
        j                  k(  r*t        | dd«      r‰�t        | ‰‰	¬«      ƒ d{  –—† }|r:|}n7|s5|€3| j                  t
        j                  k(  rt        | ‰‰	¬«      ƒ d{  –—† }| j                  r3| j                  t
        j                  k7  r|€t        | ‰«      ƒ d{  –—† }	 t        j                  | ||d	‰‰‰¬
«      ƒ d{  –—† }t        || «      }t        || j                  ‰¬«      ƒ d{  –—† }t!        || «      }t#        j$                  dt'        |«      | j(                  t'        |«      «       |t        t'        |«      ¬«      fS 7 �Œ(7 Œî7 Œ±7 ŒŽ7 Œd# t*        $ r7}t#        j$                  d| j(                  «       g t-        |«      fcY d}~S d}~wt.        $ r8}t#        j0                  d| j(                  |«       g t-        |«      fcY d}~S d}~ww xY w­w)zêFetch and filter tools from a single server, classifying any failure into that
                server's outcome so the aggregate can keep serving the healthy subset without a
                broken server masquerading as an empty one.Nr   )Ú
tool_count©r  rh  rf  ri  rn   re  r6  )Úto_server_specÚneeds_user_oauth_tokenF)r&  T)r  rf  r;  Ú
add_prefixrn   re  ri  )rl  rP   re  z@Successfully fetched %s tools from server %s, %s after filteringz3MCP list_tools: omitting %s; it needs upstream authz&Error getting tools from server %s: %s)rÎ   rD  ÚClitellm.proxy._experimental.mcp_server.outbound_credentials.adapterrz  r*  r:   r+  r—   r-  Úis_byokÚ_get_byok_credentialr×   Ú_get_tools_from_serverrý  Ú$filter_tools_by_key_team_permissionsrP   r  r   rq  rY   r  r    rÐ   rF  rG  )r  r<  r;  rz  Úmigrated_to_v2Ú
db_headersrl  Úfiltered_toolsrI  Ú_prefetched_oauth_credsræ  rf  rh  ri  rn   re  s            €€€€€€€rT   Ú_fetch_and_filter_server_toolszC_get_tools_from_mcp_servers.<locals>._fetch_and_filter_server_tools·  sB  øè ø€ ð �>Øœ|°qÔ9Ð9Ð9ä4OØ!Ø,CØ$3Ø#1Ø +Ø&7Ø"5ô5Ñ1Ð" Mõñ )7°vÓ(>ÀdÐ(J�á&Ø×(Ñ(¬G¯N©NÒ:Ü Ð(@À%ÔHØ)Ð5ä.SØØ)Ø)@ô/÷ )�Jñ
 "Ø(2™ñ (¨MÐ,AÀf×FVÑFVÔZa×ZhÑZhÒFhÜ*OØØ)Ø)@ô+÷ %�Mð —>’> f×&6Ñ&6¼'¿.¹.Ò&HÐM_ÐMgÜ/CÀFÐL]Ó/^×)^Ð&ð(:Ü)B×)YÑ)YØ%Ø(:Ø&3Ø#'Ø$/Ø*;Ø'5ô*÷ $�Eô &CÀ5È&Ó%Q�Nä+OØ,Ø"(×"2Ñ"2Ø*;ô,÷ &�Nô &:¸.È&Ó%Q�Nä"×(Ñ(ØZÜ˜E›
ØŸ™Ü˜NÓ+ô	ð *¬<Ä3À~ÓCVÔ+WÐWÐWð_)ùð%øð *_øð$øð&ùô" ,ò :ô #×(Ñ(Ð)^Ð`f×`kÑ`kÔlØÔ6°qÓ9Ð9Õ9ûÜ ò :Ü"×,Ñ,Ð-UÐW]×WbÑWbÐdeÔfØÔ6°qÓ9Ð9Õ9ûð:üs£   ƒA5H-Á8F Á9;H-Â4F#Â5>H-Ã3F%Ã4H-Ã9F+ ÄF'Ä+F+ ÅF)ÅAF+ ÆH-Æ#H-Æ%H-Æ'F+ Æ)F+ Æ+	H*Æ4,G&Ç H*Ç!H-Ç&H*Ç2-H%ÈH*È H-È%H*È*H-rf  Úallowed_server_countÚtool_count_totalÚper_server_tool_countsÚper_server_list_outcomesÚjson)Úmode©Úresultru  Úend_timez6MCP list_tools success logging failed (continuing): %sz8Successfully fetched %s tools total from all MCP serversr   ©r™  ©Úlimitz/mcp/list_tools©Úrequest_dataÚoriginal_exceptionrŸ  ÚrouteÚtraceback_strz?Failed to log MCP list_tools failure via post_call_failure_hookrî   )1r^   rÍ   r   r0  r@   rr   ÚuuidÚuuid4r9   rq   r2  r>   rr  ru   r2   r8   Ú)add_user_api_key_auth_to_request_metadatar—   rB   rk  rj  rF  r   rq  r  r   r5  r=   rD  rT  Úzipr^  rY   Úmodel_call_detailsr™   r˜   rp   rÑ   Úasync_success_handlerÚMCPToolrñ   rŽ  rM  r¢  r™  Ú	tracebackÚ
format_excr   Úpost_call_failure_hook)+re  rf  rg  rh  ri  rn   rj  rk  rÁ  r_  r”  Úlist_tools_start_timer¸  Úlist_tools_request_datart  Úlist_tools_call_idÚeffective_litellm_trace_idrf  Úuser_identifierr¥  Úlogging_errorÚ_has_oauth2_serverr†  r  ÚtasksÚresultsrl  rü  Ú	all_toolsr~  Úserver_outcomesÚserver_toolsr‰  Úmetadata_dictÚ
spend_metart   r�  Úlog_excrI  r™  r—  r…  ræ  s+   `` ```                                   @@rT   Ú_get_tools_from_mcp_serversr±  G  s\  þè ø€ õ6 Ü'¨b¸2Ô>Ð>ä'/§|¡|£~ÐØ8<ÐØ57Ðâ&ä$›wˆIÜ(+¬D¯J©J«LÓ(9Ðà0@Ò0jÔD]Ð^iÓDjÐ&à ð=Ðô Ð/´Ô5Ø0EÐ# HÑ-Ü˜+¤tÔ,Ø?JÐ#Ð$;Ñ<ð +Ü&×5Ñ5×;Ñ;Ø#5Ø$>à+>Ü7¸ÓDññ 2>˜ Ñ-À2ðð !)à-9Ø5@ñ$ñðñ'Ð#ð. !Ð,Ü(×RÑRØ0Ø&7Ø,6õô *1Ð1BÀMÐSWÓ)Xò *Ô\cØ% y°$ó]�ñ #Ø6EÐ+¨FÑ3ð+Ü)7ð *Ø&6Ø'Ø4ñ*ð .ñ	*Ñ&Ð# Qñ 'Ü4=×4LÑ4L×4RÑ4RÐ'Ô1Ø0AÐ'Ô-ð
u	Ü/GØ"3Ø'Ø#ô0÷ *Ðô "%Ñ$rÐ^qÔ$rÓ!rÐáK]Ô4Ð5FÓG×GÐGÐceð $ð_:Ü!ð_:à6÷_:ó _:ðD ReÖeÀvÑ:¸6ÕBÐeˆEÐeÜ#*§>¡>°5Ð#9×9ˆGð EL×.^Ð.^¹¸¸qÐX]Ò.^ÐPTªtÐ.^¨tÐ.^ˆIÒ.^ô -0Ð0CÀWÓ,M÷@ð @á(�F™L˜Q ØÐ%ô & fÓ-¨wÑ6ð@ˆOò @ò #ô 69Ð9LÈgÓ5V÷Að Aá1˜Ñ 1 ¨qØÐ)ô *¨&Ó1´3°|Ó3DÑDðAÐ&ò Að (;×'MÑ'M×'QÑ'QÐR\Ó']�Ü˜m¬TÔ2Ø!.×!2Ñ!2Ð3HÓ!I�JÜ% j´$Ô7Ø%'˜
Ø?I˜Ð&;Ñ<Ü9<Ð=PÓ9Q�JÐ5Ñ6Ü58¸³^�JÐ1Ñ2Ø;Q�JÐ7Ñ8àM\×MbÑMbÓMd÷>Ù=I¸SÀ'˜Ô/°Ó8Ñ8ó>�JÐ9Ñ:ô #+§,¡,£.�ðØ-×CÑCàluö Ødh¼JÀtÌWÔ<U˜DŸO™O°˜OÔ8Ð[_Ñ_ò ð $9Ø!)ð Dó ÷ ð ô ×ÑÐ ZÔ\_Ð`iÓ\jÔkä'¨iÀ/ÔRÐRøôO ò +Ü×$Ñ$Ð%ZÐ\iÔjØ&*Ö#ûð+úð
*ùð HûòJ fØ9ûô /_ùô@ùôAùó>ùò ðùô !ò ô #×*Ñ*ØPØ÷ñ ûðûô ò 	á*Ð/@Ð/LðlÝLá(Ü/8×/CÑ/CÔJhÔ/i˜Ø/×FÑFØ)@Ò)FÀBØ/0Ø.?Ø"3Ø*7ð Gó ÷ ñ ð øô !ò lÜ"×(Ñ(Ð)jÕkØðlúàûð#	üs?  ‰DRÄ:N ÅP Å"N:Å#&P Æ	N=Æ
P Æ(O Æ7P ÇOÇ
P ÇOÇ,P È OÈP È2$OÉBP Ë!OË7P ÌO* Ì"+O#ÍO* ÍO(ÍO* Í+P Î
RÎ	N7ÎN2Î,RÎ2N7Î7RÎ:P Î=P Ï P ÏP Ï#O* Ï*	PÏ3PÐ	P ÐPÐP Ð	RÐRÐ$?Q*Ñ#Q&Ñ$Q*Ñ)RÑ*RÒRÒ
RÒRÒRÒRc           
   ƒ   óú  K  — t         sg S t        | |¬«      ƒ d{  –—† }g }|D ]x  }|€Œt        |||||| |¬«      \  }	}
	 t        j                  ||	|
d|¬«      ƒ d{  –—† }|j                  |«       t        j                  dt        |«      |j                  «       Œz t        j                  dt        |«      «       |S 7 Œ¤7 Œd# t        $ r+}t        j                  d|j                  |«       Y d}~ŒÏd}~ww xY w­w)	aB  
        Helper method to fetch prompt from MCP servers based on server filtering criteria.

        Args:
            user_api_key_auth: User authentication info for access control
            mcp_auth_header: Optional auth header for MCP server (deprecated)
            mcp_servers: Optional list of server names/aliases to filter by
            mcp_server_auth_headers: Optional dict of server-specific auth headers
            oauth2_headers: Optional dict of oauth2 headers

        Returns:
            List[Prompt]: Combined list of prompts from filtered servers
        ©re  rg  Nry  T©r  rf  r;  r|  rn   z.Successfully fetched %s prompts from server %sz(Error getting prompts from server %s: %sz:Successfully fetched %s prompts total from all MCP servers)r^   r  rD  r×   Úget_prompts_from_serverÚextendr   rq  rY   r  rF  rG  rM  )re  rf  rg  rh  ri  rn   ræ  Úall_promptsr  r<  r;  rÓ  rI  s                rT   Ú_get_prompts_from_mcp_serversr¸  `  s#  è ø€ õ* ØˆIä+CØ/Ø#ô,
÷ &
Ðð  ˆØ)ò 	eˆFØˆ~Øä0KØØ(?Ø /Ø-Ø'Ø"3Ø1ô1Ñ-Ð ðeÜ 9× QÑ QØ!Ø$6Ø"/Ø#Ø +ô!÷ �ð ×"Ñ" 7Ô+ä×$Ñ$Ð%UÔWZÐ[bÓWcÐek×epÑepÕqð3	eô< 	×ÑÐXÔZ]Ð^iÓZjÔkàÐðO&
øð,ùô ò eÜ×(Ñ(Ð)SÐU[×U`ÑU`Ðbc×dÑdûðeüóK   ‚C;›C œ#C;Á CÁCÁ?CÂ$C;ÃCÃ	C8Ã!C3Ã.C;Ã3C8Ã8C;c           
   ƒ   óú  K  — t         sg S t        | |¬«      ƒ d{  –—† }g }|D ]x  }|€Œt        |||||| |¬«      \  }	}
	 t        j                  ||	|
d|¬«      ƒ d{  –—† }|j                  |«       t        j                  dt        |«      |j                  «       Œz t        j                  dt        |«      «       |S 7 Œ¤7 Œd# t        $ r+}t        j                  d|j                  |«       Y d}~ŒÏd}~ww xY w­w)	z)Fetch resources from allowed MCP servers.r³  Nry  Tr´  z0Successfully fetched %s resources from server %sz*Error getting resources from server %s: %sz<Successfully fetched %s resources total from all MCP servers)r^   r  rD  r×   Úget_resources_from_serverr¶  r   rq  rY   r  rF  rG  rM  )re  rf  rg  rh  ri  rn   ræ  Úall_resourcesr  r<  r;  rÚ  rI  s                rT   Ú_get_resources_from_mcp_serversr½  ¡  s#  è ø€ õ ØˆIä+CØ/Ø#ô,
÷ &
Ðð
 02ˆØ)ò 	gˆFØˆ~Øä0KØØ(?Ø /Ø-Ø'Ø"3Ø1ô1Ñ-Ð ðgÜ";×"UÑ"UØ!Ø$6Ø"/Ø#Ø +ô#÷ �	ð ×$Ñ$ YÔ/ä×$Ñ$Ð%WÔY\Ð]fÓYgÐio×itÑitÕuð1	gô8 	×ÑÐZÔ\_Ð`mÓ\nÔoàÐðI&
øð*ùô ò gÜ×(Ñ(Ð)UÐW]×WbÑWbÐde×fÑfûðgür¹  c           
   ƒ   ó  K  — t         sg S t        | |¬«      ƒ d{  –—† }g }|D ]x  }|€Œt        |||||| |¬«      \  }	}
	 t        j                  ||	|
d|¬«      ƒ d{  –—† }|j                  |«       t        j                  dt        |«      |j                  «       Œz t        j                  dt        |«      «       |S 7 Œ¤7 Œd# t        $ r4}t        j                  d|j                  t        |«      «       Y d}~ŒØd}~ww xY w­w)	z2Fetch resource templates from allowed MCP servers.r³  Nry  Tr´  z9Successfully fetched %s resource templates from server %sz3Error getting resource templates from server %s: %szESuccessfully fetched %s resource templates total from all MCP servers)r^   r  rD  r×   Ú"get_resource_templates_from_serverr¶  r   rq  rY   r  rF  rG  rr   rM  )re  rf  rg  rh  ri  rn   ræ  Úall_resource_templatesr  r<  r;  rß  rI  s                rT   Ú(_get_resource_templates_from_mcp_serversrÁ  Ô  s.  è ø€ õ ØˆIä+CØ/Ø#ô,
÷ &
Ðð
 ACÐØ)ò !	ˆFØˆ~Øä0KØØ(?Ø /Ø-Ø'Ø"3Ø1ô1Ñ-Ð ðÜ+D×+gÑ+gØ!Ø$6Ø"/Ø#Ø +ô,÷ &Ð"ð '×-Ñ-Ð.@ÔAÜ×$Ñ$ØOÜÐ*Ó+Ø—K‘Kõð/!	ôF 	×ÑØSÜÐ&Ó'ô	
ð
 &Ð%ð]&
øð*&ùô ò Ü×(Ñ(ØIØ—K‘KÜ˜“F÷ñ ûðüsK   ‚D›C œ#DÁ CÁCÁ?CÂ$DÃCÃ	DÃ*C<Ã7DÃ<DÄDc           	   ƒ   óô   K  — t        j                  ||¬«      ƒ d{  –—† }t        j                  |«      }| D �cg c].  }t        j                  t        |j                  |«      |«      r|‘Œ0 c}S 7 ŒSc c}w ­w)zú
        Filter tools based on key/team mcp_tool_permissions.

        Note: Tool names in the DB are stored without server prefixes,
        but tool names from MCP servers are prefixed. We need to strip
        the prefix before comparing.
        )rP   re  N)r   Úget_allowed_tools_for_serverr×   r  Útool_is_grantedrá   r  )rl  rP   re  Úallowed_tool_namesr  Úts         rT   r�  r�  	  s{   è ø€ ô +<×*XÑ*XØØ/ô+
÷ %
Ðô 2×FÑFÀyÓQˆð ö
àÜ ×0Ñ0Ô1JÈ1Ï6É6ÐSYÓ1ZÐ\nÔoò ò
ð 	
ð%
úò
ùs    ‚A8�A1žA8»3A3Á.A8Á3A8c	              ƒ   ó6  K  — t         st        g i ¬«      S 	 t        | ||||||||¬«	      ƒ d{  –—† }	t        j                  dt        |	j                  «      «       |	S 7 Œ/# t        $ r-}
t        j                  d|
«       t        g i ¬«      cY d}
~
S d}
~
ww xY w­w)an  
        List all available MCP tools.

        Args:
            user_api_key_auth: User authentication info for access control
            mcp_auth_header: Optional auth header for MCP server (deprecated)
            mcp_servers: Optional list of server names/aliases to filter by
            mcp_server_auth_headers: Optional dict of server-specific auth headers {server_alias: auth_value}
            client_ip: Client IP for IP-based server access control

        Returns:
            AggregateToolListing: Combined tools from all accessible servers plus each server's
            classified listing outcome
        ra  )	re  rf  rg  rh  ri  rn   rj  rk  r”  Nz6Successfully fetched %s tools from managed MCP serversú0Error getting tools from managed MCP servers: %s)	r^   rÍ   r±  r   rq  rY   rl  rF  rG  )re  rf  rg  rh  ri  rn   rj  rk  r”  r}  rI  s              rT   rw  rw  -	  s¡   è ø€ õ2 Ü'¨b¸2Ô>Ð>ð	?Ü#>Ø"3Ø /Ø'Ø(?Ø-Ø'Ø,GØ&;Ø#ô
$÷ 
ˆGô × Ñ Ð!YÔ[^Ð_f×_lÑ_lÓ[mÔnØˆNð
ùô ò 	?Ü×$Ñ$Ð%WÐYZÔ[ä'¨b¸2Ô>Õ>ûð	?üsD   ‚B—A  ®A¯.A  ÁBÁA  Á 	BÁ)"BÂBÂBÂBÂBc              ƒ   óò   K  — t         sg S g }	 t        | |||||¬«      ƒ d{  –—† }t        j                  dt	        |«      «       |S 7 Œ%# t
        $ r!}t        j                  d|«       Y d}~|S d}~ww xY w­w)aò  
        List all available MCP prompts.

        Args:
            user_api_key_auth: User authentication info for access control
            mcp_auth_header: Optional auth header for MCP server (deprecated)
            mcp_servers: Optional list of server names/aliases to filter by
            mcp_server_auth_headers: Optional dict of server-specific auth headers {server_alias: auth_value}

        Returns:
            List[Prompt]: Combined list of tools from all accessible servers
        rÑ  Nz8Successfully fetched %s prompts from managed MCP serversrÈ  )r^   r¸  r   rq  rY   rF  rG  )re  rf  rg  rh  ri  rn   Úmanaged_promptsrI  s           rT   rÒ  rÒ  \	  s“   è ø€ õ( ØˆIàˆð	\Ü$AØ"3Ø /Ø'Ø(?Ø-Ø'ô%÷ ˆOô × Ñ Ð![Ô]`ÐapÓ]qÔrð
 Ððùô ò 	\Ü×$Ñ$Ð%WÐYZ×[Ð[ð Ðûð		\üó>   ‚A7ŽA
 ¢A£#A
 ÁA7ÁA
 Á
	A4ÁA/Á)A7Á/A4Á4A7c              ƒ   óò   K  — t         sg S g }	 t        | |||||¬«      ƒ d{  –—† }t        j                  dt	        |«      «       |S 7 Œ%# t
        $ r!}t        j                  d|«       Y d}~|S d}~ww xY w­w)z!List all available MCP resources.rÑ  Nz:Successfully fetched %s resources from managed MCP serversz4Error getting resources from managed MCP servers: %s)r^   r½  r   rq  rY   rF  rG  )re  rf  rg  rh  ri  rn   Úmanaged_resourcesrI  s           rT   rÙ  rÙ  „	  s“   è ø€ õ ØˆIà,.Ðð	`Ü&EØ"3Ø /Ø'Ø(?Ø-Ø'ô'÷ !Ðô × Ñ Ð!]Ô_bÐctÓ_uÔvð !Ð ð!ùô ò 	`Ü×$Ñ$Ð%[Ð]^×_Ð_à Ð ûð	`ürË  c              ƒ   ó  K  — t         sg S g }	 t        | |||||¬«      ƒ d{  –—† }t        j                  dt	        |«      «       |S 7 Œ%# t
        $ r*}t        j                  dt        |«      «       Y d}~|S d}~ww xY w­w)z*List all available MCP resource templates.rÑ  NzCSuccessfully fetched %s resource templates from managed MCP serversz=Error getting resource templates from managed MCP servers: %s)r^   rÁ  r   rq  rY   rF  rG  rr   )re  rf  rg  rh  ri  rn   Úmanaged_resource_templatesrI  s           rT   rÞ  rÞ  ¡	  sœ   è ø€ õ ØˆIà=?Ð"ð	Ü/WØ"3Ø /Ø'Ø(?Ø-Ø'ô0÷ *Ð&ô × Ñ ØUÜÐ.Ó/ôð *Ð)ð%*ùô ò 	Ü×$Ñ$ØOÜ�A“÷ð ð
 *Ð)ûð	üs>   ‚B ŽA
 ¢A£#A
 ÁB ÁA
 Á
	A=ÁA8Á2B Á8A=Á=B c                 ó    — |D ]H  }|j                   xs i }|j                  «       D ]#  \  }}|| k(  sŒt        |t        |«      «      c c S  ŒJ | S )a|  Translate a display-name override back to the original prefixed tool name.

        When a client received a customised display name from tools/list (e.g.
        "Get Pet") it will call tools/call with that same string.  We need to
        reverse-map it to the original prefixed name (e.g.
        "petstore_mcp-getPetById") before any routing or permission logic runs.
        )rÿ  rp   r-   r0   )r  ræ  r  Údisplay_mapÚunprefixed_nameÚdisplay_names         rT   Ú!_resolve_display_name_to_originalrÔ  Ä	  sg   € ð *ò 	aˆFØ ×:Ñ:Ò@¸bˆKØ1<×1BÑ1BÓ1Dò aÑ-� Ø 4Ó'Ü4°_ÔFWÐX^ÓF_Ó`Ô`ñað	að
 ˆrV   c              ƒ   ót  K  — | j                   sy|r|j                  ndxs d}|sy|| j                  f}t        j	                  |«      }|�%|\  }}t        j                  «       |z
  t        k  r|S ddlm	} ddl
m} |€y |||| j                  ¬«      ƒ d{  –—† }t        || j                  |«       |S 7 Œ­w)z¹Retrieve the stored BYOK credential for a user+server pair.

        Uses the shared _byok_cred_cache to avoid a DB round-trip on every
        tool call within the TTL window.
        Nr|   r   ©Úget_user_credential©r2  ©r2  rO   rP   )r~  rO   rP   rE   r™   r[   r\   rG   r,  r×  r¢  r2  r]   )	rò  re  rO   Ú	cache_keyrN  rW   Útsr×  r2  s	            rT   r  r  Ö	  sÆ   è ø€ ð ×!Ò!ØÙ7HÐ+×3Ò3ÈdÒYÐWYˆÙØà# Z×%9Ñ%9Ð:ˆ	Ü(×,Ñ,¨YÓ7ˆØÐØ#‰NˆJ˜Ü�~‰~Ó "Ñ$Ô';Ò;Ø!Ð!åQÝ<àÐ ØÙ.Ø'ØØ ×*Ñ*ô
÷ 
ˆ
ô
 	˜w¨
×(<Ñ(<¸jÔIØÐð
ús   ‚BB8ÂB6ÂB8c              ƒ   ó&  K  — | j                   sy|r|j                  ndxs d}|s7t        dd| j                  | j                  xs | j
                  ddœddi¬	«      ‚|| j                  f}t        j                  |«      }|�]|\  }}t        j                  «       |z
  t        k  r:|€7t        dd| j                  | j                  xs | j
                  d
dœddi¬	«      ‚yddlm} ddlm} |€4t        dd| j                  | j                  xs | j
                  ddœ¬«      ‚ |||| j                  ¬«      ƒ d{  –—† }	t        || j                  |	«       |	€7t        dd| j                  | j                  xs | j
                  d
dœddi¬	«      ‚y7 ŒU­w)a6  
        If the MCP server is BYOK-enabled, verify that the requesting user has a
        stored credential.  When no credential is found, raise an HTTP 401 with a
        WWW-Authenticate header that points the MCP client to our OAuth metadata
        endpoint so it can drive the authorization flow.
        Nr|   é‘  Úbyok_auth_requiredz*User identity is required for BYOK servers©rˆ  rP   rÿ   r¿   úWWW-Authenticateú@Bearer resource_metadata="/.well-known/oauth-protected-resource"r·   úoNo stored credential found for this BYOK server. Complete the OAuth authorization flow to provide your API key.r   rÖ  rØ  é÷  Úbyok_auth_unavailablez5BYOK credential check requires a database connection.©r¸   r¹   rÙ  )r~  rO   r   rP   rÿ   r  rE   r™   r[   r\   rG   r,  r×  r¢  r2  r]   )
rò  re  rO   rÚ  rN  Úcached_credrÛ  r×  r2  rW   s
             rT   Ú_check_byok_credentialrç  ù	  sÑ  è ø€ ð ×!Ò!Øá7HÐ+×3Ò3ÈdÒYÐWYˆÙÜØà1Ø!+×!5Ñ!5Ø#-×#9Ñ#9Ò#L¸Z¿_¹_ØKñ	ð ,Ð-oÐpô	ð 	ð $ Z×%9Ñ%9Ð:ˆ	Ü(×,Ñ,¨YÓ7ˆØÐØ$‰OˆK˜Ü�~‰~Ó "Ñ$Ô';Ò;ØÐ&Ü'Ø$'à%9Ø)3×)=Ñ)=Ø+5×+AÑ+AÒ+TÀZÇ_Á_ð!añ ð /Ð0rð!ôð ð åQÝ<àÐ ô  Øà4Ø!+×!5Ñ!5Ø#-×#9Ñ#9Ò#L¸Z¿_¹_ØVñ	ôð ñ #6Ø'ØØ ×*Ñ*ô#
÷ 
ˆ
ô
 	˜w¨
×(<Ñ(<¸jÔIØÐÜØà1Ø!+×!5Ñ!5Ø#-×#9Ñ#9Ò#L¸Z¿_¹_ðYñð ,Ð-oÐpôð ð ð
ús   ‚D7FÄ9FÄ:AFru  rÃ  Úkwargsc
              ‹   ó
  ‡$‡%K  — d}|
j                  d«      Š$t        | |«      } t        | «      \  }Š%d}‰$rt        ˆ$fd„|D «       d«      }d}|�pt        | v rht        «       }t        j                  «       j                  «       D ],  }t        |«      D ]  }|j                  t        |«      «       Œ Œ. t        | |¬«      }|�|s|}|j                  Š%| }nÏt        j                  | «      }|€7|�5t        |«      D ]'  }t        j                  t        | |«      «      }|€Œ%|} n |�|j                  Š%t!        | |«      }|�e|�G|j"                  |j"                  k7  r.t%        ddd| › d	|j                  › d
|j                  › d�dœ¬«      ‚|€|}|j                  Š%t!        | |«      }‰%r<t'        j(                  |D �cg c]  }|j                  ‘Œ c}‰%¬«      st%        dd¬«      ‚t+        ||‰%t-        |«      ¬«      }|
j                  dd«      }|r+||j.                  d<   d| › �|_        d| › �|j.                  d<   |€t        j                  | «      }|r±|j2                  xs i j                  d«      |d<   |r||j.                  d<   |j4                  rR|sPt7        ||«      ƒ d{  –—† }|€7t%        dd|j"                  |j8                  xs |j                  ddœddi¬«      ‚|}n |j4                  rt;        ||«      ƒ d{  –—†  t=        j>                  | «      }|�rM|€t%        dd| › d�¬«      ‚d d!l m!} t        jD                  ||xs i ‰%xs |j                  |||||¬"«      ƒ d{  –—† }tG        |tH        «      r	d#|v r|d#   }tK        jL                  d$| «       tO        |||||¬%«      \  }}}t        jP                  ||||||¬&«      ƒ d{  –—† \  }}tS        j
                  |«      }tU        j
                  |«      } tW        j
                  |«      }!	 tY        | |«      ƒ d{  –—† }"tS        jZ                  |«       tU        jZ                  | «       tW        jZ                  |!«       n¥|rt]        ‰%|||||||||	¬'«
      ƒ d{  –—† }"n…t=        j>                  |«      �\t        ˆ%fd(„|D «       d«      }#|#€t%        dd|› d�¬«      ‚d d!l m!} t        jD                  ||‰%|||#||¬"«      ƒ d{  –—† }d#|v r|d#   }tY        ||«      ƒ d{  –—† }"t_        |"|||
¬)«      ƒ d{  –—† S c c}w 7 �Œ‡7 �Œ.7 �ŒÉ7 �Œf7 �Œ# tS        jZ                  |«       tU        jZ                  | «       tW        jZ                  |!«       w xY w7 Œù7 Œ’7 Œw7 Œb­w)*a  
        Execute MCP tool.

        This function assumes permission checks have already been performed.

        Args:
            name: Tool name (may include server prefix)
            arguments: Tool arguments
            allowed_mcp_servers: Pre-validated list of servers the user can access
            start_time: Start time for logging
            user_api_key_auth: Optional user API key auth for logging
            mcp_auth_header: Optional MCP auth header
            mcp_server_auth_headers: Optional server-specific auth headers
            oauth2_headers: Optional OAuth2 headers
            raw_headers: Optional raw HTTP headers
            **kwargs: Additional arguments (e.g., litellm_logging_obj)

        Returns:
            CallToolResult: Tool execution result
        NÚrequested_server_idc              3   óB   •K  — | ]  }|j                   ‰k(  sŒ|–— Œ y ­wr  ©rP   )r  rí  rê  s     €rT   r  z#execute_mcp_tool.<locals>.<genexpr>€
  s   øè ø€ ÒV�q°1·;±;ÐBUÓ3U”ÑVùó   ƒ˜F)Úknown_server_prefixesé“  Útool_server_mismatchúTool 'z' belongs to MCP server 'z'' but request specified server_id for 'ú'.)rˆ  r¿   rå  )ræ  rÿ   ú#User not allowed to call this tool.)r  r“  rÿ   r"  r¸  Úmcp_tool_call_metadatazMCP: rj  Úmcp_server_cost_inforÝ  rÞ  râ  rß  rà  rá  r·   rã  zMCP server for tool 'zk' is not available; refusing to dispatch without authorization checks. Retry once the server is registered.r   r�  )r  r“  rÿ   re  r™  r  rn   r¸  r“  z!Executing local registry tool: %s)rò  rf  rh  rn   re  )rò  ri  rn   rf  re  Úforwarded_headers)
rÿ   r  r“  re  rf  rh  ri  rn   r¸  rÃ  c              3   óB   •K  — | ]  }|j                   ‰k(  sŒ|–— Œ y ­wr  ©r  )r  Ú	candidaterÿ   s     €rT   r  z#execute_mcp_tool.<locals>.<genexpr>g  s   øè ø€ Òe 9ÀyÇ~Á~ÐYdÓGd”YÑeùrí  )rŽ  r¸  re  r”  )0r™   rÔ  rà   ÚnextrÝ   rn  r×   Úget_registryré  r1   Úaddrß   rÞ   r  Ú_get_mcp_server_from_tool_namer-   rá   rP   r   r   Úis_tool_allowedÚ#_get_standard_logging_mcp_tool_callrv   rœ  rj  ræ   r~  r  rÿ   rç  rÜ   Úget_toolr¢  r™  Úpre_call_tool_checkrq   r˜   r   rq  rÕ   Úresolve_openapi_upstream_authrØ   rÙ   rÚ   Ú_handle_local_mcp_toolrv  Ú_handle_managed_mcp_toolÚ_run_post_mcp_call_guardrails)&r  r“  ræ  ru  re  rf  rh  ri  rn   rÃ  rè  rò  Úoriginal_tool_nameÚrequested_serverÚname_is_prefixedÚall_registry_prefixesÚregistry_serverÚknown_prefixrù  r  Ústandard_logging_mcp_tool_callr¸  Ú	byok_credÚ
local_toolr™  Úhook_resultÚauth_header_valueÚopenapi_forwarded_headersÚupstream_credentialÚresolved_auth_headersrö  Ú_auth_tokenÚ_extra_tokenÚ_resolved_tokenrÎ  Úprefix_serverrê  rÿ   s&                                       @@rT   Úexecute_mcp_toolr  Q
  s…  ùè ø€ ðD (,ˆ
Ø17·±Ð<QÓ1RÐô 1°Ð7JÓKˆô +HÈÓ*MÑ'Ð˜Kà-1ÐÙÜ#ÛVÐ/ÔVØó Ðð
 !ÐØÐ'Ô,EÈÑ,MÜ58³UÐ!Ü#<×#IÑ#IÓ#K×#RÑ#RÓ#Tò S�Ü$>¸Ó$Oò S�LØ)×-Ñ-Ô.CÀLÓ.QÕRñSðSô  5°TÐQfÔgÐàÐ'Ñ0@ð *ˆJØ*×/Ñ/ˆKØ!%Ñô 3×QÑQÐRVÓWˆJØÐ!Ð&6Ð&BÜ$>Ð?OÓ$Pò �LÜ 9× XÑ XÜ1°$¸ÓEó!�Ið !Ñ,Ø%.˜
Ùðð Ð%Ø(Ÿo™o�Ü%>¸tÀZÓ%PÐ"àÐ+ØÐ)¨j×.BÑ.BÐFV×F`ÑF`Ò.`Ü'Ø$'à%;à"(¨¨ð /$Ø$.§O¡OÐ#4ð 52Ø2B×2GÑ2GÐ1HÈð!Lñ ô
ð 
ð Ð%Ø!1�JØ"2×"7Ñ"7�KÜ)BÀ4ÐIYÓ)ZÐ&ñ Ü$×4Ñ4Ø?RÖ$S°V V§[£[Ò$SØ'õô $Ø #Ø@ôð ô
 MpØ#ØØ#Ü3°KÓ@ô	M
Ð&ð @F¿z¹zÐJ_ÐaeÓ?fÐÙØOmÐ×2Ñ2Ð3KÑLØ*/°¨v¨ÐÔ%Ø@EÀdÀV¸nÐ×2Ñ2°7Ñ;ð ÐÜ2×QÑQÐRVÓWˆJáØFP×FYÑFYÒF_Ð]_×EdÑEdØ&óFÐ*Ð+AÑBñ #ØSqÐ#×6Ñ6Ð7OÑPð ×!Ò!©/Ü)=¸jÐJ[Ó)\×#\�	ØÐ$Ü'Ø$'à%9Ø)3×)=Ñ)=Ø+5×+AÑ+AÒ+TÀZÇ_Á_ð!añ ð /Ð0rð!ôð ð #,‘Ø×#Ò#ä,¨ZÐ9JÓK×KÐKô
 5×=Ñ=¸dÓCˆ
Úð Ð!Ü#Ø #à/°¨vð 6?ð ?ôð õ Eä 9× MÑ MØ'Ø#š/ rØ'Ò:¨:¯?©?Ø"3Ø"3Ø!Ø'Ø$7ô	!÷ 	ˆKô ˜+¤tÔ,°ÀÑ1KØ'¨Ñ4�	ä× Ñ Ð!DÀdÔKô QkØ%Ø /Ø(?Ø'Ø"3ôQÑMÐÐ8Ð:Mô 0×MÑMØ%Ø-Ø'Ø 3Ø"3Ø";ô÷ ñØ%Ø!ô "6×!9Ñ!9Ð:KÓ!LˆKÜ"8×"<Ñ"<Ð=NÓ"OˆLÜ%C×%GÑ%GÐH]Ó%^ˆOðFÜ!7¸¸iÓ!H×H�ä$×*Ñ*¨;Ô7Ü&×,Ñ,¨\Ô:Ü.×4Ñ4°_ÕEñ Ü5Ø'Ø'Ø#Ø"3Ø /Ø(?Ø-Ø'Ø$7Ø'=ô÷ ‰Hô, (×0Ñ0Ð1CÓDÐPô (,ÛeÐ0CÔeØó(�ð !Ð(ô (Ø$'à3Ð4FÐ3Gð HCð Côð õ Iä$=×$QÑ$QØ+Ø'Ø +Ø&7Ø&7Ø(Ø +Ø(;ô	%÷ 	�ð  +Ñ-Ø +¨KÑ 8�Iä3Ð4FÈ	ÓR×RˆHä2ØØ 3Ø/Øô	
÷ 
ð 	
ùòc %TðD $]ùð( LùðD	ùð8ùð Iúä$×*Ñ*¨;Ô7Ü&×,Ñ,¨\Ô:Ü.×4Ñ4°_ÕEúðøðl	øð Søð
úsÏ   „DVÄBVÆ8T#ÇCVÊ!T(Ê"AVË=T+Ë>A'VÍ%T.Í&A%VÏT1ÏAVÐT7 Ð"T4Ð#T7 Ð'AVÒU;ÒA(VÓ*U=Ó+VÔU?ÔVÔVÔ
VÔ+VÔ.VÔ1VÔ4T7 Ô7AU8Õ8VÕ=VÕ?VÖVrŽ  r¸  r”  c              ƒ   óˆ   K  — ddl m} |€| S |j                  | |�|j                  n
t	        |«      |¬«      ƒ d{  –—† S 7 Œ­w)aË  Run ``post_mcp_call`` guardrails over an executed tool result.

        Lives on ``execute_mcp_tool``'s return path rather than inside
        ``_fire_mcp_tool_call_logging`` so enforcement never depends on logging
        being configured, and so every dispatch route gets it: the MCP protocol
        handler, the REST endpoint, and tool search all funnel through here.
        A guardrail that rejects the result raises, matching ``pre_mcp_call``.
        r   r�  N)rÎ  r”  rŸ  )r¢  r™  Úpost_mcp_call_hookrœ  r˜   )rŽ  r¸  re  r”  r™  s        rT   r  r  ‘  sW   è ø€ õ 	AàÐ$ØˆMØ&×9Ñ9Øà:MÐ:YÐ#×6Ò6Ô_cÐdpÓ_qà/ð :ó 
÷ 
ð 	
ð 
ús   ‚9A»A ¼A>   rn   ri  rf  re  rh  Ú_MCP_CREDENTIAL_REQUEST_FIELDSÚlogging_objr�  c              ƒ   ó¢  K  — ddl m} | j                  |¬«       | j                  | j                  |||¬«      ƒ d{  –—†  t
        j                  j                  | _        t        |«      }|€| j                  |||¬«      ƒ d{  –—†  |S | j                  d¬«       | j                  d	¬«       t        |«      }| j                  |d
||«       | j                  |d
||«      ƒ d{  –—†  |€|S |rM|xs i j                  «       D �	�
ci c]  \  }	}
|	t         vsŒ|	|
“Œ }}	}
|j#                  |||d¬«      ƒ d{  –—†  |S 7 �Œ7 Œ½7 Œ^c c}
}	w 7 Œ­w)a  Fire post-call logging for an executed MCP tool call, returning the result to send.

        The returned result is what the caller must forward to the client: a
        ``post_mcp_call`` guardrail may rewrite the tool output (e.g. mask
        sensitive values) or reject it, in which case its exception propagates.
        Guardrails run before the success/failure logging so the masked text, not
        the raw one, is what gets logged.

        A result with ``isError=True`` is logged as a failure (``status="failure"``
        payload, so OTel marks the span ERROR) while the HTTP wire behavior stays
        200 + ``isError: true`` per the MCP spec. The error check runs after
        ``async_post_mcp_tool_call_hook`` because guardrails may flip the result
        to ``isError=True`` in that hook. Raised exceptions never reach here (the
        ``@client`` wrapper and ``call_mcp_tool``'s except path log those), so
        this cannot double-log a failure.

        ``request_data`` may carry credential-bearing fields (the REST path puts
        ``raw_headers``, ``mcp_auth_header``, ``mcp_server_auth_headers``, and
        ``oauth2_headers`` at the top level of its data dict), so those are
        stripped before the dict is handed to ``post_call_failure_hook``
        callbacks.
        r   r�  )Úoriginal_response)rè  Úresponse_objru  r�  Nr�  Úsync_success)Ú
event_typeÚasync_successr|   ú/mcp/call_tool)r”  r•  rŸ  r–  )r¢  r™  Ú	post_callÚasync_post_mcp_tool_call_hookrœ  r>   r¤  ru   rk  r/   r�  Úhas_run_loggingr   Úfailure_handlerÚasync_failure_handlerrp   r  r¡  )r  rŽ  ru  r�  re  r”  r™  Úerror_messageÚ
tool_errorrt   ru   Úsanitized_request_datas               rT   Ú_fire_mcp_tool_call_loggingr,  µ  sƒ  è ø€ õ< 	Aà×Ñ°ÐÔ7Ø×7Ñ7Ø×1Ñ1ØØ!Øð	 8ó 
÷ 	
ð 	
ô !*× 7Ñ 7× =Ñ =ˆÔÜDÀVÓLˆØÐ Ø×3Ñ3¸6ÈjÐckÐ3Ól×lÐlØˆMà×#Ñ#¨~Ð#Ô>Ø×#Ñ#¨Ð#Ô?Ü.¨}Ó=ˆ
Ø×#Ñ# J°°JÀÔIØ×/Ñ/°
¸BÀ
ÈHÓU×UÐUàÐ$ØˆMáà.:Ò.@¸b×-GÑ-GÓ-I÷-Ù)˜s EÈSÔXvÒMv��U‘
ð-Ð"ñ -ð $×:Ñ:Ø3Ø#-Ø"3Ø&ð	 ;ó ÷ ð ð ˆð?	
ùð møð 	Vúó-ðúsY   ‚;E½E ¾AEÂEÂA EÃ&EÃ'!EÄEÄEÄEÄ9EÄ:EÅEÅEÅEc              ‹   óz  K  — t        j                  «       }	|j                  dd«      }
	 |€t        dd¬«      ‚t	        j
                  |¬«      ƒ d{  –—† }g }|D ]@  }t	        j                  |«      }|€Œt        j                  |«      }|j                  |«       ŒB t        ||¬«      ƒ d{  –—† }|st        dd	¬«      ‚t        d| |||	|||||d
œ	|¤Žƒ d{  –—† }|
r+t-        |
||	t        j                  «       ||¬«      ƒ d{  –—† }|S 7 Œ»7 Œa7 Œ7# t        $ r ‚ t        $ r�}t        j                  t         ¬«      }ddlm} |
�Et        j                  «       }|
j'                  |||	|«       |
j)                  |||	|«      ƒ d{  –—†7   |r!|r|j+                  |||d|¬«      ƒ d{  –—†7   ‚ d}~ww xY w7 Œ±­w)za
        Call a specific tool with the provided arguments (handles prefixed tool names).
        r¸  Né�  zRequest arguments are requiredrå  )re  r  rï  ró  )	r  r“  ræ  ru  re  rf  rh  ri  rn   r‘  r   r�  r#  r“  )r  rŽ  ru  r�  re  r”  rî   )r   r0  r™   r   r×   r  r  rÒ   r  r†   rð  r  r    rF  rŸ  r   r   r¢  r™  r'  r(  r¡  r,  )r  r“  re  rf  rg  rh  ri  rn   rè  ru  r¸  r  ræ  r  Úallowed_serverrÎ  rI  r—  r™  r�  s                       rT   r¤  r¤  ÷  s  è ø€ ô %ŸL™L›Nˆ
Ø?E¿z¹zÐJ_ÐaeÓ?fÐðK	ØÐ Ü#°Ð<\Ô]Ð]ô 3L×2cÑ2cØ"3ô3÷ -Ð"ð 46ÐØ)?ò ?Ð%Ü!:×!OÑ!OÐPeÓ!f�Ø!Ñ-ô &6×%UÑ%UÐVdÓ%e�NØ'×.Ñ.¨~Õ>ð?ô )WØ'Ø$7ô)÷ #Ðñ 'Ü#Ø #Ø@ôð ô .ð ØØ#Ø$7Ø%Ø"3Ø /Ø(?Ø-Ø'ñð ñ÷ ˆHñ` Ü8Ø/ØØ%Ü!Ÿ™›Ø"3Ø#ô÷ ˆHð ˆðc-øð#øðùô $ò 	ð Üò 	Ü#,×#7Ñ#7Ô>\Ô#]ˆMÝDð #Ð.Ü"*§,¡,£.�Ø#×3Ñ3°A°}ÀjÐRZÔ[Ø)×?Ñ?ÀÀ=ÐR\Ð^fÓg×gÑgá Ñ%6Ø'×>Ñ>Ø!'Ø'(Ø&7Ø*Ø"/ð ?ó ÷ ñ ð ûð5	úð:ús‰   ‚'F;ª(D ÁDÁ"D Á68D Â.DÂ/+D ÃDÃD Ã(F;ÄF9ÄF;ÄD ÄD ÄD ÄF6Ä&A!F1ÆF
Æ"F1Æ*F-Æ+F1Æ1F6Æ6F;c              ƒ   ó.  ‡K  — t        ||¬«      ƒ d{  –—† }|st        dd¬«      ‚t        | «      \  }	Št        ˆfd„|D «       d«      }
|
€t        dd¬«      ‚t	        |
|||||¬«      \  }}t        j                  |
|	||||¬«      ƒ d{  –—† S 7 Œ|7 Œ­w)	z[
        Fetch a specific MCP prompt, handling both prefixed and unprefixed names.
        r³  Nrï  z$User not allowed to get this prompt.rå  c              3   óB   •K  — | ]  }|j                   ‰k(  sŒ|–— Œ y ­wr  rø  )r  rí  rÿ   s     €rT   r  z!mcp_get_prompt.<locals>.<genexpr>|  s   øè ø€ ÒV AÀÇÁÈ+Ó@UœaÑVùrí  ©r  rh  rf  ri  rn   re  )r  Úprompt_namer“  rf  r;  rn   )r  r   rà   rú  rD  r×   Úget_prompt_from_server)r  r“  re  rf  rg  rh  ri  rn   ræ  Úoriginal_prompt_namer  r<  r;  rÿ   s                @rT   rÖ  rÖ  a  sÓ   øè ø€ ô ,DØ/Ø#ô,
÷ &
Ðñ
 #ÜØØ=ôð ô -JÈ$Ó,OÑ)Ð˜käÓVÐ)<ÔVÐX\Ó]ˆØˆ>ÜØØ=ôð ô
 -HØØ$;Ø+Ø)Ø#Ø/ô-
Ñ)Ð˜Mô /×EÑEØØ,ØØ.Ø'Ø#ô
÷ 
ð 	
ð=&
øð<
ús"   ƒB”B•A7BÂBÂBÂBc              ƒ   ó  K  — t        ||¬«      ƒ d{  –—† }|st        dd¬«      ‚t        |«      dk7  rt        dd¬«      ‚|d	   }t        ||||||¬
«      \  }	}
t	        j
                  || |	|
|¬«      ƒ d{  –—† S 7 Œi7 Œ­w)z1Read resource contents from upstream MCP servers.r³  Nrï  z'User not allowed to read this resource.rå  r{   r.  z]Multiple MCP servers configured; read_resource currently supports exactly one allowed server.r   r2  )r  rá  rf  r;  rn   )r  r   rY   rD  r×   Úread_resource_from_server)rá  re  rf  rg  rh  ri  rn   ræ  r  r<  r;  s              rT   rã  rã  •  s¼   è ø€ ô ,DØ/Ø#ô,
÷ &
Ðñ
 #ÜØØ@ôð ô
 Ð"Ó# qÒ(ÜØàsôð ð ,¨AÑ.ˆä,GØØ$;Ø+Ø)Ø#Ø/ô-
Ñ)Ð˜Mô /×HÑHØØØ.Ø'Ø#ô
÷ 
ð 	
ð=&
øð<
ús"   ‚B“A=”A$BÁ8A?Á9BÁ?Brÿ   c                 ó   — t        j                  | «      }|r|› d| › �n| }|r^|j                  xs i }t        | ||j	                  d«      |j	                  d«      |||j
                  t        |j                  «      ¬«      S t        | |||¬«      S )Nú/rÿ   Úlogo_url)r  r“  Úmcp_server_nameÚmcp_server_logo_urlÚnamespaced_tool_nameÚmcp_session_idÚmcp_auth_modeÚmcp_server_resource)r  r“  r=  r>  )r×   rý  ræ   r?   r™   r*  r%   rá  )r  r“  rÿ   r"  rò  r=  ræ   s          rT   rÿ  rÿ  Æ  sŸ   € ô 6×TÑTÐUYÓZˆ
ÙAL¨¨°Q°t°fÑ&=ÐRVÐÙØ(×1Ñ1Ò7°RˆHÜ-ØØ#Ø (§¡¨]Ó ;Ø$,§L¡L°Ó$<Ø%9Ø)Ø(×2Ñ2Ü$<¸Z¿^¹^Ó$Lô	ð 	ô .ØØ#Ø%9Ø)ô	ð rV   c
              ƒ   óš   K  — ddl m}
 t        j                  | ||||||||
|	|¬«      ƒ d{  –—† }t	        j
                  d|«       |S 7 Œ­w)z.Handle tool execution for managed server toolsr   r�  )rÿ   r  r“  re  rf  rh  ri  rn   r™  rÃ  r¸  NzCALL TOOL RESULT: %s)r¢  r™  r×   Ú	call_toolr   rq  )rÿ   r  r“  re  rf  rh  ri  rn   r¸  rÃ  r™  Úcall_tool_results               rT   r  r  â  sb   è ø€ õ 	Aä(A×(KÑ(KØ#ØØØ/Ø+Ø$;Ø)Ø#Ø/Ø#9Ø 3ô)
÷ #
Ðô 	×ÑÐ3Ð5EÔFØÐð#
ús   ‚*A¬A	­Ac              ƒ   óà  K  — ddl }t        j                  | «      }|st        dd| › d�¬«      ‚	 |j	                  |j
                  «      r |j
                  di |¤Žƒ d{  –—† }n |j
                  di |¤Ž}t        t        t        |«      d	¬
«      gd¬«      S 7 Œ9# t        $ r ‚ t        $ r=}t        j                  d| |«       t        t        d|› �d	¬
«      gd¬«      cY d}~S d}~ww xY w­w)a  Execute a local-registry tool and report whether it succeeded.

        Returns the result rather than bare content because the verdict is part of it: the content
        alone cannot say whether the handler failed, so callers used to stamp isError=False on every
        outcome and an upstream rejection was served as tool output.

        A failure is reported as ``isError=True`` here rather than raised, because the REST surface
        turns an unrecognized exception into a 500 and an upstream 403 or 429 is not a gateway crash.
        ``MCPUpstreamAuthError`` is the exception: it propagates so the caller is told to
        re-authenticate, which both renderers already know how to say.

        Note: Local tools don't use prefixes, so we use the original name
        r   Ni”  rñ  z' not foundrå  z!Error executing local tool %s: %srÅ  rw   rÄ  Tr²  Frî   )ÚinspectrÜ   r   r   ÚiscoroutinefunctionÚhandlerr    rF  r   rG  rÆ   rÉ   rr   )r  r“  rE  rü  rŽ  rI  s         rT   r  r    sé   è ø€ ó 	ä.×7Ñ7¸Ó=ˆÙÜ¨C¸&ÀÀÀkÐ8RÔSÐSð		hØ×*Ñ*¨4¯<©<Ô8Ø+˜tŸ|™|Ñ8¨iÑ8×8‘à%˜Ÿ™Ñ2¨	Ñ2�ô ¤{¼¸F»È&Ô'QÐ&RÐ\aÔbÐbð 9ùô $ò 	ØÜò 	hÜ×$Ñ$Ð%HÈ$ÐPQÔRÜ!¬;¸gÀaÀS¸MÐPVÔ+WÐ*XÐbfÔgÕgûð	hüsF   ‚-C.°0B Á BÁ!B Á8"C.ÂB ÂC+Â.2C&Ã C+Ã!C.Ã&C+Ã+C.rœ  c                 óÔ  — ddl }d}| j                  d«      D �cg c]  }|sŒ|‘Œ	 }}t        |«      dk\  r|d   dk(  r|d   dk7  r|d   gS |j                  d| «      }|rù|j	                  d«      }|ræd|v rµ|j                  d	|«      }|rbd|j	                  d«      z   }|dt        |«        }	|	j                  d«      D �cg c]#  }|j                  «       sŒ|j                  «       ‘Œ% }}|S |j                  d«      D �cg c]#  }|j                  «       sŒ|j                  «       ‘Œ% }}|S |j                  d
|«      }
|
r|
j	                  d«      }|g}|S |g}|S c c}w c c}w c c}w )z3
        Get the MCP servers from the path
        r   Nr9  é   r{   rF  z ^/mcp/([^?#]+)(?:\?.*)?(?:#.*)?$rƒ   z/([^/,]+(?:/[^/,]+)*)$z^([^/]+(?:/[^/]+)?)(?:/.*)?$)ÚreÚsplitrY   ÚmatchÚgroupÚsearchr  )rœ  rJ  Úmcp_servers_from_pathrí  ÚsegmentsÚmcp_path_matchÚservers_and_pathÚ
path_matchÚ	path_partÚservers_partÚsingle_server_matchrÿ   s               rT   Ú_get_mcp_servers_in_pathrW  "  sž  € ó 	à26ÐØ&*§j¡j°£oÖ; ºš1Ð;ˆÐ;Üˆx‹=˜AÒ (¨1¡+°Ò"6¸8ÀA¹;È%Ò;OØ˜Q‘K�=Ð ð
 !#§¡Ð)LÈdÓ SˆÙØ&4×&:Ñ&:¸1Ó&=ÐáàÐ*Ñ*ð )+¯	©	Ð2KÐM]Ó(^�JÙ!à+.°×1AÑ1AÀ!Ó1DÑ+D˜	Ø.>Ð?PÄ#ÀiÃ.ÀÐ.Q˜ØDP×DVÑDVÐWZÓD[Ö0i¸qÐ_`×_fÑ_fÕ_h°·±µÐ0iÐ-Ð0ið %Ð$ð EU×DZÑDZÐ[^ÓD_Ö0m¸qÐcd×cjÑcjÕcl°·±µÐ0mÐ-Ð0mð %Ð$ð 24·±Ð:YÐ[kÓ1lÐ'Ù*Ø-@×-FÑ-FÀqÓ-I˜Ø1<°Ð-ð %Ð$ð 2BÐ0BÐ-Ø$Ð$ùòG <ùò* 1jùò 1ns"   šE¢EÃE ÃE Ä E%ÄE%c              ƒ   óÒ   K  — t        |«      }|�'t        j                  | «      ƒ d{  –—† \  }}}}}}|}	n$t        j                  | «      ƒ d{  –—† \  }}}	}}}|||	|||fS 7 Œ:7 Œ­w)zÀ
        Extracts mcp_servers from the path and processes the MCP request for auth context.
        Returns: (user_api_key_auth, mcp_auth_header, mcp_servers, mcp_server_auth_headers)
        N)rW  r   Úprocess_mcp_request)
r§   rœ  rO  re  rf  r¥  rh  ri  rn   rg  s
             rT   Úextract_mcp_auth_contextrZ  N  sž   è ø€ ô
 (@ÀÓ'EÐØ Ð,ô (×;Ñ;¸EÓB×BñØ!ØØØ'ØØà/‰Kô (×;Ñ;¸EÓB×BñØ!ØØØ'ØØð ØØØ#ØØð
ð 	
ð Cøð Cús!   ‚&A'¨A#©&A'ÁA%ÁA'Á%A'c                 ó  — | j                  dg «      }|D ]i  \  }}t        |t        «      r|n|j                  «       }|j	                  «       dk(  sŒ<t        |t        «      r|j                  «       c S t        |«      c S  y)zf
        Extract mcp-session-id from ASGI scope headers.
        Returns None if not present.
        rº   ó   mcp-session-idN)r™   rq   ÚbytesÚencoders   Údecoderr   )r§   Úscope_headersÚheader_namerC  r  s        rT   Ú_get_session_id_from_scoperb  p  s   € ð
 KPÏ)É)ÐT]Ð_aÓJbˆØ)6ò 	gÑ%ˆK˜Ü",¨[¼%Ô"@‘;Àk×FXÑFXÓFZˆDØ�z‰z‹|Ð0Ó0Ü0:¸<ÌÔ0O�|×*Ñ*Ó,ÒfÔUXÐYeÓUfÒfð	gð rV   c                 ó\  — dt         dt        dz  fd„}| �z |t        | dd«      «      }|r(t        j                  |«      j                  «       }d|› �S  |t        | dd«      «      }|r(t        j                  |«      j                  «       }d|› �S |rT|j                  d	«      xs |j                  d
«      } ||«      }	|	r&dt        j                  |	«      j                  «       › �S |rEt        |t        «      r5dt        j                  |j                  d«      «      j                  «       › �S y)uÕ  
        Stable, non-reversible identifier for the caller used to bind an
        mcp-session-id to its creator. Hash the resolved credential before
        using it so custom key formats are never stored in cleartext.

        For OAuth2 passthrough (``UserAPIKeyAuth()`` with no key/user_id),
        the caller's identity is the upstream OAuth bearer; hash it so two
        OAuth callers with different tokens don't both fingerprint to
        ``anonymous`` and end up sharing a session.

        When no caller-identifying credentials are available at all
        (e.g. proxy running without master key, or an unauthenticated
        passthrough path), fall back to the client IP so two unrelated
        anonymous callers from different sources do not collapse to a
        single ``anonymous`` owner and end up able to drive each other's
        stateful sessions. Note: when even client IP is unavailable
        (exotic deployments without trusted X-Forwarded-For and direct
        socket info), the fingerprint degrades to the ``anonymous``
        sentinel and cannot meaningfully protect against another
        unauthenticated caller who learns the session id â€” owner-binding
        is best-effort in that mode.
        ru   rQ   Nc                 óŽ   — | €yt        | t        t        f«      rt        | «      S t        | t        «      r| j	                  d«      S y)zCOnly hash str/bytes secrets; skip mocks and other unexpected types.Núutf-8)rq   r]  Ú	bytearrayrr   r^  )ru   s    rT   Ú_bytes_for_hashz/_owner_fingerprint_for.<locals>._bytes_for_hash˜  s?   € àˆ}ØÜ˜%¤%¬Ð!3Ô4Ü˜U“|Ð#Ü˜%¤Ô%Ø—|‘| GÓ,Ð,ØrV   Úapi_keyzkey:rO   zuser:r)  r  zoauth:zip:re  Ú	anonymous)
r	   r]  r—   ÚhashlibÚsha256Ú	hexdigestr™   rq   rr   r^  )
re  ri  r”  rg  Úkey_materialÚapi_key_hashÚuid_materialÚuser_id_hashÚauthzÚauthz_bytess
             rT   Ú_owner_fingerprint_forrs  |  s$  € ð8	¤3ð 	¬5°4©<ó 	ð Ð(Ù"1´'Ð:KÈYÐX\Ó2]Ó"^ˆLÙÜ&-§n¡n°\Ó&B×&LÑ&LÓ&N�Ø˜l˜^Ð,Ð,Ù"1´'Ð:KÈYÐX\Ó2]Ó"^ˆLÙÜ&-§n¡n°\Ó&B×&LÑ&LÓ&N�Ø˜|˜nÐ-Ð-ÙØ)×-Ñ-¨oÓ>ÒeÀ.×BTÑBTÐUdÓBeˆEÙ!0°Ó!7ˆKÙØ¤§¡¨{Ó ;× EÑ EÓ GÐHÐIÐIÙœ I¬sÔ3ØœŸ™¨	×(8Ñ(8¸Ó(AÓB×LÑLÓNÐOÐPÐPØrV   Úbodyc                 ó¾   — | sy	 t        j                  | «      }t        |t        «      xr |j	                  d«      dk(  S # t         j
                  t        f$ r Y yw xY w)zŸ
        Check if the request body is a JSON-RPC initialize method.
        Returns True if method is "initialize", False otherwise or on parse error.
        Fr}   Ú
initialize)r‹  Úloadsrq   r˜   r™   ÚJSONDecodeErrorr½   )rt  rž  s     rT   Ú_is_initialize_requestry  ´  sZ   € ñ
 Øð	ÜŸ*™* TÓ*ˆDÜ˜d¤DÓ)ÒP¨d¯h©h°xÓ.@ÀLÑ.PÐPøÜ×$Ñ$¤iÐ0ò 	Ùð	ús   …:A  Á AÁAÚreceivec              ƒ   óŒ  K  — g }g }d}	  | «       ƒ d{  –—† }|j                  |«       |j                  d«      dk7  rnp|j                  dd«      xs d}|r:t        |z
  }|dkD  r,|j                  |d| «       |t        t	        |«      |«      z  }|j                  dd«      sn|t        k\  rnŒ¥|dj                  |«      fS 7 Œ­­w)	uÌ  
        Read just enough of the request body to decide whether this is a
        JSON-RPC ``initialize`` call. Returns the consumed ASGI messages so
        the caller can replay them faithfully to the downstream handler, and
        the peeked body bytes (capped at ``_MCP_ROUTING_PEEK_MAX_BYTES``).

        Stops reading from the wire as soon as either (a) we have peeked
        ``_MCP_ROUTING_PEEK_MAX_BYTES`` of body, or (b) the body is complete.
        The remainder of an oversized body is streamed lazily through
        ``wrapped_receive`` in the caller â€” so an authenticated client cannot
        force the proxy to buffer an arbitrarily large payload just to make a
        routing decision.
        r   Nr±  zhttp.requestrt  rV   Ú	more_bodyF)r†   r™   rL   ÚminrY   r…   )rz  Úconsumed_messagesÚbody_chunksÚpeeked_bytesr¿   rt  Ú	remainings          rT   Ú_read_request_body_for_routingr‚  Á  sÚ   è ø€ ð  35ÐØ*,ˆØˆàÙ#›I—oˆGØ×$Ñ$ WÔ-à�{‰{˜6Ó" nÒ4Øà!Ÿ+™+ f¨cÓ2Ò9°cˆDÙô 8¸,ÑF�	Ø˜q’=Ø×&Ñ& t¨J¨YÐ'7Ô8Ø ¤C¬¨D«	°9Ó$=Ñ=�Là—;‘;˜{¨EÔ2ØàÔ:Ò:ð ð5 ð8 ! #§(¡(¨;Ó"7Ð7Ð7ð7 &ús   ‚C”C•B.CÚsendÚmgrrÅ   c              ƒ   óÀ  K  — d}| j                  dg «      }dt        dt        dz  fd„}d}|D ]A  \  }}	 ||«      |k(  sŒt        |	t        «      r|	j	                  dd¬	«      }nt        |	«      } n |€y
t        |dd«      }
|
€y
	 ||
v ry
	 | j                  dd«      j                  «       }|dk(  rCt        |«       t        j                  d|«       t        dddi¬«      } || ||«      ƒ d{  –—†  yt        j                  d|«       |D ��cg c]  \  }} ||«      |k7  sŒ||f‘Œ c}}| d<   y
# t        $ r t        j                  d|«       Y y
w xY w7 Œgc c}}w ­w)a  
        Inspect the incoming ``mcp-session-id`` header **before** the
        request reaches the MCP SDK.  If the session is stale (not known
        to this worker), strip the header so the SDK creates a fresh
        stateless session instead of returning a 400.

        Returns:
            True if the request was fully handled (e.g. DELETE on
            non-existent session).  False if the request should continue
            to the session manager.

        Fixes https://github.com/BerriAI/litellm/issues/20992
        r\  rº   ra  rQ   Nc                 ó¦   — t        | t        «      r| j                  «       S t        | t        «      r!| j                  «       j	                  dd¬«      S y )Nre  Úreplace©Úerrors)rq   r]  rs   rr   r^  )ra  s    rT   Ú_normalize_header_namez9_handle_stale_mcp_session.<locals>._normalize_header_name	  sG   € Ü˜+¤uÔ-Ø"×(Ñ(Ó*Ð*Ü˜+¤sÔ+Ø"×(Ñ(Ó*×1Ñ1°'À)Ð1ÓLÐLØrV   re  r‡  rˆ  Fr)  zMUnable to inspect active MCP sessions for '%s'. Deferring to session manager.r}   r|   ÚDELETEzXDELETE request for non-existent MCP session '%s'. Returning success (idempotent DELETE).éÈ   r¿   zSession terminated successfully©r¸   ró   TzlMCP session ID '%s' not found in this worker's memory. Stripping stale header to force new session creation.)r™   r'  r]  rq   r_  rr   r—   rF  r   rq  Úupperr,  rM  r   rŽ  )r§   rz  rƒ  r„  Ú_mcp_session_headerÚ_headersrŠ  Ú_session_idra  rC  Úknown_sessionsr}   Úsuccess_responser$  r?  s                  rT   Ú_handle_stale_mcp_sessionr”  ó  s³  è ø€ ð& &7ÐØEJÇYÁYÈyÐZ\ÓE]ˆð	´ð 	¼5À4¹<ó 	ð #'ˆØ)1ò 	Ñ%ˆK˜Ù% kÓ2Ð6IÓIÜ˜l¬EÔ2Ø".×"5Ñ"5°gÀiÐ"5Ó"P‘Kä"% lÓ"3�KÙð	ð ÐØô !(¨Ð-@À$Ó GˆàÐ!Øð	Ø˜nÑ,Øð -ð Ÿ	™	 (¨BÓ/×5Ñ5Ó7ˆà�XÒÜ-¨kÔ:Ü×ÑØjØôô '3ØØ"Ð$EÐFô'Ðñ # 5¨'°4Ó8×8Ð8Øô 	×ÑðDàô	
ð
 08×l¡t q¨!Ñ;QÐRSÓ;TÐXkÓ;k˜Q šFÓlˆˆiÑØøô= ò 	Ü× Ñ Ø_Øôñ ð	úð( 9úó mùsU   ‚=EÁ AEÂD1 Â
A$EÃ.EÃ/ EÄEÄ#EÄ)EÄ1EÅEÅEÅEÅEÚ
toolset_idc              ƒ   ó$  K  — ddl m} ddlm} | j                  }|�7t
        j                  j                  |j                  xs g v rt        dd¬«      ‚ || «      }|s4| j                  }|rt        |dd«      nd}|�||vrt        dd	|› d
�¬«      ‚t        j                  |g¬«      ƒ d{  –—† }t        |j                  «       «      }	| j                  }
|
�|
j                  |	|g dœ¬«      }n |d|	|¬«      }| j                  d|i¬«      S 7 Œa­w)aÈ  
        Restrict a key's MCP permissions to a single toolset.

        When a request arrives via /toolset/{name}/mcp we override the key's
        object_permission so that only the toolset's tools are visible.

        Raises HTTPException(403) if the key has an explicit toolset grant list
        that does not include toolset_id (i.e. mcp_toolsets is set but empty,
        or set to a list that omits this toolset).  Admin keys always pass.
        r   )ÚLiteLLM_ObjectPermissionTable)Ú_user_has_admin_viewNrï  z>API key is scoped to no MCP servers; toolset access is denied.rå  Úmcp_toolsetsz)API key does not have access to toolset 'rò  )Útoolset_ids)rg  Úmcp_tool_permissionsr™  r   ztoolset-scope)Úobject_permission_idrg  r›  ra  )Úlitellm.proxy._typesr—  Ú/litellm.proxy.management_endpoints.common_utilsr˜  ra  r5   Úno_mcp_serversru   rg  r   r—   r×   Ú resolve_toolset_tool_permissionsr2  rr  r  )re  r•  r—  r˜  Úoriginal_opÚis_adminÚopÚgrantedÚtool_permissionsÚ
server_idsÚexisting_opÚ
updated_ops               rT   Ú_apply_toolset_scoper©  F  sG  è ø€ õ 	GÝXð /×@Ñ@ˆØÐ"Ô'<×'KÑ'K×'QÑ'QÐVa×VmÑVmÒVsÐqsÑ'tÜØØWôð ñ /Ð/@ÓAˆÙØ)×;Ñ;ˆBÙBDœW R¨¸Ô>È$ˆGð ˆ *°GÑ";Ü#Ø #ØFÀzÀlÐRTÐUôð ô
 ";×![Ñ![ÐisÐhtÔ!u×uÐÜ Ð!1×!6Ñ!6Ó!8Ó9ˆ
Ø.×@Ñ@ˆØÐ"Ø$×/Ñ/à#-Ø,<Ø$&ñð 0ó ‰Jñ 7Ø%4Ø&Ø%5ôˆJð
 !×+Ñ+Ð4GÈÐ3TÐ+ÓUÐUð' vús   ‚B*DÂ,DÂ-A"DÚallowed_server_idsc           
   ƒ   óÜ  K  — |xs g D �]S  }t        j                  ||¬«      }|�|�|j                  |vrŒ.|�-|j                  t        j
                  k(  r|j                  dk(  rŒ]|�t        j                  |«      ƒ d{  –—† }|�r|j                  t        j
                  k(  r÷t        j                  |«      dk(  rŒµt        |dd«      dur®t        j                  ||«      ƒ d{  –—† rŒãt        |«      rt        ddd	t        | |¬
«      i¬«      ‚t        | «      }	t!        |	«      }
t#        | «      }|
› dt%        «       › �}|j'                  d|› �«      r|› d|› �}n|› d|› �}d|› d�}t        ddd	|i¬«      ‚|st        | |¬
«      }t        ddd	|i¬«      ‚�Œ“|r:|j                  t        j(                  k(  r|sddlm} ddlm}  || |«       ¬«       |rQ|j                  t        j(                  k(  r4|r2t3        |xs g «      dk(  r t        j4                  |||¬«      ƒ d{  –—†  |r6|j6                  r*t9        |||«      st        | |¬
«      }t        ddd	|i¬«      ‚|rR|j:                  rFt3        |xs g «      dk(  r4t=        | «      €)t?        ||«      st        | |¬
«      }t        ddd	|i¬«      ‚|s�Œ²|j@                  s�ŒÀt3        |xs g «      dk(  s�ŒÔtC        | «      r�Œát?        ||«      r�Œï|jD                  rt        ddd	t        | |¬
«      i¬«      ‚tG        |jH                  xs dd«      ƒ d{  –—† \  }}|dk(  s�ŒB|s�ŒFt        ddd	|i¬«      ‚ y7 �Œá7 �Œ~7 �ŒA7 Œ-­w)a¡  Fail fast with HTTP 401 for MCP servers that need user auth but
        didn't receive it on this request. Covers both gateway-managed OAuth2
        (points clients at the gateway AS metadata) and pass-through OAuth
        (points clients at the upstream resource-metadata via our well-known).

        ``allowed_server_ids`` may be passed by callers that have already
        narrowed the authorized server set (e.g. toolset scoping); servers
        not in that set are skipped so a client targeting a toolset that
        excludes a passthrough server is not pushed into an OAuth flow for
        a server it will be 403'd on immediately after authentication.
        ©r”  NÚclient_credentialsÚdelegate_auth_to_upstreamFTrÝ  ÚUnauthorizedúwww-authenticate)r§   rÿ   r·   z'/.well-known/oauth-authorization-serverz/mcp/r9  zBearer authorization_uri="rz   r   )Úraise_token_exchange_challenge)Úget_server_root_path)Ú	root_pathr{   )r  ri  re  r|   )%r×   Úget_mcp_server_by_namerP   r*  r:   r+  Úoauth2_flowÚ ensure_oauth_metadata_discoveredrÒ   Úeffective_oauth2_flowr—   Úhas_user_oauth_tokenr   r   r&   ÚStarletteRequestr   r'   r(   Ú
startswithÚoauth2_token_exchanger}  r±  r1  r²  rY   Úpreflight_token_exchangeÚis_oauth_passthroughr%  Úis_oauth_delegateÚ_get_forwarded_auth_from_scoper"  Úis_true_passthroughÚ_scope_has_authorization_headerÚis_dcr_bridgeÚ_probe_upstream_authrá  )r§   rg  ri  rh  re  r”  rª  rÿ   r  r­   Úbase_urlÚ_pathÚas_metadata_rootÚ_as_urlÚauthorization_uriÚwww_authenticater±  r²  Úupstream_statusÚupstream_www_authenticates                       rT   Ú1_raise_preemptive_401_for_unauthenticated_serversrÌ  †  sü  è ø€ ð( 'Ò,¨"ó }	ˆKÜ.×EÑEÀkÐ]fÔgˆFØÐ!Ð&8Ð&DÈ×IYÑIYÐasÑIsð ØÐ! f×&6Ñ&6¼'¿.¹.Ò&HÈV×M_ÑM_ÐcwÒMwð
 ØÐ!Ü8×YÑYÐZ`Óa×a�Ú˜&×*Ñ*¬g¯n©nÒ<ô $×9Ñ9¸&ÓAÐEYÒYð ä˜6Ð#>ÀÓFÈdÑRô 7×KÑKÈFÐTeÓf×fÐfØ ä4Ð5FÔGÜ+Ø(+Ø#1à 2Ô4TØ*/Ø0;ô5"ð%ô	ð 	ô /¨uÓ5�GÜ3°GÓ<�HÜ;¸EÓB�Eð +3¨Ð3ZÔ[qÓ[sÐZtÐ'uÐ$Ø×'Ñ'¨%°¨}Ð(=Ô>Ø%5Ð$6°e¸K¸=Ð"I™à%5Ð$6°a¸°}Ð"E˜Ø*DÀWÀIÈQÐ(OÐ%ä'Ø$'Ø-Ø!3Ð5FÐ Gôð ñ &ô (HØ#Ø$/ô(Ð$ô (Ø$'Ø-Ø!3Ð5EÐ Fôð ñ ñ ˜&×*Ñ*¬g×.KÑ.KÒKÑTbõõ Eá.¨vÑAUÓAWÕXñ Ø×$Ñ$¬×(EÑ(EÒEÙ"Ü˜Ò) rÓ*¨aÒ/ä/×HÑHØ!Ø#1Ø&7ô÷ ð ñ Ø×/Ò/Ü=¸fÀnÐVmÔnä#CØØ +ô$Ð ô $Ø #Ø)Ø/Ð1AÐBôð ñ Ø×,Ò,Ü˜Ò) rÓ*¨aÒ/Ü2°5Ó9ÐAÜ:¸6ÐCZÔ[ä#CØØ +ô$Ð ô $Ø #Ø)Ø/Ð1AÐBôð ó Ø×.Ô.Ü˜Ò) rÓ*¨aÔ/Ü7¸Ö>Ü:¸6ÐCZÖ[à×'Ò'Ü'Ø$'Ø-à.Ô0PØ&+Ø,7ô1ð!ô	ð 	ô DXÐX^×XbÑXbÒXhÐfhÐjlÓCm×=mÑ:�Ð!:Ø" cÔ)Ó.GÜ'Ø$'Ø-Ø!3Ð5NÐ Oôð ñs}	ð bùð8 gùð^ùð| >núsv   ‚A>M,Â M!ÂA%M,Ã&M$Ã'D?M,È&M'È'BM,Ê;M,Ë	M,ËM,Ë*M,Ë8AM,Ì<M*Ì=M,ÍM,ÍM,Í$M,Í'M,Í*M,c                 óˆ   — | j                  dg «      }|D ]+  \  }}|j                  «       dk(  sŒ|j                  d«      c S  y)z@First ``Authorization`` header value in the ASGI scope, or None.rº   s   authorizationzlatin-1N)r™   rs   r_  )r§   r`  rt   ru   s       rT   Ú$_get_authorization_header_from_scoperÎ  Y  sI   € à>C¿i¹iÈ	ÐSUÓ>VˆØ'ò 	/‰JˆC�Ø�y‰y‹{Ð.Ó.Ø—|‘| IÓ.Ò.ð	/ð rV   c                 ó   — t        | «      d uS r  )rÎ  )r§   s    rT   rÁ  rÁ  a  s   € Ü3°EÓ:À$ÐFÐFrV   c                 óf   — | j                  dg «      }t        d„ |D «       «      }|syt        | «      S )aK  Return the upstream-bound ``Authorization`` header value, or None.

        Only returns the ``Authorization`` header when ``x-litellm-api-key`` is
        also present. In that case ``Authorization`` is unambiguously the
        upstream token the caller wants forwarded to the MCP server. When
        ``x-litellm-api-key`` is absent the ``Authorization`` header may itself
        be the LiteLLM proxy API key (backward-compat path in
        ``MCPRequestHandler.process_mcp_request``), and forwarding it upstream
        would leak the proxy key to a third-party MCP server.
        rº   c              3   óH   K  — | ]  \  }}|j                  «       d k(  –— Œ y­w)s   x-litellm-api-keyN)rs   )r  rt   r¥  s      rT   r  z1_get_forwarded_auth_from_scope.<locals>.<genexpr>p  s#   è ø€ Ò+lÑTZÐTWÐYZ¨C¯I©I«KÐ;OÕ,OÑ+lùs   ‚ "N)r™   r   rÎ  )r§   r`  Úhas_litellm_key_headers      rT   r¿  r¿  d  s9   € ð ?D¿i¹iÈ	ÐSUÓ>VˆÜ(+Ñ+lÐ^kÔ+lÓ(lÐÙ%ØÜ3°EÓ:Ð:rV   c                 ó�   — | j                   t        j                  k(  xr( | j                  du xr t	        j
                  | «      dk7  S )a’  Whether ``server`` is an interactive delegate-auth server whose client-supplied
        token should be preflighted upstream.

        Mirrors the anonymous-delegate gate in ``get_allowed_mcp_servers``: the flow is
        resolved via ``effective_oauth2_flow`` so an unstamped M2M-shape row fails closed
        (its stored client credentials drive egress; the caller's bearer is irrelevant).
        Tr­  )r*  r:   r+  r®  rÒ   r·  r]  s    rT   Ú"_is_delegate_upstream_probe_targetrÔ  u  sI   € ð ×Ñ¤§¡Ñ.ò WØ×0Ñ0°DÐ8òWä ×6Ñ6°vÓ>ÐBVÑVð	
rV   Úauth_headerÚtimeoutc              ƒ   ó>  K  — t        t        j                  d|i¬«      }dddt        j                  j
                  i dddœdœd	œ}d
di|rd|ini ¥}	  |j                  | |||¬«      ƒ d{  –—† }|j                  |j                  j                  d«      fS 7 Œ+# t        j                  $ rE}|j                  j                  |j                  j                  j                  d«      fcY d}~S d}~wt        $ r!}t        j                  d| |«       Y d}~yd}~ww xY w­w)aG  JSON-RPC initialize-probe the upstream URL to check whether the token is accepted.

        Uses POST so StreamableHTTP MCP servers run the same auth path as a
        real client request. Returns (status_code, www_authenticate).
        Fails-open with (200, None) on network errors so a transient hiccup
        does not block valid requests.

        Uses the public ``AsyncHTTPHandler.post()`` interface and catches
        ``httpx.HTTPStatusError`` separately so the 401/403 we want to surface
        is not swallowed by the broad fail-open ``except Exception`` below.
        rÖ  )Úllm_providerÚparamsú2.0zlitellm-mcp-auth-proberv  z1.0.0r
  )ÚprotocolVersionÚcapabilitiesÚ
clientInfo)ÚjsonrpcÚidr}   rÙ  ÚAcceptz#application/json, text/event-streamr)  )rá  rº   r‹  rÖ  Nr°  zG_probe_upstream_auth: probe to %s failed (%s), allowing request through)rŒ  N)r   r   ÚMCPr;   Újun_2025ru   Úpostr¸   rº   r™   ÚhttpxÚHTTPStatusErrorrÎ  rF  r   rq  )rá  rÕ  rÖ  rA   Úprobe_payloadÚprobe_headersÚresprµ   s           rT   rÃ  rÃ  ƒ  s+  è ø€ ô  /Ü-×1Ñ1Ø˜wÐ'ô
ˆð
 Ø*Ø"ä#1×#:Ñ#:×#@Ñ#@Ø "à4Ø&ñññ	 
ˆð Ð;ð 
á1<� Ñ-À"ð 
ˆð	Ø + §¡ØØ%Ø"Øô	!÷ ˆDð ×#Ñ# T§\¡\×%5Ñ%5Ð6HÓ%IÐIÐIðùô ×$Ñ$ò 	Zð —<‘<×+Ñ+¨S¯\©\×-AÑ-A×-EÑ-EÐFXÓ-YÐYÕYûÜò 	Ü× Ñ Ð!jÐloÐqtÔuÜûð	üsZ   ‚ADÁB Á,BÁ-*B ÂDÂB ÂDÂ-:C-Ã'DÃ(DÃ-DÃ9DÄDÄDÄDc              ƒ   ó¶  ‡‡‡‡K  — t        | «      Š|�t        |«      dk(  r|d   ndŠ‰rt        j                  ‰|¬«      ndŠ‰�t	        ‰«      rt        | «      ndŠ‰s‰syt        |||¬«      ƒ d{  –—† }‰rt        ˆfd„|D «       «      nd}‰r‰rt        ˆˆˆfd„|D «       «      nd}||z   }|syt        j                  |D ��	�
cg c]   \  }}	}
t        |j                  xs d	|	«      ‘Œ" c}
}	}Ž ƒ d{  –—† }t        ||«      D ]A  \  \  }}
}\  }}
|d
k(  rt        | |d¬«      }t        d
dd|i¬«      ‚|dk(  sŒ6t        dd¬«      ‚ y7 ŒÙc c}
}	}w 7 Œ^­w)uI  Probe pass-through and delegate-auth upstream servers in parallel before the MCP session starts.

        Only servers the caller's key is already authorized to reach are probed â€”
        the list is derived from _get_allowed_mcp_servers so that a user cannot
        trigger an upstream probe against a server their key is not permitted for.

        The MCP SDK commits HTTP 200 headers before invoking handlers, so a 401
        can only be returned before that point. This function raises HTTPException(401)
        with a WWW-Authenticate header if any upstream rejects the client token, or 403
        if the upstream accepts it but forbids the caller.
        Fails-open: network errors are logged and the request is allowed through.

        Delegate-auth servers (``auth_type=oauth2`` + ``delegate_auth_to_upstream``)
        are probed with the caller's bare ``Authorization`` bearer. That bearer is only
        an upstream token (never a LiteLLM key) when admission took the delegate bypass,
        so the delegate target is resolved through ``get_mcp_server_by_name`` -- the same
        resolver admission used -- rather than the wider allowed-server prefix/access-group
        matching. A name that only reaches a delegate server via server_id or an access
        group would have been admitted as a real LiteLLM key, so probing it would leak that
        key upstream; requiring the admission-resolver match closes that gap. Without the
        probe a rejected token is absorbed by the tools/list handler and masked as an empty
        tool list. Gated to single-server routes so one rejected token cannot 401 a
        multi-server aggregate connect, matching the OBO preflight gating; the challenge
        echoes the requested name so aliased routes get the same resource_metadata URL as
        the tokenless preemptive challenge.
        Nr{   r   r¬  rR  c              3   óT   •K  — | ]  }|j                   r|‰|j                  f–— Œ! y ­wr  )r½  r  )r  ÚsrvÚforwarded_auths     €rT   r  z3_check_passthrough_upstream_auth.<locals>.<genexpr>õ  s/   øè ø€ ò àð ×+Ò+ð �n c§h¡hÔ/ñùs   ƒ%(rî   c              3   ó^   •K  — | ]$  }‰� |j                   ‰j                   k(  r|‰‰f–— Œ& y ­wr  rì  )r  rë  Údelegate_authÚdelegate_serverÚrequested_single_targets     €€€rT   r  z3_check_passthrough_upstream_auth.<locals>.<genexpr>  s8   øè ø€ ò àØ"Ð.°3·=±=ÀO×D]ÑD]Ò3]ð �mÐ%<Ô=ñùs   ƒ*-r|   rÝ  T)r§   rÿ   Úinvalid_tokenr¯  r°  r·   rï  Ú	Forbiddenrå  )r¿  rY   r×   r´  rÔ  rÎ  r  ÚtuplerD  rT  rÃ  rá  r›  r&   r   )r§   re  rg  r”  Úallowed_serversÚpassthrough_targetsÚdelegate_targetsÚprobe_targetsrë  rÕ  r¥  Úprobe_resultsÚchallenge_server_nameÚprobe_statusrÉ  rî  rï  rì  rð  s                  @@@@rT   Ú _check_passthrough_upstream_authrû  ¹  s×  ûè ø€ ô@ !?¸uÓ EˆØ;FÐ;RÔWZÐ[fÓWgÐklÒWl¨°QªÐrvÐñ 'ô &×<Ñ<Ð=TÐ`iÕjàð 	ð Ð*Ô/QÐRaÔ/bô 1°Ô7àð 	ñ
 ¡mØô (@Ø/Ø#Øô(
÷ "
ˆñ& ô ó à*ôô ð ð 	ñ2 Ñ!8ô õ à*ôô ð ð 	ð  3Ð5EÑEˆÙØä%,§^¡^ØZg×hÐhÑCVÀ3ÈÐUVÔ" 3§7¡7¢=¨b°+Õ>Ôhð&
÷  
ˆô CFÀmÐUbÓBcò 	Ñ>Ñ+ˆS�!Ð*Ñ->¨l¸AØ˜sÒ"ô $DØØ 5Ø"&ô$Ð ô
 $Ø #Ø)Ø/Ð1AÐBôð ð
 ˜sÓ"ô $Ø #Ø&ôð ñ'	ðQ"
úôL ið 
ús8   †A.EÁ4EÁ5AEÃ
%EÃ/	EÃ8EÃ9AEÄ?EÅEc              ƒ   óœ  ‡ ‡‡‡‡‡ ‡!‡"‡#‡$‡%‡&‡'‡(‡)‡*‡+‡,‡-‡.K  — 	 ‰ j                  dd«      }t        ‰ |«      ƒ d{  –—† \  Š.Š$Š&Š%Š'Š)t        t        |«      xs g «      dk(  Š*t	        j
                  t        ‰ «      «      Št        j                  d‰&«       t        j                  d‰%rt        ‰%j                  «       «      nd«       ‰ j                  dg «      }|D ��cg c]  \  }}|j                  «       dk7  sŒ||f‘Œ c}}‰ d<   t        j                   «       }d}|rG‰.�Et        ‰.|«      ƒ d{  –—† Š.‰.j                  }	|	rt        |	j                   xs g «      n	t        «       }t#        ‰ ‰&‰'‰%‰.‰|¬	«      ƒ d{  –—†  t%        ‰ ‰.‰&‰«      ƒ d{  –—†  t'        j(                  ‰)t+        ‰ «      ‰&‰$‰%‰'‰¬
«      }
|
rt'        j,                  ‰|
«      Št.        s/t1        «       ƒ d{  –—†  t3        j4                  d«      ƒ d{  –—†  t7        ‰ «      Š+dŠ#g Š"‰+rbt8        j                  ‰+«      }t;        ‰.‰'‰«      }|�>||k7  r9t        j<                  d‰+«       t?        ddddœ¬«      } |‰ ‰‰«      ƒ d{  –—†  y‰+r(tA        ‰ ‰‰tB        «      ƒ d{  –—† }|ryt7        ‰ «      Š+d}‰ j                  d«      dk(  r!tE        ‰«      ƒ d{  –—† \  Š"}tG        |«      Š#tI        ‰+xs ‰#«      Š-‰-rtB        ntJ        Š,t        j                  d‰-rdnd› d�‰+r	d‰+dd › d�ndz   ‰#rdndz   «       ‰#rZ‰+sXt;        ‰.‰'‰«      }tM        |«      ƒ d{  –—† s8t        j<                  d«       t?        dd d!dœ¬«      } |‰ ‰‰«      ƒ d{  –—†  y‰Š(‰"rˆ"ˆ(fd"„}|Šd}‰ j                  d«      xs djO                  «       }|rv|dk(  rq	 tQ        jR                  |«      }tU        |t*        «      rK|j                  d#«      d$k(  r7d%|v r3d|vr/d&|v sd'|v r'd(}t        j                  d)|j                  d%«      «       d}‰-r0‰+r.|d1v r*|s(t^        ja                  ‰+t3        jb                  «       «      }g Š!d2td        d3dfˆ!fd4„Š‰-r
‰+r ‰‰+«       d5td        d3dfˆfd6„Š d@ˆˆ ˆ#ˆ$ˆ%ˆ&ˆ'ˆ)ˆˆ ˆ*ˆˆ+ˆ,ˆ-ˆ.fd7„}	 |�+|4 ƒd{  –—†   |«       ƒ d{  –—†  ddd«      ƒd{  –—†  n |«       ƒ d{  –—†  ‰!D ]œ  }tf        j                  |d8«      dz
  }|d8kD  r
|tf        |<   ntf        ji                  |d«       ‰ j                  d«      d9k7  r#|tj        v rtm        jn                  «       tp        |<   |d8k  sŒ~|tj        vsŒ‡t^        ji                  |d«       Œž y7 �ŒGc c}}w 7 �Œ[7 �Œ7 �Œ 7 �Œ®7 �Œ”7 �Œ%7 �Œ7 �Œ×7 �ŒY7 �Œ%# tP        jV                  tX        f$ rE |j[                  d*d+¬,«      }d-|v r*d.|v sd/|v r"t]        |«      sd(}t        j                  d0«       Y �ŒÖw xY w7 �Œ^7 �ŒR7 �ŒE# 1 ƒd{  –—†7  sw Y   �ŒFxY w7 �ŒN# ‰!D ]œ  }tf        j                  |d8«      dz
  }|d8kD  r
|tf        |<   ntf        ji                  |d«       ‰ j                  d«      d9k7  r#|tj        v rtm        jn                  «       tp        |<   |d8k  sŒ~|tj        vsŒ‡t^        ji                  |d«       Œž w xY w# tr        $ rL}|ju                  tw        t        ‰ «      «      ‰ j                  d:«      xs ‰ j                  d«      ¬;«      ‚d}~wtx        $ r ‚ tz        $ r}t}        |«      ‚d}~wt~        $ r}}t        j€                  d<|«       	 d8d=lAmB} t?        |d>te        |«      dœ¬«      } |‰ ‰‰«      ƒ d{  –—†7   n)# t~        $ r}t        j€                  d?|«       |‚d}~ww xY wY d}~yd}~ww xY w­w)Az+Handle MCP requests through StreamableHTTP.rœ  r|   Nr{   ú)MCP request mcp_servers (header/path): %súMCP server auth headers: %srº   ó   x-mcp-toolset-id©r§   rg  ri  rh  re  r”  rª  )rn   r§   rg  rf  rh  ri  r”  çš™™™™™¹?Fz3Rejecting MCP request: session '%s' owner mismatch.rï  rò  z.mcp-session-id is bound to a different caller.©rˆ  Údetailsr�  rV   r}   ÚPOSTzMCP routing to Ústatefulr  z managerz
 (session=rŒ  z...)z (initialize)z^Rejecting MCP initialize: caller already holds the maximum number of active stateful sessions.i­  zToo Many Requestsz-Too many active MCP sessions for this caller.c               “   óT   •K  — ‰ r‰ j                  d«      S  ‰«       ƒ d {  –—† S 7 Œ­w)Nr   )rS   )r~  Úoriginal_receives   €€rT   Úwrapped_receivez3handle_streamable_http_mcp.<locals>.wrapped_receiveÊ  s*   øè ø€ Ù(Ø0×4Ñ4°QÓ7Ð7Ù!1Ó!3×3Ð3Ð3ús   ƒ(¡&¢(rÞ  rÚ  rß  rŽ  rˆ  TzUMCP: detected JSON-RPC response POST (id=%s), skipping session lock to avoid deadlockre  r‡  rˆ  z	"jsonrpc"z"result"z"error"znMCP: detected truncated JSON-RPC response POST via top-level key scan, skipping session lock to avoid deadlock)r  r‹  Úsession_id_to_trackrQ   c                 ór   •— | ‰v ry ‰j                  | «       t        j                  | d«      dz   t        | <   y )Nr   r{   )r†   r  r™   )r	  Úactive_request_session_idss    €rT   Ú!_increment_active_request_sessionzEhandle_streamable_http_mcp.<locals>._increment_active_request_session  sA   ø€ Ø&Ð*DÑDØØ*×1Ñ1Ð2EÔFä;×?Ñ?Ð@SÐUVÓWÐZ[Ñ[ô 8Ð8KÒLrV   Úinitialized_session_idc                 ó   •—  ‰| «       y r  rî   )r  r  s    €rT   Ú#_track_initialized_stateful_sessionzGhandle_streamable_http_mcp.<locals>._track_initialized_stateful_session  s   ø€ ñ 2Ð2HÕIrV   c               “   óÞ  •K  — t        ‰«       t        ‰‰‰‰‰‰	‰‰r‰nd ‰j                  d«      xs dj                  «       dk7  ‰¬«
      } ‰}‰r‰rt	        || t        ‰‰‰«      ‰«      }t        ‰‰‰‰¬«      4 ƒd {  –—†  ‰j                  ‰‰
|«      ƒ d {  –—†  ‰r!‰r‰j                  d«      dk(  rt        ‰«       d d d «      ƒd {  –—†  y 7 ŒS7 Œ:7 Œ	# 1 ƒd {  –—†7  sw Y   y xY w­w)Nr}   r|   r‹  )
re  rf  rg  rh  ri  rn   r”  r"  Útouch_last_seenÚ"copy_existing_session_auth_context©rP  )	r«   Ú_set_or_update_auth_contextr™   rŽ  Ú-_wrap_send_with_stateful_session_auth_contextrs  rZ  Úhandle_requestr,  )r	  Ú
local_sendr|  r  Úis_initializerf  rh  rg  ri  rn   rz  r§   rP  rƒ  r"  Útarget_managerÚuse_statefulre  s     €€€€€€€€€€€€€€€€rT   Ú	_dispatchz-handle_streamable_http_mcp.<locals>._dispatch  s  øè ø€ Ü5°eÔ<Ü#>Ø&7Ø$3Ø +Ø,CØ#1Ø +Ø(Ù-9™z¸tØ%*§Y¡Y¨xÓ%8Ò%>¸B×$EÑ$EÓ$GÈ8Ñ$SØ7Dô$�	ð "�
Ù¡MÜ!NØ"Ø!Ü.Ð/@À.ÐR\Ó]Ø;ó	"�Jô JØ%ØØØ+Aô	÷ Fñ Fð )×7Ñ7¸¸wÈ
ÓS×SÐSÙ#©
°u·y±yÀÓ7JÈhÒ7VÜ9¸*ÔE÷F÷ Fñ Føð TøðFø÷ F÷ Fñ FüsZ   ƒA;C-Á>CÁ?C-ÂCÂCÂ'CÃC-ÃCÃC-ÃCÃC-ÃC*ÃC!ÃC*Ã&C-r   r‹  Ú_original_path©rÄ  Úrequest_pathúError handling MCP request: %s©ÚHTTP_500_INTERNAL_SERVER_ERRORúMCP request failedú!Failed to send error response: %sr  )Cr™   rZ  rY   rW  r7   Úget_mcp_client_ipr¹  r   rq  r2  rr  rs   r!   r©  ra  rn  rg  rÌ  rû  r$   Úmaybe_build_debug_headersr˜   Úwrap_send_with_debug_headersrL  rT  rD  rE  rb  r  rs  rŽ  r   r”  r  r‚  ry  r‡   r  rB  rŽ  r‹  rw  rq   rx  r½   r_  r�   r  Ú
setdefaultÚLockrr   r  rS   r  r[   r\   r  r    Úto_http_exceptionr   r   r4   rÀ   rF  rG  Ústarlette.statusr!  )/r§   rz  rƒ  rœ  r`  r$  r?  Úactive_toolset_idÚtoolset_allowed_server_idsr£  Ú_debug_headersÚexpected_ownerÚrequest_ownerÚforbidden_responseÚhandledrt  Útoo_many_responser  Úis_jsonrpc_responseÚrequest_methodÚ_peekedÚ	_body_strÚsession_lockr  Úactive_request_session_idÚactive_request_countrI  r!  Úerror_responseÚresponse_errorr|  r  r  r  r~  r  rf  rh  rg  ri  r  rn   rP  r"  r  r  re  s/   ```                           @@@@@@@@@@@@@@@@@rT   Úhandle_streamable_http_mcpr<  /  s<  ÿÿûè ø€ ð~	Ø$Ÿy™y¨°Ó4ˆDô /¨u°dÓ;×;ñØ!ØØØ'ØØä,/Ô0HÈÓ0NÒ0TÐRTÓ,UÐYZÑ,ZÐ"ô !/× @Ñ @ÔAQÐRWÓAXÓ YˆJä× Ñ Ð!LÈkÔZÜ× Ñ Ø-ÑWn¬tÐ4K×4PÑ4PÓ4RÔ/SÐtxôð
 CHÇ)Á)ÈIÐWYÓBZˆMØ3@×e©4¨1¨aÀAÇGÁGÃIÐQdÓDd  A¢ÓeˆE�)Ñô (>×'AÑ'AÓ'CÐØ:>Ð&Ù Ð%6Ð%BÜ*>Ð?PÐRcÓ*d×$dÐ!Ø-×?Ñ?�ÙJL¬S°·±Ò1EÀ2Ô-FÔRUÓRWÐ*ô DØØ'Ø-Ø(?Ø"3Ø$Ø#=ô÷ ð ô 3°5Ð:KÈ[ÐZdÓe×eÐeô %-×$FÑ$FØ'Ü˜5“kØ'Ø /Ø(?Ø-Ø$ô%ˆNñ Ü×<Ñ<¸TÀ>ÓR�õ 1Ü1Ó3×3Ð3ä—m‘m CÓ(×(Ð(ô 4°EÓ:ˆJØ!ˆMØ/1Ðñ Ü(@×(DÑ(DÀZÓ(P�Ü 6Ð7HÈ.ÐZdÓ e�Ø!Ð-°.ÀMÒ2QÜ"×*Ñ*ØMØ"ôô 1=Ø$'à%0Ø'Wñ!ô1Ð&ñ -¨U°G¸TÓB×BÐBØñ
 Ü'@ÀÈÐQUÔWoÓ'p×!p�ÙàÜ7¸Ó>�
àˆDØ�y‰y˜Ó" fÒ,Ü0NÈwÓ0W×*WÑ'Ð! 4Ü 6°tÓ <�ä"& zÒ'B°]Ó"CˆLÙ@LÕ$<ÔRkˆNä× Ñ Ø!±¡*À+Ð!NÈhÐWÙ8B�Z 
¨2¨A Ð/¨tÑ4ÈñLá&3‘?¸ñ=ôñ ¡ZÜ 6Ð7HÈ.ÐZdÓ e�ÜDÀ]ÓS×SÐSÜ"×*Ñ*Øxôô 0<Ø$'à%8Ø'Vñ!ô0Ð%ñ ,¨E°7¸DÓA×AÐAØð '.ÐÙ õ4ð
 *�ð$ #(ÐØ%*§Y¡Y¨xÓ%8Ò%>¸B×$EÑ$EÓ$GˆNÙ˜¨&Ò0ðÜ%)§Z¡Z°Ó%5�Gä" 7¬DÔ1Ø#ŸK™K¨	Ó2°eÒ;Ø  G™OØ$¨GÑ3Ø%¨Ñ0°G¸wÑ4Fà.2Ð+Ü&×,Ñ,ØsØ#ŸK™K¨Ó-ôð. 15ˆLÙ¡
¨~ÐASÑ/SÑ\oÜ6×AÑAÀ*ÌgÏlÉlËnÓ]�à;=Ð&ðÄsð Ètõ ñ ¡
Ù1°*Ô=ðJÜ(+ðJàõJ÷
F÷ Fô FðBUØÐ+Ø+÷ *ñ *Ù'›k×)Ð)÷*÷ *ð *ñ $›+×%Ð%à1Kò UÐ-Ü+R×+VÑ+VÐWpÐrsÓ+tÐwxÑ+xÐ(Ø+¨aÒ/Ø]qÔ?Ð@YÒZä?×CÑCÐD]Ð_cÔdà—y‘y Ó*¨hÒ6Ð;TÔXwÑ;wÜ^b×^lÑ^lÓ^nÔ@ÐAZÑ[ð ,¨qÓ0Ð5NÔVuÒ5uÜ/×3Ñ3Ð4MÈtÕTñUðS <ûó  fð %eùðùð fùð" 4ùà(ùðB Cùð "qùð +Xùð" Tùð Búô^ ×,Ñ,¬iÐ8ò ð (,§{¡{°7À9 {Ó'M�Ià# yÑ0Ø'¨9Ñ4¸	ÀYÑ8NÜ BÀ9Ô Mà.2Ð+Ü&×,Ñ,ðZôúðúðX*ùØ)ùð*ù÷ *÷ *ò *úð &úà1Kò UÐ-Ü+R×+VÑ+VÐWpÐrsÓ+tÐwxÑ+xÐ(Ø+¨aÒ/Ø]qÔ?Ð@YÒZä?×CÑCÐD]Ð_cÔdà—y‘y Ó*¨hÒ6Ð;TÔXwÑ;wÜ^b×^lÑ^lÓ^nÔ@ÐAZÑ[ð ,¨qÓ0Ð5NÔVuÒ5uÜ/×3Ñ3Ð4MÈtÕTñUûô $ò 	ð ×%Ñ%Ü-Ô.>¸uÓ.EÓFØ"ŸY™YÐ'7Ó8ÒM¸E¿I¹IÀfÓ<Mð &ó ð ûô ò 	àÜò 	8ô
 5°QÓ7Ð7ûÜò 	Ü×$Ñ$Ð%EÀqÔIðÝKä(4Ø >Ø&:ÄsÈ1ÃvÑNô)�ñ % U¨G°TÓ:×:Ò:øÜò Ü×(Ñ(Ð)LÈnÔ]à�ûðúô ;ûð	üs5  –_˜![ ¹V ºB"[ ÃVÃ8VÃ>0[ Ä.V	Ä/A
[ Å9VÅ:[ ÆVÆA[ Ç$VÇ%[ ÈVÈA1[ É3VÉ4[ É8_É9[ ÊVÊ[ Ê_Ê/[ ËVËB [ ÍV!Í	6[ Í?V$Î [ Î_Î8[ Î>A0V' Ð.A3[ Ò"X* Ò*XÒ+X* Ò.XÒ9XÒ:XÒ>X* Ó	XÓ
X* ÓX'ÓX* ÓA?[ Õ[ Õ'[ Õ?_Ö [ Ö[ Ö[ Ö[ Ö[ Ö[ Ö[ Ö[ Ö[ Ö![ Ö$[ Ö'AXØ[ ØXØ[ ØX* ØXØX* ØX$ØXØX$Ø	X* Ø*B [Ú+[Ú4[Û[ Û	_	ÛA\ Ü _	Ü5] Ý _	Ý_Ý#,^Þ^Þ^Þ_Þ	^<Þ^7Þ7^<Þ<_Þ?_ß_	ß	_c           	   ƒ   ó|  K  — 	 | j                  dd«      }t        | |«      ƒ d{  –—† \  }}}}}}	t        t        |«      xs g «      dk(  }
t	        j
                  t        | «      «      }t        j                  d|«       t        j                  d|rt        |j                  «       «      nd«       | j                  dg «      }|D ��cg c]  \  }}|j                  «       dk7  sŒ||f‘Œ c}}| d<   t        j                   «       }d}|rG|�Et        ||«      ƒ d{  –—† }|j                  }|rt        |j                   xs g «      n	t        «       }t#        | ||||||¬	«      ƒ d{  –—†  t%        | |||«      ƒ d{  –—†  t'        ||||||	|¬
«       t(        s/t+        «       ƒ d{  –—†  t-        j.                  d«      ƒ d{  –—†  t1        ||||
¬«      4 ƒd{  –—†  t2        j5                  | ||«      ƒ d{  –—†  ddd«      ƒd{  –—†  y7 �Œêc c}}w 7 Œý7 Œ´7 Œ 7 Œx7 Œ]7 ŒG7 Œ*7 Œ# 1 ƒd{  –—†7  sw Y   yxY w# t6        $ rL}|j9                  t;        t        | «      «      | j                  d«      xs | j                  d«      ¬«      ‚d}~wt<        $ r ‚ t>        $ r}tA        |«      ‚d}~wtB        $ r€}t        jD                  d|«       	 ddl#m$} ddl%m&}  ||dtO        |«      dœ¬«      } || ||«      ƒ d{  –—†7   n)# tB        $ r}t        jD                  d|«       |‚d}~ww xY wY d}~yd}~ww xY w­w)z Handle MCP requests through SSE.rœ  r|   Nr{   rý  rþ  rº   rÿ  r   ©re  rf  rg  rh  ri  rn   r”  r  r  r  r  r  r   r   r   r"  r  r�  r#  )(r™   rZ  rY   rW  r7   r$  r¹  r   rq  r2  rr  rs   r!   r©  ra  rn  rg  rÌ  rû  Úset_auth_contextrL  rT  rD  rE  rZ  r.  r  r    r)  r   r   r4   rÀ   rF  rG  Ústarlette.responsesr   r*  r!  rr   )r§   rz  rƒ  rœ  re  rf  rg  rh  ri  rn   rP  Ú_sse_client_ipr`  r$  r?  r+  r,  r£  rI  r   r!  r:  r;  s                          rT   Úhandle_sse_mcprB  q  s_  è ø€ ðn	Ø$Ÿy™y¨°Ó4ˆDô /¨u°dÓ;×;ñØ!ØØØ'ØØä,/Ô0HÈÓ0NÒ0TÐRTÓ,UÐYZÑ,ZÐ"ô %3×$DÑ$DÔEUÐV[ÓE\Ó$]ˆNä× Ñ Ð!LÈkÔZÜ× Ñ Ø-ÑWn¬tÐ4K×4PÑ4PÓ4RÔ/SÐtxôð
 CHÇ)Á)ÈIÐWYÓBZˆMØ3@×e©4¨1¨aÀAÇGÁGÃIÐQdÓDd  A¢ÓeˆE�)Ñô
 (>×'AÑ'AÓ'CÐØ:>Ð&Ù Ð%6Ð%BÜ*>Ð?PÐRcÓ*d×$dÐ!Ø-×?Ñ?�ÙJL¬S°·±Ò1EÀ2Ô-FÔRUÓRWÐ*ô DØØ'Ø-Ø(?Ø"3Ø(Ø#=ô÷ ð ô  3°5Ð:KÈ[ÐZhÓi×iÐiÜØ"3Ø /Ø'Ø(?Ø-Ø'Ø(õõ 1Ü1Ó3×3Ð3Ü—m‘m CÓ(×(Ð(äEØ!ØØØ'=ô	÷ Oñ Oô *×8Ñ8¸ÀÈÓN×NÐN÷O÷ Oð Oð{ <ûó  fð %eøðøð  jøð 4øØ(øðOøð OøðOø÷ O÷ Oñ Oûô $ò 	ð ×%Ñ%Ü-Ô.>¸uÓ.EÓFØ"ŸY™YÐ'7Ó8ÒM¸E¿I¹IÀfÓ<Mð &ó ð ûô ò 	ð Üò 	8ô
 5°QÓ7Ð7ûÜò 	Ü×$Ñ$Ð%EÀqÔIðå<ÝKá(4Ø >Ø&:ÄsÈ1ÃvÑNô)�ñ % U¨G°TÓ:×:Ò:øÜò Ü×(Ñ(Ð)LÈnÔ]à�ûðúô ;ûð	üs[  ‚L<„!H= ¥H¦B"H= ÃHÃ$HÃ*0H= ÄHÄA
H= Å%HÅ&H= Å;HÅ<)H= Æ%HÆ&H= ÇH ÇH= ÇH"ÇH= ÇH(Ç9H$Ç:H(Ç>H= È	H&È
H= ÈL<ÈH= ÈH= ÈH= ÈH= ÈH= È H= È"H= È$H(È&H= È(H:È.H1È/H:È6H= È9L<È:H= È=	L9ÉAJÊL9Ê"J-Ê-L9Ê9L4Ë/LË?LÌ LÌL4Ì	L,ÌL'Ì'L,Ì,L4Ì/L<Ì4L9Ì9L<)Útitler  r  r]  z/enabledz$Returns if the MCP server is enabled)r  c                  ó   — dt         iS )z6
        Returns if the MCP server is enabled
        Úenabled)r^   rî   rV   rT   Úget_mcp_server_enabledrF  ë  s   € ð œ=Ð)Ð)rV   r9  z/mcpz/{mcp_server_name}/mcpz/sser	  c                 ón   — || _         || _        || _        |xs i | _        || _        || _        || _        y r  r>  ©r	  re  rf  rg  rh  ri  rn   r”  s           rT   Ú_update_auth_contextrI     sA   € ð '8ˆ	Ô#Ø$3ˆ	Ô!Ø +ˆ	ÔØ,CÒ,IÀrˆ	Ô)Ø#1ˆ	Ô Ø +ˆ	ÔØ'ˆ	ÕrV   c           	      óT   — t        | ||||||¬«      }t        j                  |«       |S )aç  
        Set the UserAPIKeyAuth in the auth context variable.

        Args:
            user_api_key_auth: UserAPIKeyAuth object
            mcp_auth_header: MCP auth header to be passed to the MCP server (deprecated)
            mcp_servers: Optional list of server names and access groups to filter by
            mcp_server_auth_headers: Optional dict of server-specific auth headers {server_alias: auth_value}
            client_ip: Client IP address for MCP access control
        r>  )rË   rÂ   rn  )re  rf  rg  rh  ri  rn   r”  r	  s           rT   r?  r?    s9   € ô& 0Ø/Ø+Ø#Ø$;Ø)Ø#Øô
ˆ	ô 	×Ñ˜YÔ'ØÐrV   r  r  c
           
      ó  — |rt         j                  |«      nd }
|
�]|�[|rt        j                  «       t        |<   |	rt        | ||||||¬«      S t        |
| ||||||¬«       t        j                  |
«       |
S t        | ||||||¬«      S )Nr>  rH  )	r  r™   r[   r\   r  r?  rI  rÂ   rn  )re  rf  rg  rh  ri  rn   r”  r"  r  r  r	  s              rT   r  r  1  s»   € ñ OYÔ:×>Ñ>¸zÔJÐ^bˆ	ØÐ  ZÐ%;ÙÜGKÇ~Á~ÓGWÔ8¸ÑDÙ1Ü'Ø&7Ø$3Ø +Ø,CØ#1Ø +Ø'ôð ô !Ø#Ø"3Ø /Ø'Ø(?Ø-Ø'Ø#õ	ô × Ñ  Ô+ØÐÜØ/Ø+Ø#Ø$;Ø)Ø#Øô
ð 	
rV   Úowner_fingerprintÚon_session_registeredc                 ó0   ‡ ‡‡‡— dt         dd fˆˆˆˆ fd„}|S )Nr¿   rQ   c              “   ó   •K  — | j                  d«      dk(  rÓ| j                  dg «      }|D ]¼  \  }}t        |t        «      r|nt        |«      j	                  «       }|j                  «       dk(  sŒEt        |t        «      r|j                  «       n
t        |«      }‰� ‰|«       t        j                  ‰«       ‰t        |<   t        j                  «       t        |<   ‰t        |<    n  ‰	| «      ƒ d {  –—†  y 7 Œ­w)Nr±  zhttp.response.startrº   r\  )r™   rq   r]  rr   r^  rs   r_  rÂ   rn  r  r[   r\   r  r  )
r¿   Úresponse_headersrt   ru   ra  r"  r	  rM  rL  rƒ  s
         €€€€rT   Úwrapped_sendzC_wrap_send_with_stateful_session_auth_context.<locals>.wrapped_sendg  sá   øè ø€ Ø�{‰{˜6Ó"Ð&;Ò;ØU\×U`ÑU`ÐajÐlnÓUoÐ Ø"2ò 
‘J�C˜Ü)3°C¼Ô)?¡#ÄSÈÃXÇ_Á_ÓEV�KØ"×(Ñ(Ó*Ð.?Ó?Ü7AÀ%ÌÔ7O U§\¡\¤^ÔUXÐY^ÓU_˜
Ø0Ð<Ù1°*Ô=Ü(×,Ñ,¨YÔ7ØFOÔ7¸
ÑCÜOSÏ~É~ÓO_Ô@ÀÑLØ?PÔ0°Ñ<Ùð
ñ �w“-×Òús   ƒA-C>Á1BC>Ã6C<Ã7C>)r   )rƒ  r	  rL  rM  rQ  s   ```` rT   r  r  a  s#   û€ ð	 ¬ð 	 °D÷ 	 ð 	 ð  ÐrV   c                  óî   — t        j                  «       } | r_t        | t        «      rO| j                  | j
                  | j                  | j                  | j                  | j                  | j                  fS y)a  
        Get the UserAPIKeyAuth from the auth context variable.

        Returns:
            Tuple containing: UserAPIKeyAuth, MCP auth header (deprecated),
            MCP servers, server-specific auth headers, OAuth2 headers, raw headers, client IP
        ©NNNNNNN)rÂ   r™   rq   rË   re  rf  rg  rh  ri  rn   r”  r  s    rT   Úget_auth_contextrT  y  sm   € ô  ,×/Ñ/Ó1ˆ	Ùœ IÔ/CÔDà×+Ñ+Ø×)Ñ)Ø×%Ñ%Ø×1Ñ1Ø×(Ñ(Ø×%Ñ%Ø×#Ñ#ðð ð 8rV   c                  ón   — 	 ddl m}  | j                  «       j                  S # t        t
        f$ r Y y w xY w)Nr   r_  )rm  r`  r™   ro  ÚLookupErrorr    r_  s    rT   Ú_get_current_sessionrW  –  s4   € ð	Ý>à—?‘?Ó$×,Ñ,Ð,øÜœ[Ð)ò 	Ùð	ús   ‚" ¢4³4c                  óP  — t        «       } | €y 	 | t        v ry 	 t        j                  «       }|rt        |t        «      r	 |t        | <   y y y # t        $ r, t        j                  dt        | «      j                  «       Y y w xY w# t        $ r t        j                  d«       Y y w xY w)Nz]_cache_auth_context_lazily: session object is unhashable (type=%s), cannot cache auth contextuf   _cache_auth_context_lazily: could not store auth via session identity â€” session object is unhashable)rW  rh   r½   r   rq  r±  rè   rÂ   r™   rq   rË   )ro  Úauths     rT   Ú_cache_auth_context_lazilyrZ  ž  s´   € Ü-Ó/ˆØˆ?Øð	ØÔ3Ñ3Øð 4ô '×*Ñ*Ó,ˆÙ”J˜tÔ%9Ô:ðØ59Ô)¨'Ò2ð ;ˆ4øô ò 	Ü× Ñ ØoÜ�W“×&Ñ&ôñ ð	ûô ò Ü×$Ñ$ðHöðús#   �A Á 	B Á2BÂ BÂB%Â$B%c                  óÂ   — t        «       } | €y d }	 t        j                  | «      }|S # t        $ r- t	        j
                  dt        | «      j                  «       Y |S w xY w)Nzm_recover_auth_from_session: session object is unhashable (type=%s), skipping _session_obj_auth_storage lookup)rW  rh   r™   r½   r   rq  r±  rè   )ro  Ústoreds     rT   Ú_recover_auth_from_sessionr]  ¶  sl   € Ü-Ó/ˆØˆ?Øà.2ˆð	Ü.×2Ñ2°7Ó;ˆFð ˆøô ò 	Ü× Ñ ðGä�W“×&Ñ&õð ˆð	ús   ‘( ¨2AÁAc               ƒ   ó  K  — t        «       \  } }}}}}}| �t        «        n`t        «       }|rT|j                  } |j                  }|j
                  }|j                  }|j                  }|j                  }|j                  }| ||||||fS ­w)zš
        Get auth context from ContextVar first, then fall back to session
        storage (which survives cross-task boundaries in the MCP SDK).
        )
rT  rZ  r]  re  rf  rg  rh  ri  rn   r”  )re  rf  rg  rh  ri  rn   r|  r\  s           rT   rp  rp  Ç  s¯   è ø€ ô* Óñ	
ØØØØ#ØØØð Ð(Ü&Õ(ä6Ó8ˆFáØ$*×$<Ñ$<Ð!Ø"(×"8Ñ"8�Ø$×0Ñ0�Ø*0×*HÑ*HÐ'Ø!'×!6Ñ!6�Ø$×0Ñ0�Ø#×-Ñ-�
àØØØ#ØØØð
ð 	
ùs   ‚B	Bc                  óF   — t         j                  «       } | �| S t        «       S )z@Return the active MCP session captured during handler execution.)rl   r™   rW  )ro  s    rT   Úget_active_mcp_sessionr`  õ  s$   € ä/×3Ñ3Ó5ˆØÐØˆNÜ#Ó%Ð%rV   c                  óp   — t        j                  «       } | rt        | t        «      r| S t	        «       }|�|S y)z7Return auth context from ContextVar or session storage.N)rÂ   r™   rq   rË   r]  )rY  r\  s     rT   Úget_active_auth_contextrb  ü  s8   € ä&×*Ñ*Ó,ˆÙ”J˜tÔ%9Ô:ØˆKä2Ó4ˆØÐØˆMØrV   )NNr  r  )rQ   zListToolsResult | list[Tool])NNNNN)F)NNNFNNNN)NNN)	NNNNNNFNN)NNNNNNrS  )g      @)	NNNNNNNTF(@  rë   rD  rW  Úcontextvarsrj  r‹  r[   rŸ  Útypesr˜  Úcollections.abcr   r   r   r   r   Útypingr   r	   r
   r   rä  Úfastapir   r   Úpydanticr   r   Ústarlette.requestsr   r¹  r@  r   Ústarlette.typesr   r   r   r   Úlitellm._loggingr   Úlitellm.constantsr   Ú*litellm.litellm_core_utils.litellm_loggingr   ÚLiteLLMLoggingObjÚ&litellm.llms.custom_httpx.http_handlerr   r   ÚAlitellm.proxy._experimental.mcp_server.auth.user_api_key_auth_mcpr   r   Ú=litellm.proxy._experimental.mcp_server.discoverable_endpointsr   Ú1litellm.proxy._experimental.mcp_server.exceptionsr   r    Ú2litellm.proxy._experimental.mcp_server.mcp_contextr!   r"   r#   Ú0litellm.proxy._experimental.mcp_server.mcp_debugr$   Ú2litellm.proxy._experimental.mcp_server.oauth_utilsr%   r&   r'   r(   rø  r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r�  r4   r5   r6   Ú#litellm.proxy.auth.ip_address_utilsr7   rÈ  r8   r9   Úlitellm.types.mcpr:   r;   Ú+litellm.types.mcp_server.mcp_server_managerr<   r=   Úlitellm.types.utilsr>   r?   Úlitellm.utilsr@   rA   rB   Úmcp.server.sessionrC   Ú_McpServerSessionr,  rD   rE   r˜   ró  rr   r�  rì   rG   rH   rI   rK   rL   rN   rU   r]   r^   r‡   ÚweakrefrF  r_   r`   Ú
mcp.serverra   Ú mcp.server.lowlevel.helper_typesrb   rs  rc   rd   re   rf   rg   ÚWeakKeyDictionaryrh   r    rI  rq  Ú
ContextVarrl   rL  r(  rm   rv   r�   r'  rœ   r¡   r¥   r«   r®   r±   r´   rÀ   Ú'mcp.server.auth.middleware.auth_contextrÁ   rÂ   rm  rÃ   Úmcp.server.modelsrÄ   Ú"mcp.server.streamable_http_managerrÅ   rÆ   rÇ   rÈ   rÉ   rž  Ú@litellm.proxy._experimental.mcp_server.auth.litellm_auth_handlerrË   Ú;litellm.proxy._experimental.mcp_server.faults.list_outcomesrÌ   rÍ   rÎ   rÏ   rÐ   rÑ   Ú9litellm.proxy._experimental.mcp_server.mcp_server_managerrÒ   rÓ   rÔ   rÕ   rÖ   r×   Ú?litellm.proxy._experimental.mcp_server.openapi_to_mcp_generatorrØ   rÙ   rÚ   Ú4litellm.proxy._experimental.mcp_server.sse_transportrÛ   Ú4litellm.proxy._experimental.mcp_server.tool_registryrÜ   rÝ   rÞ   rß   rà   rá   râ   rã   rå   r2  rú   r	  r  Ú
MethodTyper  r  r  r  r  r  r  r  r  r»   r  r!  r*  r,  r-  r.  rO  rP  rQ  r/  ÚTaskr7  rB  rJ  rT  r[  Úasynccontextmanagerr]  rc  r€  r’  r§  rº  rB  rÏ  rÔ  r×  rÛ  rà  rå  rð  rõ  rý  r  r
  r  r"  r%  r-  r5  rD  rO  rZ  r^  r±  r¸  r½  rÁ  r�  rw  rÒ  rÙ  rÞ  rÔ  r  rç  r  r  Ú	frozensetr  r,  r¤  rÖ  rã  rÿ  r  r  rW  rZ  rb  rs  r]  ry  r‚  r”  r©  rn  rÌ  rÎ  rÁ  r¿  rÔ  rÃ  rû  r<  rB  r  r™   rF  ÚmountÚadd_middlewarerI  r?  r  r  rT  rW  rZ  r]  rp  r`  rb  rî   rV   rT   ú<module>r‘     sC  ðòó Û Û Û Û Û Û Û Û ß FÓ FÝ ß 6Ó 6ã ß *ß 'Ý :Ý ,ß 9Ó 9å +Ý <Ý S÷÷õ÷÷ñ õ
 F÷ó ÷÷ ÷ ñ ÷ñ õ
 ?÷÷ 6ß Jß Eß 7Ñ 7áÝEåPð LNÐ �%˜˜U 3¨ 8™_¨e°C¸$±JÀÐ4EÑ.FÐFÑGÑHÓ MØ Ð �eÓ  Ø#'Ð ˜5Ó 'Ø07Ð &¨Ó 7ð +.Ð   %Ó -ð
 &*Ð ˜UÓ )ð (EÐ ˜uÓ Dð5¨ð 5¸ð 5Àó 5ðL Cð L°Cð LÀSÈ4ÁZð LÐTXó Lð €ˆtÓ ð Ûç0Ý!ÝEÝE÷õ ð \uÐ[b×[tÒ[tÓ[vÐÐXÓvð  UkÐT_×TjÒTjØ $ôUÐ ˜˜k×4Ò4Ð5OÑPÑQó ð !&Ð Ø*˜gŸlšl›nÐ �eÓ ,ð
Ø�c˜3�h‘ $Ñ&ð
àˆ4�Zó
ð3¨Sð 3°Tó 3ðl Vð °°S¸#°X±ÀÑ0Eó ð0¨¨c°3¨h©¸$Ñ)>ð À6ó ð¨ð °Dó ð4°ð 4¸4ó 4ð@4¨vð 4¸&ó 4ð vð °&ó ð ¨&ð °Tó ð¨Nð ¸}ó ò, Ý!÷õ ?Ý7ð,ÝS÷ó õ *õ÷÷ ÷÷ ÷ñ õ
 Xõ÷õ ÷ Lô@¨Gô @ð¨tð ¸Ð=QÑ8Ró ð< <@ØIMòDà1°DÑ8ðDð $(¨¨T°#°v°+Ñ->Ð(>Ñ#?À$Ñ#FðDð 
ó	Dñ, #Ø$Ø*ô€FˆE�&‰Mó ð ,<¨5×+;Ò+;Ð<bÐdjÓ+k€FÔ(Ù%7Ð8KÓ%L€CˆÐ!Ñ	"ÓLñ (DØØØØô	(Ð˜uó ñ 'CØØØØô	'Ð˜eó ð OQÐ# U¨4°Ð5IÐ0IÑ+JÑ%KÓPØHJÐ,¨e°D¸¸e¸Ñ4DÑ.EÓJð
 79Ð˜e D¨¨c¨¡NÑ3Ó8ð ?AÐ˜U 4¨¨W¯\ª\Ð(9Ñ#:Ñ;Ó@ØEGÐ+¨U°4¸¸S¸±>Ñ-BÓGô/˜xô /ô_˜Xô _ð
JÐ(:ó JðF°cð F¸dó Fð 7€O�UÓ6ñ ">ØØØØô	"Ð˜ó ð ÐØ#'Ð Ø"ÐØ?CÐ'¨¯ª¸Ñ)<ÓCð !ò!>Ø�T‰\ð!>à	ó!>ðF%Q¸Sð %QÀTó %QôNcòdò<2ð@ ×#Ò#ð.˜}¨TÑ2ò .ó $ð.ð ×ÒÓóOCó ðOCðb ¸À4¹ó  ðJ 15Ø $ò!#Øð!#à˜˜V˜Ñ$ð!#ð *ð!#ð ˜S #˜XÑ&¨Ñ-ð	!#ð
 ˜‘:ð!#ð 
˜TÑ	!ó!#ðP )-Ø&*ØDHØ04Ø-1òT
ØðT
à˜˜V˜Ñ$ tÑ+ðT
ð *¨DÑ0ðT
ð ˜‘:ð	T
ð
 ˜#‘Y Ñ%ðT
ð ˜t™ðT
ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!AðT
ð ˜S #˜X™¨Ñ-ðT
ð ˜#˜s˜(‘^ dÑ*ðT
ð 
˜$Ñ	óT
ðl ×ÒÓðhC¨ð hC¸¸cÀ6¸kÑ9JÈTÑ9Qð hCÐVdò hCó ðhCðT ×ÒÓð/C  V¡ò /Có ð/Cðb ×ÒÓð,C˜sð ,C¨t°C¸°H©~ÀÑ/Dð ,CÈò ,Có ð,Cð\ ×ÒÓð)C $ x¡.ò )Có ð)CðV ×#Ò#Ó%ð+C¨4Ð0@Ñ+Aò +Có &ð+CðZ ×ÒÓð C ð  C¨DÐ1EÑ,Fò  Có ð CðT8#Ø˜#‘Y Ñ%ð8#à! )™_ð8#ð 
ˆi‰ó8#ðt
U cð 
U¸¸S¹	ð 
UÈyð 
UÐ]aó 
Uð(Ø�G‰}ð(àð(ð 
ˆg‰ó(ðTØ�G‰}ðàðð 
ˆg‰óð.¨¨t©ó ð  !%ò;#Ø)¨DÑ0ð;#à˜#‘Y Ñ%ð;#ð ˜‘:ð;#ð 
ˆi‰ó	;#ðzØðà!% c¨4°°S°©>Ð&9Ñ!:¸TÑ!Aðð 
óð:SØðSà˜S #˜X™¨Ñ-ðSð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!AðSð 
ó	Sð, MQòGØðGà)¨DÑ0ðGð JðGð 
ˆc�3ˆh‰˜$Ñ	ô	Gð*Ø)¨DÑ0ðà	ˆcÐ+Ð+Ñ	,ôð> 48Ø04òf1Øðf1à!% c¨4°°S°©>Ð&9Ñ!:¸TÑ!Aðf1ð ˜t™ðf1ð ˜S #˜X™¨Ñ-ð	f1ð
 ˜#˜s˜(‘^ dÑ*ðf1ð *¨DÑ0ðf1ð ˜I‘¨Ñ-ðf1ð 
ˆt�C˜�H‰~ Ñ# dÑ*¨D°°c°©N¸TÑ,AÐAÑ	Bôf1ðPKØ! )™_ðKà	ˆt‰ôKð2 ×#Ò#ð
 (-ò	$>Ø)¨DÑ0ð$>à˜#‘Y Ñ%ð$>ð ˜‘:ð$>ð !%ð	$>ð
 
�tÑ	ò$>ó $ñ$>ðL6 ið 6°Cô 6ð EIØ04Ø-1Ø,1Ø,0Ø'+Ø)-Ø $òWØ)¨DÑ0ðWà˜t™ðWð ˜#‘Y Ñ%ðWð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	Wð
 ˜S #˜X™¨Ñ-ðWð ˜#˜s˜(‘^ dÑ*ðWð &*ðWð  # T™zðWð  ™*ðWð ˜3‘i $Ñ&ðWð ˜‘:ðWð 
ôWðz EIØ04Ø-1ò?Ø)¨DÑ0ð?à˜t™ð?ð ˜#‘Y Ñ%ð?ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	?ð
 ˜S #˜X™¨Ñ-ð?ð ˜#˜s˜(‘^ dÑ*ð?ð 
ˆf‰ô?ðJ EIØ04Ø-1ò1Ø)¨DÑ0ð1à˜t™ð1ð ˜#‘Y Ñ%ð1ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	1ð
 ˜S #˜X™¨Ñ-ð1ð ˜#˜s˜(‘^ dÑ*ð1ð 
ˆh‰ô1ðn EIØ04Ø-1ò;&Ø)¨DÑ0ð;&à˜t™ð;&ð ˜#‘Y Ñ%ð;&ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	;&ð
 ˜S #˜X™¨Ñ-ð;&ð ˜#˜s˜(‘^ dÑ*ð;&ð 
ÐÑ	ô;&ðz
Ø�G‰}ð
àð
ð *¨DÑ0ð
ð 
ˆg‰ô	
ð: 48Ø&*Ø(,ØDHØ04Ø-1Ø,1Ø,0Ø $ò-?Ø)¨DÑ0ð-?à˜t™ð-?ð ˜#‘Y Ñ%ð-?ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	-?ð
 ˜S #˜X™¨Ñ-ð-?ð ˜#˜s˜(‘^ dÑ*ð-?ð &*ð-?ð  # T™zð-?ð ˜‘:ð-?ð 
ô-?ð` 48Ø&*Ø(,ØDHØ04Ø-1ò&Ø)¨DÑ0ð&à˜t™ð&ð ˜#‘Y Ñ%ð&ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	&ð
 ˜S #˜X™¨Ñ-ð&ð ˜#˜s˜(‘^ dÑ*ð&ð 
ˆf‰ô&ðR 48Ø&*Ø(,ØDHØ04Ø-1ò!Ø)¨DÑ0ð!à˜t™ð!ð ˜#‘Y Ñ%ð!ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	!ð
 ˜S #˜X™¨Ñ-ð!ð ˜#˜s˜(‘^ dÑ*ð!ð 
ˆh‰ô!ð< 48Ø&*Ø(,ØDHØ04Ø-1ò!*Ø)¨DÑ0ð!*à˜t™ð!*ð ˜#‘Y Ñ%ð!*ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	!*ð
 ˜S #˜X™¨Ñ-ð!*ð ˜#˜s˜(‘^ dÑ*ð!*ð 
ÐÑ	ô!*ðFØðà! )™_ðð 
ôð$!Øð!à)¨DÑ0ð!ð 
ˆt‰ô!ðFVØðVà)¨DÑ0ðVð 
ôVðz 48Ø&*ØDHØ04Ø-1Ø26ò~
Øð~
à˜˜V˜Ñ$ð~
ð " )™_ð~
ð ð	~
ð
 *¨DÑ0ð~
ð ˜t™ð~
ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að~
ð ˜S #˜X™¨Ñ-ð~
ð ˜#˜s˜(‘^ dÑ*ð~
ð !)¨4¡ð~
ð ð~
ð 
ô~
ð@

Øð
à.°Ñ5ð
ð *¨DÑ0ð
ð ˜c 6˜kÑ*ð	
ð
 
ô
ò4 -6ò	
ó-Ñ" Eó ð 48Ø48ò@Ø&ð@àð@ð ð@ð ð	@ð
 *¨DÑ0ð@ð ˜c 6˜kÑ*¨TÑ1ð@ð 
ô@ðD ð /3Ø37Ø&*Ø(,ØDHØ04Ø-1ògØðgà˜˜V˜Ñ$ tÑ+ðgð *¨DÑ0ðgð ˜t™ð	gð
 ˜#‘Y Ñ%ðgð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Aðgð ˜S #˜X™¨Ñ-ðgð ˜#˜s˜(‘^ dÑ*ðgð ðgð 
ògó ñgðV /3Ø37Ø&*Ø(,ØDHØ04Ø-1ò2
Øð2
à˜˜V˜Ñ$ tÑ+ð2
ð *¨DÑ0ð2
ð ˜t™ð	2
ð
 ˜#‘Y Ñ%ð2
ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að2
ð ˜S #˜X™¨Ñ-ð2
ð ˜#˜s˜(‘^ dÑ*ð2
ð 
ô2
ðl 48Ø&*Ø(,ØDHØ04Ø-1ò/
Øð/
à)¨DÑ0ð/
ð ˜t™ð/
ð ˜#‘Y Ñ%ð	/
ð
 "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að/
ð ˜S #˜X™¨Ñ-ð/
ð ˜#˜s˜(‘^ dÑ*ð/
ð 
ô/
ðj "&ò	Øðà˜˜V˜Ñ$ðð ˜4‘Zðð ˜$‘Jð	ð
 
$ôð@ 48Ø&*ØDHØ04Ø-1Ø8<Ø26ò Øð àð ð ˜˜V˜Ñ$ð ð *¨DÑ0ð	 ð
 ˜t™ð ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að ð ˜S #˜X™¨Ñ-ð ð ˜#˜s˜(‘^ dÑ*ð ð /°Ñ5ð ð !)¨4¡ð ð 
ô ð@c¨3ð c¸4ÀÀVÀÑ;Lð cÐQ_ô cð@*% sð *%¨t°C©y¸4Ñ/?ô *%óX 
ðD
¨%ð 
°C¸$±Jô 
ð 15Ø $ò6Ø)¨DÑ0ð6à˜S #˜X™¨Ñ-ð6ð ˜‘:ð6ð 
ô	6ðp¡Uð ¨tô ð08Øð08à	ˆt�G‰}™eÐ#Ñ	$ô08ðdQØðQàðQð ðQð ,ð	Qð
 
ôQðf>VØ)ð>Vàð>Vð 
ô>VðN /3òQØðQà˜#‘Y Ñ%ðQð ˜S #˜X™¨Ñ-ðQð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	Qð
 *¨DÑ0ðQð ˜‘:ðQñ   ™H t™OðQð 
ôQðf°Eð ¸cÀD¹jô ðG¨uð G¸ô Gð;¨eð ;¸¸d¹
ô ;ð"
°9ð 
Àô 
ð" ò4Øð4àð4ð ð4ð 
ˆs�C˜$‘JˆÑ	ô	4ðltØðtà)¨DÑ0ðtð ˜#‘Y Ñ%ðtð ˜‘:ð	tð
 
ôtðl@°ð @Àð @Ètð @ÐX\ô @ðD
p Eð p°Gð pÀ4ð pÈDô pñd Ø%Ø2Ø*Øô	�Cñ 	‡W‚WØØ:ð ó ð* D¨¨d¨¡Oò *ó	ñ*ñ ‡I‚IˆcÑ-Ô.Ù‡I‚IˆfÑ0Ô1Ù‡I‚IÐ&Ñ(BÔCÙ‡I‚Iˆf‘nÔ%Ù×ÒÐ,Ô-ð '+Ø(,ØDHØ04Ø-1Ø $ò(Ø'ð(à)¨DÑ0ð(ð ˜t™ð(ð ˜#‘Y Ñ%ð	(ð
 "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að(ð ˜S #˜X™¨Ñ-ð(ð ˜#˜s˜(‘^ dÑ*ð(ð ˜‘:ð(ð 
ô(ð( '+Ø(,ØDHØ04Ø-1Ø $òØ)¨DÑ0ðà˜t™ðð ˜#‘Y Ñ%ðð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	ð
 ˜S #˜X™¨Ñ-ðð ˜#˜s˜(‘^ dÑ*ðð ˜‘:ðð 
ôðB '+Ø(,ØDHØ04Ø-1Ø $Ø!%Ø $Ø38ò.
Ø)¨DÑ0ð.
à˜t™ð.
ð ˜#‘Y Ñ%ð.
ð "& c¨4°°S°©>Ð&9Ñ!:¸TÑ!Að	.
ð
 ˜S #˜X™¨Ñ-ð.
ð ˜#˜s˜(‘^ dÑ*ð.
ð ˜‘:ð.
ð ˜$‘Jð.
ð ð.
ð -1ð.
ð 
ô.
ðh ?Cò	Øðà'ðð ðð  (¨¨¨t¨Ñ4°tÑ;ð	ð
 
õð08˜eØ˜ÑØˆd‰
ØˆS‰	�DÑØˆS�$�s˜C�x‘.Ð Ñ! DÑ(ØˆS�#ˆX‰˜ÑØˆS�#ˆX‰˜ÑØˆd‰
ð	ñõ 8ô:ôð0Ð(<¸tÑ(Cõ ð",
¨uØ˜ÑØˆd‰
ØˆS‰	�DÑØˆS�$�s˜C�x‘.Ð Ñ! DÑ(ØˆS�#ˆX‰˜ÑØˆS�#ˆX‰˜ÑØˆd‰
ð	ñ0õ ,
ð\&Ð$5¸Ñ$<õ &ð	Ð%9¸DÑ%@ö 	ñ  ‹)‚CøðgS ò  Ø€N×ÒÐ3°QÔ7Ø€Mð  ÐØ€OØÐØÐØ€HØÐØ€FØÖûð ûð@ ò ,Ø'+Ó$ð,ús+   ÆA}* Ê~# ý*~ ý/&~þ~ þ#~.þ-~.