o
    id                     @  s  d dl m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 d dlmZ d dl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mZmZ d dl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'm(Z( d dl)m*Z* d dl+m,Z,m-Z-m.Z. d dl/m0Z0 d dl1m2Z2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9m:Z: d dl;m<Z< d dl=m>Z> d dl?m@Z@ d dlAmBZB d dlCmDZDmEZE d dlFmGZG d dlHmIZI d dlJmKZK d d lLmMZM e
rd dlNm>Z> eMeOZPeg e!f eg ee! f B ZQG d!d" d"ZRG d#d$ d$eGeRZSG d%d& d&e<eRZTG d'd( d(e7eRZUG d)d* d*eDeKZVG d+d, d,e9eKZWG d-d. d.e:eKZXG d/d0 d0e2eKZYG d1d2 d2eBZZd=d7d8Z[G d9d: d:e!e* Z\G d;d< d<e\e* Z]dS )>    )annotationsN)	AwaitableCallable)Path)TYPE_CHECKINGAnycastquote)ServerSession)ClientSession)LifespanContextTRequestContext)McpError)METHOD_NOT_FOUNDBlobResourceContentsGetPromptResultTextResourceContents)AnyUrl)ClientFastMCP1Server)ElicitResult)
LogMessage)	RootsList)ClientTransportT)NotFoundErrorResourceError	ToolError)	MCPConfig)PromptPromptMessage)PromptArgument)PromptManager)ResourceResourceTemplate)ResourceManager)Context)get_context)FastMCP)Tool
ToolResult)ToolManager)apply_transformations_to_tools)MirroredComponent)
get_loggerc                   @  s$   e Zd ZU dZded< d	ddZdS )
ProxyManagerMixinzHA mixin for proxy managers to provide a unified client retrieval method.ClientFactoryTclient_factoryreturnr   c                   s"   |   }t|r|I dH }|S )z<Gets a client instance by calling the sync or async factory.N)r1   inspectisawaitable)selfclient r7   Z/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/fastmcp/server/proxy.py_get_client=   s
   

zProxyManagerMixin._get_clientN)r2   r   )__name__
__module____qualname____doc____annotations__r9   r7   r7   r7   r8   r/   8   s   
 r/   c                      sH   e Zd ZdZd fddZd fd
dZdddZd fddZ  ZS )ProxyToolManagerzaA ToolManager that sources its tools from a remote client in addition to local and mounted tools.r1   r0   kwargsr   c                      t  jdi | || _d S Nr7   super__init__r1   r5   r1   r@   	__class__r7   r8   rE   H      
zProxyToolManager.__init__r2   dict[str, Tool]c              
     s   t   I dH }z?|  I dH }|4 I dH % | I dH }|D ]}|j|vr1t||||j< q!W d  I dH  n1 I dH sBw   Y  W n tyc } z|jj	t
krWn|W Y d}~nd}~ww t|| jd}|S )zMGets the unfiltered tool inventory including local, mounted, and proxy tools.N)toolstransformations)rD   	get_toolsr9   
list_toolsname	ProxyToolfrom_mcp_toolr   errorcoder   r,   rL   )r5   	all_toolsr6   client_toolstooletransformed_toolsrG   r7   r8   rM   L   s2   
(zProxyToolManager.get_tools
list[Tool]c                      |   I dH }t| S )zJGets the filtered list of tools including local, mounted, and proxy tools.N)rM   listvalues)r5   
tools_dictr7   r7   r8   rN   f      zProxyToolManager.list_toolskeystr	argumentsdict[str, Any]r*   c                   s   zt  ||I dH W S  tyL   |  I dH }|4 I dH  |||I dH }t|j|jdW  d  I dH   Y S 1 I dH sDw   Y  Y dS w )zBCalls a tool, trying local/mounted first, then proxy if not found.Ncontentstructured_content)rD   	call_toolr   r9   r*   rd   re   )r5   r_   ra   r6   resultrG   r7   r8   rf   k   s   6zProxyToolManager.call_toolr1   r0   r@   r   )r2   rJ   )r2   rY   )r_   r`   ra   rb   r2   r*   )	r:   r;   r<   r=   rE   rM   rN   rf   __classcell__r7   r7   rG   r8   r?   E   s    
r?   c                      s`   e Zd ZdZd fddZd fd
dZd fddZdddZdddZd fddZ	  Z
S ) ProxyResourceManagerzmA ResourceManager that sources its resources from a remote client in addition to local and mounted resources.r1   r0   r@   r   c                   rA   rB   rC   rF   rG   r7   r8   rE   ~   rI   zProxyResourceManager.__init__r2   dict[str, Resource]c              
     s   t   I dH }zF|  I dH }|4 I dH + | I dH }|D ]}t|j|vr5t|||t|j< q!W d  I dH  W |S 1 I dH sHw   Y  W |S  tyk } z|j	j
tkr^n|W Y d}~|S d}~ww )zUGets the unfiltered resource inventory including local, mounted, and proxy resources.N)rD   get_resourcesr9   list_resourcesr`   uriProxyResourcefrom_mcp_resourcer   rR   rS   r   )r5   all_resourcesr6   client_resourcesresourcerW   rG   r7   r8   rl      s0   

z"ProxyResourceManager.get_resourcesdict[str, ResourceTemplate]c              
        t   I dH }zB|  I dH }|4 I dH ' | I dH }|D ]}|j|vr1t||||j< q!W d  I dH  W |S 1 I dH sDw   Y  W |S  tyg } z|jj	t
krZn|W Y d}~|S d}~ww )zUGets the unfiltered template inventory including local, mounted, and proxy templates.N)rD   get_resource_templatesr9   list_resource_templatesuriTemplateProxyTemplatefrom_mcp_templater   rR   rS   r   )r5   all_templatesr6   client_templatestemplaterW   rG   r7   r8   rv      s0   


z+ProxyResourceManager.get_resource_templateslist[Resource]c                   rZ   )zRGets the filtered list of resources including local, mounted, and proxy resources.N)rl   r[   r\   )r5   resources_dictr7   r7   r8   rm      r^   z#ProxyResourceManager.list_resourceslist[ResourceTemplate]c                   rZ   )zRGets the filtered list of templates including local, mounted, and proxy templates.N)rv   r[   r\   )r5   templates_dictr7   r7   r8   rw      r^   z,ProxyResourceManager.list_resource_templatesrn   AnyUrl | strstr | bytesc                   s   z
t  |I dH W S  tyr   |  I dH }|4 I dH E ||I dH }t|d tr@|d jW  d  I dH   Y S t|d trX|d jW  d  I dH   Y S t	dt
|d  d1 I dH sjw   Y  Y dS w )zFReads a resource, trying local/mounted first, then proxy if not found.Nr   Unsupported content type: )rD   read_resourcer   r9   
isinstancer   textr   blobr   type)r5   rn   r6   rg   rG   r7   r8   r      s(   z"ProxyResourceManager.read_resourcerh   )r2   rk   )r2   rt   )r2   r~   )r2   r   )rn   r   r2   r   )r:   r;   r<   r=   rE   rl   rv   rm   rw   r   ri   r7   r7   rG   r8   rj   {   s    

rj   c                      sL   e Zd ZdZd fddZd fd
dZdddZ	dd fddZ  ZS )ProxyPromptManagerzgA PromptManager that sources its prompts from a remote client in addition to local and mounted prompts.r1   r0   r@   r   c                   rA   rB   rC   rF   rG   r7   r8   rE      rI   zProxyPromptManager.__init__r2   dict[str, Prompt]c              
     ru   )zQGets the unfiltered prompt inventory including local, mounted, and proxy prompts.N)rD   get_promptsr9   list_promptsrO   ProxyPromptfrom_mcp_promptr   rR   rS   r   )r5   all_promptsr6   client_promptspromptrW   rG   r7   r8   r      s2   


zProxyPromptManager.get_promptslist[Prompt]c                   rZ   )zNGets the filtered list of prompts including local, mounted, and proxy prompts.N)r   r[   r\   )r5   prompts_dictr7   r7   r8   r      r^   zProxyPromptManager.list_promptsNrO   r`   ra   dict[str, Any] | Noner   c                   s   zt  ||I dH W S  tyF   |  I dH }|4 I dH  |||I dH }|W  d  I dH   Y S 1 I dH s>w   Y  Y dS w )zFRenders a prompt, trying local/mounted first, then proxy if not found.N)rD   render_promptr   r9   
get_prompt)r5   rO   ra   r6   rg   rG   r7   r8   r      s   6z ProxyPromptManager.render_promptrh   )r2   r   )r2   r   N)rO   r`   ra   r   r2   r   )	r:   r;   r<   r=   rE   r   r   r   ri   r7   r7   rG   r8   r      s    
r   c                      s>   e Zd ZdZd fddZedddZ	ddddZ  ZS )rP   zH
    A Tool that represents and executes a tool on a remote server.
    r6   r   r@   r   c                   rA   rB   rD   rE   _clientr5   r6   r@   rG   r7   r8   rE     rI   zProxyTool.__init__mcp_toolmcp.types.Toolr2   c                 C  s<   | ||j |j|j|j|j|j|jpi di dg dd	S )z@Factory method to create a ProxyTool from a raw MCP tool schema._fastmcptagsT)	r6   rO   description
parametersr   output_schemametar   	_mirrored)rO   r   inputSchemar   outputSchemar   get)clsr6   r   r7   r7   r8   rQ     s   zProxyTool.from_mcp_toolNra   rb   contextContext | Noner*   c              	     s   | j 4 I dH  | j j| j|dI dH }W d  I dH  n1 I dH s%w   Y  |jr:tttjj|j	d j
t|j	|jdS )z6Executes the tool by making a call through the client.N)rO   ra   r   rc   )r   call_tool_mcprO   isErrorr   r   mcptypesTextContentrd   r   r*   structuredContent)r5   ra   r   rg   r7   r7   r8   run  s   (zProxyTool.runr6   r   r@   r   )r6   r   r   r   r2   rP   r   )ra   rb   r   r   r2   r*   )	r:   r;   r<   r=   rE   classmethodrQ   r   ri   r7   r7   rG   r8   rP     s    rP   c                      sV   e Zd ZU dZded< dZded< ddd fd	d
ZedddZdddZ	  Z
S )ro   zO
    A Resource that represents and reads a resource from a remote server.
    r   r   Nstr | bytes | None_value)r   r6   c                  s"   t  jdi | || _|| _d S rB   )rD   rE   r   r   )r5   r6   r   r@   rG   r7   r8   rE   5  s   
zProxyResource.__init__mcp_resourcemcp.types.Resourcer2   c                 C  s<   | ||j |j|j|jpd|j|jpi di dg ddS )zHFactory method to create a ProxyResource from a raw MCP resource schema.
text/plainr   r   T)r6   rn   rO   r   	mime_typer   r   r   )rn   rO   r   mimeTyper   r   )r   r6   r   r7   r7   r8   rp   @  s   zProxyResource.from_mcp_resourcer   c              	     s   | j dur	| j S | j4 I dH  | j| jI dH }W d  I dH  n1 I dH s+w   Y  t|d tr<|d jS t|d trH|d jS t	dt
|d  )z1Read the resource content from the remote server.Nr   r   )r   r   r   rn   r   r   r   r   r   r   r   )r5   rg   r7   r7   r8   readS  s   
(

zProxyResource.read)r6   r   r   r   )r6   r   r   r   r2   ro   )r2   r   )r:   r;   r<   r=   r>   r   rE   r   rp   r   ri   r7   r7   rG   r8   ro   -  s   
 ro   c                      s>   e Zd ZdZd fddZedddZ	ddddZ  ZS )ry   za
    A ResourceTemplate that represents and creates resources from a remote server template.
    r6   r   r@   r   c                   rA   rB   r   r   rG   r7   r8   rE   g  rI   zProxyTemplate.__init__mcp_templatemcp.types.ResourceTemplater2   c                 C  s>   | ||j |j|j|jpdi |j|jpi di dg dd	S )zHFactory method to create a ProxyTemplate from a raw MCP template schema.r   r   r   T)	r6   uri_templaterO   r   r   r   r   r   r   )rx   rO   r   r   r   r   )r   r6   r   r7   r7   r8   rz   k  s   zProxyTemplate.from_mcp_templateNrn   r`   paramsrb   r   r   ro   c                   s   | j jd	i dd | D }| j4 I dH  | j|I dH }W d  I dH  n1 I dH s2w   Y  t|d trD|d j}nt|d trQ|d j	}nt
dt|d  t| j|| j| j|d j| j| jpni di dg |dS )
zACreate a resource from the template by calling the remote server.c                 S  s   i | ]\}}|t |d dqS ) )safer	   ).0kvr7   r7   r8   
<dictcomp>  s    z1ProxyTemplate.create_resource.<locals>.<dictcomp>Nr   r   r   r   )r6   rn   rO   r   r   r   r   r   r7   )r   formatitemsr   r   r   r   r   r   r   r   r   ro   rO   r   r   r   r   )r5   rn   r   r   parameterized_urirg   valuer7   r7   r8   create_resource|  s,   

(zProxyTemplate.create_resourcer   )r6   r   r   r   r2   ry   r   )rn   r`   r   rb   r   r   r2   ro   )	r:   r;   r<   r=   rE   r   rz   r   ri   r7   r7   rG   r8   ry   b  s    ry   c                      sD   e Zd ZU dZded< d fddZedd
dZdddZ  Z	S )r   zM
    A Prompt that represents and renders a prompt from a remote server.
    r   r   r6   c                   rA   rB   r   r   rG   r7   r8   rE     rI   zProxyPrompt.__init__
mcp_promptmcp.types.Promptr2   c              
   C  sF   dd |j pg D }| ||j|j||j|jpi di dg ddS )zDFactory method to create a ProxyPrompt from a raw MCP prompt schema.c                 S  s$   g | ]}t |j|j|jpd dqS )F)rO   r   required)r!   rO   r   r   )r   argr7   r7   r8   
<listcomp>  s    z/ProxyPrompt.from_mcp_prompt.<locals>.<listcomp>r   r   T)r6   rO   r   ra   r   r   r   )ra   rO   r   r   r   )r   r6   r   ra   r7   r7   r8   r     s   zProxyPrompt.from_mcp_promptra   rb   list[PromptMessage]c              	     s\   | j 4 I dH  | j | j|I dH }W d  I dH  |jS 1 I dH s&w   Y  |jS )z6Render the prompt by making a call through the client.N)r   r   rO   messages)r5   ra   rg   r7   r7   r8   render  s   zProxyPrompt.render)r6   r   )r6   r   r   r   r2   r   )ra   rb   r2   r   )
r:   r;   r<   r=   r>   rE   r   r   r   ri   r7   r7   rG   r8   r     s   
 r   c                      s,   e Zd ZdZ	d
ddd fdd	Z  ZS )FastMCPProxyz
    A FastMCP server that acts as a proxy to a remote MCP-compliant server.
    It uses specialized managers that fulfill requests via a client factory.
    Nr1   r6   Client | Noner1   ClientFactoryT | Nonec                  s   t  jdi |  dur|durtd dur/tjjr%tjdtdd  fdd}|| _	n|dur7|| _	ntdt
| j	| jjd	| _t| j	d
| _t| j	d
| _dS )a,  
        Initializes the proxy server.

        FastMCPProxy requires explicit session management via client_factory.
        Use FastMCP.as_proxy() for convenience with automatic session strategy.

        Args:
            client: [DEPRECATED] A Client instance. Use client_factory instead for explicit
                   session management. When provided, a client_factory will be automatically
                   created that provides session isolation for backwards compatibility.
            client_factory: A callable that returns a Client instance when called.
                           This gives you full control over session creation and reuse.
                           Can be either a synchronous or asynchronous function.
            **kwargs: Additional settings for the FastMCP server.
        Nz1Cannot specify both 'client' and 'client_factory'zPassing 'client' to FastMCPProxy is deprecated. Use 'client_factory' instead for explicit session management. For automatic session strategy, use FastMCP.as_proxy().   )
stacklevelc                     s      S r   )newr7   r6   r7   r8   deprecated_client_factory  s   z8FastMCPProxy.__init__.<locals>.deprecated_client_factoryzMust specify 'client_factory')r1   rL   r   r7   )rD   rE   
ValueErrorfastmcpsettingsdeprecation_warningswarningswarnDeprecationWarningr1   r?   _tool_managerrL   rj   _resource_managerr   _prompt_manager)r5   r6   r1   r@   r   rG   r   r8   rE     s.   zFastMCPProxy.__init__r   )r6   r   r1   r   )r:   r;   r<   r=   rE   ri   r7   r7   rG   r8   r     s    r   r   /RequestContext[ClientSession, LifespanContextT]r2   r   c                   s   t  }| I dH S )z
    A handler that forwards the list roots request from the remote server to the proxy's connected clients and relays the response back to the remote server.
    N)r'   
list_roots)r   ctxr7   r7   r8   default_proxy_roots_handler  s   r   c                      sZ   e Zd ZdZd# fddZed$ddZed%ddZed&ddZed'd!d"Z	  Z
S )(ProxyClientz
    A proxy client that forwards advanced interactions between a remote MCP server and the proxy's connected clients.
    Supports forwarding roots, sampling, elicitation, logging, and progress.
    	transportcClientTransportT | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | strc                   s   d|vr
|   |d< d|vrt|d< d|vrtj|d< d|vr$tj|d< d|vr-tj|d< d|vr6tj|d< t jdi |d|iB  d S )	NrO   rootssampling_handlerelicitation_handlerlog_handlerprogress_handlerr   r7   )	generate_namer   r   default_sampling_handlerdefault_elicitation_handlerdefault_log_handlerdefault_progress_handlerrD   rE   )r5   r   r@   rG   r7   r8   rE     s   



zProxyClient.__init__r   list[mcp.types.SamplingMessage]r   $mcp.types.CreateMessageRequestParamsr   r   r2   mcp.types.CreateMessageResultc                   s^   t  }|jt||j|j|j|jdI dH }t|tj	j
tj	jB r&tdtj	jdd|dS )z
        A handler that forwards the sampling request from the remote server to the proxy's connected clients and relays the response back to the remote server.
        )system_prompttemperature
max_tokensmodel_preferencesNzContent is not supported	assistantzfastmcp-client)rolemodelrd   )r'   sampler[   systemPromptr   	maxTokensmodelPreferencesr   r   r   ResourceLinkEmbeddedResourceRuntimeErrorCreateMessageResult)r   r   r   r   r   rd   r7   r7   r8   r   5  s    
z$ProxyClient.default_sampling_handlermessager`   response_typer   mcp.types.ElicitRequestParamsr   c                   s4   t  }|jj||j|jdI dH }t|j|jdS )z
        A handler that forwards the elicitation request from the remote server to the proxy's connected clients and relays the response back to the remote server.
        )r	  requestedSchemarelated_request_idN)actionrd   )r'   sessionelicitr  
request_idr   r  rd   )r   r	  r
  r   r   r   rg   r7   r7   r8   r   O  s   z'ProxyClient.default_elicitation_handlerr   Nonec                   s@   t  }|jd}|jd}|j||j|j|dI dH  dS )zw
        A handler that forwards the log notification from the remote server to the proxy's connected clients.
        msgextra)levellogger_namer  N)r'   datar   logr  logger)r   r	  r   r  r  r7   r7   r8   r   b  s
    zProxyClient.default_log_handlerprogressfloattotalfloat | None
str | Nonec                   s    t  }||||I dH  dS )z|
        A handler that forwards the progress notification from the remote server to the proxy's connected clients.
        N)r'   report_progress)r   r  r  r	  r   r7   r7   r8   r   l  s   
z$ProxyClient.default_progress_handler)r   r   )r   r   r   r   r   r   r2   r   )
r	  r`   r
  r   r   r  r   r   r2   r   )r	  r   r2   r  )r  r  r  r  r	  r  r2   r  )r:   r;   r<   r=   rE   r   r   r   r   r   ri   r7   r7   rG   r8   r     s    	r   c                      s>   e Zd ZdZd fddZdd	d
Zdd ZdddZ  ZS )StatefulProxyClienta  
    A proxy client that provides a stateful client factory for the proxy server.

    The stateful proxy client bound its copy to the server session.
    And it will be disconnected when the session is exited.

    This is useful to proxy a stateful mcp server such as the Playwright MCP server.
    Note that it is essential to ensure that the proxy server itself is also stateful.
    argsr   r@   c                   s   t  j|i | i | _d S r   )rD   rE   _caches)r5   r!  r@   rG   r7   r8   rE     rI   zStatefulProxyClient.__init__r2   r  c                   s   dS )z
        The stateful proxy client will be forced disconnected when the session is exited.
        So we do nothing here.
        Nr7   )r5   exc_type	exc_value	tracebackr7   r7   r8   	__aexit__  s    zStatefulProxyClient.__aexit__c                   s6   | j r| j  \}}|jddI dH  | j sdS dS )zE
        Clear all cached clients and force disconnect them.
        TforceN)r"  popitem_disconnect)r5   _cacher7   r7   r8   clear  s
   zStatefulProxyClient.clearClient[ClientTransportT]c                   sd   t  jjd  du r0  t  d   j<  fdd}j|  S )z
        Create a new stateful proxy client instance with the same configuration.

        Use this method as the client factory for stateful proxy server.
        Nz created for c                     s4   j  t  d  jddI d H  d S )Nz will be disconnectTr'  )r"  popr  debugr*  r7   proxy_clientr5   r  r7   r8   _on_session_exit  s   z:StatefulProxyClient.new_stateful.<locals>._on_session_exit)	r'   r  r"  r   r   r  r0  _exit_stackpush_async_callback)r5   r3  r7   r1  r8   new_stateful  s   
z StatefulProxyClient.new_stateful)r!  r   r@   r   )r2   r  )r2   r.  )	r:   r;   r<   r=   rE   r&  r-  r6  ri   r7   r7   rG   r8   r   z  s    

r   )r   r   r2   r   )^
__future__r   r3   r   collections.abcr   r   pathlibr   typingr   r   r   urllib.parser
   	mcp.typesr   r   mcp.client.sessionr   mcp.shared.contextr   r   mcp.shared.exceptionsr   r   r   r   r   pydantic.networksr   r   fastmcp.client.clientr   r   fastmcp.client.elicitationr   fastmcp.client.loggingr   fastmcp.client.rootsr   fastmcp.client.transportsr   fastmcp.exceptionsr   r   r   fastmcp.mcp_configr   fastmcp.promptsr   r    fastmcp.prompts.promptr!   fastmcp.prompts.prompt_managerr"   fastmcp.resourcesr#   r$   "fastmcp.resources.resource_managerr%   fastmcp.server.contextr&   fastmcp.server.dependenciesr'   fastmcp.server.serverr(   fastmcp.tools.toolr)   r*   fastmcp.tools.tool_managerr+   fastmcp.tools.tool_transformr,   fastmcp.utilities.componentsr-   fastmcp.utilities.loggingr.   fastmcp.serverr:   r  r0   r/   r?   rj   r   rP   ro   ry   r   r   r   r   r   r7   r7   r7   r8   <module>   sf    6S4+5=)
C
e