o
    ưi,]                     @   s  U d Z ddlZddl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ZddlmZmZmZmZ ddlmZ ddlmZ dZe	e ed< zddlm  mZ eeddZW n	 ey_   Y nw ddlm Z! dd	lm"Z# dd
lm$Z$m%Z%m&Z&m'Z'm(Z( ddlm)Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6m7Z7m8Z8m9Z9m:Z: de;de;fddZ<edZ=G dd dZ>dS )zF
LiteLLM Proxy uses this MCP Client to connnect to other MCP servers.
    N)	Any	AwaitableCallableDictListOptionalTupleTypeVarUnion)ClientSessionReadResourceResultResourceStdioServerParameters)
sse_client)stdio_clientstreamable_http_client)CallToolRequestParams)CallToolResult)GetPromptRequestParamsGetPromptResultPromptResourceTemplateTextContent)Tool)AnyUrl)verbose_logger)MCP_CLIENT_TIMEOUT)get_ssl_configuration)VerifyTypes)MCPAuthMCPAuthTypeMCPStdioConfigMCPTransportMCPTransportType
auth_valuereturnc                 C   s   t | d S )z(Convert auth value to Basic Auth format.zutf-8)base64	b64encodeencodedecode)r$    r*   ]/home/app/Keep/.python/lib/python3.10/site-packages/litellm/experimental_mcp_client/client.pyto_basic_auth-   s   r,   TSessionResultc                   @   s  e Zd ZdZdejddddddfdededede	e
eeeef f  de	e d	e	e d
e	eeef  de	e fddZdeee	ej f fddZdedeegee f defddZdeegee f defddZde
eeeef f fddZdefddZdedejf fddZdee  fdd Z!	d1d!e"d"e	e de#fd#d$Z$dee% fd%d&Z&d'e'de(fd(d)Z)de*e+ fd*d+Z,de*e- fd,d-Z.d.e/de0fd/d0Z1dS )2	MCPClientz
    MCP Client supporting:
      SSE and HTTP transports
      Authentication via Bearer token, Basic Auth, or API Key
      Tool calling with error handling and result parsing
     N
server_urltransport_type	auth_typer$   timeoutstdio_configextra_headers
ssl_verifyc	           	      C   sR   || _ || _|| _|d ur|nt| _d | _|| _|| _|| _|r'| 	| d S d S N)
r0   r1   r2   r   r3   _mcp_auth_valuer4   r5   r6   update_auth_value)	selfr0   r1   r2   r$   r3   r4   r5   r6   r*   r*   r+   __init__=   s   zMCPClient.__init__r%   c                 C   s   d}| j tjkr+| jstdt| jdd| jdg | jdi d}t|dfS | j tjkrE| 	 }| 
 }t| j| j||ddfS tdu rMtd	| 	 }| 
 }td
| ||t| jd}t| j|d}||fS )z
        Create the appropriate transport context based on transport type.

        Returns:
            Tuple of (transport_context, http_client).
            http_client is only set for HTTP transport and needs cleanup.
        Nz,stdio_config is required for stdio transportcommandr/   argsenv)r<   r=   r>   )urlr3   headershttpx_client_factoryzNstreamable_http_client is not available. Please install mcp with HTTP support.z.litellm headers for streamable_http_client: %s)r@   r3   )r?   http_client)r1   r"   stdior4   
ValueErrorr   getr   Zsse_get_auth_headers_create_httpx_client_factoryr   r0   r3   r   ImportErrorr   debughttpxTimeout)r:   rB   Zserver_paramsr@   rA   transport_ctxr*   r*   r+   _create_transport_contextT   sN   

z#MCPClient._create_transport_contextrL   	operationc           	         s  |  I dH }z|d |d }}t||}|  I dH }z]| I dH  ||I dH W z|dddI dH  W n tyS } ztd|  W Y d}~nd}~ww W z|dddI dH  W S  ty{ } ztd|  W Y d}~S d}~ww z|dddI dH  W w  ty } ztd|  W Y d}~w d}~ww z|dddI dH  W w  ty } ztd|  W Y d}~w d}~ww )z
        Execute an operation within a transport and session context.

        Handles entering/exiting contexts and running the operation.
        Nr      z#Error during session context exit: z%Error during transport context exit: )
__aenter__r   Z
initialize	__aexit__BaseExceptionr   rI   )	r:   rL   rN   	transportread_streamZwrite_streamZsession_ctxsessioner*   r*   r+   _execute_session_operation   sD   

z$MCPClient._execute_session_operationc                    s   d}zKz9|   \}}| ||I dH W W |dur=z	| I dH  W S  ty< } ztd|  W Y d}~S d}~ww S  tyN   td| jpKd  w |durwz	| I dH  W w  tyv } ztd|  W Y d}~w d}~ww w )z9Open a session, run the provided coroutine, and clean up.Nz"Error during http_client cleanup: z)MCP client run_with_session failed for %srC   )	rM   rW   acloserR   r   rI   	Exceptionwarningr0   )r:   rN   rB   rL   rV   r*   r*   r+   run_with_session   s6   
zMCPClient.run_with_sessionmcp_auth_valuec                 C   s2   t |tr
|| _dS | jtjkrt|}|| _dS )zC
        Set the authentication header for the MCP client.
        N)
isinstancedictr8   r2   r   basicr,   )r:   r\   r*   r*   r+   r9      s
   


zMCPClient.update_auth_valuec                 C   s   i }| j r\t| j trP| jtjkrd| j  |d< nB| jtjkr)d| j  |d< n3| jtjkr5| j |d< n'| jtjkrA| j |d< n| jtj	krOd| j  |d< nt| j t
r\|| j  | jre|| j |S )z3Generate authentication headers based on auth type.zBearer AuthorizationzBasic z	X-API-Key)r8   r]   strr2   r   Zbearer_tokenr_   Zapi_keyauthorizationZoauth2r^   updater5   )r:   r@   r*   r*   r+   rF      s&   zMCPClient._get_auth_headers.c              	      sF   dddddt tttf  dt tj dt tj dtjf fdd}|S )	a  
        Create a custom httpx client factory that uses LiteLLM's SSL configuration.

        This factory follows the same CA bundle path logic as http_handler.py:
        1. Check ssl_verify parameter (can be SSLContext, bool, or path to CA bundle)
        2. Check SSL_VERIFY environment variable
        3. Check SSL_CERT_FILE environment variable
        4. Fall back to certifi CA bundle
        N)r@   r3   authr@   r3   rd   r%   c                    s4   t  j}tdt|j  tj| |||ddS )z=Create an httpx.AsyncClient with LiteLLM's SSL configuration.z$MCP client using SSL configuration: T)r@   r3   rd   verifyZfollow_redirects)r   r6   r   rI   type__name__rJ   AsyncClient)r@   r3   rd   Z
ssl_configr:   r*   r+   factory   s   
z7MCPClient._create_httpx_client_factory.<locals>.factory)r   r   ra   rJ   rK   ZAuthrh   )r:   rj   r*   ri   r+   rG      s   z&MCPClient._create_httpx_client_factoryc                    s  t d| jpd  dtfdd}z*| |I dH }t|j}dd |jD }t d	| d
| jp3d d|  |jW S  tj	yK   t 
d   ty } z1t|j}t d| dt| d| jpfd d| j  d|v svd|v r{t d g W  Y d}~S d}~ww )z%List available tools from the server.MCP client listing tools from rC   rU   c                       |   I d H S r7   )
list_toolsrU   r*   r*   r+   _list_tools_operation	     z3MCPClient.list_tools.<locals>._list_tools_operationNc                 S      g | ]}|j qS r*   name).0Ztoolr*   r*   r+   
<listcomp>      z(MCPClient.list_tools.<locals>.<listcomp>MCP client listed  tools from : z#MCP client list_tools was cancelledz+MCP client list_tools failed - Error Type: 	, Error: 
, Server: , Transport: BrokenResourceErrorBroken|MCP client detected broken connection/stream during list_tools - the MCP server may have crashed, disconnected, or timed out)r   rI   r0   r   r[   lenZtoolsinfoasyncioCancelledErrorrZ   rY   rf   rg   	exceptionra   r1   error)r:   ro   resultZ
tool_countZ
tool_namesrV   
error_typer*   r*   r+   rm     H   


	zMCPClient.list_toolscall_tool_request_paramshost_progress_callbackc           	         s\  t d j d j  dtdtdB dtdB f fddd	tf fd
d}z| |I dH }t d j d |W S  tj	yM   t 
d   ty } zUddl}| }t d|  t|j}t d| dt| d j d| jp|d d| j 
 d|v sd|v rt d ttd| dt| dgddW  Y d}~S d}~ww )z#
        Call an MCP Tool.
        zMCP client calling tool '' with arguments: progresstotalNmessagec                    s   |r	| | d nd}t d j d|  d| d|dd|pd	 
 rLz| |I d H  W d S  tyK } zt d
|  W Y d }~d S d }~ww d S )Nd   r   z
MCP Tool 'z' progress: /z (z.0fz%) - r/   zFailed to forward to Host: )r   r   rs   rY   rZ   )r   r   r   
percentagerV   )r   r   r*   r+   on_progress7  s*   
z(MCPClient.call_tool.<locals>.on_progressrU   c                    s&   t d | j j jdI d H S )Nz'MCP client sending tool call to session)rs   	argumentsZprogress_callback)r   rI   	call_toolrs   r   rn   )r   r   r*   r+   _call_tool_operationE  s   
z1MCPClient.call_tool.<locals>._call_tool_operationzMCP client tool call '' completed successfullyz"MCP client tool call was cancelledr   z MCP client tool call traceback:
z*MCP client call_tool failed - Error Type: rz   z, Tool: r{   rC   r|   r}   r~   zkMCP client detected broken connection/stream - the MCP server may have crashed, disconnected, or timed out.textry   )rf   r   T)contentZisError)r   r   rs   r   floatra   r   r[   r   r   rZ   rY   	traceback
format_excrI   rf   rg   r   r0   r1   MCPCallToolResultr   )	r:   r   r   r   Ztool_resultrV   r   error_tracer   r*   )r   r   r   r+   r   +  sX   $


zMCPClient.call_toolc                      t d| jpd  dtfdd}z*| |I dH }t|j}dd |jD }t d	| d
| jp3d d|  |jW S  tj	yK   t 
d   ty } z1t|j}t d| dt| d| jpfd d| j  d|v svd|v r{t d g W  Y d}~S d}~ww )z'List available prompts from the server.rk   rC   rU   c                    rl   r7   )list_promptsrn   r*   r*   r+   _list_prompts_operation|  rp   z7MCPClient.list_prompts.<locals>._list_prompts_operationNc                 S   rq   r*   rr   )rt   promptr*   r*   r+   ru     rv   z*MCPClient.list_prompts.<locals>.<listcomp>rw   rx   ry   z%MCP client list_prompts was cancelledz-MCP client list_prompts failed - Error Type: rz   r{   r|   r}   r~   r   )r   rI   r0   r   r[   r   Zpromptsr   r   r   rZ   rY   rf   rg   r   ra   r1   )r:   r   r   Zprompt_countZprompt_namesrV   r   r*   r*   r+   r   v  r   zMCPClient.list_promptsget_prompt_request_paramsc                    s  t d j d j  dtf fdd}z| |I dH }t d j d |W S  tjy:   t d	   t	y } z>d
dl
}| }t d|  t|j}t d| dt| d j d| jpid d| j 
 d|v syd|v r~t d  d}~ww )z.Fetch a prompt definition from the MCP server.zMCP client fetching prompt 'r   rU   c                    s$   t d | j j jdI d H S )Nz0MCP client sending get_prompt request to session)rs   r   )r   rI   
get_promptrs   r   rn   r   r*   r+   _get_prompt_operation  s   
z3MCPClient.get_prompt.<locals>._get_prompt_operationNzMCP client get_prompt 'r   z#MCP client get_prompt was cancelledr   z!MCP client get_prompt traceback:
z+MCP client get_prompt failed - Error Type: rz   z
, Prompt: r{   rC   r|   r}   r~   z}MCP client detected broken connection/stream during get_prompt - the MCP server may have crashed, disconnected, or timed out.)r   r   rs   r   r   r[   r   r   rZ   rY   r   r   rI   rf   rg   r   ra   r0   r1   )r:   r   r   Zget_prompt_resultrV   r   r   r   r*   r   r+   r     sN   


zMCPClient.get_promptc                    r   )z)List available resources from the server.z"MCP client listing resources from rC   rU   c                    rl   r7   )list_resourcesrn   r*   r*   r+   _list_resources_operation  rp   z;MCPClient.list_resources.<locals>._list_resources_operationNc                 S   rq   r*   rr   )rt   resourcer*   r*   r+   ru     rv   z,MCPClient.list_resources.<locals>.<listcomp>rw   z resources from ry   z'MCP client list_resources was cancelledz/MCP client list_resources failed - Error Type: rz   r{   r|   r}   r~   zMCP client detected broken connection/stream during list_resources - the MCP server may have crashed, disconnected, or timed out)r   rI   r0   r   r[   r   	resourcesr   r   r   rZ   rY   rf   rg   r   ra   r1   )r:   r   r   Zresource_countZresource_namesrV   r   r*   r*   r+   r     r   zMCPClient.list_resourcesc                    r   )z2List available resource templates from the server.z+MCP client listing resource templates from rC   rU   c                    rl   r7   )list_resource_templatesrn   r*   r*   r+   "_list_resource_templates_operation  rp   zMMCPClient.list_resource_templates.<locals>._list_resource_templates_operationNc                 S   rq   r*   rr   )rt   ZresourceTemplater*   r*   r+   ru     s    z5MCPClient.list_resource_templates.<locals>.<listcomp>rw   z resource templates from ry   z0MCP client list_resource_templates was cancelledz8MCP client list_resource_templates failed - Error Type: rz   r{   r|   r}   r~   zMCP client detected broken connection/stream during list_resource_templates - the MCP server may have crashed, disconnected, or timed out)r   rI   r0   r   r[   r   ZresourceTemplatesr   r   r   rZ   rY   rf   rg   r   ra   r1   )r:   r   r   Zresource_template_countZresource_template_namesrV   r   r*   r*   r+   r     sL   


	z!MCPClient.list_resource_templatesr?   c                    s   t d  d dtf fdd}z| |I dH }t d  d |W S  tjy5   t d	   ty} } z=d
dl}|	 }t 
d|  t|j}t d| dt| d  d| jpcd d| j 
 d|v ssd|v rxt d  d}~ww )z,Fetch resource contents from the MCP server.zMCP client fetching resource ''rU   c                    s   t d |  I d H S )Nz3MCP client sending read_resource request to session)r   rI   read_resourcern   r?   r*   r+   _read_resource_operation&  s   
z9MCPClient.read_resource.<locals>._read_resource_operationNzMCP client read_resource 'r   z&MCP client read_resource was cancelledr   z$MCP client read_resource traceback:
z.MCP client read_resource failed - Error Type: rz   z, Url: r{   rC   r|   r}   r~   zMCP client detected broken connection/stream during read_resource - the MCP server may have crashed, disconnected, or timed out.)r   r   r   r[   r   r   rZ   rY   r   r   rI   rf   rg   r   ra   r0   r1   )r:   r?   r   Zread_resource_resultrV   r   r   r   r*   r   r+   r   "  sJ   



zMCPClient.read_resourcer7   )2rg   
__module____qualname____doc__r"   httpra   r#   r    r   r
   r   r   r!   r   r;   r   r   rJ   rh   rM   r   r   r   r-   rW   r[   r9   r^   rF   rG   r   MCPToolrm   MCPCallToolRequestParamsr   r   r   r   r   r   r   listr   r   r   r   r   r   r   r*   r*   r*   r+   r.   5   s~    		

6

#+
K(
2(*r.   )?r   r   r&   typingr   r   r   r   r   r   r   r	   r
   rJ   Zmcpr   r   r   r   Zmcp.client.sser   Zmcp.client.stdior   r   __annotations__Zmcp.client.streamable_httpclientZstreamable_httpZstreamable_http_modulegetattrrH   Z	mcp.typesr   r   r   r   r   r   r   r   r   r   r   Zpydanticr   Zlitellm._loggingr   Zlitellm.constantsr   Z&litellm.llms.custom_httpx.http_handlerr   Zlitellm.types.llms.custom_httpr   Zlitellm.types.mcpr   r    r!   r"   r#   ra   r,   r-   r.   r*   r*   r*   r+   <module>   s8    ,	