
    i1                       d Z ddlmZ ddlZddl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ZddlmZmZmZmZmZ ddlmZmZ dd	lmZ dd
lmZ erddlmZmZm Z m!Z! ddl"m#Z# 	 	 	 	 ddZ$ G d de      Z% G d de      Z& G d de%e&      Z' G d de      Z( G d de%e(      Z)e'e)z  Z*e&e(z  Z+e*e+z  Z, G d de      Z- G d de-      Z.	 	 	 	 	 	 	 	 ddZ/y)a  Canonical MCP Configuration Format.

This module defines the standard configuration format for Model Context Protocol (MCP) servers.
It provides a client-agnostic, extensible format that can be used across all MCP implementations.

The configuration format supports both stdio and remote (HTTP/SSE) transports, with comprehensive
field definitions for server metadata, authentication, and execution parameters.

Example configuration:
```json
{
    "mcpServers": {
        "my-server": {
            "command": "npx",
            "args": ["-y", "@my/mcp-server"],
            "env": {"API_KEY": "secret"},
            "timeout": 30000,
            "description": "My MCP server"
        }
    }
}
```
    )annotationsN)Path)TYPE_CHECKING	AnnotatedAnyLiteralcast)urlparse)AnyUrl	BaseModel
ConfigDictFieldmodel_validator)Selfoverride)ToolTransformConfig)FastMCPBaseModel)ClientTransportSSETransportStdioTransportStreamableHttpTransport)FastMCPc                    t        |       } | j                  d      st        d|        t        |       }|j                  }t        j                  d|      ryy)zB
    Infer the appropriate transport type from the given URL.
    httpzInvalid URL: z/sse(/|\?|&|$)sse)str
startswith
ValueErrorr
   pathresearch)url
parsed_urlr   s      b/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/mcp_config.pyinfer_transport_type_from_urlr%   8   sT     c(C>>&!=.//#J??D 
yy"D)    c                       e Zd ZU dZ ee      Zded<   	  edd      Zded	<    edd
      Z	ded<    e
d      e	 	 	 	 dd              Z	 	 d	 	 	 	 	 d fdZddZ xZS )_TransformingMCPServerMixinzAA mixin that enables wrapping an MCP Server with tool transforms.default_factoryzdict[str, ToolTransformConfig]toolsNz!The tags to include in the proxy.)defaultdescriptionzset[str] | Noneinclude_tagsz!The tags to exclude in the proxy.exclude_tagsbeforemodec                    t        |t              rQt        |j                  d            }|j                  d      du}|j                  d      du}|s|s|st	        d      |S )a  Reject if none of the transforming fields are set.

        This ensures that plain server configs (without tools, include_tags,
        or exclude_tags) fall through to the base server types during union
        validation, avoiding unnecessary proxy wrapping.
        r+   r.   Nr/   zFAt least one of 'tools', 'include_tags', or 'exclude_tags' is required)
isinstancedictboolgetr   )clsvalues	has_toolshas_includehas_excludes        r$   %_require_at_least_one_transform_fieldzA_TransformingMCPServerMixin._require_at_least_one_transform_field\   se     fd#VZZ01I **^4D@K **^4D@K \  r&   c                   ddl m} ddlm} ddlm} t        
|          }t        ||      } |||      } |||      }| j                  |j                  | j                  d       | j                  |j                  | j                  	       | j                  r'dd
lm}	 |j!                   |	| j                               ||fS )z_Turn the Transforming MCPServer into a FastMCP Server and also return the underlying transport.r   )Client)r   )create_proxy)	transportname)rB   T)tagsonly)rC   )ToolTransform)fastmcp.clientr?   fastmcp.client.transportsr   fastmcp.serverr@   superto_transportr	   r.   enabler/   disabler+   fastmcp.server.transformsrE   add_transform)selfserver_nameclient_namer?   r   r@   rA   clientwrapped_mcp_serverrE   	__class__s             r$   #_to_server_and_underlying_transportz?_TransformingMCPServerMixin._to_server_and_underlying_transportq   s     	*	
 	0%*W%9%;	)4	*09;*W)

 (%%4+<+<4%H(&&D,=,=&> ::?,,]4::-FG!9,,r&   c                B    ddl m}  || j                         d         S )z2Get the transport for the transforming MCP server.r   )FastMCPTransport)mcp)rG   rW   rU   )rO   rW   s     r$   rJ   z(_TransformingMCPServerMixin.to_transport   s    >D$L$L$Nq$QRRr&   r9   dict[str, Any]returnrZ   )NN)rP   
str | NonerQ   r\   r[   z$tuple[FastMCP[Any], ClientTransport])r[   r   )__name__
__module____qualname____doc__r   r5   r+   __annotations__r.   r/   r   classmethodr=   rU   rJ   __classcell__)rT   s   @r$   r(   r(   L   s    K,1$,GE)G9$)7%L/ 
 %*7%L/ 
 (##	  $* #'"&!-!-  !- 
.	!-FSr&   r(   c                      e Zd ZU dZded<    ee      Zded<    ee      Z	ded<   d	Z
d
ed<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<    ed      ZddZy)StdioMCPServerzMCP server configuration for stdio transport.

    This is the canonical configuration format for MCP servers using stdio transport.
    r   commandr)   z	list[str]argsrZ   envstdiozLiteral['stdio']rA   NzLiteral['stdio'] | Nonetyper\   cwd
int | Nonetimeoutzbool | None
keep_aliver-   icondict[str, Any] | Noneauthenticationallowextrac                    ddl m}  || j                  | j                  | j                  | j
                  | j                        S )Nr   )r   )rf   rg   rh   rk   rn   )rG   r   rf   rg   rh   rk   rn   )rO   r   s     r$   rJ   zStdioMCPServer.to_transport   s5    <LL
 	
r&   )r[   r   )r]   r^   r_   r`   ra   r   listrg   r5   rh   rA   rj   rk   rm   rn   r-   ro   rq   r   model_configrJ    r&   r$   re   re      s     L D1D)15C5 #*I)$(D
!( CGZ  
 #K"D* -1N)0G,L	
r&   re   c                      e Zd ZdZy)TransformingStdioMCPServerz$A Stdio server with tool transforms.Nr]   r^   r_   r`   rx   r&   r$   rz   rz      s    .r&   rz   c                      e Zd ZU dZded<   dZded<    ee      Zded	<   dZ	d
ed<   dZ
ded<   dZded<   dZded<   dZded<   dZded<    edd      ZddZy)RemoteMCPServerzMCP server configuration for HTTP/SSE transport.

    This is the canonical configuration format for MCP servers using remote transports.
    r   r"   Nz0Literal['http', 'streamable-http', 'sse'] | NonerA   r)   zdict[str, str]headerszAnnotated[str | Literal['oauth'] | httpx.Auth | None, Field(description='Either a string representing a Bearer token, the literal "oauth" to use OAuth authentication, or an httpx.Auth instance for custom authentication.')]authz'datetime.timedelta | int | float | Nonesse_read_timeoutrl   rm   r\   r-   ro   rp   rq   rr   T)rt   arbitrary_types_allowedc                H   ddl m}m} | j                  t	        | j
                        }n| j                  }|dk(  r4 || j
                  | j                  | j                  | j                        S  || j
                  | j                  | j                  | j                        S )Nr   )r   r   r   )r~   r   r   )	rG   r   r   rA   r%   r"   r~   r   r   )rO   r   r   rA   s       r$   rJ   zRemoteMCPServer.to_transport   s    S>>!5dhh?IIYY!%!6!6	  +YY!%!6!6	 r&   )r[   z&StreamableHttpTransport | SSETransport)r]   r^   r_   r`   ra   rA   r   r5   r~   r   r   rm   r-   ro   rq   r   rw   rJ   rx   r&   r$   r}   r}      s     
H CGI?F#D9G^9 	 	   AE=DGZ #K"D* -1N)0tLr&   r}   c                      e Zd ZdZy)TransformingRemoteMCPServerz%A Remote server with tool transforms.Nr{   rx   r&   r$   r   r   	  s    /r&   r   c                      e Zd ZU dZ ee      Zded<    ed      Z	 e
d      edd	              Zdd
Zedd       ZddZddZedd       Zy)	MCPConfiga8  A configuration object for MCP Servers that conforms to the canonical MCP configuration format
    while adding additional fields for enabling FastMCP-specific features like tool transformations
    and filtering by tags.

    For an MCPConfig that is strictly canonical, see the `CanonicalMCPConfig` class.
    r)   zdict[str, MCPServerTypes]
mcpServersrr   rs   r0   r1   c                Z    d|vr&t        d |j                         D              }|rd|iS |S )zMIf there's no mcpServers key but there are server configs at root, wrap them.r   c              3  T   K   | ]   }t        |t              xr
 d |v xs d|v  " yw)rf   r"   N)r4   r5   ).0vs     r$   	<genexpr>z1MCPConfig.wrap_servers_at_root.<locals>.<genexpr>&  s4      (A 1d#Fa)E5A:F(s   &()anyr9   )r8   r9   has_serverss      r$   wrap_servers_at_rootzMCPConfig.wrap_servers_at_root   s>     v%  K $f--r&   c                "    || j                   |<   yz,Add or update a server in the configuration.Nr   rO   rB   servers      r$   
add_serverzMCPConfig.add_server/  s     &r&   c                $    | j                  |      S )z/Parse MCP configuration from dictionary format.)model_validate)r8   configs     r$   	from_dictzMCPConfig.from_dict3  s     !!&))r&   c                &    | j                  d      S )z>Convert MCPConfig to dictionary format, preserving all fields.Texclude_none)
model_dump)rO   s    r$   to_dictzMCPConfig.to_dict8  s    D11r&   c                    |j                   j                  dd       |j                  | j                  d             y)z!Write configuration to JSON file.T)parentsexist_ok   )indentN)parentmkdir
write_textmodel_dump_json)rO   	file_paths     r$   write_to_filezMCPConfig.write_to_file<  s7    td;T111;<r&   c                    |j                         r1|j                         j                         x}r| j                  |      S t	        d|       )z"Load configuration from JSON file.z&No MCP servers defined in the config: )exists	read_textstripmodel_validate_jsonr   )r8   r   contents      r$   	from_filezMCPConfig.from_fileA  sP     i.A.A.C.I.I.K#K7#K**733A)MNNr&   NrY   )rB   r   r   MCPServerTypesr[   None)r   rZ   r[   r   )r[   rZ   )r   r   r[   r   )r   r   r[   r   )r]   r^   r_   r`   r   r5   r   ra   r   rw   r   rb   r   r   r   r   r   r   rx   r&   r$   r   r     s{     -2$,GJ)GG,L(#  $' * *2=
 O Or&   r   c                  @    e Zd ZU dZ ee      Zded<   edd       Z	y)CanonicalMCPConfigzCanonical MCP configuration format.

    This defines the standard configuration format for Model Context Protocol servers.
    The format is designed to be client-agnostic and extensible for future use cases.
    r)   z"dict[str, CanonicalMCPServerTypes]r   c                "    || j                   |<   yr   r   r   s      r$   r   zCanonicalMCPConfig.add_serverS  s     !'r&   N)rB   r   r   CanonicalMCPServerTypesr[   r   )
r]   r^   r_   r`   r   r5   r   ra   r   r   rx   r&   r$   r   r   J  s+     6;45PJ2P' 'r&   r   c                B   t         j                  |       }|j                  j                  |      x}rJ|j	                         }|j	                  d      }|j                  i ||      }|j                  ||       n|j                  ||       |j                  |        y)zUpdate an MCP configuration file from a server object, preserving existing fields.

    This is used for updating the mcpServer configurations of third-party tools so we do not
    worry about transforming server objects here.Tr   N)r   r   r   r7   r   r   r   r   )r   rP   server_configr   existing_serverexisting_dictnew_dictmerged_configs           r$   update_config_filer   Y  s       +F !++//<<<'224 +++> &445R5R5RS+}5+}5
#r&   )r"   zstr | AnyUrlr[   zLiteral['http', 'sse'])r   r   rP   r   r   r   r[   r   )0r`   
__future__r   datetimer    pathlibr   typingr   r   r   r   r	   urllib.parser
   httpxpydanticr   r   r   r   r   typing_extensionsr   r   fastmcp.tools.tool_transformr   fastmcp.utilities.typesr   rG   r   r   r   r   fastmcp.server.serverr   r%   r(   re   rz   r}   r   TransformingMCPServerTypesr   r   r   r   r   rx   r&   r$   <module>r      s  0 #  	  ? ? !   - < 4  .	(LS"2 LS^*
Y *
Z/!<n /:i :z0"= 0 8:UU (?: +.EE3O	 3Ol' '$$$ +$ 
	$r&   