o
    i>                     @   s   d Z ddlZddlmZ ddlmZmZ ddl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mZ dd	lmZ d
dlmZmZmZ d
dlmZmZmZmZmZmZ ee Z!de"de"fddZ#G dd deZ$dgZ%dS )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                 C   s@   | sdS t dd| }t dd|}t dd|}|d}|S )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   slug r   p/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/fastmcp/experimental/server/openapi/server.py_slugify&   s   
r!   c                       s  e Zd ZdZ							ddeeef dejdedB de	e
 dB dedB dedB d	eeef dB d
ee dB dedB def fddZ	ddedeeef dB defddZdeded defddZdeded
ee fddZdeded
ee fddZdeded
ee fddZ  ZS ) FastMCPOpenAPIa  
    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
                    s  t  jdd|pdi|
 || _|	| _|| _t t t t d| _zt|| _	t
| j	| _W n tyL } ztd|  td| |d}~ww t|}|pTg t }|D ]}t||}|j}|durz|||}|dur|}td|j d|j d	|j  W n# ty } ztd
|j d|j d| d W Y d}~nd}~ww | ||}t|j|jB |pt B }|tjkr| j|||d qY|tj kr| j!|||d qY|tj"kr| j#|||d qY|tj$krtd|j d|j  qYtdt%| d dS )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 routesr   )&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+   r,   ehttp_routesroute	route_map
route_typeresultcomponent_name
route_tags	__class__r   r    r5   c   sf   %





zFastMCPOpenAPI.__init__rT   mcp_names_mapr   c                 C   sv   d}|pi }|j r|j |v r||j  }n|j dd }n|jp(|j d|j }t|}t|dkr9|dd }|S )zEGenerate a default name from the route using the configured strategy.r   __r   r   8   N)operation_idsplitsummaryrC   rD   r!   rP   )rQ   rT   r\   r%   r   r   r    rF      s   
z%FastMCPOpenAPI._generate_default_namecomponent_typer-   c              	   C   sn   | j | |  d7  < | j | | dkr|S | d| j | |  }td| d|dd  d| d |S )	a4  
        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.)r9   r>   rB   )rQ   r%   rb   new_namer   r   r    _get_unique_name   s   zFastMCPOpenAPI._get_unique_namec                 C   s  |j }t|j|j|j}| |d}|jp!|jp!d|j d|j	 }t
||j|jd}t| j|| j||||t|jp:g |B | jd	}	| jdurwz| ||	 td| d W n tyv }
 ztd	| d
|
 d W Y d}
~
nd}
~
ww |	j}|	| jj|< dS )z?Creates and registers an OpenAPITool with enhanced description.r.   z	Executes r2   base_description
parametersrequest_body)	r$   rT   directorr%   descriptionrh   output_schemar*   r+   NzTool  customized by component_fnzError in component_fn for tool r3   . Using component as-is.)flat_param_schemar   	responsesresponse_schemasopenapi_versionre   rk   ra   rC   rD   r   rh   ri   r   r6   r<   rG   r*   r7   r8   r>   rB   r=   rE   r%   _tool_manager_tools)rQ   rT   r%   r*   combined_schemarl   	tool_namerg   enhanced_descriptionr.   rR   final_tool_namer   r   r    rJ      sP   
z#FastMCPOpenAPI._create_openapi_toolc              
   C   s   |  |d}d| }|jp|jpd|j }t||j|jd}t| j|| j	|||t
|jp.g |B | jd}| jdurkz| || td| d W n tyj }	 ztd	| d
|	 d W Y d}	~	nd}	~	ww t|j}
|| jj|
< dS )zCCreates and registers an OpenAPIResource with enhanced description.r/   resource://zRepresents rf   )r$   rT   rj   urir%   rk   r*   r+   Nz	Resource rm   z#Error in component_fn for resource r3   rn   )re   rk   ra   rD   r   rh   ri   r   r6   r<   rG   r*   r7   r8   r>   rB   r=   rE   strrz   _resource_manager
_resources)rQ   rT   r%   r*   resource_nameresource_urirg   rw   r/   rR   final_resource_urir   r   r    rL   >  s>   


z'FastMCPOpenAPI._create_openapi_resourcec                 C   sJ  |  |d}dd |jD }|  d| }|r'|dddd |D  7 }|jp2|jp2d|j }t||j|jd	}d
dd |jD dd |jD d}	t	| j
|| j||||	t|jp]g |B | jd	}
| jdurz| ||
 td| d W n ty } ztd| d| d W Y d}~nd}~ww |
j}|
| jj|< dS )zKCreates and registers an OpenAPIResourceTemplate with enhanced description.r0   c                 S   s   g | ]
}|j d kr|jqS rD   )locationr%   .0pr   r   r    
<listcomp>z  s    z;FastMCPOpenAPI._create_openapi_template.<locals>.<listcomp>ry   /c                 s   s    | ]	}d | dV  qdS ){}Nr   r   r   r   r    	<genexpr>  s    z:FastMCPOpenAPI._create_openapi_template.<locals>.<genexpr>zTemplate for rf   objectc                 S   sb   i | ]-}|j d kr|ji t|jtr|j ni |jr,t|jtr'd|jv s,d|jini qS )rD   rk   )r   r%   
isinstanceschema_dictcopyrk   r   r   r   r    
<dictcomp>  s    



z;FastMCPOpenAPI._create_openapi_template.<locals>.<dictcomp>c                 S   s"   g | ]}|j d kr|jr|jqS r   )r   requiredr%   r   r   r   r    r     s    )type
propertiesr   )	r$   rT   rj   uri_templater%   rk   rh   r*   r+   Nz	Template rm   z#Error in component_fn for template r3   rn   )re   rh   sortjoinrk   ra   rD   r   ri   r   r6   r<   rG   r*   r7   r8   r>   rB   r=   rE   r   r|   
_templates)rQ   rT   r%   r*   template_namepath_paramsuri_template_strrg   rw   template_params_schematemplaterR   final_template_urir   r   r    rN   p  sX   

z'FastMCPOpenAPI._create_openapi_template)NNNNNNN)N)__name__
__module____qualname____doc__r   r{   r   httpxAsyncClientlistr   r   r   rG   floatr5   r   rF   r   re   rJ   rL   rN   __classcell__r   r   rZ   r    r"   =   s    )


	
g


>
2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   r>   r{   r!   r"   __all__r   r   r   r    <module>   s(     	   