
    [ǻi)                         d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZmZ dd	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 ddlmZ ddlmZmZmZm Z m!Z!m"Z"m#Z# ddl$m%Z% dZ& G d d      Z'g dZ(y)zClient for connecting to multiple MCP servers and loading LC tools/resources.

This module provides the `MultiServerMCPClient` class for managing connections
to multiple MCP servers and loading tools, prompts, and resources from them.
    N)AsyncIterator)asynccontextmanager)TracebackType)Any)Blob)	AIMessageHumanMessage)BaseTool)ClientSession)CallbackContext	Callbacks)ToolCallInterceptor)load_mcp_prompt)load_mcp_resources)
ConnectionMcpHttpClientFactorySSEConnectionStdioConnectionStreamableHttpConnectionWebsocketConnectioncreate_session)load_mcp_toolsa  As of langchain-mcp-adapters 0.1.0, MultiServerMCPClient cannot be used as a context manager (e.g., async with MultiServerMCPClient(...)). Instead, you can do one of the following:
1. client = MultiServerMCPClient(...)
   tools = await client.get_tools()
2. client = MultiServerMCPClient(...)
   async with client.session(server_name) as session:
       tools = await load_mcp_tools(session)c                   V   e Zd ZdZ	 ddddddeeef   dz  dedz  dee	   dz  de
d	df
d
Zedddede
d	ee   fd       Zdddedz  d	ee   fdZdddededeeef   dz  d	eeez     fdZ	 ddddedz  deee   z  dz  d	ee   fdZddZdee   dz  dedz  dedz  d	dfdZy) MultiServerMCPClientzClient for connecting to multiple MCP servers.

    Loads LangChain-compatible tools, prompts and resources from MCP servers.
    NF)	callbackstool_interceptorstool_name_prefixconnectionsr   r   r   returnc                d    ||ni | _         |xs
 t               | _        |xs g | _        || _        y)a  Initialize a `MultiServerMCPClient` with MCP servers connections.

        Args:
            connections: A `dict` mapping server names to connection configurations. If
                `None`, no initial connections are established.
            callbacks: Optional callbacks for handling notifications and events.
            tool_interceptors: Optional list of tool call interceptors for modifying
                requests and responses.
            tool_name_prefix: If `True`, tool names are prefixed with the server name
                using an underscore separator (e.g., `"weather_search"` instead of
                `"search"`). This helps avoid conflicts when multiple servers have tools
                with the same name. Defaults to `False`.

        !!! example "Basic usage (starting a new session on each tool call)"

            ```python
            from langchain_mcp_adapters.client import MultiServerMCPClient

            client = MultiServerMCPClient(
                {
                    "math": {
                        "command": "python",
                        # Make sure to update to the full absolute path to your
                        # math_server.py file
                        "args": ["/path/to/math_server.py"],
                        "transport": "stdio",
                    },
                    "weather": {
                        # Make sure you start your weather server on port 8000
                        "url": "http://localhost:8000/mcp",
                        "transport": "http",
                    }
                }
            )
            all_tools = await client.get_tools()
            ```

        !!! example "Explicitly starting a session"

            ```python
            from langchain_mcp_adapters.client import MultiServerMCPClient
            from langchain_mcp_adapters.tools import load_mcp_tools

            client = MultiServerMCPClient({...})
            async with client.session("math") as session:
                tools = await load_mcp_tools(session)
            ```
        N)r   r   r   r   r   )selfr   r   r   r   s        [/opt/lhia/marcimex/agent/venv/lib/python3.12/site-packages/langchain_mcp_adapters/client.py__init__zMultiServerMCPClient.__init__3   s<    r '2K 	 #1ik!2!8b 0    T)auto_initializeserver_namer%   c                 K   || j                   vr5d| dt        | j                   j                                d}t        |      | j                  j                  t        |            }t        | j                   |   |      4 d{   }|r|j                          d{    | ddd      d{    y7 47 7 	# 1 d{  7  sw Y   yxY ww)aq  Connect to an MCP server and initialize a session.

        Args:
            server_name: Name to identify this server connection
            auto_initialize: Whether to automatically initialize the session

        Raises:
            ValueError: If the server name is not found in the connections

        Yields:
            An initialized `ClientSession`

        "Couldn't find a server with name '', expected one of ''r&   )context)mcp_callbacksN)	r   listkeys
ValueErrorr   to_mcp_formatr   r   
initialize)r!   r&   r%   msgr-   sessions         r"   r4   zMultiServerMCPClient.sessionr   s     ( d...4[M B$$()9)9)>)>)@$A#B!E  S/!44#< 5 
 "[)
 	 	((***M	 	 	 +		 	 	 	sZ   BC
B?CC$C%	C.C9C:CCCCCCCr+   c                ~  K   ||| j                   vr5d| dt        | j                   j                                d}t        |      t	        d| j                   |   | j
                  || j                  | j                         d{   S g }g }| j                   j                         D ]X  \  }}t        j                  t	        d|| j
                  || j                  | j                              }|j                  |       Z t        j                  |  d{   }|D ]  }	|j                  |	        |S 7 7  w)a  Get a list of all tools from all connected servers.

        Args:
            server_name: Optional name of the server to get tools from.
                If `None`, all tools from all servers will be returned.

        !!! note

            A new session will be created for each tool call

        Returns:
            A list of LangChain [tools](https://docs.langchain.com/oss/python/langchain/tools)

        Nr(   r)   r*   )
connectionr   r&   r   r   )r   r.   r/   r0   r   r   r   r   itemsasynciocreate_taskappendgatherextend)
r!   r&   r3   	all_toolsload_mcp_tool_tasksnamer6   load_mcp_tool_task
tools_listtoolss
             r"   	get_toolszMultiServerMCPClient.get_tools   sZ     "$"2"228 F((,T-=-=-B-B-D(E'FaI  !o%'++K8..'"&"8"8!%!6!6   %'	  $ 0 0 6 6 8 	;D*!(!4!4)"nn $&*&<&<%)%:%:	"  &&'9:	; #>>+>??
 	$EU#	$5. @s%   BD=D9BD=D;D=;D=	argumentsprompt_namerE   c                   K   | j                  |      4 d{   }t        |||       d{   cddd      d{    S 7 +7 7 	# 1 d{  7  sw Y   yxY ww)z%Get a prompt from a given MCP server.NrD   )r4   r   )r!   r&   rF   rE   r4   s        r"   
get_promptzMultiServerMCPClient.get_prompt   sa      <<, 	T 	T(+SS	T 	T 	TS	T 	T 	T 	TsQ   AAAA
AA
AAAA
A
AAAAurisrJ   c                `   K   || j                   vr5d| dt         j                   j                                d}t        |       j	                  |      4 d{   }t        |       d{   cddd      d{    S dt        dt        t           f fd}g } j                   D cg c]  }t        j                   ||             }}t        j                  |  d{   }	|	D ]  }
|j                  |
        |S 7 7 7 # 1 d{  7  sw Y   xY wc c}w 7 >w)	a  Get resources from MCP server(s).

        Args:
            server_name: Optional name of the server to get resources from.
                If `None`, all resources from all servers will be returned.
            uris: Optional resource URI or list of URIs to load. If not provided,
                all resources will be loaded.

        Returns:
            A list of LangChain [Blob][langchain_core.documents.base.Blob] objects.

        Nr(   r)   r*   rI   r?   r   c                    K   j                  |       4 d {   }t        |       d {   cd d d       d {    S 7 *7 7 	# 1 d {  7  sw Y   y xY ww)NrI   )r4   r   )r?   r4   r!   rJ   s     r"   _load_resources_from_serverzGMultiServerMCPClient.get_resources.<locals>._load_resources_from_server   s^     ||D) D DW/dCCD D DCD D D DsQ   AAAA
AA
AAAA
A
AAAA)r   r.   r/   r0   r4   r   strr   r8   r9   r;   r<   )r!   r&   rJ   r3   r4   rM   all_resourcesr?   
load_tasksresources_list	resourcess   ` `        r"   get_resourcesz"MultiServerMCPClient.get_resources   sQ    $ "$"2"228 F((,T-=-=-B-B-D(E'FaI  !o%||K0 D DG/dCCD D D	DC 	DDJ 	D %' ((
  ;D AB

 
  '~~z::' 	,I  +	,DCD D D D
 ;sr   AD.D D.#D4D5D8D.D/D.4"D'D.-D,.D.DD.D$DD$ D.c                 (   K   t        t              w)zAsync context manager entry point.

        Raises:
            NotImplementedError: Context manager support has been removed.
        NotImplementedErrorASYNC_CONTEXT_MANAGER_ERROR)r!   s    r"   
__aenter__zMultiServerMCPClient.__aenter__   s      ""=>>s   exc_typeexc_valexc_tbc                      t        t              )aU  Async context manager exit point.

        Args:
            exc_type: Exception type if an exception occurred.
            exc_val: Exception value if an exception occurred.
            exc_tb: Exception traceback if an exception occurred.

        Raises:
            NotImplementedError: Context manager support has been removed.
        rU   )r!   rY   rZ   r[   s       r"   	__aexit__zMultiServerMCPClient.__aexit__  s      ""=>>r$   )N)r   r   )__name__
__module____qualname____doc__dictrN   r   r   r.   r   boolr#   r   r   r   r4   r
   rC   r   r	   r   rH   r   rS   rX   typeBaseExceptionr   r]    r$   r"   r   r   -   s    59=1 '+>B!&=1#z/*T1=1 t#	=1
   34t;=1 =1 
=1~ 
 !%	## 	#
 
}	%# #J <@ 0cDj 0DN 0n ,0	T	T 	T
 S>D(	T 
lY&	'	T #'( (,	(4Z( DIo$	(
 
d(T??}%,? %? $	?
 
?r$   r   )r   r   r   r   r   r   r   ))ra   r8   collections.abcr   
contextlibr   typesr   typingr   langchain_core.documents.baser   langchain_core.messagesr   r	   langchain_core.toolsr
   mcpr    langchain_mcp_adapters.callbacksr   r   #langchain_mcp_adapters.interceptorsr   langchain_mcp_adapters.promptsr    langchain_mcp_adapters.resourcesr   langchain_mcp_adapters.sessionsr   r   r   r   r   r   r   langchain_mcp_adapters.toolsr   rW   r   __all__rf   r$   r"   <module>rv      se     ) *   . ; )  G C : ?   83 j? j?Zr$   