Ë
    tPêjB ã                   ó´  — U d 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 ddl	m
Z
 ddlmZmZmZ ddlmZmZmZmZ ddlmZmZmZmZmZmZmZmZmZ ddlmZ dd	lm Z m!Z! 	 dd
l"m#Z#m$Z$ ddl'Z'ddl(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 ddl/m7Z8 ddl9m:Z:m;Z; ddl<m=Z=m>Z> ddl?m@Z@mAZA  eddg¬«      ZBeeCd<   dZDeEeCd<   dZFeeCd<   dZGeeCd<    G d„ de«      ZHdeeH   d eId!eEfd"„ZJd#ZKeeCd$<   erdd%lLmMZN dd&lOmPZP 	  ej¢                  d«       eD�rå	 dd)lTmUZU dd/lYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_m`Z`maZambZbmcZcmdZdmeZemfZfmgZgmhZhmiZimjZjmkZkmlZlmmZmmnZnmoZompZp dd0lqmrZrmsZsmtZtmuZumvZvmwZwmxZxmyZy dd1lzm{Z{ dd2l|m}Z}m~Z~mZ dd3l€m�Z�m‚Z‚mƒZƒm„Z„m…Z…m†Z†m‡Z‡mˆZˆm‰Z‰mŠZŠm‹Z‹mŒZŒm�Z�mŽZŽm�Z�m�Z�m‘Z‘m’Z’m“Z“m”Z” dd4l•m–Z–m—Z— dd5l˜m™Z™mšZš dd6l›mœZœ dd7l�mžZžmŸZŸm Z m¡Z¡m¢Z¢m£Z£m¤Z¤m¥Z¥ dd8l¦m§Z§ dd9l¨m©Z©mªZªm«Z«m¬Z¬ dd:l­m®Z® e
 G d;„ d<«      «       Z¯d=e2d!dfd>„Z°d=e2d!dfd?„Z±d=e2d!dfd@„Z7d=e�d!dfdA„Z² e³e��jh                  «      Zµee³   eCdB<   d=e�d!dfdC„Z¶d!eEfdD„Z·dEeIdFeId!eIfdG„Z¸dHe®d!eIfdI„Z¹ G dJ„ dKe!«      Zº G dL„ dMe!«      Z»dHe®dEeId!e»fdN„Z¼dEeId!e»fdO„Z½i Z¾ee¿eIe¯f      eCdP<   �ddQ„ZÀdHe®dReÁd!e®fdS„ZÂdHe®dReÁd!dfdT„ZÃdUeId!e®dz  fdV„ZÄ�ddW„ZÅd=e�dUeIdXeId!dfdY„ZÆdUeId!e®dz  fdZ„ZÇdUeId!e®dz  fd[„ZÈd\e�d!e�fd]„ZÉ	 	 	 	 �dd_„ZÊd`ee�   d!eËe�   fda„ZÌdbe“d!eEfdc„ZÍdbe“d!eEfdd„ZÎd\e�d!e�fde„ZÏd`ee�   d!eËe�   fdf„ZÐd\e�d!e�fdg„ZÑd`ee�   d!eËe�   fdh„ZÒdiZÓeeÔeÔeIeIf   djf      eCdk<   d^dld!eEfdm„ZÕd=e�d!e�fdn„ZÖd=e�d!eIfdo„Z×d=e�dXeIdz  dUeId!e�fdp„ZØdqeIfdr„ZÙeB�jµ                  dsdg ee—«      g¬t«       ee—«      fdbe“fdu„«       ZÛeB�jµ                  dvdg ee—«      g¬t«       ee—«      fdbe“fdw„«       ZÜeB�jµ                  dxdg ee—«      gdy¬z«      d{efd|„«       ZÝeB�jµ                  d}dgd~¬«      d{efd€„«       ZÞd!e”fd�„Zßd‚eId!eËe�   fdƒ„Zàdbe“d!eËe�   fd„„Zádbe“d!e³eI   fd…„ZâeB�jµ                  d†d‡ ee—«      geËe�   ¬ˆ«       ee—«       edd‰¬Š«       ed(d‹¬Š«      fdbe“d‚eIdz  dŒeEfd�„«       ZãeB�jµ                  dŽd� ee—«      g¬�«       edd‘¬Š«       ee—«      fd’eËeI   dz  dbe“fd“„«       ZäeB�jË                  d”d• ee—«      ge�e�jÌ                  ¬–«      e§ ee—«      fd=e�dbe“fd—„«       «       ZçeB�jµ                  d˜d™ ee—«      ge‡¬ˆ«      e§ ee—«      fdbe“fdš„«       «       ZèeB�jÓ                  d›dœ ee—«      ge�¬ˆ«      e§ ee—«      fdUeIdbe“fd�„«       «       ZêeB�jÓ                  dždŸ ee—«      ge�¬ˆ«      e§ ee—«      fdUeId=e�dbe“fd „«       «       ZëeB�jµ                  d¡d¢ ee—«      ge�¬ˆ«       ee—«      fd{edUeIdbe“fd£„«       ZìeB�jË                  d†d¤ ee—«      ge�e�jÌ                  ¬–«      e§ ee—«       edd¥¬Š«      fd=e�dbe“d¦eIdz  fd§„«       «       ZíeB�jË                  d¨d© ee—«      fe¢e�jÜ                  ¬–«      e§ ee—«      fd=e¡dbe“fdª„«       «       ZïeB�jË                  d«d¬ ee—«      ge�jÜ                  ¬­«      e§ ee—«       edd¥¬Š«      fd=e�dbe“d¦eIdz  fd®„«       «       Zðd{ed!e“fd¯„Zñ	 �ddUeIdbe“d{edz  d!e®fd°„ZòeB�jµ                  d±d( eeñ«      g¬²«       eeñ«      d edj«      d³ddddfd{edUeIdbe“d´eIdz  dµeId¶eId·eIdz  d¸eIdz  d¹eIdz  dºeIdz  fd»„«       ZóeB�jË                  d¼d( eeñ«      g¬²«       eeñ«       edj«       ed«       ed«       ed«       ed«       ed«       ed«       ed«      f	d{edUeIdbe“d½eId¾eIdz  dµeIdz  d´eIdz  d¿eIdz  dÀeIdz  dÁeIdz  dºeIdz  fdÂ„«       ZôeB�jË                  dÃd( ee—«      g¬²«       ee—«      fd{edUeIdbe“fdÄ„«       ZõeB�jí                  d¡dÅ ee—«      gee�jî                  ¬Æ«      e§ ee—«       edd¥¬Š«      fdUeIdbe“d¦eIdz  fdÇ„«       «       ZøeB�jË                  dÈdÉ ee—«      ge‹¬ˆ«      e§ ee—«      fdUeId=eŠdbe“fdÊ„«       «       ZùeB�jí                  dÈdË ee—«      ge‹¬ˆ«      e§ ee—«      fdUeIdbe“fdÌ„«       «       ZúeB�jË                  dÍdÎ ee—«      ge†¬ˆ«      e§ ee—«      fdUeId=e…dbe“fdÏ„«       «       ZûeB�jí                  dÍdÐ ee—«      ge†¬ˆ«      e§ ee—«      fdUeIdbe“fdÑ„«       «       ZüeB�jµ                  dÒdÓ ee—«      ge†¬ˆ«      e§ ee—«      fdUeIdbe“fdÔ„«       «       ZýeB�jµ                  dÕdÖ ee—«      geËe‰   ¬ˆ«      e§ ee—«      fdbe“fd×„«       «       Zþdbe“dUeId!e�fdØ„ZÿdHe�dÙe¿eIeIf   d!eŽfdÚ„�Z eB�jµ                  dÛdÜ ee—«      geŽ¬ˆ«      e§ ee—«      fdUeIdbe“d!eŽfdÝ„«       «       �ZeB�jË                  dÛdÞ ee—«      geŽ¬ˆ«      e§ ee—«      fdUeId=e�dbe“d!eŽfdß„«       «       �ZeB�jí                  dÛdà ee—«      geŽ¬ˆ«      e§ ee—«      fdUeIdbe“d!eŽfdá„«       «       �ZeB�jµ                  dâdã ee—«      geËeŽ   ¬ˆ«      e§ ee—«      fdbe“d!eËeŽ   fdä„«       «       �ZeB�jÓ                  d†dÅ ee—«      ge�e�jî                  ¬–«      e§ ee—«       edd¥¬Š«      fd=e’dbe“d¦eIdz  fdå„«       «       �ZeB�jË                  dædç ee—«      ge�jî                  ¬­«       ee—«      fd{eƒdbe“fdè„«       �Ze�j                  �j                  e�j                  �j                  e�j                  �j                  e�j                  �j                  �e«      «      «      dé«      �ZeeCdê<   d�aeeIeeeIeIf      f   dz  eCdë<   d!eeIeeeIeIf      f   fdì„�ZeB�jµ                  dídî ee—«      g¬�«       eddï¬Š«       eddð¬Š«       ee—«      fdñeIdz  dòeIdz  dbe“fdó„«       �Ze�j                  �j                  e�j                  �j                  e�j                  �j                  e�j                  �j                  �e«      «      «      dô«      �ZeeCdõ<    e�j"                  dö¬÷«      d!e¿eI�ef   fdø„«       �ZeB�jµ                  dùdú¬Š«       ee—«      fdbe“fdû„«       �Zddü�l�m�Z�m�Z�m�Z�m�Z�m�Z ddý�l�m�Z�m�Z eB�jË                  dþdÿe�jÌ                  �¬ «      e§ ee—«       ed«      fd=�edbe“d¦eIdz  f�d„«       «       �ZeB�jµ                  dþ�d¬Š«      e§ ee—«      fdbe“f�d„«       «       �ZeB�jµ                  �d�d¬Š«      e§ ee—«      f�deIdbe“f�d„«       «       �Z eB�jÓ                  dþ�d¬Š«      e§ ee—«       ed«      fd=�edbe“d¦eIdz  f�d	„«       «       �Z!eB�jí                  �d�d
e�jî                  �¬ «      e§ ee—«       ed«      f�deIdbe“d¦eIdz  f�d„«       «       �Z"yy# e%$ r e&Z#e&Z$Y �Œ¢w xY w# e%$ r ZR e)j¦                  d'eR«       d(ZDY dZR[R�ŒdZR[Rww xY w# e%$ r dd*lVmWZW  G d+„ d,eW«      ZXd-eId!eXfd.„ZUY �Œ8w xY w(  až  
1. Allow proxy admin to perform create, update, and delete operations on MCP servers in the db.
2. Allows users to view the mcp servers they have access to.

Endpoints here:
- GET `/v1/mcp/server` - Returns all of the configured mcp servers in the db filtered by requestor's access
- GET `/v1/mcp/server/{server_id}` - Returns the the specific mcp server in the db given `server_id` filtered by requestor's access
- POST `/v1/mcp/server` - Add a new external mcp server.
- PUT `/v1/mcp/server` -  Edits an existing mcp server.
- DELETE `/v1/mcp/server/{server_id}` - Deletes the mcp server given `server_id`.
- GET `/v1/mcp/tools - lists all the tools available for a key
- GET `/v1/mcp/access_groups` - lists all available MCP access groups
- GET `/v1/mcp/discover` - Returns curated list of well-known MCP servers for discovery UI
- GET `/v1/mcp/openapi-registry` - Returns well-known OpenAPI APIs with OAuth 2.0 metadata

é    N)ÚIterableÚMappingÚSequence)Ú	dataclass)ÚdatetimeÚ	timedeltaÚtimezone)ÚTYPE_CHECKINGÚFinalÚLiteralÚProtocol)	Ú	APIRouterÚDependsÚFormÚHeaderÚHTTPExceptionÚQueryÚRequestÚResponseÚstatus)ÚJSONResponse)ÚReadOnlyÚ	TypedDict)ÚRecordNotFoundErrorÚUniqueViolationError)Úverbose_loggerÚverbose_proxy_logger)Úuuid)ÚLITELLM_PROXY_ADMIN_NAME)ÚLITELLM_MCP_SERVER_DESCRIPTIONÚLITELLM_MCP_SERVER_NAMEÚMcpServerPayloadLikeÚbuild_env_var_setup_urlÚcollect_env_var_referencesÚget_server_prefixÚparse_admin_env_vars)Ú)validate_and_normalize_mcp_server_payload)Údecrypt_value_helperÚencrypt_value_helper)Úget_audit_log_changed_byÚis_audit_logging_enabled)ÚMCPServerRepositoryÚMCPUserCredentialsRepositoryz/v1/mcpÚmcp)ÚprefixÚtagsÚrouterTÚMCP_AVAILABLEi,  Ú TEMPORARY_MCP_SERVER_TTL_SECONDSzlitellm:mcp:temporary_serverÚ%TEMPORARY_MCP_SERVER_REDIS_KEY_PREFIXc                   ó   — e Zd ZU eed<   y)Ú_HasServerIdÚ	server_idN)Ú__name__Ú
__module__Ú__qualname__ÚstrÚ__annotations__© ó    ú€/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/mcp_management_endpoints.pyr6   r6   T   s   … Ø„Nr>   r6   Úmcp_server_recordsÚmcp_server_idÚreturnc                 ó4   — | D ]  }|j                   |k(  sŒ y y)zë
    Check if the mcp server with the given id exists in the iterable of mcp servers.

    Defined at module level (outside ``if MCP_AVAILABLE``) so it can be imported
    on Python < 3.10 where the ``mcp`` package is unavailable.
    TF©r7   )r@   rA   Úmcp_server_records      r?   Údoes_mcp_server_existrF   X   s*   € ð 0ò ÐØ×&Ñ&¨-Ó7Ùðð r>   z1.0.0ÚDEFAULT_MCP_REGISTRY_VERSION)Úmodels)ÚPrismaClientzMCP module not found: %sF)Úvalidate_tool_name)Ú	BaseModelc                   ó0   — e Zd ZU dZeed<   g Zee   ed<   y)Ú_ToolNameValidationResultTÚis_validÚwarningsN)	r8   r9   r:   rN   Úboolr<   rO   Úlistr;   r=   r>   r?   rM   rM   z   s   … Ø!ˆH�dÓ!Ø"$ˆH�d˜3‘iÔ$r>   rM   Únamec                 ó   — t        «       S ©N)rM   )rR   s    r?   rJ   rJ   ~   s   € Ü,Ó.Ð.r>   )Úapprove_mcp_serverÚcreate_draft_mcp_serverÚcreate_mcp_serverÚdelete_mcp_serverÚdelete_user_credentialÚdelete_user_env_varsÚget_all_mcp_serversÚget_all_mcp_servers_for_userÚget_draft_mcp_serverÚget_mcp_serverÚget_mcp_serversÚget_mcp_submissionsÚget_user_env_varsÚget_user_env_vars_bulkÚget_user_oauth_credentialÚlist_user_oauth_credentialsÚmcp_oauth_token_identityÚmerge_user_env_varsÚ'purge_user_oauth_credentials_for_serverÚreject_mcp_serverÚstore_user_credentialÚstore_user_oauth_credentialÚupdate_mcp_server)Ú_raise_if_not_oauth2Úauthorize_with_serverÚclient_supplied_redirect_urisÚexchange_token_with_serverÚget_request_base_urlÚ%redeem_passthrough_authorization_codeÚregister_client_with_serverÚresolve_ephemeral_dcr_client©Úglobal_mcp_server_manager)Úadmitted_user_contextÚbuild_effective_auth_contextsÚis_ui_session_credential)ÚLiteLLM_MCPServerTableÚLitellmUserRolesÚMakeMCPServersPublicRequestÚMCPApprovalStatusÚMCPOAuthUserCredentialRequestÚMCPOAuthUserCredentialStatusÚMCPSubmissionsSummaryÚMCPTransportÚMCPUserCredentialListItemÚMCPUserCredentialRequestÚMCPUserCredentialResponseÚMCPUserEnvVarSpecÚMCPUserEnvVarsRequestÚMCPUserEnvVarsStatusÚNewMCPServerRequestÚRejectMCPServerRequestÚSpecialMCPServerNameÚUpdateMCPServerRequestÚUserAPIKeyAuthÚUserMCPManagementMode)Ú_user_api_key_auth_builderÚuser_api_key_auth)Ú_read_request_bodyÚ!populate_request_with_path_params)Ú_user_has_admin_view)ÚConnectorConversionErrorÚConvertedConnectorÚMCPConnectorImportFailureÚMCPConnectorImportRequestÚMCPConnectorImportResponseÚMCPConnectorImportResultÚMCPConnectorImportSkippedÚconvert_connector_entries)Úmanagement_endpoint_wrapper)Ú MCP_ADMIN_CONFIG_CREDENTIAL_KEYSÚMCPAuthÚMCPCredentialsÚnormalize_upstream_header_name)Ú	MCPServerc                   ó"   — e Zd ZU eed<   eed<   y)Ú_TemporaryMCPServerEntryÚserverÚ
expires_atN)r8   r9   r:   rŸ   r<   r   r=   r>   r?   r¡   r¡   Þ   s   … àÓØÔr>   r¡   Úpayloadc                 ó|  — g }t        | dd «      }t        | dd «      }|r|j                  d|f«       |r|j                  d|f«       |D ]q  \  }}|sŒ	t        |«      }|j                  rŒ!d|› d|› �}|j                  r!|dz   dj                  |j                  «      z   }t        t        j                  d|i¬«      ‚ y )NÚserver_nameÚaliaszInvalid MCP tool prefix 'z' provided via ú
Úerror©Ústatus_codeÚdetail)	ÚgetattrÚappendrJ   rN   rO   Újoinr   r   ÚHTTP_400_BAD_REQUEST)r¤   Ú
candidatesr¦   r§   Ú
field_nameÚvalueÚvalidation_resultÚerror_messages_texts           r?   Ú _validate_mcp_server_name_fieldsr¶   ã   sÝ   € Ø:<ˆ
ä$ W¨m¸TÓBˆÜ˜w¨°Ó6ˆáØ×Ñ˜}¨kÐ:Ô;ÙØ×Ñ˜w¨Ð.Ô/à!+ò 	ÑˆJ˜ÙØä 2°5Ó 9ÐØ ×)Ò)Øà$=¸e¸WÀOÐT^ÐS_Ð"`ÐØ ×)Ò)Ø&9¸DÑ&@À4Ç9Á9ÐM^×MgÑMgÓChÑ&hÐ#ÜÜ"×7Ñ7ØÐ!4Ð5ôð ñ	r>   c                 óè   — t        | dd «      }t        |t        «      r|j                  d«      nd }t        |t        «      r|dk(  ry t        |«      €!t        t        j                  dd|›d�i¬«      ‚y )NÚcredentialsÚupstream_token_headerÚ r©   zInvalid upstream_token_header zE: must be a valid HTTP header name (RFC 7230 token, e.g. 'esb-oauth')rª   )	r­   Ú
isinstanceÚdictÚgetr;   rž   r   r   r°   )r¤   r¸   Úraws      r?   Ú_validate_upstream_token_headerr¿   þ   s   € Ü$ W¨m¸TÓBˆÜAKÈKÔY]ÔA^�[—_‘_Ð%<Ô=ÐdhˆÜ˜#œsÔ# s¨b¢yØÜ)¨#Ó.Ð6ÜÜ"×7Ñ7àØ8¸¸ð @=ð =ðôð ð 7r>   c                 óF   — t        | «       t        | «       t        | «       y rT   )Ú/_base_validate_and_normalize_mcp_server_payloadr¶   r¿   )r¤   s    r?   r'   r'     s   € Ü7¸Ô@Ü(¨Ô1Ü'¨Õ0r>   c                 ó0  — | j                   t        j                  k7  ry| j                  ry| j                  xs i }t        | j                  xr3 |j                  d«      xr  |j                  d«      xr | j                   «      }|rd| _        yd| _        y)a  Fallback only: fill in oauth2_flow when an oauth2 create omits it.

        An explicit oauth2_flow from the caller (the dashboard's flow selector, a REST
        body, config.yaml) always wins and is never touched. The shape check below runs
        solely for oauth2 creates that leave the field unset, so those rows still
        persist a flow instead of relying on read-time inference.

        The create payload carries the plaintext credentials, so the M2M-vs-interactive
        decision is reliable here in a way it is not at read time (credentials are
        encrypted at rest and redacted in responses). The client_credentials shape
        mirrors the legacy inference in MCPServerManager._resolve_oauth2_flow; every
        other oauth2 configuration is the authorization_code grant, including
        delegate_auth_to_upstream, where the client runs that grant upstream.
        NÚ	client_idÚclient_secretÚclient_credentialsÚauthorization_code)	Ú	auth_typerœ   Úoauth2Úoauth2_flowr¸   rP   Ú	token_urlr½   Úauthorization_url)r¤   r¸   Úhas_m2m_shapes      r?   Ústamp_omitted_oauth2_flowrÍ     s“   € ð ×Ñ¤§¡Ò.ØØ×ÒØØ$×0Ñ0Ò6°BˆÜ#Ø×Ñò .Ø—‘ Ó,ò.à—‘ Ó0ò.ð ×-Ñ-Ð-ó	 
ˆñ 7DÐ2ˆÕÐI]ˆÕr>   Ú_VALID_MCP_REQUIRED_FIELDSc                 óf  ‡ ‡— ddl m} |j                  d«      }|sy|D �cg c]  }|t        vsŒ|‘Œ }}|r!t	        t
        j                  dd|› d�i¬«      ‚d	Šd
t        dt        fˆˆ fd„}|D �cg c]  } ||«      rŒ|‘Œ }}|r!t	        t
        j                  dd|› d�i¬«      ‚yc c}w c c}w )zIValidate submission payload against admin-configured mcp_required_fields.r   ©Úgeneral_settingsÚmcp_required_fieldsNr©   z2mcp_required_fields contains unknown field names: zB. Check general_settings.mcp_required_fields in your proxy config.rª   Únoner²   rB   c                 ón   •— t        ‰| d «      }|€yt        |t        t        f«      r|sy| dk(  r|‰k(  ryy)NFrÇ   T)r­   r»   r;   rQ   )r²   r³   Ú_AUTH_TYPE_SENTINELr¤   s     €€r?   Ú_field_presentz5_validate_mcp_required_fields.<locals>._field_presentK  sB   ø€ Ü" 7¨J¸Ó=ˆEØˆ}Øä˜%¤#¤t Ô-±eØØ˜[Ò(¨UÐ6IÒ-IØØr>   z'Submission is missing required fields: zE. Configure required fields via general_settings.mcp_required_fields.)
Úlitellm.proxy.proxy_serverrÑ   r½   rÎ   r   r   ÚHTTP_500_INTERNAL_SERVER_ERRORr;   rP   r°   )r¤   Úproxy_general_settingsÚrequired_fieldsÚfÚunknownrÖ   ÚmissingrÕ   s   `      @r?   Ú_validate_mcp_required_fieldsrÞ   1  só   ù€ õ	
ð 4J×3MÑ3MÐNcÓ3dˆÙØð &5Ö\ ¸ÔA[Ò8[š!Ð\ˆÐ\ÙÜÜ"×AÑAàÐQÐRYÐQZð [Wð Wðôð ð &,Ðð		¤sð 		¬tö 		ð &5ÖN ¹NÈ1Õ<Mš!ÐNˆÐNÙÜÜ"×7Ñ7àÐFÀwÀið PZð Zðôð ð ùò5 ]ùò2 Os   ¡B)¯B)Á1B.Á?B.c                  óB   — ddl m}  t        | j                  d«      «      S )Nr   rÐ   Úenable_mcp_registry)r×   rÑ   rP   r½   )rÙ   s    r?   Ú_is_public_registry_enabledrá   `  s!   € õ	
ô Ð*×.Ñ.Ð/DÓEÓFÐFr>   Úbase_urlÚpathc                 ó`   — | j                  d«      }|j                  d«      r|nd|› �}|› |› �S )Nú/)ÚrstripÚ
startswith)râ   rã   Únormalized_baseÚnormalized_paths       r?   Ú_build_registry_remote_urlrê   g  s9   € Ø!)§¡°Ó!5ˆØ)-¯©¸Ô)=¡ÀQÀtÀfÀ:ˆØ!Ð" ?Ð"3Ð4Ð4r>   r¢   c                 óz   — | j                   r| j                   S | j                  r| j                  S | j                  S rT   )r§   r¦   r7   )r¢   s    r?   Ú_build_mcp_registry_server_namerì   l  s4   € Ø�<Š<Ø—<‘<ÐØ×ÒØ×%Ñ%Ð%Ø×ÑÐr>   c                   ó.   — e Zd ZU ee   ed<   ee   ed<   y)Ú_McpRegistryRemoteÚtypeÚurlN)r8   r9   r:   r   r;   r<   r=   r>   r?   rî   rî   s  s   … Ø�s‰mÓØ�c‰]Ôr>   rî   c                   ód   — e Zd ZU ee   ed<   ee   ed<   ee   ed<   ee   ed<   eee      ed<   y)Ú_McpRegistryEntryrR   ÚtitleÚdescriptionÚversionÚremotesN)r8   r9   r:   r   r;   r<   r   rî   r=   r>   r?   rò   rò   w  s;   … Ø�s‰mÓØ˜‰}ÓØ˜c‘]Ó"Ø˜#‘ÓØ˜(Ð#5Ñ6Ñ7Ô7r>   rò   c                 ó”   — t        | «      }|}|}t        }t        | «      }|st        d«      ‚t	        |d|› d�«      }||||d|dœgdœS )NzMCP server prefix is missingrå   ú/mcpústreamable-http©rï   rð   ©rR   ró   rô   rõ   rö   )rì   rG   r%   Ú
ValueErrorrê   )r¢   râ   r¦   ró   rô   rõ   Úserver_prefixÚ
remote_urls           r?   Ú$_build_mcp_registry_entry_for_serverrÿ   ~  st   € Ü<¸VÓDˆØ"ˆØ(ˆÜ5ˆä0°Ó8ˆÙÜÐ;Ó<Ð<Ü6°xÀ1À]ÀOÐSWÐAXÓYˆ
ð  ØØ&Øð .Ø%ñðñ
ð 	
r>   c                 óR   — t        | d«      }t        t        t        t        d|dœgdœS )Nrø   rù   rú   rû   )rê   r!   r    rG   )râ   rþ   s     r?   Ú_build_builtin_registry_entryr  –  s6   € Ü6°xÀÓHˆ
ä+Ü,Ü9Ü3ð .Ø%ñðñ
ð 	
r>   Ú_temporary_mcp_serversc                  óì   — t         sy t        j                  «       } t         j                  «       D ��cg c]  \  }}|j                  | k  sŒ|‘Œ }}}|D ]  }t         j                  |d «       Œ y c c}}w rT   )r  r   ÚutcnowÚitemsr£   Úpop)Únowr7   ÚentryÚexpired_idss       r?   Ú$_prune_expired_temporary_mcp_serversr
  §  si   € Ý%Øä—_‘_Ó&ˆÜ9O×9UÑ9UÓ9W×sÑ%5 Y°Ð[`×[kÑ[kÐorÓ[r’yÐsˆÑsØ$ò 	8ˆIÜ"×&Ñ& y°$Õ7ñ	8ùó ts   ³A0ÁA0Úttl_secondsc                 ó°   — t        d|«      }t        «        t        j                  «       t	        |¬«      z   }t        | |¬«      t        | j                  <   | S )Né   )Úseconds)r¢   r£   )Úmaxr
  r   r  r   r¡   r  r7   )r¢   r  r£   s      r?   Ú_cache_temporary_mcp_serverr  °  sM   € Ü˜!˜[Ó)ˆÜ,Ô.Ü$ŸO™OÓ-´	À+Ô0NÑNˆ
Ü3KØØ!ô4
Ô˜v×/Ñ/Ñ0ð ˆr>   c              ƒ   ó�  K  — t         j                  �t        t         j                  d«      syt        t         j                  dd«      }|�t        |d«      sy| j	                  d¬«      }t        j                  |«      }	 t        |«      }t        |t        «      st        j                  d«       y	 |j                  t        › d| j                  › �|t!        d	|«      ¬
«      ƒ d{  –—†  y# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w7 Œ1# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)z§
        Best-effort write-through to Redis so temporary MCP OAuth sessions are
        shared across proxy instances. Keep local in-memory cache as fallback.
        NÚcacheÚasync_set_cacheÚjson)ÚmodezBFailed to encrypt temporary MCP server payload for Redis cache: %szKEncrypted temporary MCP payload is not a string; skipping Redis cache writeú:r  )Úkeyr³   Úttlz7Failed to write temporary MCP server to Redis cache: %s)Úlitellmr  Úhasattrr­   Ú
model_dumpr  Údumpsr)   Ú	Exceptionr   Údebugr»   r;   r  r4   r7   r  )r¢   r  Úcache_backendr¤   Úpayload_jsonÚencrypted_payloadÚes          r?   Ú$_cache_temporary_mcp_server_in_redisr#  º  s1  è ø€ ô
 �=‰=Ð ¬´·±¸wÔ(GØÜ&¤w§}¡}°g¸tÓDˆØÐ ¬°Ð?PÔ(QØà,2×,=Ñ,=À6Ð,=Ó,JˆÜ"Ÿj™j¨Ó1ˆð	Ü';¸LÓ'IÐô
 Ð+¬SÔ1Ü ×&Ñ&Ð'tÔuØð	eØ×/Ñ/Ü<Ð=¸Q¸v×?OÑ?OÐ>PÐQØ'Ü˜˜;Ó'ð 0ó ÷ ñ øô ò 	Ü ×&Ñ&Ð'kÐmnÔoÜûð	úðùô
 ò 	eÜ ×&Ñ&Ð'`Ðbc×dÑdûð	eüsl   ‚A=EÂ C, Â&EÂ24D Ã&DÃ'D Ã+EÃ,	DÃ5DÄEÄDÄEÄD Ä	EÄ#D>Ä9EÄ>EÅEr7   c              ƒ   óô  K  — t         j                  �t        t         j                  d«      syt        t         j                  dd«      }|�t        |d«      sy	 |j	                  t
        › d| › �¬«      ƒ d{  –—† }t        |t        «      st        j                  d«       yt        |dd	¬
«      }|€y	 t        j                  |«      }t        |t        «      sy|}	 t        j                   |«      S 7 Œz# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)zð
        Best-effort read from Redis shared cache. Returns None on miss/errors.

        Values must be encrypted strings (same contract as _cache_temporary_mcp_server_in_redis);
        legacy plaintext dict payloads are rejected.
        Nr  Úasync_get_cacher  ©r  z8Failed reading temporary MCP server from Redis cache: %szYTemporary MCP Redis cache value must be an encrypted string; rejecting non-string payloadÚtemporary_mcp_serverr  )r³   r  Úexception_typez:Invalid decrypted temporary MCP payload in Redis cache: %sz7Invalid temporary MCP server payload in Redis cache: %s)r  r  r  r­   r%  r4   r  r   r  r»   r;   r(   r  Úloadsr¼   rŸ   Úmodel_validate)r7   r  Úcached_serverr"  Údecrypted_jsonÚloadedÚpayload_dicts          r?   Ú$_get_temporary_mcp_server_from_redisr/  Ú  sj  è ø€ ô �=‰=Ð ¬´·±¸wÔ(GØÜ&¤w§}¡}°g¸tÓDˆØÐ ¬°Ð?PÔ(QØð	Ø)6×)FÑ)FÜ<Ð=¸Q¸y¸kÐJð *Gó *÷ $ˆMô ˜-¬Ô-Ü ×&Ñ&Økôð ä 4ØØ&Ø"ô!
ˆð
 Ð!Øð	Ü ŸJ™J ~Ó6ˆFô ˜&¤$Ô'ØØ17ˆð	Ü×+Ñ+¨LÓ9Ð9ð=$ùô ò 	Ü ×&Ñ&Ð'aÐcdÔeÜûð	ûô& ò 	Ü ×&Ñ&Ð'cÐefÔgÜûð	ûô ò 	Ü ×&Ñ&Ð'`ÐbcÔdÜûð	üs–   ‚AE8ÁC4 Á7C2Á8C4 Á<7E8Â4D  Ã	E8ÃE Ã1E8Ã2C4 Ã4	DÃ=DÄE8ÄDÄE8Ä 	E	Ä)EÄ?E8ÅE	Å	E8Å	E5ÅE0Å+E8Å0E5Å5E8c                  ó   — ddl m}  | S )z®Non-throwing counterpart to ``get_prisma_client_or_throw`` for paths that degrade
        gracefully: a proxy configured without a database keeps the in-memory OAuth session.r   ©Úprisma_client)r×   r2  r1  s    r?   Ú_get_prisma_client_or_noner3    s   € õ 	=àÐr>   Ú
created_byc              ƒ   ób   K  — t        «       }|€yt        || |t        |¬«      ƒ d{  –—†  y7 Œ­w)a  Write the draft row that makes the OAuth session resolvable from any worker.

        A failure here is raised, not swallowed: without the shared row the flow degrades to
        the per-process cache and fails intermittently, which is the defect being fixed.
        N)r  r7   )r3  rV   r3   )r¤   r7   r4  r2  s       r?   Ú_persist_draft_mcp_serverr6    s:   è ø€ ô  :Ó;ˆØÐ ØÜ%ØØØÜ8Øô
÷ 	
ò 	
ús   ‚%/§-¨/c              ƒ   ó    K  — t        «       }|€yt        || t        ¬«      ƒ d{  –—† }|€yt        j                  |«      ƒ d{  –—† S 7 Œ$7 Œ­w)zTResolve a database-backed draft, which is the only lookup that works across workers.N©r  )r3  r]   r3   ru   Úbuild_mcp_server_from_table)r7   r2  Údrafts      r?   Ú#_get_draft_mcp_server_as_mcp_serverr;  )  sX   è ø€ ä9Ó;ˆØÐ ØÜ1Ø˜9Ô2Rô
÷ 
ˆð ˆ=ØÜ.×JÑJÈ5ÓQ×QÐQð
øð
 Rús!   ‚#A¥A
¦AÁAÁAÁAc              ƒ   óÊ   K  — t        «        t        j                  | «      }|�|j                  S t	        | «      ƒ d {  –—† }|�|S t        | «      ƒ d {  –—† }|€y |S 7 Œ 7 Œ­wrT   )r
  r  r½   r¢   r;  r/  )r7   r  Údraft_serverÚredis_servers       r?   Úget_cached_temporary_mcp_serverr?  5  su   è ø€ ô 	-Ô.Ü-×1Ñ1°)Ó<ˆØÐØ—<‘<Ðô %HÈ	Ó$R×RˆØÐ#ØÐä$HÈÓ$S×SˆØÐØð Ðð Søð Tús!   ‚<A#¾A¿A#ÁA!Á
A#Á!A#Ú
mcp_serverc                 óÆ   — 	 | j                  d¬«      }t        |d«      r t	        |dt        |j                  «      «       |S # t        $ r | j                  d¬«      }Y ŒKw xY w)zºReturn a copy with secret credentials removed, keeping only non-secret admin config so the
        admin form can show and clear it. Non-admin and virtual-key views strip the whole blob.T)Údeepr¸   )Ú
model_copyÚAttributeErrorÚcopyr  ÚsetattrÚ#_preserved_admin_config_credentialsr¸   )r@  Úredacted_servers     r?   Ú_redact_mcp_credentialsrI  L  sf   € ð	9Ø(×3Ñ3¸Ð3Ó>ˆOô �? MÔ2Ü�O ]Ô4WÐXg×XsÑXsÓ4tÔuàÐøô ò 	9Ø(Ÿo™o°4˜oÓ8ŠOð	9ús   ‚A ÁA ÁA r¸   c                 ó"  — | }t        | t        «      r	 t        j                  | «      }t        |t        «      syt        D �ci c](  }t        |j                  |«      x}t        «      r|r||“Œ* }}|xs dS # t        t
        f$ r Y yw xY wc c}w )aì  Keep only the non-secret admin-config keys, which are stored unencrypted so they lift out
        as plaintext; every secret and minted-token key is dropped.

        Total over every stored shape: a dict is read directly, a JSON-object string is parsed, and
        anything else (a malformed or non-object JSON string, a scalar, ``None``) falls back to full
        redaction rather than raising, because this runs on every admin list and get and one bad row
        must not fail them all.N)	r»   r;   r  r)  rü   Ú	TypeErrorr¼   r›   r½   )r¸   Úparsedr  r³   Ú	preserveds        r?   rG  rG  \  s›   € ð %ˆÜ�k¤3Ô'ðÜŸ™ KÓ0�ô ˜&¤$Ô'Øô 8ö
àÜ F§J¡J¨s£OÐ3˜5´cÔ:¹uð �‰Jð
ˆ	ð 
ð
 Ò ˜DÐ øô ¤	Ð*ò Ùðüò
s   ”A7 Á-BÁ7B	ÂB	Úmcp_serversc                 ó>   — | D �cg c]  }t        |«      ‘Œ c}S c c}w rT   )rI  ©rN  r¢   s     r?   Ú_redact_mcp_credentials_listrQ  u  s   € ð ?JÖJ°FÔ'¨Õ/ÒJÐJùÒJó   …Úuser_api_key_dictc                 ó<   — | j                   t        j                  k(  S )a  True only for ``PROXY_ADMIN``; ``PROXY_ADMIN_VIEW_ONLY`` returns False.

        Global env var secrets pre-fill the admin edit form, so a full admin
        must see them, but a read-only admin gets the same redacted view as
        any other non-managing caller.
        )Ú	user_rolerz   ÚPROXY_ADMIN)rS  s    r?   Ú_user_is_full_adminrW  z  s   € ð !×*Ñ*Ô.>×.JÑ.JÑJÐJr>   c                 ó\   — t        | dd«      }t        |t        «      xr t        |«      dkD  S )a(  Best-effort detection for route-restricted virtual keys.

        We treat a requestor as a "restricted" virtual key if `allowed_routes`
        is a non-empty list. This matches the auth gate that blocks routes with
        the error: "Virtual key is not allowed to call this route...".
        Úallowed_routesNr   )r­   r»   rQ   Úlen)rS  rY  s     r?   Ú"_is_restricted_virtual_key_requestr[  ƒ  s0   € ô !(Ð(9Ð;KÈTÓ RˆÜ˜.¬$Ó/ÒK´C¸Ó4GÈ!Ñ4KÐKr>   c                 ó
  — t        | «      }d|_        d|_        d|_        d|_        g |_        i |_        d|_        g |_        d|_	        d|_
        d|_        d|_        d|_        d|_        d|_        d|_        d|_        |S )a¢  Strip credential-bearing fields for non-admin viewers.

        Non-admin users may legitimately need to discover MCP servers
        their team has access to (so they can pick one in the UI), but
        they must never see fields that can carry bearer tokens or
        upstream API keys. ``_redact_mcp_credentials`` already clears
        the explicit ``credentials`` field; this layers on top to catch
        the URL+headers+env vectors that the virtual-key sanitizer also
        strips. Reset values match each field's declared default on
        ``LiteLLM_MCPServerTable`` (``None`` for Optional fields,
        ``[]``/``{}`` for required list/dict fields).
        N)rI  r¸   rð   Ú	spec_pathÚstatic_headersÚextra_headersÚenvÚcommandÚargsÚissuerrË   rÊ   Úregistration_urlÚtoken_exchange_endpointÚaudienceÚsubject_token_typeÚtoken_exchange_profileÚenv_vars)r@  Ú	sanitizeds     r?   Ú"_sanitize_mcp_server_for_non_adminrk  Ž  s�   € ô 3°:Ó>ˆ	Ø $ˆ	Ôð ˆ	ŒØ"ˆ	ÔØ#'ˆ	Ô Ø"$ˆ	ÔØˆ	ŒØ ˆ	ÔØˆ	ŒØˆ	ÔØ&*ˆ	Ô#Ø"ˆ	ÔØ%)ˆ	Ô"Ø,0ˆ	Ô)Ø!ˆ	ÔØ'+ˆ	Ô$Ø+/ˆ	Ô(ð
 "ˆ	ÔØÐr>   c                 ó>   — | D �cg c]  }t        |«      ‘Œ c}S c c}w rT   )rk  )rN  Úss     r?   Ú'_sanitize_mcp_server_list_for_non_adminrn  ¸  s    € ð @KÖK¸!Ô2°1Õ5ÒKÐKùÒKrR  c                 ó"  — t        | «      }d|_        d|_        d|_        i |_        d|_        g |_        g |_        g |_        g |_	        g |_
        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d|_        d}t5        |j6                  t8        «      r$t;        |j6                  j=                  d«      «      }|rddi|_        |S d|_        |S )aY  Return a minimally sufficient MCP server view for virtual keys.

        Security model:
        - Virtual keys should be able to *discover* accessible servers.
        - They should NOT receive sensitive configuration details like upstream
          URLs, env vars, headers, commands/args, access-group names, or
          credentials.
        NFÚ	is_publicT)rI  r¸   rð   r^  r`  ra  rb  r_  Úallowed_toolsÚmcp_access_groupsÚteamsri  rc  rË   rÊ   rd  re  rf  rg  rh  Úhealth_check_errorÚlast_health_checkr4  Ú
updated_byÚ
created_atÚ
updated_atr»   Úmcp_infor¼   rP   r½   )r@  rj  rp  s      r?   Ú$_sanitize_mcp_server_for_virtual_keyrz  ½  s-  € ô 3°:Ó>ˆ	Ø $ˆ	Ôð ˆ	ŒØ#'ˆ	Ô Øˆ	ŒØ ˆ	ÔØˆ	ŒØ"$ˆ	ÔØ"$ˆ	ÔØ&(ˆ	Ô#Øˆ	ŒØ!ˆ	Ôàˆ	ÔØ&*ˆ	Ô#Ø"ˆ	ÔØ%)ˆ	Ô"Ø,0ˆ	Ô)Ø!ˆ	ÔØ'+ˆ	Ô$Ø+/ˆ	Ô(à'+ˆ	Ô$Ø&*ˆ	Ô#à#ˆ	ÔØ#ˆ	ÔØ#ˆ	ÔØ#ˆ	Ôð ˆ	Ü�i×(Ñ(¬$Ô/Ü˜Y×/Ñ/×3Ñ3°KÓ@ÓAˆIÙ4=˜k¨4Ð0ˆ	ÔàÐð DHˆ	ÔàÐr>   c                 ó>   — | D �cg c]  }t        |«      ‘Œ c}S c c}w rT   )rz  rP  s     r?   Ú)_sanitize_mcp_server_list_for_virtual_keyr|  ñ  s    € ð LWÖWÀÔ4°VÕ<ÒWÐWùÒWrR  ))Úauthentication_tokenÚ
auth_value)rÃ   rÃ   )rÄ   rÄ   )Úscopesr  )Úaws_access_key_idr€  )Úaws_secret_access_keyr�  )Úaws_session_tokenr‚  )Úaws_region_namerƒ  )Úaws_service_namer„  )Úupstream_resourcer…  )r¹   r¹   .Ú_INHERITED_CREDENTIAL_FIELDSzMCPCredentials | Nonec                 ó^   — | syt        | «      }t        d„ |j                  «       D «       «      S )z®Did the caller supply an actual credential? Admin config rides in the same blob but is not
        one, so a form that round-trips it must not read as "credentials supplied".Fc              3   ó8   K  — | ]  \  }}|t         vsŒ|–— Œ y ­wrT   )r›   )Ú.0r  r³   s      r?   ú	<genexpr>z4_has_non_admin_config_credentials.<locals>.<genexpr>  s   è ø€ Òj™Z˜S %¸cÔIiÒ>i”5Ñjùs   ‚“)r¼   Úanyr  )r¸   Úas_dicts     r?   Ú!_has_non_admin_config_credentialsr�    s+   € ñ ØÜ,0°Ó,=ˆÜÑj¨7¯=©=«?ÔjÓjÐjr>   c           	      ó
  — | j                   rt        | j                  «      r| S t        j                  | j                   «      }|€| S t
        D ��ci c]  \  }}t        ||d «      x}r||“Œ }}}i |¥t        | j                  xs i «      ¥}|s| S 	 | j                  d|i¬«      S c c}}w # t        $ r Y nw xY w	 | j                  «       }n# t        $ r | j                  «       }Y nw xY w||d<   t        j                  |«      S )Nr¸   )Úupdate)r7   r�  r¸   ru   Úget_mcp_server_by_idr†  r­   r¼   rC  rD  r  r‡   r*  )r¤   Úexisting_serverÚserver_attrÚcredential_keyr³   Úinherited_credentialsr.  s          r?   Ú)_inherit_credentials_from_existing_serverr•    s-  € ð × Ò Ô$EÀg×FYÑFYÔ$ZØˆNä!:×!OÑ!OÐPW×PaÑPaÓ!bˆØÐ"ØˆNô 0L÷4
á+�˜^Ü  °+¸tÓDÐD�ÐDð ˜EÑ!ð4
Ðñ 4
ð !]Ð#8Ð \¼DÀ×ATÑATÒAZÐXZÓ<[Ð \Ðá$ØˆNð	Ø×%Ñ%¨mÐ=RÐ-SÐ%ÓTÐTùó4
øô ò 	Ùð	úð	*Ø"×-Ñ-Ó/‰LøÜò 	*Ø"Ÿ<™<›>ŠLð	*úà&;ˆ�]Ñ#Ü"×1Ñ1°,Ó?Ð?s*   ÁB%ÂB+ Â+	B7Â6B7Â;C ÃC(Ã'C(c              ƒ   óR  K  — | j                   }|st        t        j                  «       «      S t	        j
                  |«      �|S t        «       }|€|S t        ||«      ƒ d{  –—† }|�|j                  t        j                  k(  rt        t        j                  «       «      S |S 7 ŒB­w)a÷  Decide the id an OAuth session runs under.

        A caller-supplied id is honoured only when it names a server that really exists, which is
        the edit form re-authorizing a saved server against its own id. Anything else gets a fresh
        id, so two concurrent sessions can never land on one id and silently adopt each other's
        URL or client credentials. Without a database there is nothing shared to collide over, so
        the supplied id is kept and behaviour is unchanged.
        N)r7   r;   r   Úuuid4ru   r�  r3  r^   Úapproval_statusr|   r:  )r¤   Úsuppliedr2  Úexistings       r?   Ú_resolve_session_server_idr›  1  s—   è ø€ ð "×+Ñ+ˆÙÜ”t—z‘z“|Ó$Ð$Ü$×9Ñ9¸(ÓCÐOØˆOÜ9Ó;ˆØÐ ØˆOô !/¨}¸hÓ G×GˆØÐ˜x×7Ñ7Ô;L×;RÑ;RÒRÜ”t—z‘z“|Ó$Ð$Øˆð Hús   ‚A B'Á"B%Á#AB'c                 óî  — t        j                  «       }| j                  xs | j                  xs |}t	        di d|“d|“d| j                  “d| j
                  “d| j                  “d| j                  “d| j                  “d| j                  “d	|“d
|“d|“d|“dg “d| j                  “d| j                  xs g “d| j                  xs g “d| j                  “d| j                  “d| j                  “d| j                   “d| j"                  “d| j$                  “d| j&                  “d| j(                  “d| j*                  “d| j,                  “d| j.                  “d| j0                  “d| j2                  “ŽS )Nr7   r¦   r§   rô   rð   Ú	transportrÇ   r¸   rw  rx  r4  rv  rs  rr  rq  r_  ry  r^  ra  rb  r`  rc  rË   rÊ   rd  Úallow_all_keysÚavailable_on_public_internetÚtimeoutÚmax_concurrent_requestsr=   )r   r  r¦   r§   ry   rô   rð   r�  rÇ   r¸   rr  rq  r_  ry  r^  ra  rb  r`  rc  rË   rÊ   rd  rž  rŸ  r   r¡  )r¤   r4  r7   r  r¦   s        r?   Ú"_build_temporary_mcp_server_recordr¢  I  sÖ  € ô
 —_‘_Ó&ˆØ$×0Ñ0ÒN°G·M±MÒNÀYˆÜ%ò 
Ùð
á#ð
ð —-’-ð
ð  ×+Ò+ð	
ð
 —’ð
ð ×'Ò'ð
ð ×'Ò'ð
ð  ×+Ò+ð
ñ ð
ñ ð
ñ "ð
ñ "ð
ñ ð
ð &×7Ò7ð
ð "×/Ñ/Ò5°2øð
ð  "×/Ñ/Ò5°2øð!
ð" ×%Ò%ð#
ð$ #×1Ò1ð%
ð& —O’Oð'
ð( —’ð)
ð* —’ð+
ð, —>’>ð-
ð. &×7Ò7ð/
ð0 ×'Ò'ð1
ð2 %×5Ò5ð3
ð4 #×1Ò1ð5
ð6 *1×)MÒ)Mð7
ð8 —O’Oð9
ð: %,×$CÒ$Cð;
ð 	
r>   Úmessagec                 óP   — ddl m} |€t        t        j                  d| i¬«      ‚|S )Nr   r1  r©   rª   )r×   r2  r   r   rØ   )r£  r2  s     r?   Úget_prisma_client_or_throwr¥  p  s1   € Ý<àÐ ÜÜ"×AÑAØ Ð)ôð ð Ðr>   z/tools)r0   Údependenciesc              ƒ   óœ   K  — ddl m}  || ddd¬«      ƒ d{  –—† }|j                  }|D �cg c]  }t        |«      ‘Œ }}d|iS 7 Œ,c c}w ­w)ze
        Get all MCP tools available for the current key, including those from access groups
        r   )Ú_list_mcp_toolsN)rŽ   Úmcp_auth_headerrN  Úmcp_server_auth_headersÚtools)Ú-litellm.proxy._experimental.mcp_server.serverr¨  r«  r¼   )rS  r¨  Úlistingr«  ÚtoolÚdumped_toolss         r?   Úget_mcp_toolsr°  |  s^   è ø€ õ 	Rá.Ø/Ø ØØ$(ô	 
÷ 
ˆð —}‘}ˆØ6;Ö<¨dœt D�zÐ<ˆÐ<à˜Ð&Ð&ð
úò =ùs   ‚A˜A™A­A¿AÁAz/access_groupsc              ƒ   ó&  K  — ddl m} ddlm} t	        «       }|j
                  j                  «       D ]*  }|j                  sŒ|j                  |j                  «       Œ, |�i	 t        |«      j                  j                  «       ƒ d{  –—† }|D ]7  }t        |d«      sŒ|j                  sŒ|j                  |j                  «       Œ9 	 t#        t%        |«      «      }d|iS 7 ŒY# t        $ r }t        j                   d|«       Y d}~Œ>d}~ww xY w­w)zR
        Get all available MCP access groups from the database AND config
        r   rt   r1  Nrr  z#Error getting MCP access groups: %sÚaccess_groups)Ú9litellm.proxy._experimental.mcp_server.mcp_server_managerru   r×   r2  ÚsetÚconfig_mcp_serversÚvaluesr²  r�  r,   ÚtableÚ	find_manyr  rr  r  r   r  ÚsortedrQ   )rS  ru   r2  r²  r¢   rN  r"  Úaccess_groups_lists           r?   Úget_mcp_access_groupsr»  ”  s  è ø€ õ	
õ 	=ä"›uˆð 0×BÑB×IÑIÓKò 	;ˆFØ×#Ó#Ø×$Ñ$ V×%9Ñ%9Õ:ð	;ð
 Ð$ðUÜ[nØ!ó\ç‘%Ÿ	™	›÷V$�ð *ò G�FÜ˜vÐ':Õ;À×@XÓ@XØ%×,Ñ,¨V×-EÑ-EÕFñGô %+¬4°Ó+>Ó$?ÐØÐ!3Ð4Ð4ðV$ùô ò UÜ$×*Ñ*Ð+PÐRS×TÑTûðUüsT   ‚A DÁDÁ#&C% Â	C#Â
C% Â C% Â-C% Ã
DÃ#C% Ã%	DÃ.D	ÄDÄ	DÄDz/network/client-ipz5Returns the caller's IP address as seen by the proxy.)r0   r¦  rô   Úrequestc              ƒ   ó@   K  — ddl m} |j                  | «      }d|iS ­w)Nr   ©ÚIPAddressUtilsÚip)Ú#litellm.proxy.auth.ip_address_utilsr¿  Úget_mcp_client_ip)r¼  r¿  Ú	client_ips      r?   Úget_client_iprÄ  »  s'   è ø€ õ 	Gà)×;Ñ;¸GÓDˆ	Ø�iÐ Ð ùó   ‚z/registry.jsonzMMCP registry endpoint. Spec: https://github.com/modelcontextprotocol/registry)r0   rô   c           
   ƒ   óJ  K  — t        «       st        t        j                  d¬«      ‚ddlm} |j                  | «      }t        j                  d|«       t        | «      }g }|j                  dt        |«      i«       t        t        j                  |«      j                  «       «      }|j!                  t"        ¬«       |D ]"  }	 t%        ||«      }|j                  d|i«       Œ$ d|iS # t&        $ r,}t        j                  dt)        |d	d
«      |«       Y d }~ŒYd }~ww xY w­w)NzMCP registry is not enabledrª   r   r¾  zMCP registry request from IP=%sr¢   r&  z&Skipping MCP server %s in registry: %sr7   rÜ   Úservers)rá   r   r   ÚHTTP_404_NOT_FOUNDrÁ  r¿  rÂ  r   r  rp   r®   r  rQ   ru   Úget_filtered_registryr¶  Úsortrì   rÿ   r  r­   )	r¼  r¿  rÃ  râ   Úregistry_serversÚregistered_serversr¢   r  r"  s	            r?   Úget_mcp_registryrÍ  Ç  s%  è ø€ ô +Ô,ÜÜ"×5Ñ5Ø4ôð õ
 	Gà)×;Ñ;¸GÓDˆ	ä×"Ñ"Ð#DÀiÔPä.¨wÓ7ˆØFHÐØ×Ñ Ô+HÈÓ+RÐ SÔTô %)Ô)B×)XÑ)XÐYbÓ)c×)jÑ)jÓ)lÓ$mÐà×ÑÔ$CÐÔDà(ò 	7ˆFðÜ<¸VÀXÓN�ð ×#Ñ# X¨uÐ$5Õ6ð	7ð Ð+Ð,Ð,øô ò Ü$×*Ñ*Ø<¼gÀfÈkÐ[dÓ>eÐghôô ûð	üs0   ‚CD#ÃC+ÃD#Ã+	D Ã4"DÄD#ÄD Ä D#c                  ó>   — ddl m}  | j                  d«      }|dk(  ryy)Nr   rÐ   Úuser_mcp_management_modeÚview_allÚ
restricted)r×   rÑ   r½   )rÙ   r  s     r?   Ú_get_user_mcp_management_moderÒ  ï  s(   € õ	
ð -×0Ñ0Ð1KÓLˆØ�:ÒØØr>   Úteam_idc              ƒ   óJ  K  — ddl m} ddlm}m} ddlm}m}  || ||d¬«      ƒ d{  –—† } ||«      ƒ d{  –—† } |«       }||z  }	|	sg S g }
|	D ]@  }t        j                  |«      }|€Œt        j                  |«      }|
j                  |«       ŒB t        |
«      S 7 Œv7 Œh­w)z®
        Return MCP servers scoped to a team: team's allowed servers + allow_all_keys servers.
        Used by the Create Key UI to populate the MCP server dropdown.
        r   ©Úget_team_object)Ú_get_allow_all_keys_server_idsÚ_get_team_allowed_mcp_servers©r2  Úuser_api_key_cacheT©rÓ  r2  rÚ  Úcheck_db_onlyN)Úlitellm.proxy.auth.auth_checksrÖ  Ú8litellm.proxy.management_helpers.object_permission_utilsr×  rØ  r×   r2  rÚ  ru   r�  Ú_build_mcp_server_tabler®   rQ  )rÓ  rÖ  r×  rØ  r2  rÚ  Úteam_objÚteam_server_idsÚallow_all_server_idsÚall_allowed_idsrÇ  r7   r¢   Úmcp_server_tables                 r?   Ú _get_team_scoped_mcp_server_listrå  ù  sÂ   è ø€ õ 	C÷	
÷ 	Qá /ØØ'Ø1Øô	!
÷ 
ˆñ (EÀXÓ'N×!NˆÙ&DÓ&FÐØ!0Ð3GÑ!GˆáØˆIð 8:ˆØ(ò 	1ˆIÜ.×CÑCÀIÓNˆFØÑ!Ü#<×#TÑ#TÐU[Ó#\Ð Ø—‘Ð/Õ0ð		1ô ,¨GÓ4Ð4ð-
øð "Oús%   ‚&B#¨B©B#¸B!¹2B#Á,4B#Â!B#c              ƒ   ób  K  — t        «       dk(  r't        | «      st        j                  «       ƒ d{  –—† S i }t	        | «      ƒ d{  –—† D ]A  }t        j
                  |¬«      ƒ d{  –—† D ]  }|j                  |j                  |«       Œ  ŒC t        |j                  «       «      S 7 Œv7 Œc7 ŒD­w)a+  The server set the dashboard grid shows (GET /v1/mcp/server, no team
        filter), returned unredacted. Callers that surface this to a client must
        apply their own redaction; the per-user env-var status endpoint relies on
        the raw env_vars and only ever returns is_set booleans, never secrets.

        Sharing this resolution keeps the red "missing user fields" card status
        aligned with the cards actually rendered: an admin in view_all mode sees
        every server even when their key carries no per-server MCP grant.
        rÐ  N)rŽ   )
rÒ  r[  ru   Úget_all_mcp_servers_unfilteredrw   Úget_all_allowed_mcp_serversÚ
setdefaultr7   rQ   r¶  )rS  Ú
aggregatedÚauth_contextr¢   s       r?   Ú_resolve_accessible_mcp_serversrì    sª   è ø€ ô )Ó*¨jÒ8ÔAcÐduÔAvÜ2×QÑQÓS×SÐSà?Aˆ
Ü"?Ð@QÓ"R×Rò 	@ˆLÜ 9× UÑ UÐhtÔ u×uò @�Ø×%Ñ% f×&6Ñ&6¸Õ?ñ@ð	@ô �J×%Ñ%Ó'Ó(Ð(ð Tøð SøØuús4   ‚0B/²B)³B/ÁB+Á B/Á(B-Á)AB/Â+B/Â-B/c              ƒ   óœ   K  — t        | «      ƒ d{  –—† }|€
t        «       S t        t        j                  |«      ƒ d{  –—† «      S 7 Œ67 Œ
­w)aV  Server ids a connected app authorized by this dashboard user is served on the aggregate
        MCP endpoint, resolved through the one owner of the admitted subject so the page and the
        session cannot drift. Empty when that identity cannot be built, which is the true answer:
        the same user cannot open a gateway session either.N)rv   Ú	frozensetru   Úget_allowed_mcp_servers)rS  Úadmitteds     r?   Ú#_connected_app_reachable_server_idsrñ  4  sL   è ø€ ô
 !6Ð6GÓ H×HˆØÐÜ“;ÐÜÔ8×PÑPÐQYÓZ×ZÓ[Ð[ð Iøð [ús    ‚A‘A’-A¿A
Á 	AÁ
Az/serverz1Returns the mcp server list with associated teams)rô   r¦  Úresponse_modelzÉFilter MCP servers by team scope. When provided, returns only servers the team has access to plus globally available (allow_all_keys) servers. Used by the Create Key UI to show team-scoped MCP servers.)rô   zÁAnnotate each returned server with connected_app_reachable: whether a connected app authorized by the calling user (a gateway OAuth session) is served this server on the aggregate MCP endpoint.Úconnected_app_viewc              ƒ   óÊ  ‡ K  — t        ‰ «      }|�¯t        |t        «      rŸ|j                  «       r�|rt	        dd¬«      ‚|j                  «       }t        ‰ «      }|sOddlm} ddlm	}m
}  ||||d¬	«      ƒ d{  –—† }	t        ˆ fd
„|	j                  D «       «      }
|
st	        dd¬«      ‚t        |«      ƒ d{  –—† }nt        ‰ «      ƒ d{  –—† }t        |«      }|du r8t!        ‰ «      r-t#        ‰ «      ƒ d{  –—† }|D ]  }|j$                  |v |_        Œ t(        j*                  �F|D ]A  }|j$                  t(        j*                  v sŒ |j,                  €i |_        d|j,                  d<   ŒC ddlm	} ‰ j.                  xs d}|rž|�œ|D �cg c]  }t1        |dd«      sŒ|j$                  ‘Œ }}|rst3        |«      j4                  j7                  |d|idœ¬«      ƒ d{  –—† }|D �ch c]  }|j$                  ’Œ }}|D ]#  }t1        |dd«      sŒ|j$                  |v |_        Œ% |rt;        |«      S t=        ‰ «      st?        |«      S |S 7 �ŒÑ7 �Œ”7 �Œƒ7 �ŒYc c}w 7 Œ{c c}w ­w)a¹  
        Get all of the configured mcp servers for the user in the db with their associated teams
        ```
        curl --location 'http://localhost:4000/v1/mcp/server'         --header 'Authorization: Bearer your_api_key_here'

        # Filter by team scope (for Create Key UI)
        curl --location 'http://localhost:4000/v1/mcp/server?team_id=team-123'         --header 'Authorization: Bearer your_api_key_here'
        ```
        Né“  z=Restricted virtual keys cannot query team-scoped MCP servers.rª   r   rÕ  rÙ  TrÛ  c              3   óp   •K  — | ]-  }|j                   d uxr |j                   ‰j                   k(  –— Œ/ y ­wrT   )Úuser_id)r‰  ÚmrS  s     €r?   rŠ  z(fetch_all_mcp_servers.<locals>.<genexpr>{  s:   øè ø€ ò *àð —I‘I TÐ)ÒT¨a¯i©iÐ;L×;TÑ;TÑ.TÓTñ*ùs   ƒ36z=You do not have permission to view MCP servers for this team.rp  r1  rº   Úis_byokFÚin)r÷  r7   )Úwhere) r[  r»   r;   Ústripr   r‘   rÝ  rÖ  r×   r2  rÚ  r‹  Úmembers_with_rolesrå  rì  rQ  rx   rñ  r7   Úconnected_app_reachabler  Úpublic_mcp_serversry  r÷  r­   r-   r·  r¸  Úhas_user_credentialr|  rW  rn  )rS  rÓ  ró  Úis_restricted_virtual_keyÚsanitized_team_idÚis_adminrÖ  r2  rÚ  rà  Úuser_in_teamÚredacted_mcp_serversrÇ  Úreachable_idsr¢   Ú_byok_prisma_clientr÷  rm  Úbyok_server_idsÚ	cred_rowsÚrÚcred_sets   `                     r?   Úfetch_all_mcp_serversr  >  sž  øè ø€ ôD ,NÐN_Ó+`Ð!ØÐ¤:¨g´sÔ#;ÀÇÁÄñ )Ü#Ø #ØZôð ð (/§}¡}£ÐÜ2Ð3DÓEˆHÙÝJ÷ñ
 )8Ø-Ø"/Ø'9Ø"&ô	)÷ #�ô '*ó *à%×8Ñ8ô*ó '�ñ $Ü'Ø$'Ø^ôð ô
 *JÐJ[Ó)\×#\Ñ ä#BÐCTÓ#U×UˆGÜ#?ÀÓ#HÐ à Ñ%Ô*BÐCTÔ*UÜ)LÐM^Ó)_×#_ˆMØ.ò S�Ø17×1AÑ1AÀ]Ð1R�Õ.ðSô ×%Ñ%Ð1Ø.ò 8�Ø×#Ñ#¤w×'AÑ'AÒAØ—‘Ð.Ø*,˜œØ37�F—O‘O KÒ0ð	8õ 	Tà*×2Ñ2Ò8°bˆÙÐ*Ð6Ø;OÖ%p°aÔSZÐ[\Ð^gÐinÕSo a§k£kÐ%pˆOÐ%pÙô 7Ð7JÓK×QÑQ×[Ñ[Ø&-¸TÀ?Ð<SÑTð \ó ÷ ð ð
 9BÖ"B°1 1§;£;Ð"B�Ð"BØ2ò R�FÜ˜v y°%Õ8Ø5;×5EÑ5EÈÐ5Q˜Õ2ðRñ
 %Ü<Ð=QÓRÐRô #Ð#4Ô5Ü:Ð;OÓPÐPà#Ð#ðy#ùð  $]ùàUùð $`ûò" &qðúò #CùsŒ   ƒA7I#Á:IÁ;?I#Â:IÂ;I#ÃIÃ,I#Ã;IÃ<AI#ÅAI#ÆIÆ!IÆ/1I#Ç IÇ!I#Ç)IÇ<I#È;I#ÉI#ÉI#ÉI#ÉI#ÉI#z/server/healthzHealth check for MCP servers)rô   r¦  zDServer IDs to check. If not provided, checks all accessible servers.Ú
server_idsc              ƒ   óô  K  — t        «       }|dk(  rEt        j                  | ¬«      ƒ d{  –—† }|D �cg c]  }|j                  |j                  dœ‘Œ c}S t        |«      ƒ d{  –—† }i }|D ]P  }t        j                  || ¬«      ƒ d{  –—† }|D ]*  }|j                  |vsŒ|j                  ||j                  <   Œ, ŒR |j                  «       D ��	cg c]
  \  }}	||	dœ‘Œ c}	}S 7 Œ»c c}w 7 Œˆ7 Œdc c}	}w ­w)aŒ  
        Perform health checks on one or more MCP servers.

        Parameters:
        - server_ids: Optional list of server IDs. If not provided, checks all accessible servers.

        Returns:
        - Health check results for requested servers

        ```
        # Check all accessible servers
        curl --location 'http://localhost:4000/v1/mcp/server/health'         --header 'Authorization: Bearer your_api_key_here'

        # Check specific servers
        curl --location 'http://localhost:4000/v1/mcp/server/health?server_ids=server-1&server_ids=server-2'         --header 'Authorization: Bearer your_api_key_here'
        ```
        rÐ  )r  N)r7   r   )rŽ   r  )rÒ  ru   Ú*get_all_mcp_servers_with_health_unfilteredr7   r   rw   Ú)get_all_mcp_servers_with_health_and_teamsr  )
r  rS  rÏ  rÇ  r¢   Úauth_contextsÚserver_status_maprë  r7   r   s
             r?   Úhealth_check_serversr  ³  s  è ø€ ô> +HÓ*IÐ à# zÒ1Ü5×`Ñ`ÐlvÔw×wˆGØ[bÖcÐQW &×"2Ñ"2¸f¿m¹mÓLÒcÐcä%BÐCTÓ%U×UˆàacÐØ)ò 	HˆLÜ5×_Ñ_Ø".Ø%ô÷ ˆGð "ò H�Ø×#Ñ#Ð+<Ò<Ø:@¿-¹-Ð% f×&6Ñ&6Ò7ñHð	Hð Uf×TkÑTkÓTm×nÑ?P¸yÈ&˜i°6Ó:ÓnÐnð xúÚcàUøðúó oùsV   ‚)C8«C'¬C8´ C)ÁC8Á%C.Á&%C8ÂC0ÂC8Â$0C8ÃC2Ã#C8Ã)C8Ã0C8Ã2C8z/server/registerz^Submit a new MCP server for admin review (non-admin users). Mirrors POST /guardrails/register.)rô   r¦  rò  r«   c              ƒ   ó>  K  — |j                   t        j                  k(  rt        t        j
                  ddi¬«      ‚|j                  st        t        j                  ddi¬«      ‚| j                  t        j                  k(  rt        t        j                  ddi¬«      ‚t        d«      }t        | «       t        | «       t        | «       t        j                   | _        |j$                  | _        t)        j*                  t,        j.                  «      | _        	 t3        || |j$                  xs |j                  ¬«      ƒ d{  –—† }t=        |«      S 7 Œ# t4        $ r;}t7        j8                  d	|«       t        t        j:                  dd
|› �i¬«      ‚d}~ww xY w­w)z¶
        Allow team members to submit an MCP server for admin review.
        Creates the server with approval_status=pending_review.
        Requires a team-scoped API key.
        r©   zoPROXY_ADMIN users should use POST /v1/mcp/server to create servers directly instead of the submission workflow.rª   zORegistration requires an API key associated with a team. Use a team-scoped key.z§stdio MCP servers cannot be submitted via the user registration workflow. Ask a proxy admin to add this server via POST /v1/mcp/server or to declare it in config.yaml.ú8Database not connected. Connect a database to your proxy©Ú
touched_byNz Error registering mcp server: %szError registering mcp server: )rU  rz   rV  r   r   ÚHTTP_403_FORBIDDENrÓ  r°   r�  r€   Ústdior¥  r'   rÍ   rÞ   r|   Úpending_reviewr˜  r÷  Úsubmitted_byr   r  r	   ÚutcÚsubmitted_atrW   r  r   Ú	exceptionrØ   rI  )r¤   rS  r2  Únew_mcp_serverr"  s        r?   Úregister_mcp_serverr   æ  sƒ  è ø€ ð" ×&Ñ&Ô*:×*FÑ*FÒFÜÜ"×5Ñ5àð  Oðôð ð !×(Ò(ÜÜ"×7Ñ7ØÐ!rÐsôð ð ×Ñ¤× 2Ñ 2Ò2ÜÜ"×7Ñ7àð'ðô
ð 
ô  :Ð:tÓuˆä1°'Ô:Ü! 'Ô*Ü% gÔ.ä"3×"BÑ"BˆÔØ0×8Ñ8ˆÔÜ'Ÿ|™|¬H¯L©LÓ9ˆÔð	Ü*;ØØØ,×4Ñ4ÒQÐ8I×8QÑ8Qô+÷ %ˆNô ' ~Ó6Ð6ð%ùô
 ò 	Ü ×*Ñ*Ð+MÈqÔQÜÜ"×AÑAØÐ#AÀ!ÀÐ!EÐFôð ûð	üs<   ‚DFÄ)E ÅEÅE Å	FÅE Å	FÅ6FÆFÆFz/server/submissionszoReturns all MCP servers submitted by non-admin users (admin review queue). Mirrors GET /guardrails/submissions.c              ƒ   ó^  K  — | j                   t        j                  t        j                  fvrt	        t
        j                  ddi¬«      ‚t        d«      }t        |«      ƒ d{  –—† }t        |j                  «      |_
        t        | «      st        |j                  «      |_
        |S 7 ŒE­w)z\
        Admin-only endpoint to view all user-submitted MCP servers pending review.
        r©   z5Admin access required to view MCP server submissions.rª   r  N)rU  rz   rV  ÚPROXY_ADMIN_VIEW_ONLYr   r   r  r¥  r`   rQ  r  rW  rn  )rS  r2  Úsubmissionss      r?   Úget_mcp_server_submissionsr$  0  s£   è ø€ ð ×&Ñ&Ü×(Ñ(Ü×2Ñ2ð/
ñ 
ô  Ü"×5Ñ5ØÐ!XÐYôð ô
  :Ð:tÓuˆä#6°}Ó#E×EˆÜ8¸×9JÑ9JÓKˆÔÜ"Ð#4Ô5Ü GÈ×HYÑHYÓ ZˆKÔØÐð	 Fús   ‚A#B-Á%B+Á&AB-z/server/{server_id}/approvez[Approve a pending MCP server submission (admin only). Mirrors PUT /guardrails/{id}/approve.c              ƒ   ór  K  — t         j                  |j                  k7  rt        t        j
                  ddi¬«      ‚t        d«      }t        || «      ƒ d{  –—† }|€!t        t        j                  dd| › d�i¬«      ‚|j                  t        j                  k(  rt        t        j                  ddi¬«      ‚t        || |j                  xs t        ¬	«      ƒ d{  –—† }t!        j"                  |j$                  «      ƒ d{  –—†  t!        j&                  «       ƒ d{  –—†  t)        |«      S 7 Œ×7 ŒT7 Œ/7 Œ­w)
u”   
        Admin approves a pending or previously-rejected MCP server â€” sets approval_status=active and loads it into the runtime registry.
        r©   z8Admin access required to approve MCP server submissions.rª   r  NúMCP server 'ú' not found.zMCP server is already active.r  )rz   rV  rU  r   r   r  r¥  r^   rÈ  r˜  r|   Úactiver°   rU   r÷  r   ru   Ú'invalidate_byom_submitted_servers_cacher  Úreload_servers_from_databaserI  )r7   rS  r2  rš  Úapproveds        r?   Úapprove_mcp_server_submissionr,  N  s2  è ø€ ô ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5ØÐ![Ð\ôð ô
  :Ð:tÓuˆä .¨}¸iÓ H×HˆØÐÜÜ"×5Ñ5Ø <°	¨{¸,Ð!GÐHôð ð ×#Ñ#Ô'8×'?Ñ'?Ò?ÜÜ"×7Ñ7ØÐ!@ÐAôð ô
 !3ØØØ(×0Ñ0ÒLÔ4Lô!
÷ 
ˆô
 (×OÑOÐPX×PeÑPeÓf×fÐfÜ'×DÑDÓF×FÐFä& xÓ0Ð0ð) Iøð
øð
 	gøØFúsI   ‚AD7ÁD/ÁBD7ÃD1Ã&D7ÄD3ÄD7ÄD5Ä D7Ä1D7Ä3D7Ä5D7z/server/{server_id}/rejectzYReject a pending MCP server submission (admin only). Mirrors PUT /guardrails/{id}/reject.c              ƒ   ót  K  — t         j                  |j                  k7  rt        t        j
                  ddi¬«      ‚t        d«      }t        || «      ƒ d{  –—† }|€!t        t        j                  dd| › d�i¬«      ‚|j                  t        j                  k(  rt        t        j                  ddi¬«      ‚|j                  t        j                  k(  }t        || |j                  xs t         |j"                  ¬	«      ƒ d{  –—† }|rt%        j&                  «       ƒ d{  –—†  t)        |«      S 7 ŒÚ7 Œ/7 Œ­w)
ur   
        Admin rejects a pending MCP server â€” sets approval_status=rejected with optional review_notes.
        r©   z7Admin access required to reject MCP server submissions.rª   r  Nr&  r'  zMCP server is already rejected.)r  Úreview_notes)rz   rV  rU  r   r   r  r¥  r^   rÈ  r˜  r|   Úrejectedr°   r(  rh   r÷  r   r.  ru   r*  rI  )r7   r¤   rS  r2  rš  Ú
was_activer/  s          r?   Úreject_mcp_server_submissionr1  z  s6  è ø€ ô ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5ØÐ!ZÐ[ôð ô
  :Ð:tÓuˆä .¨}¸iÓ H×HˆØÐÜÜ"×5Ñ5Ø <°	¨{¸,Ð!GÐHôð ð ×#Ñ#Ô'8×'AÑ'AÒAÜÜ"×7Ñ7ØÐ!BÐCôð ð
 %×4Ñ4Ô8I×8PÑ8PÑPˆ
Ü 1ØØØ(×0Ñ0ÒLÔ4LØ ×-Ñ-ô	!
÷ 
ˆñ Ü+×HÑHÓJ×JÐJÜ& xÓ0Ð0ð- Iøð
øð Kús7   ‚AD8ÁD2ÁB,D8ÄD4ÄD8Ä"D6Ä#D8Ä4D8Ä6D8z/server/{server_id}zReturns the mcp server infoc              ƒ   óÆ  K  — t        d«      }t        ||«      ƒ d{  –—† }|du}|€vddlm} |j	                  | «      }t        j                  |«      }|�t        j                  ||«      sd}|€t        j                  ||¬«      }|�t        j                  |«      }|€!t        t        j                  dd|› d�i¬	«      ‚t        |«      }	t        |«      }
|	sq|r!t        ||«      ƒ d{  –—† }t!        ||«      }n+t        j"                  |«      ƒ d{  –—† }|j$                  |v }|s!t        t        j&                  dd
|› d�i¬	«      ‚|rt        j(                  |«      ƒ d{  –—†  	 t        j*                  |«      ƒ d{  –—† }|j                  r|j                  nd|_        |j,                  |_        |j.                  |_        t=        |«      }|
rt?        |«      S tA        |«      stC        |«      S |S 7 �ŒÛ7 �Œ7 Œé7 Œ›7 Œ# t0        $ rQ}t3        j4                  d||«       d|_        t7        j8                  «       |_        t;        |«      |_        Y d}~Œ‘d}~ww xY w­w)aY  
        Get the info on the mcp server specified by the `server_id`
        Parameters:
        - server_id: str - Required. The unique identifier of the mcp server to get info on.
        ```
        curl --location 'http://localhost:4000/v1/mcp/server/server_id'         --header 'Authorization: Bearer your_api_key_here'
        ```
        r  Nr   r¾  ©rÃ  r©   úMCP Server with id ú
 not foundrª   z9User does not have permission to view mcp server with id z8. You can only view mcp servers that you have access to.rÜ   z.Error performing health check on server %s: %s)"r¥  r^   rÁ  r¿  rÂ  ru   r�  Ú_is_server_accessible_from_ipÚget_mcp_server_by_namerß  r   r   rÈ  r‘   r[  r\   rF   rï  r7   r  Ú
add_serverÚhealth_check_serverru  rt  r  r   r  r   r  r;   rI  rz  rW  rk  )r¼  r7   rS  r2  r@  Úfrom_dbr¿  rÃ  Úregistry_serverÚis_admin_viewr  r@   ÚexistsÚallowed_server_idsÚhealth_resultr"  Úredacteds                    r?   Úfetch_mcp_serverrA  ©  s  è ø€ ô(  :Ð:tÓuˆô *¨-¸ÓC×Cˆ
Ø#¨4Ð/ˆàÐåJà-×?Ñ?ÀÓHˆIÜ7×LÑLÈYÓWˆOØÐ*Ô3L×3jÑ3jØ ô4ð #'�ØÐ&ä";×"RÑ"RÐS\ÐhqÔ"r�ØÐ*Ü6×NÑNÈÓ_�
àÐÜÜ"×5Ñ5ØÐ#6°y°kÀÐ!LÐMôð ô  4Ð4EÓFˆÜ+MÐN_Ó+`Ð!áñ Ü2NÈ}Ð^oÓ2p×,pÐ"Ü.Ð/AÀ9ÓM‘ô 3L×2cÑ2cÐduÓ2v×,vÐ"Ø#×-Ñ-Ð1CÐC�áÜ#Ü &× 9Ñ 9àØWÐXaÐWbð cUð Uðôð ñ Ü+×6Ñ6°zÓB×BÐBð
	3Ü)B×)VÑ)VÐW`Ó)a×#aˆMà8E×8LÒ8L × 4Ò 4ÐR[ˆJÔØ+8×+JÑ+JˆJÔ(Ø,9×,LÑ,LˆJÔ)ô 2°*Ó=ˆÙ$Ü7¸ÓAÐAô #Ð#4Ô5Ü5°hÓ?Ð?ØˆðW DùðB -qùð -wøð  Cøð $bùô
 ò 	3Ü ×&Ñ&Ð'WÐYbÐdeÔfØ )ˆJÔÜ+3¯<©<«>ˆJÔ(Ü,/°«FˆJ×)Ñ)ûð		3üs…   ‚I!�G8žCI!Ã*G;Ã+)I!ÄG>ÄAI!Å$H Å%I!Å*H ÆHÆAH Ç1I!Ç;I!Ç>I!È I!ÈH È	IÈAIÉI!ÉIÉI!zAllows creation of mcp serversz�The litellm-changed-by header enables tracking of actions performed by authorized users on behalf of other users, providing an audit trail for accountabilityÚlitellm_changed_byc              ƒ   óz  K  — t        d«      }t        | «       t        | «       t        j                  |j
                  k7  rt        t        j                  ddi¬«      ‚t        j                  | j                  k(  st        j                  | j                  k(  r+t        t        j                  dd| j                  › d�i¬«      ‚| j                  �Kt        || j                  «      ƒ d{  –—† }|�+t        t        j                  dd| j                  › d�i¬«      ‚t        j                   | _        d| _        d| _        	 t)        || |j*                  xs t,        ¬	«      ƒ d{  –—† }	 t7        j8                  |«      ƒ d{  –—†  t7        j:                  «       ƒ d{  –—†  t=        |«      S 7 ŒÂ7 ŒK# t.        $ r;}t1        j2                  d
|«       t        t        j4                  dd|› �i¬«      ‚d}~ww xY w7 Œv7 Œ\# t.        $ r5}t1        j2                  d|j                  |«       Y d}~t=        |«      S d}~ww xY w­w)z?
        Allow users to add a new external mcp server.
        r  r©   znUser does not have permission to create mcp servers. You can only create mcp servers if you are a PROXY_ADMIN.rª   r4  z is special and cannot be used.Nz' already exists. Cannot create another.r  zError creating mcp server: %szError creating mcp server: z?MCP server %s created but in-memory registry refresh failed: %s)r¥  r'   rÍ   rz   rV  rU  r   r   r  r‰   Úall_team_serversr7   Úall_proxy_serversr°   r^   r|   r(  r˜  r  r  rW   r÷  r   r  r   r  rØ   ru   r8  r*  rI  )r¤   rS  rB  r2  r@  r  r"  s          r?   Úadd_mcp_serverrF    s2  è ø€ ô&  :Ð:tÓuˆô 	2°'Ô:Ü! 'Ô*ô ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5àð  Nðôð ô !×1Ñ1°W×5FÑ5FÒFÜ#×5Ñ5¸×9JÑ9JÒJäÜ"×7Ñ7ØÐ#6°w×7HÑ7HÐ6IÐIhÐ!iÐjôð ð
 ×ÑÐ(ä&4°]ÀG×DUÑDUÓ&V× VˆJØÐ%Ü#Ü &× ;Ñ ;Ø#Ð':¸7×;LÑ;LÐ:MÐMtÐ%uÐvôð ô #4×":Ñ":ˆÔØ#ˆÔØ#ˆÔð	Ü*;ØØØ,×4Ñ4ÒPÔ8Pô+÷ %ˆNð 	Ü+×6Ñ6°~ÓF×FÐFÜ+×HÑHÓJ×JÐJô ' ~Ó6Ð6ðW !Wøð&%ùô
 ò 	Ü ×*Ñ*Ð+JÈAÔNÜÜ"×AÑAØÐ#>¸q¸cÐ!BÐCôð ûð	úð GøØJùÜò 	Ü ×*Ñ*ØQÐSa×SkÑSkÐmn÷ð ô ' ~Ó6Ð6ûð	üs‘   ‚C&H;Ã(F+Ã)AH;Ä>#F/ Å!F-Å"F/ Å'G: Å?G6Æ G: ÆG8ÆG: Æ H;Æ-F/ Æ/	G3Æ86G.Ç.G3Ç3H;Ç6G: Ç8G: Ç:	H8È!H3È$H;È3H8È8H;z/server/importzHBulk-import MCP connectors from Anthropic mcpServers or mcp_servers JSONc           	   ƒ   óh  ‡‡	‡
‡‡K  — t        d«      Št        j                  ‰j                  k7  rt	        t
        j                  ddi¬«      ‚t        | «      Š
t        ‰«      ƒ d{  –—† }t        d„ |D «       «      Šdt        dt        t        z  d	t        t        z  t        z  fˆ
ˆfd
„Š	dt        d	t        t        z  fˆˆfd„}t!        ˆ	fd„t#        ‰
«      D «       «      }t!        |D �cg c]$  }t%        |t        «      r ||«      ƒ d{  –—† n|‘Œ& c}«      }t!        d„ |D «       «      }|r	 t'        j(                  «       ƒ d{  –—†  t1        |t!        d„ |D «       «      t!        d„ |D «       «      ¬«      S 7 �Œ7 Œqc c}w 7 Œ<# t*        $ r }t-        j.                  d|«       Y d}~Œ^d}~ww xY w­w)a2  
        Bulk-import MCP connectors. Accepts the Claude Desktop / Claude Code
        ``mcpServers`` mapping or the Anthropic Messages API ``mcp_servers``
        array, creates each entry as a LiteLLM MCP server, and returns
        per-entry results so partial imports are visible to the caller.
        r  r©   znUser does not have permission to import mcp servers. You can only import mcp servers if you are a PROXY_ADMIN.rª   Nc              3   ó`   K  — | ]&  }|j                   |j                  fD ]	  }|sŒ|–— Œ Œ( y ­wrT   )r§   r¦   )r‰  r¢   rR   s      r?   rŠ  z%import_mcp_servers.<locals>.<genexpr>†  s9   è ø€ ò *
Ø¸V¿\¹\È6×K]ÑK]Ð<^ò*
Ø48ÒbfŒDð*
Øñ*
ùs   ‚".¥	.ÚindexÚ
conversionrB   c                 ó  •— t        |t        «      r|S |j                  j                  xs d}|‰v rt	        |j
                  d|› d�¬«      S t        d„ ‰d |  D «       «      }||v rt	        |j
                  d|› d�¬«      S |S )Nrº   zAn MCP server named 'ú' already exists.)rR   Úreasonc              3   óp   K  — | ].  }t        |t        «      r|j                  j                  xs d –— Œ0 y­w)rº   N)r»   r“   r¼  r§   )r‰  Úearliers     r?   rŠ  z8import_mcp_servers.<locals>._classify.<locals>.<genexpr>”  s5   è ø€ ò /àÜ˜gÔ'9Ô:ð —‘×%Ñ%Ò+¨Ó+ñ/ùs   ‚46zDuplicate connector name 'z' in the import payload.)r»   r’   r¼  r§   r˜   rR   rî  )rI  rJ  r§   Úearlier_aliasesÚconversionsÚexisting_namess       €€r?   Ú	_classifyz%import_mcp_servers.<locals>._classifyŠ  s¨   ø€ ô ˜*Ô&>Ô?Ø!Ð!Ø%×-Ñ-×3Ñ3Ò9°rˆEØ˜Ñ&Ü0Ø#Ÿ™Ð3HÈÈÐO`Ð1aôð ô &/ñ /à*¨6¨EÐ2ô/ó &ˆOð
 ˜Ñ'Ü0Ø#Ÿ™Ð3MÈeÈWÐTlÐ1môð ð Ðr>   c              “   óx  •K  — 	 t        | j                  «       	 t        ‰| j                  ‰j                  xs t        ¬«      ƒ d {  –—† }	 t!        j"                  |«      ƒ d {  –—†  t%        | j                  |j&                  |j(                  xs d¬«      S # t        $ r}t        |j                  t
        «      r/t        |j                  j                  d|j                  «      «      nt        |j                  «      }t        | j                  |¬«      cY d }~S d }~ww xY w7 ŒÝ# t        $ rK}t        j                  d| j                  |«       t        | j                  t        |«      ¬«      cY d }~S d }~ww xY w7 �Œ# t        $ r,}t        j                  d| j                  |«       Y d }~�ŒGd }~ww xY w­w)Nr©   ©rR   r©   r  z!Error importing mcp server %s: %szFImported mcp server %s committed but in-memory registration failed: %srº   )rR   r7   r§   )r'   r¼  r   r»   r¬   r¼   r;   r½   r”   rR   rW   r÷  r   r  r   r  ru   r8  r—   r7   r§   )rJ  r"  Ú
error_textÚcreatedr2  rS  s       €€r?   Ú_createz#import_mcp_servers.<locals>._createŸ  ss  øè ø€ ðYÜ9¸*×:LÑ:LÔMðUÜ'8Ø!Ø×&Ñ&Ø0×8Ñ8ÒTÔ<Tô(÷ "�ðÜ/×:Ñ:¸7ÓC×CÐCô
 ,Ø—_‘_°×0AÑ0AÈÏÉÒI\ÐZ\ôð øô) !ò Yä<FÀqÇxÁxÔQUÔ<V”C˜Ÿ™Ÿ™ W¨a¯h©hÓ7Ô8Ô\_Ð`a×`hÑ`hÓ\ið ô 1°j·o±oÈZÔXÕXûð	Yúð"ùô
 ò UÜ$×.Ñ.Ð/RÐT^×TcÑTcÐefÔgÜ0°j·o±oÌSÐQRËVÔTÕTûðUúð DúÜò Ü$×.Ñ.Ø\Ð^h×^mÑ^mÐop÷ò ûðüs§   ƒF:…B ›-D( ÁD&Á	D( ÁF Á&E?Á'F Á+0F:Â	D#Â$A4DÄD#ÄF:ÄD#Ä#F:Ä&D( Ä(	E<Ä1A E7Å1E<Å2F:Å7E<Å<F:Å?F Æ	F7Æ!F2Æ,F:Æ2F7Æ7F:c              3   ó6   •K  — | ]  \  }} ‰||«      –— Œ y ­wrT   r=   )r‰  rI  rJ  rS  s      €r?   rŠ  z%import_mcp_servers.<locals>.<genexpr>¼  s   øè ø€ Ò!oÑCTÀ5È*¡)¨E°:×">Ñ!oùs   ƒc              3   óB   K  — | ]  }t        |t        «      sŒ|–— Œ y ­wrT   )r»   r—   ©r‰  r  s     r?   rŠ  z%import_mcp_servers.<locals>.<genexpr>Ã  s   è ø€ Òk¨%¼zÈ%ÔQiÕ?j¤Ñkùó   ‚˜z>MCP connector import committed but registry refresh failed: %sc              3   óB   K  — | ]  }t        |t        «      sŒ|–— Œ y ­wrT   )r»   r˜   r[  s     r?   rŠ  z%import_mcp_servers.<locals>.<genexpr>Ì  s   è ø€ Òf E¼ÀEÔKdÕ9eœ%Ñfùr\  c              3   ó®   K  — | ]M  }t        |t        t        f«      r5t        |t        «      r!t        |j                  |j                  ¬ «      n|–— ŒO y­w)rU  N)r»   r’   r”   rR   r©   r[  s     r?   rŠ  z%import_mcp_servers.<locals>.<genexpr>Í  sO   è ø€ ò ð Ü˜eÔ&>Ô@YÐ%ZÔ[ô ˜eÔ%=Ô>ô *¨u¯z©zÀÇÁÕMàóñùs   ‚AA)ÚimportedÚskippedÚerrors)r¥  rz   rV  rU  r   r   r  r™   r[   rî  Úintr“   r’   r˜   r—   r”   ÚtupleÚ	enumerater»   ru   r*  r  r   r  r–   )r¤   rS  Úexisting_serversrX  Ú
classifiedr  Úoutcomesr_  r"  rS  rQ  rR  r2  s    `       @@@@r?   Úimport_mcp_serversrh  h  s»  üè ø€ ô$  :Ð:tÓuˆä×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5àð  Nðôð ô 7°wÓ?ˆÜ(;¸MÓ(J×"JÐÜ )ñ *
Ø/ô*
ó !
ˆð	Üð	Ü$6Ô9QÑ$Qð	äÔ":Ñ:Ô=VÑVö	ð*	Ü*ð	ä%Ô(AÑAö	ô: "Ó!oÔXaÐbmÓXnÔ!oÓoˆ
ÜàfpöØ]b¬
°5Ô:LÔ(M‘g˜e“n×$Ð$ÐSXÑXòó
ˆô  Ñk°8ÔkÓkˆÙðtÜ/×LÑLÓN×NÐNô *ØÜÑf¨XÔfÓfÜñ ð &ô	ó ô

ð 
	
ðK #Kùðt %úòð OùÜò tÜ$×.Ñ.Ð/oÐqr×sÑsûðtüss   ‡AF2Á&E:Á'BF2Ã+ E?ÄE=ÄE?ÄF2Ä0F ÅFÅF Å/F2Å=E?Å?F2ÆF Æ	F/ÆF*Æ%F2Æ*F/Æ/F2z/server/oauth/sessionzITemporarily cache an MCP server in memory without writing to the database)rô   r¦  r«   c              ƒ   óª  K  — t        | «       t        | «       t        j                  |j                  k7  rt        t        j                  ddi¬«      ‚|j                  xs t        }t        | «      }t        ||t        |«      ƒ d{  –—† «      }	 t        j                  |d¬«      ƒ d{  –—† }t        |t         ¬«       t#        ||j$                  |«      ƒ d{  –—†  t'        |t         ¬«      ƒ d{  –—†  t1        |«      S 7 Œ|7 ŒZ7 Œ,7 Œ# t(        $ r;}t+        j,                  d|«       t        t        j.                  dd	|› �i¬«      ‚d}~ww xY w­w)
a  
        Cache MCP server info in memory for a short duration (~5 minutes).

        This endpoint does not write to the database. If the same server_id is provided
        again while the cache entry is active, it will refresh the cached data + TTL.
        r©   z‚User does not have permission to create temporary mcp servers. You can only create temporary mcp servers if you are a PROXY_ADMIN.rª   NF)Úcredentials_are_encryptedr8  z&Error caching temporary mcp server: %sz$Error caching temporary mcp server: )r'   rÍ   rz   rV  rU  r   r   r  r÷  r   r•  r¢  r›  ru   r9  r  r3   r6  r7   r#  r  r   r  rØ   rI  )r¤   rS  rB  r4  Úpayload_with_credentialsÚtemp_recordÚtemporary_serverr"  s           r?   Úadd_session_mcp_serverrn  Ö  sj  è ø€ ô. 	2°'Ô:Ü! 'Ô*ô ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5àð  bðôð ð .×5Ñ5ÒQÔ9Qˆ
Ü*SÐT[Ó*\Ð Ü?Ø$ØÜ,Ð-EÓF×Fó
ˆð	Ü,E×,aÑ,aØØ*/ô-÷ 'Ðô (Ø Ü<õô ,Ø(Ø×%Ñ%Øó÷ ð ô
 7Ø Ü<ô÷ ð ô ' {Ó3Ð3ð9 Gøð'øðøð
ùô ò 	Ü ×*Ñ*Ð+SÐUVÔWÜÜ"×AÑAØÐ#GÈÀsÐ!KÐLôð ûð	üsl   ‚BEÂDÂEÂD Â+DÂ,/D ÃDÃD Ã4D
Ã5D Ã9EÄD ÄD Ä
D Ä	EÄ6EÅEÅEc           	   ƒ   óæ  K  — ddl }ddlm} | j                  j	                  dd«      }|}|se| j
                  j	                  d«      }|rH|rF	 |j                  ||dgddd	œ¬
«      }|j	                  d«      dv r|j	                  dd«      }|rd|› �}|�sddlm	} ddl
m}	 | j                  j	                  dd«      }
|
rÛ |j                  |
«      }|s |j                  |
«      }|r³t        |dd«      t         j"                  k(  r•t        |dd«      du r†|j$                  sz |	| «      j'                  d«      j)                  «       }|j+                  d«      r:t-        | ¬«      ƒ d{  –—† }|xs i j	                  dd«      }|dk7  rnt/        «       S t/        «       S t-        | ¬«      ƒ d{  –—† }t1        || ¬«      }t3        | |dddd|¬«      ƒ d{  –—† S # |j                  $ r Y �ŒUw xY w7 Œ…7 ŒC7 Œ­w)af  
        Auth dependency for MCP OAuth browser-navigation endpoints (/authorize, /token).

        Tries the Authorization header first. Falls back to decoding the UI
        'token' session cookie (set by SSO login) to extract the API key, which
        allows browser-based OAuth redirects to work without an explicit
        Authorization header.
        r   N)Ú
master_keyÚAuthorizationrº   ÚtokenÚHS256F)Ú
verify_expÚ
verify_aud)Ú
algorithmsÚoptionsÚlogin_method)ÚssoÚusername_passwordr  zBearer rt   )Úget_request_router7   rÇ   Údelegate_auth_to_upstreamTrå   z/token©r¼  Ú
grant_typerÆ   )Úrequest_datar¼  )r¼  Úapi_keyÚazure_api_key_headerÚanthropic_api_key_headerÚgoogle_ai_studio_api_key_headerÚazure_apim_headerr  )Újwtr×   rp  Úheadersr½   ÚcookiesÚdecodeÚInvalidTokenErrorr³  ru   Úlitellm.proxy.auth.auth_utilsr{  Úpath_paramsr�  r7  r­   rœ   rÈ   Úhas_client_credentialsræ   ÚlowerÚendswithr�   r‹   r�   r�   )r¼  Ú_jwtrp  Úauth_headerr€  Útoken_cookieÚdecodedÚ
cookie_keyru   r{  r7   Ú_sÚ
path_lowerÚ	body_datar~  r  s                   r?   Ú_mcp_oauth_user_api_key_authr—    s  è ø€ ó 	å9à$Ÿ_™_×0Ñ0°À"ÓEˆØˆáØ")§/¡/×"5Ñ"5°gÓ">ˆLÙ¡
ðØ%)§[¡[Ø$Ø"Ø$+ 9à/4ÀEÑ Jð &1ó &�Gð —{‘{ >Ó2Ð6RÑRØ18·±¸UÀBÓ1G˜
Ù%Ø(/°
¨|Ð&<˜Gò" õõð %,×$7Ñ$7×$;Ñ$;¸KÈÓ$LˆIÙØCÐ.×CÑCÀIÓN�ÙØIÐ2×IÑIÈ)ÓT�BáÜ  K°Ó6¼'¿.¹.ÒHÜ Ð$?ÀÓGÈ4ÑOð ×5Ò5ñ ):¸'Ó(B×(IÑ(IÈ#Ó(N×(TÑ(TÓ(V�JØ!×*Ñ*¨8Ô4Ü1CÈGÔ1T×+T˜	Ø-6ª_¸"×,AÑ,AÀ,ÐPRÓ,S˜
Ø%Ð)=Ò=ð !ä#1Ó#3Ð3ô  .Ó/Ð/ä/¸Ô@×@ˆÜ8ÀlÐ\cÔdˆä/ØØØ!#Ø%)Ø,0Ø"Ø%ô
÷ 
ð 	
øðw ×-Ñ-ò ÚðúðR ,Uøð Aøð
ús]   ‚A
G1ÁAG ÂCG1Å%G+Å&AG1Æ)G-Æ*&G1ÇG/ÇG1ÇG(Ç$G1Ç'G(Ç(G1Ç-G1Ç/G1c              ƒ   óx  K  — t        | «      ƒ d {  –—† }|d u}|€Iddlm} |r|j                  |«      nd }t	        j
                  | «      xs t	        j                  | |¬«      }|€!t        t        j                  dd| › d�i¬«      ‚t        |«      sž|r t        t        j                  dd| › �i¬«      ‚t        «       }t        |«      ƒ d {  –—† D ].  }|j                  t	        j                  |«      ƒ d {  –—† «       Œ0 |j                   |vr t        t        j                  dd| › �i¬«      ‚|S 7 �Œ"7 Œh7 Œ?­w)	Nr   r¾  r3  r©   zMCP server r5  rª   zAccess denied to MCP server )r?  rÁ  r¿  rÂ  ru   r�  r7  r   r   rÈ  r‘   r  r´  rw   r�  rï  r7   )	r7   rS  r¼  r¢   Úresolved_from_temp_cacher¿  rÃ  r>  rë  s	            r?   Ú'_get_cached_temporary_mcp_server_or_404rš  €  s_  è ø€ ô
 7°yÓA×AˆØ*0¸Ð*<Ð Øˆ>õ KáLS˜~×?Ñ?ÀÔHÐY]ˆIÜ.×CÑCØóò bä*×AÑAÀ)ÐW`Ôað ð ˆ>ÜÜ"×5Ñ5Ø ;¨y¨k¸Ð!DÐEôð ô $Ð$5Ô6Ù'Ü#Ü &× 9Ñ 9Ø#Ð'CÀIÀ;Ð%OÐPôð ô 36³%ÐÜ&CÐDUÓ&V× Vò q�Ø"×)Ñ)Ô0I×0aÑ0aÐbnÓ0o×*oÕpðqà×ÑÐ'9Ñ9Ü#Ü &× 9Ñ 9Ø#Ð'CÀIÀ;Ð%OÐPôð ð ˆðI Bùð: !WøØ*oús4   ‚D:‘D3’B;D:ÃD6Ã*D:Ã8D8
Ã9;D:Ä6D:Ä8D:z#/server/oauth/{server_id}/authorize)Úinclude_in_schemar¦  rº   rÃ   Úredirect_uriÚstateÚcode_challengeÚcode_challenge_methodÚresponse_typeÚscopec
              ƒ   óZ  K  — t        ||| ¬«      ƒ d {  –—† }
t        |
«       |
j                  xs |xs d}|st        | |
|||¬«      ƒ d {  –—† nd }|xs |r|j                  nd}|st	        t
        j                  dddœ¬«      ‚t        | |
|||||||	|¬«
      ƒ d {  –—† S 7 Œ�7 ŒY7 Œ­w)	Nr}  rº   )r¼  r@  rž  rŸ  rœ  Úmissing_client_idúvNo client_id available for this MCP server. Either configure the server with a client_id or supply one in the request.©r©   r£  rª   )
r¼  r@  rÃ   rœ  r�  rž  rŸ  r   r¡  Úephemeral_dcr_client)rš  rl   rÃ   rs   r   r   r°   rm   )r¼  r7   rS  rÃ   rœ  r�  rž  rŸ  r   r¡  r@  Ústored_or_supplied_client_idr¦  Úresolved_client_ids                 r?   Úmcp_authorizer©  «  sø   è ø€ ô" #JÈ)ÐUfÐpwÔ"x×xˆ
Ü˜ZÔ(à.8×.BÑ.BÒ.UÀiÒ.UÐSUÐ$ñ 0ô /ØØ%Ø-Ø&;Ø)ô÷ ð ð ð 	ð %Aò %
Ù.BÐ ×*Ò*Èð 	ñ "ÜÜ"×7Ñ7à0ðeñô	ð 	ô +ØØ!Ø(Ø%ØØ)Ø"7Ø'ØØ!5ô
÷ 
ð 	
ð; yøð
øð0
ús4   ‚B+”B%•8B+ÁB'ÁAB+Â B)Â!B+Â'B+Â)B+z/server/oauth/{server_id}/tokenr~  ÚcoderÄ   Úcode_verifierÚrefresh_tokenc              ƒ   óÂ  K  — t        ||| ¬«      ƒ d {  –—† }t        |«       |dk(  rt        |||¬«      nd }|r|j                  n|}|rt	        | «      › d�n|}|r|j
                  n|}|r|j                  n|}|j
                  xs |xs d}|st        t        j                  dddœ¬	«      ‚t        | ||||||||	|
|r|j                  nd ¬
«      ƒ d {  –—† S 7 ŒÆ7 Œ­w)Nr}  rÆ   )rª  r@  r«  z	/callbackrº   r£  r¤  r¥  rª   )r¼  r@  r~  rª  rœ  rÃ   rÄ   r«  r¬  r¡  Ú!client_token_endpoint_auth_method)rš  rl   rq   Úupstream_coderp   rÃ   rÄ   r   r   r°   ro   Útoken_endpoint_auth_method)r¼  r7   rS  r~  rª  rœ  rÃ   rÄ   r«  r¬  r¡  r@  Úsealed_codeÚresolved_codeÚresolved_redirect_uriÚcaller_client_idÚcaller_client_secretr¨  s                     r?   Ú	mcp_tokenr¶  æ  s!  è ø€ ô$ #JÈ)ÐUfÐpwÔ"x×xˆ
Ü˜ZÔ(ð Ð1Ò1ô 2°tÈ
ÐboÕpàð 	ñ
 =H˜{×8Ò8ÈTˆñ WbÔ*>¸wÓ*GÐ)HÈ	Ñ'RÐgsÐÙ;F +×"7Ò"7ÈIÐÙCN k×&?Ò&?ÐTaÐØ$.×$8Ñ$8Ò$RÐ<LÒ$RÐPRÐÙ!ÜÜ"×7Ñ7à0ðeñô	ð 	ô 0ØØ!Ø!ØØ.Ø(Ø.Ø'Ø'ØÙXc¨k×.TÒ.TÐimô
÷ 
ð 	
ð9 yøð8
ús"   ‚C”C•CCÃCÃCÃCz"/server/oauth/{server_id}/registerc              ƒ   óp  K  — t        ||| ¬«      ƒ d {  –—† }t        | ¬«      ƒ d {  –—† }i |¥}t        |j                  d«      «      }t	        | ||j                  dd«      |j                  dg «      |j                  dg «      |j                  dd«      |t        |«      |¬«	      ƒ d {  –—† S 7 Œ›7 Œ‰7 Œ­w)	Nr}  Úredirect_urisÚclient_namerº   Úgrant_typesÚresponse_typesr°  )	r¼  r@  r¹  rº  r»  r°  Úfallback_client_idÚpersist_credentialsÚclient_redirect_uris)rš  r�   rn   r½   rr   rW  )r¼  r7   rS  r@  r  Údatar¾  s          r?   Úmcp_registerrÀ  "  s¸   è ø€ ô #JÈ)ÐUfÐpwÔ"x×xˆ
Ü$6¸wÔ$G×GˆØ,˜|Ð,ˆÜ&CÀDÇHÁHÈ_ÓD]Ó&^Ðä0ØØ!ØŸ™ °Ó3ØŸ™ °Ó3ØŸ8™8Ð$4°bÓ9Ø'+§x¡xÐ0LÈbÓ'QØ(Ü 3Ð4EÓ FØ!5ô

÷ 

ð 
	
ð yøØGøð

ús2   ‚B6”B0•B6¨B2©BB6Â+B4Â,B6Â2B6Â4B6z$Allows deleting mcp serves in the db)rô   r¦  Úresponse_classr«   c              ƒ   óÒ  K  — t        d«      }t        j                  |j                  k7  r,t	        t
        j                  ddj                  d«      i¬«      ‚t        || «      ƒ d{  –—† }|€ t	        t
        j                  dd| › �i¬«      ‚t        j                  |«       t        j                  «       ƒ d{  –—†  t        «       r	 t        t
        j                  ¬«      S 7 Œ|7 Œ+­w)	ak  
        Delete MCP Server from db and associated MCP related server entities.

        Parameters:
        - server_id: str - Required. The unique identifier of the mcp server to delete.
        ```
        curl -X "DELETE" --location 'http://localhost:4000/v1/mcp/server/server_id'         --header 'Authorization: Bearer your_api_key_here'
        ```
        ú�Database not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keysr©   zJCall not allowed to delete MCP server. User is not a proxy admin. route={}zDELETE /v1/mcp/serverrª   Nú'MCP Server not found, passed server_id=©r«   )r¥  rz   rV  rU  r   r   r  ÚformatrX   rÈ  ru   Úremove_serverr*  r+   r   ÚHTTP_202_ACCEPTED)r7   rS  rB  r2  Úmcp_server_record_deleteds        r?   Úremove_mcp_serverrÊ  =  sî   è ø€ ô4  :ð Pó 
ˆô
 ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5àÐi×pÑpØ/óðôð ô 2CÀ=ÐR[Ó1\×+\Ð!à$Ð,ÜÜ"×5Ñ5ØÐ#JÈ9È+Ð!VÐWôð ô 	"×/Ñ/Ð0IÔJô (×DÑDÓF×FÐFô $Ô%Øô ¤F×$<Ñ$<Ô=Ð=ð- ,]øð 	Gús%   ‚A$C'Á&C#Á'AC'Â9C%Â:*C'Ã%C'z#/server/{server_id}/user-credentialz@Store or update the calling user's API key for a BYOK MCP serverc              ƒ   ó®  K  — t        d«      }t        ||| «      ƒ d{  –—† }t        |dd«      st        t        j
                  ddi¬«      ‚|j                  xs d}|st        t        j
                  dd	i¬«      ‚|j                  r<t        ||| |j                  «      ƒ d{  –—†  d
dl
m}  ||| «       t        | d¬«      S t        | d¬«      S 7 Œ²7 Œ/­w)z-Store a BYOK credential for the calling user.r  Nrù  Fr©   z1This MCP server does not support BYOK credentialsrª   rº   úUser ID not found in tokenr   ©Ú_invalidate_byok_cred_cacheT©r7   Úhas_credential)r¥  Ú_authorize_and_fetch_mcp_serverr­   r   r   r°   r÷  Úsaveri   Ú
credentialr¬  rÎ  rƒ   )r7   r¤   rS  r2  r@  r÷  rÎ  s          r?   Ústore_mcp_user_credentialrÔ    sá   è ø€ ô  :Ð:tÓuˆÜ"AÀ-ÐQbÐdmÓ"n×nˆ
Ü�z 9¨eÔ4ÜÜ"×7Ñ7ØÐ!TÐUôð ð +×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ð �<Š<Ü'¨°wÀ	È7×K]ÑK]Ó^×^Ð^õñ (¨°Ô;Ü,°yÐQUÔVÐVä(°9ÈUÔSÐSð+ oøð _ús"   ‚CžCŸBCÂ#CÂ$.CÃCz>Delete the calling user's stored API key for a BYOK MCP serverc              ƒ   ó  K  — t        d«      }|j                  xs d}|st        t        j                  ddi¬«      ‚	 t        ||| «      ƒ d{  –—†  ddlm}  ||| «       t        | d	¬
«      S 7 Œ # t        $ r Y Œ)w xY w­w)z*Remove the calling user's BYOK credential.r  rº   r©   rÌ  rª   Nr   rÍ  FrÏ  )
r¥  r÷  r   r   r°   rY   r   r¬  rÎ  rƒ   )r7   rS  r2  r÷  rÎ  s        r?   Údelete_mcp_user_credentialrÖ  ¤  s‘   è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ð	Ü(¨¸ÀÓK×KÐKõ	
ñ 	$ G¨YÔ7Ü(°9ÈUÔSÐSð LùÜ"ò 	Ùð	üs:   ‚;B ¾A1 ÁA/ÁA1 ÁB Á/A1 Á1	A=Á:B Á<A=Á=B z)/server/{server_id}/oauth-user-credentialz?Store the calling user's OAuth2 token for an OpenAPI MCP serverc           	   ƒ   óð  K  — t        d«      }t        ||| «      ƒ d{  –—†  |j                  xs d}|st        t        j
                  ddi¬«      ‚t        ||| |j                  |j                  |j                  |j                  ¬«      ƒ d{  –—†  dd	lm}  |j                  || «      ƒ d{  –—†  t        ||| «      ƒ d{  –—† }|r|j                  d
«      nd}t!        | d|d¬«      S 7 ŒÏ7 Œ`7 ŒA7 Œ.­w)z=Persist the OAuth2 access token obtained by the calling user.r  Nrº   r©   rÌ  rª   )r¬  Ú
expires_inr  r   rt   r£   TF)r7   rÐ  r£   Ú
is_expired)r¥  rÑ  r÷  r   r   r°   rj   Úaccess_tokenr¬  rØ  r  r³  ru   Ú!invalidate_user_oauth_token_cacherc   r½   r~   )r7   r¤   rS  r2  r÷  ru   Ústoredr£   s           r?   Ústore_mcp_oauth_user_credentialrÝ  Ä  s  è ø€ ô  :Ð:tÓuˆÜ-¨mÐ=NÐPYÓZ×ZÐZØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô *ØØØØ× Ñ Ø!×/Ñ/Ø×)Ñ)Ø—>‘>ô
÷ 	
ð 	
õ	
ð JÐ'×IÑIÈ'ÐS\Ó]×]Ð]ô 8¸ÀwÐPYÓZ×ZˆÙDJ¨¯
©
°<Ô(@ÐPTˆ
Ü+ØØØ!Øô	
ð 	
ð5 	[øð	
øð 	^øð [úsF   ‚C6žC.ŸA0C6ÂC0Â C6Â0C2Â1C6ÃC4Ã)C6Ã0C6Ã2C6Ã4C6z?Revoke the calling user's stored OAuth2 token for an MCP serverc              ƒ   ó`  K  — t        d«      }|j                  xs d}|st        t        j                  ddi¬«      ‚t        ||| «      ƒ d{  –—† }|�7	 t        ||| «      ƒ d{  –—†  ddlm	}  |j                  || «      ƒ d{  –—†  t        | d	d	¬
«      S 7 ŒK7 Œ5# t        $ r Y Œ>w xY w7 Œ%­w)z+Revoke/delete the user's OAuth2 credential.r  rº   r©   rÌ  rª   Nr   rt   F©r7   rÐ  rÙ  )r¥  r÷  r   r   r°   rc   rY   r   r³  ru   rÛ  r~   )r7   rS  r2  r÷  Úcred_to_deleteru   s         r?   Ú delete_mcp_oauth_user_credentialrá  ó  sÔ   è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô '@ÀÈwÐXaÓ&b× bˆØÐ%ðÜ,¨]¸GÀYÓO×OÐOõð NÐ+×MÑMÈgÐW`Óa×aÐaÜ+ØØ Øô
ð 	
ð !cøð PùÜ&ò Ùðúð búsT   ‚AB.ÁBÁB.ÁB Á%BÁ&B Á*B.ÂB,ÂB.ÂB Â	B)Â&B.Â(B)Â)B.z0/server/{server_id}/oauth-user-credential/statuszQCheck whether the calling user has a stored OAuth2 credential for this MCP serverc           	   ƒ   óÊ  K  — t        d«      }|j                  xs d}|st        t        j                  ddi¬«      ‚t        ||| «      ƒ d{  –—† }|€t        | dd¬«      S |j                  d	«      }d}|r<	 t        j                  |«      }|t        j                  t        j                  «      k  }t        | d
|||j                  d«      ¬«      S 7 Œ„# t        $ r Y Œ,w xY w­w)zMReturn credential status (has_credential, expiry) without exposing the token.r  rº   r©   rÌ  rª   NFrß  r£   TÚconnected_at)r7   rÐ  r£   rÙ  rã  )r¥  r÷  r   r   r°   rc   r~   r½   r   Úfromisoformatr  r	   r  r  )r7   rS  r2  r÷  Úcredr£   rÙ  Úexps           r?   Ú$get_mcp_oauth_user_credential_statusrç  	  sð   è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô 6°mÀWÈiÓX×XˆØˆ<Ü/¸)ÐTYÐfkÔlÐlØ(,¯©°Ó(>ˆ
Øˆ
ÙðÜ%×3Ñ3°JÓ?�Ø ¤8§<¡<´·±Ó#=Ñ=�
ô ,ØØØ!Ø!ØŸ™ .Ó1ô
ð 	
ð Yùô ò Ùðüs6   ‚AC#ÁCÁ)C#Á8;C Â3 C#Ã	C ÃC#ÃC Ã C#z/user-credentialsz;List all OAuth2 MCP credentials stored for the calling userc              ƒ   óZ  K  — t        d«      }| j                  xs d}|st        t        j                  ddi¬«      ‚t        ||«      ƒ d{  –—† }|sg S |D �cg c]  }d|v sŒ|d   ‘Œ }}t        ||«      ƒ d{  –—† D �ci c]  }|j                  |“Œ }}g }|D ]|  }	d|	vrŒ|	d   }
|j                  |
«      }|	j                  d«      }|j                  t        |
|rt        |d	d«      nd|rt        |d
d«      nddd||	j                  d«      ¬«      «       Œ~ |S 7 ŒÐc c}w 7 Œ¨c c}w ­w)z=Return all servers the calling user has connected via OAuth2.r  rº   r©   rÌ  rª   Nr7   r£   r¦   r§   rÈ   Trã  )r7   r¦   r§   Úcredential_typerÐ  r£   rã  )r¥  r÷  r   r   r°   rd   r_   r7   r½   r®   r�   r­   )rS  r2  r÷  Úoauth_credsÚcr  ÚsrvrÇ  r  rå  Úsidr£   s               r?   Úlist_mcp_user_credentialsrî  @	  sN  è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô $?¸}ÈgÓ#V×VˆÙØˆIà5@ÖU°ÀKÐSTÒDT˜Q˜{›^ÐUˆ
ÐUÜ>MÈmÐ]gÓ>h×8hÖi°˜#Ÿ-™-¨Ñ,ÐiˆÐiØ8:ˆØò 	ˆDØ $Ñ&ØØ�{Ñ#ˆCØ—+‘+˜cÓ"ˆCØ%)§X¡X¨lÓ%;ˆJØ�L‰LÜ)Ø!ÙEH¤¨¨]¸DÔ AÈdÙ9<œ' # w°Ô5À$Ø$,Ø#'Ø)Ø!%§¡¨.Ó!9ôõ
ð	ð" ˆð1 Wúò VØ8húÒiùsI   ‚A
D+ÁDÁD+Á	DÁ#DÁ*D+Á;D$Á<D+ÂD&ÂBD+ÄD+Ä&D+c              ƒ   óü  K  — t        | |«      ƒ d{  –—† }|€,t        j                  |«      }|�t        j                  |«      }t	        |«      r%|€!t        t        j                  dd|› d�i¬«      ‚|S t        «       }t        |«      ƒ d{  –—† D ].  }|j                  t        j                  |«      ƒ d{  –—† «       Œ0 |�|j                  |vr!t        t        j                  dd|› d�i¬«      ‚|S 7 Œã7 Œj7 ŒA­w)a  Resolve the MCP server a caller may manage their own per-user state for.

        Looks the server up in the DB, then the in-memory registry, so a
        config-defined server (which never gets a DB row) resolves too. Admins
        may reach any server and get a 404 for an unknown id. A non-admin may
        only reach a server in their allowed set and otherwise gets 403 (never
        404, so server ids can't be enumerated), using the same allowed-server
        resolution the MCP gateway enforces on tool calls.
        Nr©   zMCP Server r5  rª   z;User does not have permission to access mcp server with id z:. You can only manage mcp servers that you have access to.)r^   ru   r�  rß  r‘   r   r   rÈ  r´  rw   r�  rï  r7   r  )r2  rS  r7   r¢   r;  r>  rë  s          r?   rÑ  rÑ  n	  s  è ø€ ô & m°YÓ?×?ˆØˆ>Ü%>×%SÑ%SÐT]Ó%^ˆOØÐ*Ü2×JÑJÈ?Ó[�äÐ 1Ô2Øˆ~Ü#Ü &× 9Ñ 9Ø# {°9°+¸ZÐ%HÐIôð ð ˆMä.1«eÐÜ"?Ð@QÓ"R×Rò 	mˆLØ×%Ñ%Ô,E×,]Ñ,]Ð^jÓ,k×&kÕlð	màˆ>˜V×-Ñ-Ð5GÑGÜÜ"×5Ñ5àØUÐV_ÐU`ð aSð Sðôð ð ˆð7 @øð SøØ&kús4   ‚C<’C6“A:C<ÂC8Â*C<Â8C:
Â9>C<Ã8C<Ã:C<Ústored_valuesc           
      ó.  — t        t        | dd«      «      \  }}|j                  «       D ��ci c]  \  }}|sŒ	||“Œ }}}t        | dd«      xs i }t        |t        «      r	 t        j                  |«      xs i }t        |j                  «       ¬«      }|D �ch c]  }|d   ’Œ	 }	}||	z  D �ch c]	  }||vsŒ|’Œ }
}g }d}|D ][  }|d   }||
vrŒ|j                  |«      }t        |«      }|s|dz  }|j                  t        ||j                  d«      |¬	«      «       Œ] t        | j                   t        | d
d«      t        | dd«      |||rt#        | j                   «      ¬«      S d¬«      S c c}}w # t        t        f$ r i }Y �Œw xY wc c}w c c}w )a8  Build a status object for one server given the user's stored values.

        Stored credentials are write-only: the response reports only whether
        each value ``is_set`` and never echoes the decrypted secret back, so a
        leaked token can't be used to exfiltrate the raw upstream credential.
        ri  Nr^  )ÚstringsrR   r   r  rô   )rR   rô   Úis_setr¦   r§   )r7   r¦   r§   ÚrequiredÚmissing_countÚ	setup_url)r&   r­   r  r»   r;   r  r)  rü   rK  r$   r¶  r½   rP   r®   r„   r†   r7   r#   )r¢   rð  Úglobal_valuesÚ
user_specsrR   r³   r^  Ú
referencedÚspecÚuser_var_namesÚblockingrô  rõ  ró  s                 r?   Ú_compute_user_env_var_statusrý  ™	  sÆ  € ô %9¼ÀÈÐUYÓ9ZÓ$[Ñ!ˆ�zð
 9F×8KÑ8KÓ8M×W©¨¨uÒQV˜˜u™ÐWˆÑWô ! Ð)9¸4Ó@ÒFÀBˆÜ�n¤cÔ*ð$Ü!%§¡¨NÓ!;Ò!A¸r�ô 7¸~×?TÑ?TÓ?VÔWˆ
Ø:DÖ E°$  f£Ð EˆÐ EØ-7¸.Ñ-HÖg DÈTÐYfÒMfš4ÐgˆÐgà35ˆØˆØò 	ˆDØ˜V™ˆDØ˜8Ñ#ØØ!×%Ñ% dÓ+ˆEÜ˜%“[ˆFÙØ Ñ"�Ø�O‰OÜ!ØØ $§¡¨Ó 7Ø!ôõð	ô  $Ø×&Ñ&Ü ¨°tÓ<Ü˜& '¨4Ó0ØØ'ÙCKÔ-¨f×.>Ñ.>Ó?ô
ð 	
ð RVô
ð 	
ùóE Xøô ¤	Ð*ò $Ø!#“ð$üò !FùÚgs.   ­
E/¸E/Á"E5 ÂFÂ.	FÂ8FÅ5F
Æ	F
z!/server/{server_id}/user-env-varszFReturn the calling user's per-user MCP env var status for this server.c              ƒ   óô   K  — t        d«      }|j                  xs d}|st        t        j                  ddi¬«      ‚t        ||| «      ƒ d {  –—† }t        ||| «      ƒ d {  –—† }t        ||¬«      S 7 Œ&7 Œ­w)Nr  rº   r©   rÌ  rª   ©r¢   rð  )r¥  r÷  r   r   r°   rÑ  ra   rý  )r7   rS  r2  r÷  r¢   rÜ  s         r?   Úget_mcp_user_env_varsr   Ô	  s‚   è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô >¸mÐM^Ð`iÓj×jˆÜ/°¸wÈ	ÓR×RˆÜ+°6ÈÔPÐPð køØRús$   ‚AA8ÁA4ÁA8Á"A6Á#A8Á6A8a  Store the calling user's per-user MCP env var values for this server. Submitted values are merged over any previously stored values, so you only send the fields you want to set or change; a variable omitted (or sent empty) keeps its stored value. Use DELETE to clear all stored values.c              ƒ   óò  K  — t        d«      }|j                  xs d}|st        t        j                  ddi¬«      ‚t        ||| «      ƒ d {  –—† }t        t        |dd «      «      \  }}|D �ch c]  }|d   ’Œ	 }	}|j                  j                  «       D �
�ci c]  \  }
}|
|	v sŒ|dk7  sŒ|
|“Œ }}
}t        ||| ||	«      ƒ d {  –—† }dd	lm}  ||| «       t        ||¬
«      S 7 Œšc c}w c c}}
w 7 Œ-­w)Nr  rº   r©   rÌ  rª   ri  rR   r   ©Úinvalidate_user_env_vars_cacherÿ  )r¥  r÷  r   r   r°   rÑ  r&   r­   r¶  r  rf   r³  r  rý  )r7   r¤   rS  r2  r÷  r¢   Ú_rø  rú  Úallowed_namesÚkÚvÚupdatesÚmergedr  s                  r?   Ústore_mcp_user_env_varsr
  ê	  s	  è ø€ ô$  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô >¸mÐM^Ð`iÓj×jˆô -¬W°V¸ZÈÓ-NÓO‰ˆˆ:Ø9CÖD°  V£ÐDˆÐDØ+2¯>©>×+?Ñ+?Ó+A×d¡4 1 aÀQÈ-ÒEWÐ\]ÐacÓ\c˜!˜Q™$ÐdˆÑdÜ1°-ÀÈ)ÐU\Ð^kÓl×lˆõ	
ñ 	' w°	Ô:Ü+°6ÈÔPÐPð kúò  EùÛdØlúsH   ‚AC7ÁC(Á!C7Á/C*Á;C7ÂC/Â'C/Â-C/Â2C7ÃC5Ã!C7Ã*C7zEClear the calling user's per-user MCP env var values for this server.c              ƒ   ó  K  — t        d«      }|j                  xs d}|st        t        j                  ddi¬«      ‚t        ||| «      ƒ d {  –—† }t        ||| «      ƒ d {  –—†  ddlm}  ||| «       t        |i ¬«      S 7 Œ57 Œ"­w)	Nr  rº   r©   rÌ  rª   r   r  rÿ  )
r¥  r÷  r   r   r°   rÑ  rZ   r³  r  rý  )r7   rS  r2  r÷  r¢   r  s         r?   Úclear_mcp_user_env_varsr  
  s”   è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙÜÜ"×7Ñ7ØÐ!=Ð>ôð ô >¸mÐM^Ð`iÓj×jˆÜ" =°'¸9ÓE×EÐEõ	
ñ 	' w°	Ô:Ü+°6ÈÔLÐLð køØEús$   ‚ABÁBÁBÁ"BÁ#!BÂBz/user-env-vars/statusz‹Per-user MCP env var status across every server the user can access. Used by the dashboard to highlight servers with missing per-user vars.c              ƒ   óˆ  K  — t        d«      }| j                  xs d}|sg S t        | «      ƒ d {  –—† }|sg S |D �cg c]  }|j                  ‘Œ }}t	        |||«      ƒ d {  –—† }g }|D ]I  }|j                  |j                  i «      }	t        ||	¬«      }
|
j                  sŒ9|j                  |
«       ŒK |S 7 Œˆc c}w 7 Œ]­w)Nr  rº   rÿ  )	r¥  r÷  rì  r7   rb   r½   rý  rô  r®   )rS  r2  r÷  Ú
accessiblerm  r  Ústored_bulkÚstatusesr¢   rÜ  Ú
status_objs              r?   Úlist_mcp_user_env_var_statusr  /
  sË   è ø€ ô  :Ð:tÓuˆØ*×2Ñ2Ò8°bˆÙØˆIÜ"AÐBSÓ"T×Tˆ
ÙØˆIØ2<Ö=¨Q˜QŸ[›[Ð=ˆ
Ð=Ü#9¸-ÈÐR\Ó#]×]ˆØ68ˆØ ò 	,ˆFØ —_‘_ V×%5Ñ%5°rÓ:ˆFÜ5¸VÐSYÔZˆJØ×"Ó"Ø—‘ 
Õ+ð		,ð
 ˆð Uúò >Ø]ús3   ‚.C°B9±C½B;ÁCÁ"C Á#A CÂ$CÂ;Cc              ƒ   ó0  K  — t        d«      }t        | j                  «       «      }t        | «       t        j
                  |j                  k7  r,t        t        j                  ddj                  d«      i¬«      ‚	 t        || j                  «      ƒ d{  –—† }d}| j                   rp| j"                  €d|€|r`|r|j"                  nd}t%        |d
|«      }	|t&        j(                  t&        j*                  fvr!t        t        j,                  dd|	›d�i¬«      ‚t/        || |j0                  xs t2        |¬«      ƒ d{  –—† }
|
€*t        t        j4                  dd| j                  › �i¬«      ‚t7        j8                  |
«      ƒ d{  –—†  t7        j:                  «       ƒ d{  –—†  |�Yt=        |«      t=        |
«      k7  rB	 t?        || j                  «      ƒ d{  –—† }|r!t        j@                  d| j                  |«       tC        «       r	 tE        |
«      S 7 �Œ‚# t        $ r0}t        j                  d| j                  |«       d}d	}Y d}~�Œ²d}~ww xY w7 �Œ7 ŒÓ7 Œ¹7 Œƒ# t        $ r+}t        j                  d| j                  |«       Y d}~Œ�d}~ww xY w­w)a5  
        Updates the MCP Server in the db.

        Parameters:
        - payload: UpdateMCPServerRequest - Required. The updated mcp server data.
        ```
        curl -X "PUT" --location 'http://localhost:4000/v1/mcp/server'         --header 'Authorization: Bearer your_api_key_here'
        ```
        rÃ  r©   zJCall not allowed to update MCP server. User is not a proxy admin. route={}zPUT /v1/mcp/serverrª   NFz[MCP server %s: could not snapshot the pre-update record; skipping the stale-token check: %sTr³   zadcr_bridge is only supported for auth_type true_passthrough or oauth_delegate (stored auth_type: zs). Include the server's auth_type in the update payload or configure one of the client-forwarded token modes first.)r  Ú
fields_setrÄ  zZMCP server %s: purged %d stale per-user OAuth token(s) after a mint-relevant config changezRMCP server %s: failed to purge stale per-user OAuth tokens after config change: %s)#r¥  r´  r  r'   rz   rV  rU  r   r   r  rÆ  r^   r7   r  r   ÚwarningÚ
dcr_bridgerÇ   r­   rœ   Útrue_passthroughÚoauth_delegater°   rk   r÷  r   rÈ  ru   Úupdate_serverr*  re   rg   Úinfor+   rI  )r¤   rS  rB  r2  Úpayload_fields_setÚold_server_recordÚold_server_record_read_failedÚexcÚstored_auth_typeÚstored_auth_type_nameÚmcp_server_record_updatedÚpurgeds               r?   Úedit_mcp_serverr#  K
  sÀ  è ø€ ô4  :ð Pó 
ˆô %(¨×(:Ñ(:Ó(<Ó$=Ðô 	2°'Ô:ô ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5àÐi×pÑpØ,óðôð ð
	1Ü&4°]ÀG×DUÑDUÓ&V× VÐØ,1Ð)ð ×ÒØ×!Ñ!Ð)Ø"Ð.Ñ2OáEVÐ&7×&AÒ&AÐ\`ÐÜ+2Ð3CÀWÐN^Ó+_Ð!Ø¬×(@Ñ(@Ä'×BXÑBXÐ'YÑYÜ#Ü &× ;Ñ ;àðAØAVÐ@Yð ZBðBðô
ð 
ô 2CØØØ(×0Ñ0ÒLÔ4LØ)ô	2
÷ ,
Ð!ð %Ð,ÜÜ"×5Ñ5ØÐ#JÈ7×K\ÑK\ÐJ]Ð!^Ð_ôð ô (×5Ñ5Ð6OÓP×PÐPô (×DÑDÓF×FÐFð Ð(Ô-EÐFWÓ-XÔ\tØ%ó]
ò .
ðÜ&MÈmÐ]d×]nÑ]nÓ&o× o�ÙÜ"×'Ñ'ØtØ×)Ñ)Øôô $Ô%Øä&Ð'@ÓAÐAð[ !Wúäò 	1Ü×"Ñ"ØmØ×!Ñ!Øôð
 !%ÐØ,0Ö)ûð	1úð<,
ùð 	Qøð 	Gøð !pùô ò Ü×&Ñ&ØhØ×%Ñ%Ø÷ñ ûðüs°   ‚A9JÁ<H ÂHÂH ÂB JÄ<IÄ=AJÆIÆJÆ!IÆ"JÇ I ÇIÇ'I ÈJÈH È	IÈ#%IÉJÉIÉJÉJÉJÉI É	JÉ(!JÊ	JÊJÊJz/make_publicz+Allows making MCP servers public for AI Hubc              ƒ   ó  K  — 	 ddl }ddlm} ddlm} |j                  «       ƒ d{  –—† }|j                  t        j                  k7  rt        ddd|j                  › �i¬«      ‚|j                  €g |_
        | j                  D ](  } |j                  |¬	«      }|�Œt        d
d|› d�¬«      ‚ | j                  |_
        d|vs|d   €i |d<   |j                  |d   d<   |j                  |¬«      ƒ d{  –—†  t        j                  d|j                  |j                   «       d|j                  |j                   dœS 7 �Œ7 ŒL# t        $ r ‚ t"        $ r1}t        j$                  d|«       t        dt'        |«      ¬«      ‚d}~ww xY w­w)z4
        Make MCP servers public for AI Hub
        r   Nrt   )Úproxy_configrõ  r©   z;Only proxy admins can update public mcp servers. Your role=rª   rD   i”  zMCP Server with ID r5  Úlitellm_settingsrÿ  )Ú
new_configz-Updated public mcp servers to: %s by user: %sz'Successfully updated public mcp servers)r£  rÿ  rv  zError making agent public: %siô  )r  r³  ru   r×   r%  Ú
get_configrU  rz   rV  r   rÿ  Úmcp_server_idsr�  Úsave_configr   r  r÷  r  r  r;   )	r¼  rS  r  ru   r%  Úconfigr7   r¢   r"  s	            r?   Úmake_mcp_servers_publicr,  Ì
  s¼  è ø€ ð6	@ãõõ @ð #/×"9Ñ"9Ó";×;ˆFà ×*Ñ*Ô.>×.JÑ.JÒJÜ#Ø #àÐ#^Ð_p×_zÑ_zÐ^{Ð!|ðôð ð ×)Ñ)Ð1Ø-/�Ô*à$×3Ñ3ò �	ØGÐ2×GÑGÐR[Ô\�Ø‘>Ü'Ø$'Ø!4°Y°K¸zÐJôð ðð *1×)?Ñ)?ˆGÔ&ð "¨Ñ/°6Ð:LÑ3MÐ3UØ-/�Ð)Ñ*à?F×?YÑ?YˆFÐ%Ñ&Ð';Ñ<ð ×*Ñ*°fÐ*Ó=×=Ð=ä ×&Ñ&Ø?À×A[ÑA[Ð]n×]vÑ]vôð
 EØ&-×&@Ñ&@Ø/×7Ñ7ñð ðI <ùð< >ùô ò 	ØÜò 	@Ü ×*Ñ*Ð+JÈAÔNÜ¨C¼¸A»Ô?Ð?ûð	@üsS   ‚F
„#E §D?¨A4E ÂAE Ã5EÃ6AE Ä>F
Ä?E ÅE ÅFÅ,FÆFÆF
zmcp_registry.jsonÚ_MCP_REGISTRY_PATHÚ_mcp_registry_cachec                  ó  — t         �t         S 	 t        t        d«      5 } t        j                  | «      }ddd«       a |S # 1 sw Y   ŒxY w# t
        $ r,}t        j                  dt        |«       dg i}Y d}~|a |S d}~ww xY w)zALoad the curated MCP registry from disk. Cached after first read.Nr
  z'Failed to load MCP registry from %s: %srÇ  )r.  Úopenr-  r  Úloadr  r   r  )rÛ   r¿  r"  s      r?   Ú_load_mcp_registryr2    s�   € ô Ð*Ü&Ð&ð	#ÜÔ(¨#Ó.ð O°!ÜBFÇ)Á)ÈAÃ,�÷Oð
 #ÐØˆ÷Oð Oûäò 	#Ü ×(Ñ(Ð)RÔTfÐhiÔjØ˜r�?ŒDØ"ÐØˆûð		#ús-   ŽA žA ´A Á A	ÁA Á	BÁA<Á<Bz	/discoverzAReturns a curated list of well-known MCP servers for discovery UIz/Search filter for server names and descriptionszFilter by categoryÚqueryÚcategoryc              ƒ   ód  K  — t        |«      st        ddd|j                  › �i¬«      ‚t        «       }|j	                  dg «      }| r…| j                  «       }|D �cg c]j  }||j	                  dd«      j                  «       v sD||j	                  dd«      j                  «       v s"||j	                  d	d«      j                  «       v r|‘Œl }}|r%|D �cg c]  }|j	                  d
d«      |k(  sŒ|‘Œ }}|j	                  dg «      }t        t        d„ |D «       «      «      }||dœS c c}w c c}w ­w)z°
        Returns a curated list of well-known MCP servers that can be added to the proxy.

        Used by the UI to show a discovery grid when adding new MCP servers.
        rõ  r©   z6Only proxy admins can access MCP discovery. Your role=rª   rÇ  rR   rº   ró   rô   r4  c              3   ó@   K  — | ]  }|j                  d d«      –— Œ y­w)r4  ÚOtherN)r½   )r‰  rm  s     r?   rŠ  z'discover_mcp_servers.<locals>.<genexpr>T  s   è ø€ Ò&WÀa q§u¡u¨Z¸×'AÑ&WùrÅ  )rÇ  Ú
categories)r‘   r   rU  r2  r½   r�  r¹  r´  )	r3  r4  rS  ÚregistryrÇ  Úquery_lowerrm  Úall_serversr8  s	            r?   Údiscover_mcp_serversr<  (  sF  è ø€ ô  $Ð$5Ô6ÜØàÐUÐVg×VqÑVqÐUrÐsðôð ô -Ó.ˆØ—,‘,˜y¨"Ó-ˆñ Ø!&§¡£ˆKð !öàØ !§%¡%¨°Ó"3×"9Ñ"9Ó";Ñ;Ø !§%¡%¨°Ó"4×":Ñ":Ó"<Ñ<Ø !§%¡%¨°rÓ":×"@Ñ"@Ó"BÑBò	 ðˆGð ñ Ø")ÖO˜Q¨Q¯U©U°:¸rÓ-BÀhÓ-N’qÐOˆGÐOð &Ÿ\™\¨)°RÓ8ˆÜ"¤3Ñ&WÈ;Ô&WÓ#WÓXˆ
ð Ø$ñ
ð 	
ùò!ùò Pùs%   ‚AD0ÁA/D&ÃD0ÃD+Ã.D+Ã2>D0zopenapi_registry.jsonÚ_OPENAPI_REGISTRY_PATHr  )Úmaxsizec                  ó|   — t        t        d«      5 } t        j                  | «      }d d d «       |S # 1 sw Y   S xY w)Nr
  )r0  r=  r  r1  )rÛ   r¿  s     r?   Ú_load_openapi_registryr@  b  s6   € äÔ(¨#Ó.ð 	:°!Ü-1¯Y©Y°q«\ˆD÷	:àˆ÷	:àˆús   ‘1±;z/openapi-registryzRReturns well-known OpenAPI APIs with OAuth 2.0 metadata for the OpenAPI MCP pickerc              ƒ   óØ   K  — t        | «      st        ddd| j                  › �i¬«      ‚	 t        «       S # t        $ r)}t        j                  dt        |«       dg icY d }~S d }~ww xY w­w)Nrõ  r©   z=Only proxy admins can access the OpenAPI registry. Your role=rª   z+Failed to load OpenAPI registry from %s: %sÚapis)r‘   r   rU  r@  r  r   r  r=  )rS  r"  s     r?   Úget_openapi_registryrC  h  sw   è ø€ ô $Ð$5Ô6ÜØàÐ\Ð]n×]xÑ]xÐ\yÐzðôð ð	 Ü)Ó+Ð+øÜò 	 Ü ×(Ñ(Ð)VÔXnÐpqÔrØ˜B�<Õûð	 üs0   ‚(A*«	5 ´A*µ	A'¾A"ÁA'ÁA*Á"A'Á'A*)Úcreate_mcp_toolsetÚdelete_mcp_toolsetÚget_mcp_toolsetÚlist_mcp_toolsetsÚupdate_mcp_toolset)ÚNewMCPToolsetRequestÚUpdateMCPToolsetRequestz/toolsetz%Create a new MCP toolset (admin only))rô   r«   c              ƒ   óš  K  — t        d«      }t        j                  |j                  k7  rt	        t
        j                  ddi¬«      ‚t        ||t        ¬«      xs t        }	 t        || |«      ƒ d{  –—† }d	d
lm}  |j                  «        |S 7 Œ# t        $ r, t	        t
        j                  dd| j                  › d�i¬«      ‚w xY w­w)uO   Create a named toolset â€” a curated selection of {server_id, tool_name} pairs.r  r©   z*Only proxy admins can create MCP toolsets.rª   ©rB  rS  Úlitellm_proxy_admin_nameNúA toolset named 'rL  r   rt   )r¥  rz   rV  rU  r   r   r  r*   r   rD  r   ÚHTTP_409_CONFLICTÚtoolset_namer³  ru   Úinvalidate_toolset_cache©r¤   rS  rB  r2  r  Úresultru   s          r?   Úadd_mcp_toolsetrT  �  sÞ   è ø€ ô  :Ð:tÓuˆÜ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5ØÐ!MÐNôð ô
 %Ø#5Ø"3Ü)Aôò (ô
 (ð 	ð	Ü"4°]ÀGÈZÓ"X×XˆFõ	
ð 	;Ð!×:Ñ:Ô<Øˆð YùÜ#ò 	ÜÜ"×4Ñ4ØÐ#4°W×5IÑ5IÐ4JÐJ[Ð!\Ð]ôð ð	üs0   ‚A CÁ#B Á3BÁ4B Á8CÂB Â5CÃCz/List MCP toolsets accessible to the calling keyc              ƒ   óÔ   K  — t        d«      }t        | «      }| j                  }|rt        |dd«      nd}|s|rt	        |«      ƒ d{  –—† S g S t	        ||¬«      ƒ d{  –—† S 7 Œ7 Œ­w)z5Return toolsets the calling key is allowed to access.r  Úmcp_toolsetsN)Útoolset_ids)r¥  r‘   Úobject_permissionr­   rG  )rS  r2  r  ÚopÚraw_toolsetss        r?   Úfetch_mcp_toolsetsr[  µ  sq   è ø€ ô  :Ð:tÓuˆÜ.Ð/@ÓAˆØ%×7Ñ7ˆñ
 DFœg b¨.¸$Ô?È4ˆÙÙÜ.¨}Ó=×=Ð=ØˆIÜ& }À,ÔO×OÐOð >øàOús$   ‚AA(ÁA$Á	A(ÁA&Á A(Á&A(z/toolset/{toolset_id}z Get a specific MCP toolset by IDÚ
toolset_idc              ƒ   ó,  K  — t        d«      }t        |«      s@|j                  }|rt        |dd «      nd }|�| |vrt	        t
        j                  ddi¬«      ‚t        || «      ƒ d {  –—† }|€!t	        t
        j                  dd| › d�i¬«      ‚|S 7 Œ)­w)Nr  rV  r©   z-API key does not have access to this toolset.rª   ú	Toolset 'r'  )	r¥  r‘   rX  r­   r   r   r  rF  rÈ  )r\  rS  r2  rY  ÚgrantedÚtoolsets         r?   Úfetch_mcp_toolsetra  Ì  s®   è ø€ ô  :Ð:tÓuˆä#Ð$5Ô6Ø)×;Ñ;ˆBÙBDœW R¨¸Ô>È$ˆGØˆ *°GÑ";Ü#Ü &× 9Ñ 9Ø#Ð%TÐUôð ô  /¨}¸jÓI×IˆØˆ?ÜÜ"×5Ñ5Ø 9¨Z¨L¸Ð!EÐFôð ð ˆð Jús   ‚A&BÁ(BÁ)*Bz+Update an existing MCP toolset (admin only)c              ƒ   ó4  K  — t        d«      }t        j                  |j                  k7  rt	        t
        j                  ddi¬«      ‚t        ||t        ¬«      xs t        }	 t        || |«      ƒ d {  –—† }|€+t	        t
        j                  dd	| j                  › d
�i¬«      ‚ddlm}  |j"                  t%        | dd «      «       |S 7 ŒV# t        $ r@ t	        t
        j                  d| j                  rd| j                  › d�i¬«      ‚di¬«      ‚w xY w­w)Nr  r©   z*Only proxy admins can update MCP toolsets.rª   rL  rN  rL  z(A toolset with that name already exists.r^  r'  r   rt   r\  )r¥  rz   rV  rU  r   r   r  r*   r   rH  r   rO  rP  rÈ  r\  r³  ru   rQ  r­   rR  s          r?   Úedit_mcp_toolsetrc  ç  sA  è ø€ ô  :Ð:tÓuˆÜ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5ØÐ!MÐNôð ô
 %Ø#5Ø"3Ü)Aôò (ô
 (ð 	ð	Ü"4°]ÀGÈZÓ"X×XˆFð ˆ>ÜÜ"×5Ñ5Ø 9¨W×-?Ñ-?Ð,@ÀÐ!MÐNôð õ	
ð 	;Ð!×:Ñ:¼7À7ÈLÐZ^Ó;_Ô`Øˆð- YùÜ#ò 
	ÜÜ"×4Ñ4àà"×/Ò/ð ,¨G×,@Ñ,@Ð+AÐARÐSðô	ð 	ð Hð	ô	ð 	ð
	üs2   ‚A DÁ#C Á3C
Á4C Á8ADÃ
C ÃA	DÄDz"Delete an MCP toolset (admin only)c              ƒ   ój  K  — t        d«      }t        j                  |j                  k7  rt	        t
        j                  ddi¬«      ‚t        || «      ƒ d {  –—† }|€!t	        t
        j                  dd| › d�i¬«      ‚ddl	m
}  |j                  | «       t        t
        j                  ¬	«      S 7 ŒY­w)
Nr  r©   z*Only proxy admins can delete MCP toolsets.rª   r^  r'  r   rt   rÅ  )r¥  rz   rV  rU  r   r   r  rE  rÈ  r³  ru   rQ  r   rÈ  )r\  rS  rB  r2  Údeletedru   s         r?   Úremove_mcp_toolsetrf    s³   è ø€ ô  :Ð:tÓuˆÜ×'Ñ'Ð+<×+FÑ+FÒFÜÜ"×5Ñ5ØÐ!MÐNôð ô  2°-ÀÓL×LˆØˆ?ÜÜ"×5Ñ5Ø 9¨Z¨L¸Ð!EÐFôð õ	
ð 	;Ð!×:Ñ:¸:ÔFÜ¤F×$<Ñ$<Ô=Ð=ð Mús   ‚AB3ÁB1ÁAB3)rB   N)rB   zPrismaClient | None)r¸   zMCPCredentials | str | NonerB   zdict[str, str] | NonerT   (#  Ú__doc__Ú	functoolsÚ	importlibr  ÚosÚcollections.abcr   r   r   Údataclassesr   r   r   r	   Útypingr
   r   r   r   Úfastapir   r   r   r   r   r   r   r   r   Úfastapi.responsesr   Útyping_extensionsr   r   Úprisma.errorsr   r   ÚImportErrorr  r  Úlitellm._loggingr   r   Úlitellm._uuidr   Úlitellm.constantsr   Ú,litellm.proxy._experimental.mcp_server.utilsr    r!   r"   r#   r$   r%   r&   r'   rÁ   Ú0litellm.proxy.common_utils.encrypt_decrypt_utilsr(   r)   Ú+litellm.proxy.management_helpers.audit_logsr*   r+   Ú'litellm.repositories.table_repositoriesr,   r-   r1   r<   r2   rP   r3   r4   r6   r;   rF   rG   ÚprismarH   Úprisma_modelsÚlitellm.proxy.utilsrI   Úimport_moduler"  r  Úmcp.shared.tool_name_validationrJ   ÚpydanticrK   rM   Ú)litellm.proxy._experimental.mcp_server.dbrU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   Ú=litellm.proxy._experimental.mcp_server.discoverable_endpointsrl   rm   rn   ro   rp   rq   rr   rs   r³  ru   Ú7litellm.proxy._experimental.mcp_server.ui_session_utilsrv   rw   rx   Úlitellm.proxy._typesry   rz   r{   r|   r}   r~   r   r€   r�   r‚   rƒ   r„   r…   r†   r‡   rˆ   r‰   rŠ   r‹   rŒ   Ú$litellm.proxy.auth.user_api_key_authr�   rŽ   Ú-litellm.proxy.common_utils.http_parsing_utilsr�   r�   Ú/litellm.proxy.management_endpoints.common_utilsr‘   Ú7litellm.proxy.management_endpoints.mcp_connector_importr’   r“   r”   r•   r–   r—   r˜   r™   Ú&litellm.proxy.management_helpers.utilsrš   Úlitellm.types.mcpr›   rœ   r�   rž   Ú+litellm.types.mcp_server.mcp_server_managerrŸ   r¡   r¶   r¿   rÍ   rî  Úmodel_fieldsrÎ   rÞ   rá   rê   rì   rî   rò   rÿ   r  r  r¼   r
  rb  r  r#  r/  r3  r6  r;  r?  rI  rG  rQ   rQ  rW  r[  rk  rn  rz  r|  r†  rc  r�  r•  r›  r¢  r¥  r½   r°  r»  rÄ  rÍ  rÒ  rå  rì  rñ  r  r  ÚpostÚHTTP_201_CREATEDr   r$  Úputr,  r1  rA  rF  ÚHTTP_200_OKrh  rn  r—  rš  r©  r¶  rÀ  ÚdeleterÈ  rÊ  rÔ  rÖ  rÝ  rá  rç  rî  rÑ  rý  r   r
  r  r  r#  r,  rã   r¯   ÚdirnameÚabspathÚ__file__r-  r.  r2  r<  r=  Ú	lru_cacheÚobjectr@  rC  Ú1litellm.proxy._experimental.mcp_server.toolset_dbrD  rE  rF  rG  rH  Ú$litellm.types.mcp_server.mcp_toolsetrI  rJ  rT  r[  ra  rc  rf  r=   r>   r?   ú<module>r˜     s]  ðòó" Û Û Û 	ß 7Ñ 7Ý !ß 2Ñ 2ß :Ó :÷
÷ 
õ 
õ +ß 1ð%ßGó
 ß AÝ Ý 6÷÷ ñ õ÷÷÷ñ
  °%°Ô9€ˆÓ 9à€ˆtÓ à*-Ð   %Ó -Ø/MÐ % uÓ Mô�8ô ð
¨h°|Ñ.Dð 
ÐUXð 
Ð]aó 
ð '.Ð ˜eÓ -áÝ.å0ðØ€I×Ñ˜EÔ"ò
 ð/õ	
÷÷ ÷ ÷ ÷ ÷ ñ ÷2	÷ 	ó 	õ÷ñ ÷
÷ ÷ ÷ ÷ ó ÷,÷õ U÷	÷ 	ó 	õ S÷ó õ Fà÷ð ó ððÐ2Fð È4ó ð6Ð1Eð È$ó ð 1Ð;Oð 1ÐTXó 1ð
^Ð+>ð ^À4ó ^ñ8 4=Ð=P×=]Ò=]Ó3^Ð  iÑ 0Ó^ð-Ð/Bð -Àtó -ð^G¨ó Gð5¨Sð 5¸ð 5Àó 5ð
 °	ð  ¸có  ô˜Yô ô8˜Iô 8ð
°Yð 
È#ð 
ÐRcó 
ð0
°ð 
Ð8Ió 
ð JLÐ˜E $ sÐ,DÐ'DÑ"EÑFÓKô8ð¨Ið ÀCð ÈIó ðe¸9ð eÐSVð eÐ[_ó eð@1Øð1à	�TÑ	ó1ôfð
Ø$ð
àð
ð ð
ð 
ó	
ð*
R¸Sð 
RÀYÐQUÑEUó 
RðØðà	�TÑ	óð.Ø*ðà	óð !Ø2ð!à	 ô!ð2KØÐ4Ñ5ðKà	Ð$Ñ	%óKð
K¨~ð KÀ$ó Kð	L¸nð 	LÐQUó 	Lð(Ø*ð(à	ó(ðTLØÐ4Ñ5ðLà	Ð$Ñ	%óLð
2Ø*ð2à	ó2ðhXØÐ4Ñ5ðXà	Ð$Ñ	%óXðHÐ  %¨¨e°C¸°H©o¸sÐ.BÑ(CÑ"Dó ðkÐ7Nð kÐSWó kð!@Ø$ð!@à	ó!@ðFÐ2Eð È#ó ð0%
Ø$ð%
à˜$‘Jð%
ð ð%
ð 
 ó	%
ðN¨Có ð ‡Z‚ZØØˆWÙÐ/Ó0Ð1ð ó ñ -4Ð4EÓ,Fñ'Ø)ò'óð
'ð& ‡Z‚ZØØˆWÙÐ/Ó0Ð1ð ó ñ -4Ð4EÓ,Fñ 5Ø)ò 5óð
 5ðD ‡Z‚ZØØˆWÙÐ/Ó0Ð1ØKð	 ó ð! Wò !óð!ð ‡Z‚ZØØˆWØcð ó ð
 -¨ò  -óð
 -ðFÐ+@ó ð$5Øð$5à	Ð$Ñ	%ó$5ðL)Ø)ð)à	Ð$Ñ	%ó)ð*\À^ð \ÐXaÐbeÑXfó \ð ‡Z‚ZØØGÙÐ/Ó0Ð1ØÐ2Ñ3ð	 ó ñ -4Ð4EÓ,FÙ#ØðIô
ñ $)Øð9ô$
ñm$Ø)ðm$à�t‘ðm$ð !òm$óðm$ð^ ‡Z‚ZØØ2ÙÐ/Ó0Ð1ð ó ñ (-ØØ^ô(
ñ -4Ð4EÓ,Fñ,oØ˜‘I Ñ$ð,oð
 *ò,oóð
,oð\ ‡[‚[ØØtÙÐ/Ó0Ð1Ø-Ø×+Ò+ð ó ð !ñ -4Ð4EÓ,Fñ@7Ø$ð@7à)ò@7ó !óð@7ðD ‡Z‚ZØð FÙÐ/Ó0Ð1Ø,ð	 ó ð !á,3Ð4EÓ,FñØ)òó !óðð. ‡Z‚ZØ%ØqÙÐ/Ó0Ð1Ø-ð	 ó ð !ñ -4Ð4EÓ,Fñ#1Øð#1à)ò#1ó !óð#1ðJ ‡Z‚ZØ$ØoÙÐ/Ó0Ð1Ø-ð	 ó ð !ñ -4Ð4EÓ,Fñ&1Øð&1à'ð&1ð *ò&1ó !óð&1ðP ‡Z‚ZØØ1ÙÐ/Ó0Ð1Ø-ð	 ó ñ -4Ð4EÓ,Fñ\Øð\àð\ð *ò\óð\ð| ‡[‚[ØØ4ÙÐ/Ó0Ð1Ø-Ø×+Ò+ð ó ð !ñ -4Ð4EÓ,FÙ)/Øð xô*
ñQ7Ø$ðQ7à)ðQ7ð   $™JòQ7ó !óðQ7ðf ‡[‚[ØØ^ÙÐ/Ó0Ð2Ø1Ø×&Ò&ð ó ð !ñ -4Ð4EÓ,Fñd
Ø*ðd
à)òd
ó !óðd
ðL ‡[‚[ØØ_ÙÐ/Ó0Ð1Ø×&Ò&ð	 ó ð !ñ -4Ð4EÓ,FÙ)/Øð xô*
ñ=4Ø$ð=4à)ð=4ð   $™Jò=4ó !óð=4ð~b
°Gð b
Àó b
ðN #'ò)Øð)à)ð)ð ˜4‘ð)ð 
ó	)ðV ‡Z‚ZØ-ØÙÐ:Ó;Ð<ð ó ñ -4Ð4PÓ,QØ $Ù! #›JØØ%)Ø,0Ø$(Ø ñ4
Øð4
àð4
ð *ð4
ð ˜‘:ð	4
ð
 ð4
ð ð4
ð ˜d™
ð4
ð  # T™zð4
ð ˜T‘zð4
ð �T‰zò4
óð
4
ðl ‡[‚[Ø)ØÙÐ:Ó;Ð<ð ó ñ -4Ð4PÓ,QÙ˜s›)Ù ›:Ù#'¨£:Ù $ T£
Ù$(¨£JÙ$(¨£JÙ$(¨£JÙ  ›Jñ5
Øð5
àð5
ð *ð5
ð ð	5
ð
 �D‰jð5
ð ˜D‘jð5
ð ˜‘:ð5
ð ˜T‘zð5
ð ˜T‘zð5
ð ˜T‘zð5
ð �T‰zò5
óð
5
ðn ‡[‚[Ø,ØÙÐ/Ó0Ð1ð ó ñ -4Ð4EÓ,Fñ
Øð
àð
ð *ò
óð

ð, ‡]‚]ØØ:ÙÐ/Ó0Ð1Ø#Ø×,Ò,ð ó ð !ñ -4Ð4EÓ,FÙ)/Øð xô*
ñ8>Øð8>à)ð8>ð   $™Jò8>ó !óð8>ðt ‡[‚[Ø-ØVÙÐ/Ó0Ð1Ø0ð	 ó ð !ñ -4Ð4EÓ,FñTØðTà)ðTð *òTó !óðTð< ‡]‚]Ø-ØTÙÐ/Ó0Ð1Ø0ð	 ó ð !ñ -4Ð4EÓ,FñTØðTà)òTó !óðTð2 ‡[‚[Ø3ØUÙÐ/Ó0Ð1Ø3ð	 ó ð !ñ -4Ð4EÓ,Fñ&
Øð&
à.ð&
ð *ò&
ó !óð&
ðP ‡]‚]Ø3ØUÙÐ/Ó0Ð1Ø3ð	 ó ð !ñ -4Ð4EÓ,Fñ
Øð
à)ò
ó !óð
ð@ ‡Z‚ZØ:ØgÙÐ/Ó0Ð1Ø3ð	 ó ð !ñ -4Ð4EÓ,Fñ
Øð
à)ò
ó !óð
ð> ‡Z‚ZØØQÙÐ/Ó0Ð1ØÐ5Ñ6ð	 ó ð !á,3Ð4EÓ,Fñ#Ø)ò#ó !óð#ðN)à)ð)ð ð)ð 
 ó	)ðV9
à&ð9
ð ˜C ˜H‘~ð9
ð 
ô	9
ðv ‡Z‚ZØ+Ø\ÙÐ/Ó0Ð1Ø+ð	 ó ð !ñ -4Ð4EÓ,FñQØðQà)ðQð 
òQó !óñQð ‡[‚[Ø+ð1ñ Ð/Ó0Ð1Ø+ð ó ð !ñ -4Ð4EÓ,FñQØðQà&ðQð *ðQð 
ò	Qó !óñQð: ‡]‚]Ø+Ø[ÙÐ/Ó0Ð1Ø+ð	 ó ð !ñ -4Ð4EÓ,FñMØðMà)ðMð 
òMó !óñMð( ‡Z‚ZØðQáÐ/Ó0Ð1ØÐ0Ñ1ð ó ð !á,3Ð4EÓ,FñØ)ðà	Ð"Ñ	#òó !óñð( ‡Z‚ZØØ:ÙÐ/Ó0Ð1Ø-Ø×,Ò,ð ó ð !ñ -4Ð4EÓ,FÙ)/Øð xô*
ñwBØ'ðwBà)ðwBð   $™JòwBó !óñwBðr ‡[‚[ØØAÙÐ/Ó0Ð1Ø×,Ò,ð	 ó ñ -4Ð4EÓ,Fñ=@Ø,ð=@à)ò=@óñ=@ðB !#§¢§¢Ø
�Š�Š˜ŸšŸš¨¯ª¯ª¹Ó(AÓBÓCØó!Ñ˜ó ð
 MQÑ˜  h¨w°s¸C°xÑ/@Ñ&AÐ!AÑBÀTÑIÓPð ¨¨X°g¸cÀ3¸hÑ6GÑ-HÐ(HÑ Iô ð ‡Z‚ZØØWÙÐ/Ó0Ð1ð ó ñ " $Ð4eÔfÙ$ TÐ7KÔLÙ,3Ð4EÓ,Fñ,
Ø�T‰zð,
à˜‘*ð,
ð *ò,
óñ
,
ð` %'§G¢G§L¢LØ
�Š�Š˜ŸšŸš¨¯ª¯ª¹Ó(AÓBÓCØó%Ñ˜Eó ð
 €Y×Ò Ô#ð D¨©f¨Ñ$5ò ó $ñð
 ‡Z‚ZØØhð ó ñ
 -4Ð4EÓ,Fñ Ø)ò ó	ñ ÷*÷ ÷ ð ÷ô ð
 ‡[‚[ØØ;Ø×+Ò+ñ ó ð
 !ñ -4Ð4EÓ,FÙ)/°«ñ Ù%ð à)ð ð   $™Jó ó !óñ ðD ‡Z‚ZØÙEð ó ð !á,3Ð4EÓ,FñPØ)óPó !ó	ñ
Pð$ ‡Z‚ZÙÙ6ð ó ð !ñ -4Ð4EÓ,FòØðà)óó !ó	ñ
ð, ‡Z‚ZØÙAð ó ð !ñ -4Ð4EÓ,FÙ)/°«ñ*Ù(ð*à)ð*ð   $™Jó*ó !ó	ñ
*ðX ‡]‚]ÙÙ8Ø×,Ò,ñ ó ð
 !ñ -4Ð4EÓ,FÙ)/°«ò>Øð>à)ð>ð   $™Jó>ó !óò>ðY] øðO ò %Ø#ÐØ$Óð%ûðF ò Ø€N×ÑÐ3°QÔ7Ø†Mûðûð ò /Ý&ô	%¨	ô 	%ð	/ Sð 	/Ð-Fö 	/ð/ús<   Áw= Äx Äx5 ÷=	x
ø	x
øx2øx-ø-x2ø5yùy