o
    i#-                  
   @  s@  d dl mZ d dlZd dlmZmZ d dlmZmZ d dl	m
Z
 d dlmZ d dlmZmZ d dlmZ d d	lmZmZ z$d d
lmZmZ d dlmZ d dlmZ d dlmZmZ d dlm Z  W n e!yq Z" ze!de"dZ"["ww ddl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z* e$Z+G dd deZ,G dd de,Z-G dd de,Z.dS )    )annotationsN)ABCabstractmethod)AbstractAsyncContextManagerAsyncExitStack)	timedelta)Path)AnyLiteral)urlparse)MemoryObjectReceiveStreamMemoryObjectSendStream)ClientSessionstdio_client)
sse_client)StdioServerParameters)GetSessionIdCallbackstreamablehttp_client)SessionMessagezThe 'mcp' package is required to run the MCP server integration but is not installed.
To fix this, install the optional dependency: pip install 'livekit-agents[mcp]'   )RawFunctionTool	ToolErrorfunction_toolget_function_infoget_raw_function_infois_function_toolis_raw_function_toolc                   @  sd   e Zd Zd"ddZed#dd	Zd$d
dZd$ddZd%ddZd&ddZ	d$ddZ
ed'dd Zd!S )(	MCPServerclient_session_timeout_secondsfloatreturnNonec                C  s$   d | _ t | _|| _d| _d | _d S NT)_clientr   _exit_stack_read_timeout_cache_dirty	_lk_tools)selfr    r)   X/var/www/html/livekit_bhavya/venv/lib/python3.10/site-packages/livekit/agents/llm/mcp.py__init__*   s
   
zMCPServer.__init__boolc                 C  s
   | j d uS N)r#   r(   r)   r)   r*   initialized2   s   
zMCPServer.initializedc                 C  s
   d| _ d S r"   )r&   r.   r)   r)   r*   invalidate_cache6   s   
zMCPServer.invalidate_cachec                   s   z:| j |  I d H }|d |d }}| j t||| jr%t| jdnd dI d H | _| j I d H  d| _W d S  t	yJ   | 
 I d H   w )Nr   r   seconds)read_timeout_secondsT)r$   enter_async_contextclient_streamsr   r%   r   r#   
initialize_initialized	Exceptionaclose)r(   streamsreceive_streamsend_streamr)   r)   r*   r6   9   s&   	zMCPServer.initializelist[MCPTool]c                   s^    j d u r
td js jd ur jS  j  I d H } fdd|jD }| _d _|S )NzMCPServer isn't initializedc                   s$   g | ]}  |j|j|j|jqS r)   )_make_function_toolnamedescriptioninputSchemameta).0toolr.   r)   r*   
<listcomp>T   s    z(MCPServer.list_tools.<locals>.<listcomp>F)r#   RuntimeErrorr&   r'   
list_toolstools)r(   rH   lk_toolsr)   r.   r*   rG   L   s   

zMCPServer.list_toolsr?   strr@   
str | Noneinput_schemadict[str, Any]rB   dict[str, Any] | NoneMCPToolc                   s4   d
 fdd} ||d}|r||d< t ||d	S )Nraw_argumentsrM   r    r	   c                   s   j d u r
tdj  | I d H }|jr&ddd |jD }t|t|jdkr4|jd  S t|jdkrFt	dd |jD S td	  d
)NzjTool invocation failed: internal service is unavailable. Please check that the MCPServer is still running.
c                 s  s(    | ]}t |d r|jnt|V  qdS )textN)hasattrrR   rJ   )rC   partr)   r)   r*   	<genexpr>o   s
    
zFMCPServer._make_function_tool.<locals>._tool_called.<locals>.<genexpr>r   r   c                 S  s   g | ]}|  qS r)   )
model_dump)rC   itemr)   r)   r*   rE   y   s    zGMCPServer._make_function_tool.<locals>._tool_called.<locals>.<listcomp>zTool 'z^' completed without producing a result. This might indicate an issue with internal processing.)
r#   r   	call_toolisErrorjoincontentlenmodel_dump_jsonjsondumps)rP   tool_result	error_strr?   r(   r)   r*   _tool_calledd   s$   


z3MCPServer._make_function_tool.<locals>._tool_called)r?   r@   
parametersrB   )
raw_schema)rP   rM   r    r	   )r   )r(   r?   r@   rL   rB   rc   re   r)   rb   r*   r>   ]   s   zMCPServer._make_function_toolc                   s4   z| j  I d H  W d | _d | _d S d | _d | _w r-   )r$   r9   r#   r'   r.   r)   r)   r*   r9      s   
zMCPServer.acloseAbstractAsyncContextManager[tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]] | tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage], GetSessionIdCallback]]c                 C  s   d S r-   r)   r.   r)   r)   r*   r5      s   zMCPServer.client_streamsN)r   r   r    r!   )r    r,   )r    r!   r    r=   )
r?   rJ   r@   rK   rL   rM   rB   rN   r    rO   r    rf   )__name__
__module____qualname__r+   propertyr/   r0   r6   rG   r>   r9   r   r5   r)   r)   r)   r*   r   )   s    





-r   c                      sf   e Zd ZdZ						d#d$ fddZd%ddZd&ddZd' fddZd(dd Zd)d!d"Z	  Z
S )*MCPServerHTTPa  
    HTTP-based MCP server with configurable transport type and tool filtering.

    Args:
        url: The URL of the MCP server
        transport_type: Explicit transport type - "sse" or "streamable_http".
            If None, transport type is auto-detected from URL path:
            - URLs ending with 'sse' use Server-Sent Events (SSE) transport
            - URLs ending with 'mcp' use streamable HTTP transport
            - For other URLs, defaults to SSE transport for backward compatibility
        allowed_tools: Optional list of tool names to filter. If provided, only
            tools whose names are in this list will be available. If None, all
            tools from the server will be available.
        headers: Optional HTTP headers to include in requests
        timeout: Connection timeout in seconds (default: 5)
        sse_read_timeout: SSE read timeout in seconds (default: 300)
        client_session_timeout_seconds: Client session timeout in seconds (default: 5)

    Note: SSE transport is being deprecated in favor of streamable HTTP transport.
    See: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/206
    N   ,  urlrJ   transport_type(Literal['sse', 'streamable_http'] | Noneallowed_toolslist[str] | NoneheadersrN   timeoutr   sse_read_timeoutr   r    r!   c                   sv   t  j|d || _|| _|| _|| _|rt|nd | _|d ur3|dvr,td| d|dk| _	d S | 
|| _	d S )Nr   )ssestreamable_httpz8transport_type must be 'sse' or 'streamable_http', got ''rz   )superr+   rp   ru   _timeout_sse_read_timeoutset_allowed_tools
ValueError_use_streamable_http_should_use_streamable_http)r(   rp   rq   rs   ru   rv   rw   r   	__class__r)   r*   r+      s   

zMCPServerHTTP.__init__r,   c                 C  s"   t |}|j d}|dS )z
        Determine transport type based on URL path (for backward compatibility).

        Returns True for streamable HTTP if URL ends with 'mcp',
        False for SSE if URL ends with 'sse' or for backward compatibility.
        /z/mcp)r   pathlowerrstripendswith)r(   rp   
parsed_url
path_lowerr)   r)   r*   r      s   
z)MCPServerHTTP._should_use_streamable_httprf   c                 C  sB   | j rt| j| jt| jdt| jddS t| j| j| j| jdS )Nr1   )rp   ru   rv   rw   )r   r   rp   ru   r   r}   r~   r   r.   r)   r)   r*   r5      s   

zMCPServerHTTP.client_streamsr=   c                   s*   t   I dH }| jdu r|S | |S )zY
        List tools from the MCP server, filtered by allowed_tools if specified.
        N)r|   rG   r   _filter_tools)r(   	all_toolsr   r)   r*   rG      s
   

zMCPServerHTTP.list_toolsrH   c                 C  s^   | j du r|S g }|D ]!}t|rt|j}nt|r!t|j}nq|| j v r,|| q|S )z=
        Filter tools by allowed_tools if specified.
        N)r   r   r   r?   r   r   append)r(   rH   filtered_toolsrD   	tool_namer)   r)   r*   r     s   


zMCPServerHTTP._filter_toolsc                 C  s@   | j rdnd}| jrdt| j nd}d| j d| | dS )Nrz   ry   z, allowed_tools= zMCPServerHTTP(url=z, transport=))r   r   listrp   )r(   rq   allowed_strr)   r)   r*   __repr__  s   zMCPServerHTTP.__repr__)NNNrn   ro   rn   )rp   rJ   rq   rr   rs   rt   ru   rN   rv   r   rw   r   r   r   r    r!   )rp   rJ   r    r,   rh   rg   )rH   r=   r    r=   r    rJ   )ri   rj   rk   __doc__r+   r   r5   rG   r   r   __classcell__r)   r)   r   r*   rm      s    


rm   c                      s:   e Zd Z			dd fddZdddZdddZ  ZS )MCPServerStdioNrn   commandrJ   args	list[str]envdict[str, str] | Nonecwdstr | Path | Noner   r   r    r!   c                   s*   t  j|d || _|| _|| _|| _d S )Nrx   )r|   r+   r   r   r   r   )r(   r   r   r   r   r   r   r)   r*   r+   &  s
   
zMCPServerStdio.__init__AbstractAsyncContextManager[tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]]]c                 C  s   t t| j| j| j| jdS )N)r   r   r   r   )r   r   r   r   r   r   r.   r)   r)   r*   r5   4  s   zMCPServerStdio.client_streamsc                 C  s   d| j  d| j d| j dS )NzMCPServerStdio(command=z, args=z, cwd=r   )r   r   r   r.   r)   r)   r*   r   @  s   zMCPServerStdio.__repr__)NNrn   )r   rJ   r   r   r   r   r   r   r   r   r    r!   )r    r   r   )ri   rj   rk   r+   r5   r   r   r)   r)   r   r*   r   %  s    
r   )/
__future__r   r^   abcr   r   
contextlibr   r   datetimer   pathlibr   typingr	   r
   urllib.parser   anyio.streams.memoryr   r   mcpr   r   mcp.client.sser   mcp.client.stdior   mcp.client.streamable_httpr   r   mcp.shared.messager   ImportErroretool_contextr   r   r   r   r   r   r   rO   r   rm   r   r)   r)   r)   r*   <module>   s:   $
x 