o
    i                  
   @  s\  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlmZm	Z	 d dl
mZ d dlmZmZmZmZ d dlmZ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Zd dl Z d dl!Z!d dl"m#Z#m$Z$ d dl%m&Z&m'Z'm(Z(m)Z) d dl!m*Z*m+Z+ d dl,m-Z-m.Z.m/Z/ d dl0m1Z1m2Z2 ddl3m4Z4 ddl5m6Z6m7Z7 z:d dl8m9Z: d dl;m<Z<m=Z=m>Z> d dl?m@Z@ d dlAmBZBmCZC d dlDmEZEmFZF d dlGmHZH d dlImJZJ d dlKmLZL W n eMy ZN zeMdeNdZN[Nww ddlOmPZPmQZQmRZRmSZSmTZT dZUe!jVe!j+We!j+X e!j+Y dZZe[dZ\G d d! d!e6e eZ]G d"d# d#e]Z^G d$d% d%e]Z_G d&d' d'e_Z`e/d(G d)d* d*e`ZaG d+d, d,e_ZbeceSjdB eeecef B efe B eeceSjdB eeecef B efe B  B Zg	 eeceeecef eeecef dB geeg f Zh	 ee1e eheceeecef geeg f Zi	 d=d1d2ZjG d3d4 d4e&Zkd>d6d7Zld?d;d<ZmdS )@    )annotationsN)ABCabstractmethod)Lock)AsyncIterator	AwaitableCallableSequence)AbstractAsyncContextManagerAsyncExitStackasynccontextmanager)fieldreplace)	timedelta)Path)	AnnotatedAny)MemoryObjectReceiveStreamMemoryObjectSendStream)	BaseModelDiscriminatorFieldTag)
CoreSchemacore_schema)Selfassert_never
deprecated)
RunContextToolDefinition   )model_request)AbstractToolsetToolsetTool)types)ClientSessionElicitationFnT
LoggingFnT
sse_client)StdioServerParametersstdio_client)GetSessionIdCallbackstreamablehttp_client)RequestContext)McpError)SessionMessageu   Please install the `mcp` package to use the MCP server, you can use the `mcp` optional group — `pip install "pydantic-ai-slim[mcp]"`)_mcp_utils
exceptionsmessagesmodels)	MCPServerMCPServerStdioMCPServerHTTPMCPServerSSEMCPServerStreamableHTTPload_mcp_servers)schemaz\$\{([^}:]+)(:-([^}]*))?\}c                      s  e Zd ZU dZded< 	 ded< 	 ded< 	 ded	< 	 ded
< 	 ded< 	 ded< 	 ded< 	 ded< 	 dZded< 	 ded< eddZded< ded< ded< ded< d ed!< d"ed#< d$ed%< 				&	'		(		)	dudd*dvd,d-Zd.d/ Z	e
edwd2d3Zedxd4d5Zejdyd7d5Zedz fd9d:Zedzd;d<Zed{d=d>Zd|d@dAZ	d}d~dHdIZddOdPZddRdSZddVdWZddYdZZdd]d^Zedd_d`ZddfdgZddkdlZddpdqZddsdtZ  ZS )r6   zuBase class for attaching agents to MCP servers.

    See <https://modelcontextprotocol.io> for more information.
    
str | Nonetool_prefixmcp_types.LoggingLevel | None	log_levelLoggingFnT | Nonelog_handlerfloattimeoutread_timeoutProcessToolCallback | Noneprocess_tool_callboolallow_samplingmodels.Model | Nonesampling_modelintmax_retriesNElicitationFnT | Noneelicitation_callback_idF)comparer   _enter_lock_running_countzAsyncExitStack | None_exit_stackr%   _clientz5MemoryObjectReceiveStream[SessionMessage | Exception]_read_streamz&MemoryObjectSendStream[SessionMessage]_write_streammcp_types.Implementation_server_info   ,  Tr    idr]   c                C  sR   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	|p!|| _
|   d S N)r>   r@   rB   rD   rE   rG   rI   rK   rM   rO   rP   __post_init__)selfr>   r@   rB   rD   rE   rG   rI   rK   rM   rO   r]    ra   U/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/pydantic_ai/mcp.py__init__~   s   
zMCPServer.__init__c                 C  s   t  | _d| _d | _d S )Nr   )r   rR   rS   rT   r`   ra   ra   rb   r_      s   
zMCPServer.__post_init__returnsAsyncIterator[tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]]]c                 C s
   t d)z&Create the streams for the MCP server.z1MCP Server subclasses must implement this method.)NotImplementedErrorrd   ra   ra   rb   client_streams   s   zMCPServer.client_streamsc                 C  s   | j S r^   rP   rd   ra   ra   rb   r]      s   zMCPServer.idvaluec                 C  s
   || _ d S r^   ri   r`   rj   ra   ra   rb   r]      s   
strc                   s   | j rt jS t| S r^   )r]   superlabelreprrd   	__class__ra   rb   rn      s   zMCPServer.labelc                 C  s   dS )Nz8Set the `tool_prefix` attribute to avoid name conflicts.ra   rd   ra   ra   rb   tool_name_conflict_hint      z!MCPServer.tool_name_conflict_hintc                 C  s*   t | dddu rtd| jj d| jS )zDAccess the information send by the MCP server during initialization.rY   NzThe `z8.server_info` is only instantiated after initialization.)getattrAttributeErrorrq   __name__rY   rd   ra   ra   rb   server_info   s
   zMCPServer.server_infolist[mcp_types.Tool]c              	     sT   | 4 I dH  | j  I dH }W d  I dH  |jS 1 I dH s"w   Y  |jS )zRetrieve tools that are currently active on the server.

        Note:
        - We don't cache tools as they might change.
        - We also don't subscribe to the server to avoid complexity.
        N)rU   
list_toolstools)r`   resultra   ra   rb   ry      s   zMCPServer.list_toolsnameargsdict[str, Any]metadatadict[str, Any] | None
ToolResultc           
        s`   4 I dH E z& j ttjdtj|||r tjjdi |ndddtjI dH }W n t	yA } zt
|jjd}~ww W d  I dH  n1 I dH sRw   Y  |jrsd}|jrldd |jD }d|}t
|pqd|j }rtd	d
 |jD st|trt|dkrd|v r|d S |S  fdd|jD I dH }	t|	dkr|	d S |	S )aK  Call a tool on the server.

        Args:
            name: The name of the tool to call.
            args: The arguments to pass to the tool.
            metadata: Request-level metadata (optional)

        Returns:
            The result of the tool call.

        Raises:
            ModelRetry: If the tool call fails.
        Nz
tools/call)r|   	arguments_meta)methodparamsc                 S  s   g | ]}t |tjr|jqS ra   )
isinstance	mcp_typesTextContenttext.0partra   ra   rb   
<listcomp>   s    z.MCPServer.direct_call_tool.<locals>.<listcomp>
zMCP tool call failedc                 s  s    | ]
}t |tj V  qd S r^   )r   r   r   r   ra   ra   rb   	<genexpr>  s    
z-MCPServer.direct_call_tool.<locals>.<genexpr>r    r{   c                   s   g | ]
}  |I d H qS r^   )_map_tool_result_partr   rd   ra   rb   r     s    r   ra   )rU   send_requestr   ClientRequestCallToolRequestCallToolRequestParamsRequestParamsMetaCallToolResultr/   r3   
ModelRetryerrormessageisErrorcontentjoinstructuredContentanyr   dictlen)
r`   r|   r}   r   r{   er   
text_parts
structuredmappedra   rd   rb   direct_call_tool   sH   
(
zMCPServer.direct_call_tool	tool_argsctxRunContext[Any]toolToolsetTool[Any]c                   sZ   | j r|| j  d}t||d}| jd ur$| || j||I d H S | ||I d H S )N_)	tool_name)r>   removeprefixr   rG   r   )r`   r|   r   r   r   ra   ra   rb   	call_tool  s   
zMCPServer.call_tooldict[str, ToolsetTool[Any]]c                   s     fdd  I d H D S )Nc                   sj   i | ]1}j rj  d |j n|j  r t |j|j|j|jr(|j nd|j	p-dddqS )r   N)metar   output_schema)r|   descriptionparameters_json_schemar   )
r>   r|   tool_for_tool_defr   r   inputSchemar   r   
model_dumpoutputSchema)r   mcp_toolr|   r`   ra   rb   
<dictcomp>"  s      z'MCPServer.get_tools.<locals>.<dictcomp>)ry   )r`   r   ra   r   rb   	get_tools!  s   zMCPServer.get_toolstool_defr   c                 C  s   t | || jtdS )N)toolsetr   rM   args_validator)r#   rM   TOOL_SCHEMA_VALIDATOR)r`   r   ra   ra   rb   r   3  s   zMCPServer.tool_for_tool_defr   c                   s\  | j 4 I dH  | jdkrt 4 I dH o}||  I dH \| _| _t| j| j| jr/| j	nd| j
| jt| jdd}||I dH | _t| j" | j I dH }|j| _| j }rf| j|I dH  W d   n1 spw   Y  | | _W d  I dH  n1 I dH sw   Y  |  jd7  _W d  I dH  | S 1 I dH sw   Y  | S )a*  Enter the MCP server context.

        This will initialize the connection to the server.
        If this server is an [`MCPServerStdio`][pydantic_ai.mcp.MCPServerStdio], the server will first be started as a subprocess.

        This is a no-op if the MCP server has already been entered.
        Nr   )seconds)read_streamwrite_streamsampling_callbackrO   logging_callbackread_timeout_secondsr    )rR   rS   r   enter_async_contextrh   rV   rW   r%   rI   _sampling_callbackrO   rB   r   rE   rU   anyio
fail_afterrD   
initialize
serverInforY   r@   set_logging_levelpop_allrT   )r`   
exit_stackclientr{   r@   ra   ra   rb   
__aenter__;  s8   


(zMCPServer.__aenter__r   bool | Nonec              	     s   | j dkr
td| j4 I d H ( |  j d8  _ | j dkr.| jd ur.| j I d H  d | _W d   I d H  d S 1 I d H s?w   Y  d S )Nr   z5MCPServer.__aexit__ called more times than __aenter__r    )rS   
ValueErrorrR   rT   aclose)r`   r}   ra   ra   rb   	__aexit__[  s   
.zMCPServer.__aexit__c                 C  s
   t | jS )z#Check if the MCP server is running.)rH   rS   rd   ra   ra   rb   
is_runningd  s   
zMCPServer.is_runningcontext"RequestContext[ClientSession, Any]r   $mcp_types.CreateMessageRequestParams3mcp_types.CreateMessageResult | mcp_types.ErrorDatac           	        s   | j du r
tdt|}t }|j }r||d< |j }r%||d< |j }r.||d< t	| j ||dI dH }t
jdt|| j jdS )	zMCP sampling callback.NzSampling model is not set
max_tokenstemperaturestop_sequences)model_settings	assistant)roler   model)rK   r   r1   map_from_mcp_paramsr5   ModelSettings	maxTokensr   stopSequencesr!   r   CreateMessageResultmap_from_model_response
model_name)	r`   r   r   pai_messagesr   r   r   r   model_responsera   ra   rb   r   i  s"   




zMCPServer._sampling_callbackr   mcp_types.ContentBlock9str | messages.BinaryContent | dict[str, Any] | list[Any]c                   s  t |tjr"|j}|dr zt|W S  ty   Y |S w |S t |tjr4t	j
t|j|jdS t |tjrFt	j
t|j|jdS t |tjrT|j} |S t |tjr} j|jI d H }t|jdkrs |jd S  fdd|jD S t| d S )N)[{data
media_typer    r   c                   s   g | ]}  |qS ra   )_get_content)r   resourcerd   ra   rb   r     s    z3MCPServer._map_tool_result_part.<locals>.<listcomp>)r   r   r   r   
startswithpydantic_core	from_jsonr   ImageContentr4   BinaryContentbase64	b64decoder   mimeTypeAudioContentEmbeddedResourcer   r   ResourceLinkrU   read_resourceurir   contentsr   )r`   r   r   r   resource_resultra   rd   rb   r     s8   

zMCPServer._map_tool_result_partr   ?mcp_types.TextResourceContents | mcp_types.BlobResourceContentsstr | messages.BinaryContentc                 C  sF   t |tjr	|jS t |tjrtjt|j	|j
pddS t| d S )Nzapplication/octet-streamr   )r   r   TextResourceContentsr   BlobResourceContentsr4   r   r   r   blobr   r   )r`   r   ra   ra   rb   r     s   zMCPServer._get_contentobjectc                C  s"   t |to| j|jko| j|jkS r^   )r   r6   r]   r>   rk   ra   ra   rb   __eq__     "zMCPServer.__eq__)
NNNrZ   r[   NTNr    N)r>   r=   r@   r?   rB   rA   rD   rC   rE   rC   rG   rF   rI   rH   rK   rJ   rM   rL   rO   rN   r]   r=   re   rf   )re   r=   )rj   r=   re   rl   )re   rX   )re   rx   r^   )r|   rl   r}   r~   r   r   re   r   )
r|   rl   r   r~   r   r   r   r   re   r   )r   r   re   r   )r   r   re   r   )re   r   )r}   r   re   r   )re   rH   )r   r   r   r   re   r   )r   r   re   r   )r   r  re   r  rj   r  re   rH   ) rv   
__module____qualname____doc____annotations__rO   r   rR   rc   r_   r   r   rh   propertyr]   setterrn   rr   rw   ry   r   r   r   r   r   r   r   r   r   r   r	  __classcell__ra   ra   rp   rb   r6   @   s   
 

;



 	


"r6   c                      s   e Zd ZU dZded< 	 ded< 	 ded< 	 ded	< 	 d
ed< ded< ded< ded< ded< ded< ded< ded< ded< dZded< ddddddddd dd!ddd"d6 fd$d%Zed7d+d,Ze	d8d.d/Z
d9d0d1Zd: fd4d5Z  ZS );r7   aJ  Runs an MCP server in a subprocess and communicates with it over stdin/stdout.

    This class implements the stdio transport from the MCP specification.
    See <https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio> for more information.

    !!! note
        Using this class as an async context manager will start the server as a subprocess when entering the context,
        and stop it when exiting the context.

    Example:
    ```python {py="3.10"}
    from pydantic_ai import Agent
    from pydantic_ai.mcp import MCPServerStdio

    server = MCPServerStdio(  # (1)!
        'uv', args=['run', 'mcp-run-python', 'stdio'], timeout=10
    )
    agent = Agent('openai:gpt-4o', toolsets=[server])
    ```

    1. See [MCP Run Python](https://github.com/pydantic/mcp-run-python) for more information.
    rl   commandSequence[str]r}   dict[str, str] | Noneenvstr | Path | Nonecwdr=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   NrN   rO   rZ   r[   Tr    )r  r  r>   r@   rB   rD   rE   rG   rI   rK   rM   rO   r]   r]   c                  s>   || _ || _|| _|| _t j|||||	|
|||||d dS )a]  Build a new MCP server.

        Args:
            command: The command to run.
            args: The arguments to pass to the command.
            env: The environment variables to set in the subprocess.
            cwd: The working directory to use when spawning the process.
            tool_prefix: A prefix to add to all tools that are registered with the server.
            log_level: The log level to set when connecting to the server, if any.
            log_handler: A handler for logging messages from the server.
            timeout: The timeout in seconds to wait for the client to initialize.
            read_timeout: Maximum time in seconds to wait for new messages before timing out.
            process_tool_call: Hook to customize tool calling and optionally pass extra metadata.
            allow_sampling: Whether to allow MCP sampling through this client.
            sampling_model: The model to use for sampling.
            max_retries: The maximum number of times to retry a tool call.
            elicitation_callback: Callback function to handle elicitation requests from the server.
            id: An optional unique ID for the MCP server. An MCP server needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the server's activities within the workflow.
        r\   N)r  r}   r  r  rm   rc   )r`   r  r}   r  r  r>   r@   rB   rD   rE   rG   rI   rK   rM   rO   r]   rp   ra   rb   rc     s"   &
zMCPServerStdio.__init__r   r   __re   r   c                 C  sR   t dd t t t  t t t  t jt t  t  dddS )Nc                 S     t di | S Nra   )r7   dctra   ra   rb   <lambda>"      z=MCPServerStdio.__get_pydantic_core_schema__.<locals>.<lambda>Frequired)r  r}   r  )r    no_info_after_validator_functiontyped_dict_schematyped_dict_field
str_schemalist_schemadict_schemaclsr   r  ra   ra   rb   __get_pydantic_core_schema__  s   z+MCPServerStdio.__get_pydantic_core_schema__rf   c              	   C sp   t | jt| j| j| jd}t|d4 I d H \}}||fV  W d   I d H  d S 1 I d H s1w   Y  d S )N)r  r}   r  r  )server)r*   r  listr}   r  r  r+   )r`   r-  r   r   ra   ra   rb   rh   /  s
   	.zMCPServerStdio.client_streamsc                 C  sJ   d| j d| jg}| jr|d| j | jj dd| dS )Nzcommand=zargs=id=(, ))r  r}   r]   appendrq   rv   r   r`   	repr_argsra   ra   rb   __repr__<  s   

zMCPServerStdio.__repr__rj   r  c                  sF   t  |o"t|to"| j|jko"| j|jko"| j|jko"| j|jkS r^   )rm   r	  r   r7   r  r}   r  r  rk   rp   ra   rb   r	  E  s   



zMCPServerStdio.__eq__)r  rl   r}   r  r  r  r  r  r>   r=   r@   r?   rB   rA   rD   rC   rE   rC   rG   rF   rI   rH   rK   rJ   rM   rL   rO   rN   r]   r=   r   r   r  r   re   r   r  r  r  )rv   r  r  r  r  rO   rc   classmethodr,  r   rh   r6  r	  r  ra   ra   rp   rb   r7     sP   
 9
	r7   c                      s   e Zd ZU ded< 	 ded< 	 ded< 	 ded< d	ed
< ded< ded< ded< ded< ded< ded< ded< dZded< ddddddddddddddd/ fd$d%Zeed0d(d)Ze	d1d+d,Z
d2d-d.Z  ZS )3_MCPServerHTTPrl   urlr   headershttpx.AsyncClient | Nonehttp_clientr=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   NrN   rO   rZ   Tr    )r;  r=  r]   r>   r@   rB   rD   rE   rG   rI   rK   rM   rO   r  r]   float | None_deprecated_kwargsr   c                  s   d|v r|	durt dtjdtdd |d}	t| |	du r$d}	|| _|| _|| _	t
 j|||||	|
|||||d dS )	aM  Build a new MCP server.

        Args:
            url: The URL of the endpoint on the MCP server.
            headers: Optional HTTP headers to be sent with each request to the endpoint.
            http_client: An `httpx.AsyncClient` to use with the endpoint.
            id: An optional unique ID for the MCP server. An MCP server needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the server's activities within the workflow.
            tool_prefix: A prefix to add to all tools that are registered with the server.
            log_level: The log level to set when connecting to the server, if any.
            log_handler: A handler for logging messages from the server.
            timeout: The timeout in seconds to wait for the client to initialize.
            read_timeout: Maximum time in seconds to wait for new messages before timing out.
            process_tool_call: Hook to customize tool calling and optionally pass extra metadata.
            allow_sampling: Whether to allow MCP sampling through this client.
            sampling_model: The model to use for sampling.
            max_retries: The maximum number of times to retry a tool call.
            elicitation_callback: Callback function to handle elicitation requests from the server.
        sse_read_timeoutNzE'read_timeout' and 'sse_read_timeout' cannot be set at the same time.z='sse_read_timeout' is deprecated, use 'read_timeout' instead.   )
stacklevelr[   r\   )	TypeErrorwarningswarnDeprecationWarningpopr2   validate_empty_kwargsr:  r;  r=  rm   rc   )r`   r:  r;  r=  r]   r>   r@   rB   rD   rE   rG   rI   rK   rM   rO   r?  rp   ra   rb   rc     s4   %


z_MCPServerHTTP.__init__re   +  Callable[..., AbstractAsyncContextManager[tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage], GetSessionIdCallback],] | AbstractAsyncContextManager[tuple[MemoryObjectReceiveStream[SessionMessage | Exception], MemoryObjectSendStream[SessionMessage]]]]c                 C  s   d S r^   ra   rd   ra   ra   rb   _transport_client  s   z _MCPServerHTTP._transport_clientrf   c              	    s    j r jrtdtj j j j jd} j d urR	 	 	 dd fdd}||d4 I d H ^}}}||fV  W d   I d H  d S 1 I d H sKw   Y  d S | jd4 I d H ^}}}||fV  W d   I d H  d S 1 I d H svw   Y  d S )Nz3`http_client` is mutually exclusive with `headers`.)r:  rD   r@  r;  r  rD   httpx.Timeout | Noneauthhttpx.Auth | Nonere   httpx.AsyncClientc                   s    j d usJ  j S r^   )r=  )r;  rD   rL  rd   ra   rb   httpx_client_factory  s   z;_MCPServerHTTP.client_streams.<locals>.httpx_client_factory)rO  )r;  )NNN)r;  r  rD   rK  rL  rM  re   rN  )	r=  r;  r   	functoolspartialrJ  r:  rD   rE   )r`   transport_client_partialrO  r   r   r   ra   rd   rb   rh     s.   	
..z_MCPServerHTTP.client_streamsc                 C  s@   d| j g}| jr|d| j | jj dd| dS )Nzurl=r/  r0  r1  r2  )r:  r]   r3  rq   rv   r   r4  ra   ra   rb   r6    s
   
z_MCPServerHTTP.__repr__)r:  rl   r;  r  r=  r<  r]   r=   r>   r=   r@   r?   rB   rA   rD   rC   rE   r>  rG   rF   rI   rH   rK   rJ   rM   rL   rO   rN   r?  r   )re   rI  r  r  )rv   r  r  r  rO   rc   r  r   rJ  r   rh   r6  r  ra   ra   rp   rb   r9  P  sJ   
 E&r9  c                      <   e Zd ZdZedddZed	d
 Zd fddZ  Z	S )r9   a  An MCP server that connects over streamable HTTP connections.

    This class implements the SSE transport from the MCP specification.
    See <https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse> for more information.

    !!! note
        Using this class as an async context manager will create a new pool of HTTP connections to connect
        to a server which should already be running.

    Example:
    ```python {py="3.10"}
    from pydantic_ai import Agent
    from pydantic_ai.mcp import MCPServerSSE

    server = MCPServerSSE('http://localhost:3001/sse')
    agent = Agent('openai:gpt-4o', toolsets=[server])
    ```
    r   r   r  re   r   c                 C  @   t dd t t t  t jt t  t  dddS )Nc                 S  r  r  )r9   r  ra   ra   rb   r   !  r!  z;MCPServerSSE.__get_pydantic_core_schema__.<locals>.<lambda>Fr"  r:  r;  r   r$  r%  r&  r'  r)  r*  ra   ra   rb   r,       z)MCPServerSSE.__get_pydantic_core_schema__c                 C     t S r^   r(   rd   ra   ra   rb   rJ  ,  rs   zMCPServerSSE._transport_clientrj   r  rH   c                  "   t  |ot|to| j|jkS r^   )rm   r	  r   r9   r:  rk   rp   ra   rb   r	  0  r
  zMCPServerSSE.__eq__r7  r  
rv   r  r  r  r8  r,  r  rJ  r	  r  ra   ra   rp   rb   r9   
      
r9   zDThe `MCPServerHTTP` class is deprecated, use `MCPServerSSE` instead.c                   @  s   e Zd ZdZdS )r8   a  An MCP server that connects over HTTP using the old SSE transport.

    This class implements the SSE transport from the MCP specification.
    See <https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse> for more information.

    !!! note
        Using this class as an async context manager will create a new pool of HTTP connections to connect
        to a server which should already be running.

    Example:
    ```python {py="3.10" test="skip"}
    from pydantic_ai import Agent
    from pydantic_ai.mcp import MCPServerHTTP

    server = MCPServerHTTP('http://localhost:3001/sse')
    agent = Agent('openai:gpt-4o', toolsets=[server])
    ```
    N)rv   r  r  r  ra   ra   ra   rb   r8   4  s    r8   c                      rS  )r:   a  An MCP server that connects over HTTP using the Streamable HTTP transport.

    This class implements the Streamable HTTP transport from the MCP specification.
    See <https://modelcontextprotocol.io/introduction#streamable-http> for more information.

    !!! note
        Using this class as an async context manager will create a new pool of HTTP connections to connect
        to a server which should already be running.

    Example:
    ```python {py="3.10"}
    from pydantic_ai import Agent
    from pydantic_ai.mcp import MCPServerStreamableHTTP

    server = MCPServerStreamableHTTP('http://localhost:8000/mcp')
    agent = Agent('openai:gpt-4o', toolsets=[server])
    ```
    r   r   r  re   r   c                 C  rT  )Nc                 S  r  r  )r:   r  ra   ra   rb   r   a  r!  zFMCPServerStreamableHTTP.__get_pydantic_core_schema__.<locals>.<lambda>Fr"  rU  rV  r*  ra   ra   rb   r,  ^  rW  z4MCPServerStreamableHTTP.__get_pydantic_core_schema__c                 C  rX  r^   )r-   rd   ra   ra   rb   rJ  l  rs   z)MCPServerStreamableHTTP._transport_clientrj   r  rH   c                  rY  r^   )rm   r	  r   r:   r:  rk   rp   ra   rb   r	  p  r
  zMCPServerStreamableHTTP.__eq__r7  r  rZ  ra   ra   rp   rb   r:   J  r[  r:   rj   r~   re   r=   c                 C  s"   d| v r| d  drdS dS dS )Nr:  z/ssessezstreamable-httpstdio)endswith)rj   ra   ra   rb   _mcp_server_discriminator  s
   r_  c                   @  s   e Zd ZU dZded< dS )MCPServerConfigzConfiguration for MCP servers.zAnnotated[dict[str, Annotated[Annotated[MCPServerStdio, Tag('stdio')] | Annotated[MCPServerStreamableHTTP, Tag('streamable-http')] | Annotated[MCPServerSSE, Tag('sse')], Discriminator(_mcp_server_discriminator)]], Field(alias='mcpServers')]mcp_serversN)rv   r  r  r  r  ra   ra   ra   rb   r`    s   
 r`  r   c                 C  s\   t | trddd}t|| } | S t | tr dd |  D S t | tr,d	d
 | D S | S )a  Recursively expand environment variables in a JSON structure.

    Environment variables can be referenced using `${VAR_NAME}` syntax,
    or `${VAR_NAME:-default}` syntax to provide a default value if the variable is not set.

    Args:
        value: The value to expand (can be str, dict, list, or other JSON types).

    Returns:
        The value with all environment variables expanded.

    Raises:
        ValueError: If an environment variable is not defined and no default value is provided.
    matchre.Match[str]re   rl   c                 S  sZ   |  d}|  dd u}|r|  dnd }|tjv rtj| S |r%|p$dS td| d)Nr    rA      zEnvironment variable ${z} is not defined)grouposenvironr   )rb  var_namehas_defaultdefault_valuera   ra   rb   replace_match  s   


z'_expand_env_vars.<locals>.replace_matchc                 S  s   i | ]	\}}|t |qS ra   _expand_env_vars)r   kvra   ra   rb   r     s    z$_expand_env_vars.<locals>.<dictcomp>c                 S  s   g | ]}t |qS ra   rm  )r   itemra   ra   rb   r     s    z$_expand_env_vars.<locals>.<listcomp>N)rb  rc  re   rl   )r   rl   _ENV_VAR_PATTERNsubr   itemsr.  )rj   rl  ra   ra   rb   rn    s   



rn  config_path
str | Path=list[MCPServerStdio | MCPServerStreamableHTTP | MCPServerSSE]c                 C  sr   t | } |  std|  dt|  }t|}t|}g }|j	
 D ]\}}||_||_|| q'|S )a  Load MCP servers from a configuration file.

    Environment variables can be referenced in the configuration file using:
    - `${VAR_NAME}` syntax - expands to the value of VAR_NAME, raises error if not defined
    - `${VAR_NAME:-default}` syntax - expands to VAR_NAME if set, otherwise uses the default value

    Args:
        config_path: The path to the configuration file.

    Returns:
        A list of MCP servers.

    Raises:
        FileNotFoundError: If the configuration file does not exist.
        ValidationError: If the configuration file does not match the schema.
        ValueError: If an environment variable referenced in the configuration is not defined and no default value is provided.
    zConfig file z
 not found)r   existsFileNotFoundErrorr   r   
read_bytesrn  r`  model_validatera  rt  r]   r>   r3  )ru  config_dataexpanded_config_dataconfigserversr|   r-  ra   ra   rb   r;     s   
r;   )rj   r~   re   r=   )rj   r   re   r   )ru  rv  re   rw  )n
__future__r   r   rP  rg  rerD  abcr   r   asyncior   collections.abcr   r   r   r	   
contextlibr
   r   r   dataclassesr   r   datetimer   pathlibr   typingr   r   r   httpxr   anyio.streams.memoryr   r   pydanticr   r   r   r   r   r   typing_extensionsr   r   r   pydantic_ai.toolsr   r   directr!   toolsets.abstractr"   r#   mcpr$   r   mcp.client.sessionr%   r&   r'   mcp.client.sser)   mcp.client.stdior*   r+   mcp.client.streamable_httpr,   r-   mcp.shared.contextr.   mcp.shared.exceptionsr/   mcp.shared.messager0   ImportError_import_errorre  r1   r2   r3   r4   r5   __all__SchemaValidatorr)  r'  
any_schemar   compilerr  r6   r7   r9  r9   r8   r:   rl   r   r   r.  r   CallToolFuncProcessToolCallbackr_  r`  rn  r;   ra   ra   ra   rb   <module>   s    
  t  ;*+
 *
	
	
,