
    k7i>                         S r SSKrSSKJr  SSKJrJr  SSKrSSKJ	r	  SSK
JrJrJrJr  SSKJr  SSKJr  SS	KJr  S
SKJrJrJr  S
SKJrJrJrJrJrJr  \" \ 5      r!S\"S\"4S jr# " S S\5      r$S/r%g)z6FastMCP server implementation for OpenAPI integration.    N)Counter)AnyLiteral)
SchemaPath)	HTTPRoute$extract_output_schema_from_responsesformat_simple_descriptionparse_openapi_to_http_routes)RequestDirector)FastMCP)
get_logger   )OpenAPIResourceOpenAPIResourceTemplateOpenAPITool)DEFAULT_ROUTE_MAPPINGSComponentFnMCPTypeRouteMap
RouteMapFn_determine_route_typetextreturnc                     U (       d  g[         R                  " SSU 5      n[         R                  " SSU5      n[         R                  " SSU5      nUR                  S5      nU$ )z
Convert text to a URL-friendly slug format that only contains lowercase
letters, uppercase letters, numbers, and underscores.
 z	[\s\-\.]+_z[^a-zA-Z0-9_]z_+)resubstrip)r   slugs     d/home/james-whalen/.local/lib/python3.13/site-packages/fastmcp/experimental/server/openapi/server.py_slugifyr"   &   s[    
  66,T*D 66"B-D 66%d#D ::c?DK    c                   d  ^  \ rS rSrSr       SS\\\4   S\R                  S\S-  S\
\   S-  S\S-  S	\S-  S
\\\4   S-  S\\   S-  S\S-  S\4U 4S jjjr SS\S\\\4   S-  S\4S jjrS\S\S   S\4S jrS\S\S\\   4S jrS\S\S\\   4S jrS\S\S\\   4S jrSrU =r$ )FastMCPOpenAPI=   a
  
FastMCP server implementation that creates components from an OpenAPI schema.

This class parses an OpenAPI specification and creates appropriate FastMCP components
(Tools, Resources, ResourceTemplates) based on route mappings.

Example:
    ```python
    from fastmcp.server.openapi import FastMCPOpenAPI, RouteMap, MCPType
    import httpx

    # Define custom route mappings
    custom_mappings = [
        # Map all user-related endpoints to ResourceTemplate
        RouteMap(
            methods=["GET", "POST", "PATCH"],
            pattern=r".*/users/.*",
            mcp_type=MCPType.RESOURCE_TEMPLATE
        ),
        # Map all analytics endpoints to Tool
        RouteMap(
            methods=["GET"],
            pattern=r".*/analytics/.*",
            mcp_type=MCPType.TOOL
        ),
    ]

    # Create server with custom mappings and route mapper
    server = FastMCPOpenAPI(
        openapi_spec=spec,
        client=httpx.AsyncClient(),
        name="API Server",
        route_maps=custom_mappings,
    )
    ```
Nopenapi_specclientname
route_mapsroute_map_fnmcp_component_fn	mcp_namestagstimeoutsettingsc
                   > [         TU ]  " SSU=(       d    S0U
D6  X l        Xl        X`l        [        5       [        5       [        5       [        5       S.U l         [        R                  " U5      U l	        [        U R                  5      U l        [!        U5      nU=(       d    / ["        -   nU GHk  n[%        X5      nUR&                  nUbJ   U" X5      nUb>  Un[        R)                  SUR*                   SUR,                   S	UR.                   35        U R3                  X5      n[5        UR6                  5      UR8                  -  U=(       d
    [5        5       -  nU[:        R<                  :X  a  U R?                  UUUS9  M  U[:        R@                  :X  a  U RC                  UUUS9  M  U[:        RD                  :X  a  U RG                  UUUS9  GM%  U[:        RH                  :X  d  GM<  [        R)                  SUR*                   SUR,                   35        GMn     [        R)                  S[K        U5       S35        g! [         a,  n[        R                  SU 35        [        SU 35      UeSnAff = f! [         a>  n[        R1                  S
UR*                   SUR,                   SU S35         SnAGNSnAff = f)a  
Initialize a FastMCP server from an OpenAPI schema.

Args:
    openapi_spec: OpenAPI schema as a dictionary or file path
    client: httpx AsyncClient for making HTTP requests
    name: Optional name for the server
    route_maps: Optional list of RouteMap objects defining route mappings
    route_map_fn: Optional callable for advanced route type mapping.
        Receives (route, mcp_type) and returns MCPType or None.
        Called on every route, including excluded ones.
    mcp_component_fn: Optional callable for component customization.
        Receives (route, component) and can modify the component in-place.
        Called on every created component.
    mcp_names: Optional dictionary mapping operationId to desired component names.
        If an operationId is not in the dictionary, falls back to using the
        operationId up to the first double underscore. If no operationId exists,
        falls back to slugified summary or path-based naming.
        All names are truncated to 56 characters maximum.
    tags: Optional set of tags to add to all components. Components always receive any tags
        from the route.
    timeout: Optional timeout (in seconds) for all requests
    **settings: Additional settings for FastMCP
r)   zOpenAPI FastMCPtoolresourceresource_templatepromptz&Failed to initialize RequestDirector: zInvalid OpenAPI specification: NzRoute  z* mapping customized by route_map_fn: type=zError in route_map_fn for : z. Using default values.)r.   zExcluding route: z$Created FastMCP OpenAPI server with z routes )&super__init___client_timeout_mcp_component_fnr   _used_namesr   	from_dict_specr   	_director	Exceptionloggererror
ValueErrorr
   r   r   mcp_typedebugmethodpathr)   warning_generate_default_namesetr.   mcp_tagsr   TOOL_create_openapi_toolRESOURCE_create_openapi_resourceRESOURCE_TEMPLATE_create_openapi_templateEXCLUDElen)selfr'   r(   r)   r*   r+   r,   r-   r.   r/   r0   ehttp_routesroute	route_map
route_typeresultcomponent_name
route_tags	__class__s                      r!   r;   FastMCPOpenAPI.__init__c   s   J 	Dd7&7D8D!1 I	!(i	
	K#--l;DJ,TZZ8DN
 3<@ !&B*@@
 E-e@I"++J ')%<F)%+
$U\\N!EJJ< @$$.OO#46 "88JNUZZ9+=+==OJ W\\)))%j)Qw///--e^*-Uw888--e^*-Uw.0a

|LMG !J 	;C<L;MWUV[  	KLLA!EF>qcBCJ	K0 ! NN4U\\N!EJJ<rRSQT U0 1 s1   5I A	I<
I9'I44I9<
K3J??KrZ   mcp_names_mapr   c                 X   SnU=(       d    0 nUR                   (       a>  UR                   U;   a  X!R                      nOMUR                   R                  S5      S   nO.UR                  =(       d    UR                   SUR                   3n[        U5      n[        U5      S:  a  USS nU$ )zEGenerate a default name from the route using the configured strategy.r   __r   r   8   N)operation_idsplitsummaryrI   rJ   r"   rV   )rW   rZ   rb   r)   s       r!   rL   %FastMCPOpenAPI._generate_default_name   s     %+ !!]2$%7%78 ))//5a8==Bu||nAejj\$BD~ t9r>9Dr#   component_typer2   c           	          U R                   U   U==   S-  ss'   U R                   U   U   S:X  a  U$ U SU R                   U   U    3n[        R                  SU SUSS  SU S35        U$ )	z
Ensure the name is unique within its component type by appending numbers if needed.

Args:
    name: The proposed name
    component_type: The type of component ("tools", "resources", or "templates")

Returns:
    str: A unique name for the component
r   r   zName collision detected: 'z' already exists as a Nz	. Using 'z
' instead.)r?   rD   rH   )rW   r)   rj   new_names       r!   _get_unique_nameFastMCPOpenAPI._get_unique_name   s      	(.!3.N+D1Q6K q!1!1.!A$!G HIHLL,TF2HX[Y[I\H] ^":/
 r#   c                    UR                   n[        UR                  UR                  UR                  5      nU R                  US5      nUR                  =(       d/    UR                  =(       d    SUR                   SUR                   3n[        UUR                  UR                  S9n[        U R                  UU R                  UUUU[!        UR"                  =(       d    / 5      U-  U R$                  S9	n	U R&                  b+   U R'                  X5        [(        R+                  SU S35        U	R0                  nXR2                  R4                  U'   g! [,         a&  n
[(        R/                  S	U S
U
 S35         Sn
A
NPSn
A
ff = f)z?Creates and registers an OpenAPITool with enhanced description.r3   z	Executes r7   base_description
parametersrequest_body)	r(   rZ   directorr)   descriptionrs   output_schemar.   r/   NzTool  customized by component_fnzError in component_fn for tool r8   . Using component as-is.)flat_param_schemar   	responsesresponse_schemasopenapi_versionrn   rv   rh   rI   rJ   r	   rs   rt   r   r<   rB   rM   r.   r=   r>   rD   rH   rC   rK   r)   _tool_manager_tools)rW   rZ   r)   r.   combined_schemarw   	tool_namerr   enhanced_descriptionr3   rX   final_tool_names               r!   rP   #FastMCPOpenAPI._create_openapi_tool   s|     11 =OO""!!
 ))$7	  7}}75<<.%**6 	  9-''++ 
 <<^^,&'UZZ%2&-MM

 !!-&&u3uYK/JKL )) 6:!!/2  5i[1# F- . s   *E 
F FFc                    U R                  US5      nSU 3nUR                  =(       d"    UR                  =(       d    SUR                   3n[	        UUR
                  UR                  S9n[        U R                  UU R                  UUU[        UR                  =(       d    / 5      U-  U R                  S9nU R                  b+   U R                  X5        [        R                  SU S35        [%        UR&                  5      n
XR(                  R*                  U
'   g! [          a&  n	[        R#                  S	U S
U	 S35         Sn	A	NYSn	A	ff = f)zCCreates and registers an OpenAPIResource with enhanced description.r4   resource://zRepresents rq   )r(   rZ   ru   urir)   rv   r.   r/   Nz	Resource rx   z#Error in component_fn for resource r8   ry   )rn   rv   rh   rJ   r	   rs   rt   r   r<   rB   rM   r.   r=   r>   rD   rH   rC   rK   strr   _resource_manager
_resources)rW   rZ   r)   r.   resource_nameresource_urirr   r   r4   rX   final_resource_uris              r!   rR   'FastMCPOpenAPI._create_openapi_resource>  sJ    --dJ?$]O4LLK

|2L 	
  9-''++ 
 #<<^^,UZZ%2&-MM	
 !!-&&u7y6QRS !. AI))*<=  9,r! M- . s   *D 
E)E

Ec                    U R                  US5      nUR                   Vs/ s H   oUR                  S:X  d  M  UR                  PM"     nnUR	                  5         SU 3nU(       a  USSR                  S U 5       5      -   -  nUR                  =(       d"    UR                  =(       d    SUR                   3n[        UUR                  UR                  S9n	SUR                   Vs0 s H  nUR                  S:X  d  M  UR                  0 [        UR                  [        5      (       a  UR                  R                  5       O0 EUR                  (       a=  [        UR                  [        5      (       a  S	UR                  ;   d  S	UR                  0O0 E_M     snUR                   Vs/ s H3  oUR                  S:X  d  M  UR                  (       d  M'  UR                  PM5     snS
.n
[!        U R"                  UU R$                  UUU	U
['        UR(                  =(       d    / 5      U-  U R*                  S9	nU R,                  b+   U R-                  X5        [.        R1                  SU S35        UR6                  nXR8                  R:                  U'   gs  snf s  snf s  snf ! [2         a&  n[.        R5                  SU SU S35         SnAN_SnAff = f)zKCreates and registers an OpenAPIResourceTemplate with enhanced description.r5   rJ   r   /c              3   .   #    U  H  nS U S3v   M     g7f){}Nr9   ).0ps     r!   	<genexpr>:FastMCPOpenAPI._create_openapi_template.<locals>.<genexpr>  s     .O;aA3bz;s   zTemplate for rq   objectrv   )type
propertiesrequired)	r(   rZ   ru   uri_templater)   rv   rs   r.   r/   Nz	Template rx   z#Error in component_fn for template r8   ry   )rn   rs   locationr)   sortjoinrv   rh   rJ   r	   rt   
isinstanceschema_dictcopyr   r   r<   rB   rM   r.   r=   r>   rD   rH   rC   rK   r   r   
_templates)rW   rZ   r)   r.   template_namer   path_paramsuri_template_strrr   r   template_params_schematemplaterX   final_template_uris                 r!   rT   'FastMCPOpenAPI._create_openapi_templatep  s    --d4GH','7'7P'7!::;Ovqvv'7P(8chh.O;.O&O OO NNM%**2N 	
  9-''++ 
  )) *A::'
 
+5aii+F+Fqyy~~'B
 ==&qyy$77MQYY<V '6
  
 
 *  !& 0 0 01JJ&4HQZZ 0#"
, +<<^^),-UZZ%2&-MM

 !!-&&u7y)9(::UVW &22 AI))*<=G Q(,  9:J9K2aS Q- . sA   JJ'J?BJ+JJJ*J$ $
K.KK)r<   rB   r>   rA   r=   r?   )NNNNNNN)N)__name__
__module____qualname____firstlineno____doc__r   r   r   httpxAsyncClientlistr   r   r   rM   floatr;   r   rL   r   rn   rP   rR   rT   __static_attributes____classcell__)r`   s   @r!   r%   r%   =   s   #R  ,0*./3+/ $ $dW38ndW !!dW Dj	dW
 NT)dW !4'dW &,dW S>D(dW #hodW dW dW dWN HL/3CH~/D	2   QR 
	<<:<: <: #h	<:|0I0I 0I #h	0IdMIMI MI #h	MI MIr#   r%   )&r   r   collectionsr   typingr   r   r   jsonschema_pathr   &fastmcp.experimental.utilities.openapir   r   r	   r
   /fastmcp.experimental.utilities.openapi.directorr   fastmcp.server.serverr   fastmcp.utilities.loggingr   
componentsr   r   r   routingr   r   r   r   r   r   r   rD   r   r"   r%   __all__r9   r#   r!   <module>r      s}    < 	    &  L ) 0 
  
H	3 3 .@IW @IJ r#   