o
    i\                     @  s  d Z ddlmZ ddlZddlZddl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 ddlZdd	lmZ dd
lmZ ddlZddl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%m&Z& ddl'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ erddl0m1Z1 e(e2Z3ed Z4d3ddZ5e
e*dgdf Z6e
e*dgdf Z7G dd dej8Z9G dd dej8Z:ed d!G d"d# d#Z;e;e9j<d$gZ=d4d)d*Z>G d+d, d,e#Z?G d-d. d.eZ@G d/d0 d0eZAG d1d2 d2e!ZBdS )5z6FastMCP server implementation for OpenAPI integration.    )annotationsN)Counter)Callable)	dataclassfield)Pattern)TYPE_CHECKINGAnyLiteral)ToolAnnotations)AnyUrl)	ToolError)ResourceResourceTemplate)get_http_headers)FastMCP)Tool
ToolResult)openapi)
get_logger)	HTTPRoute_combine_schemas$extract_output_schema_from_responsesformat_array_parameterformat_deep_object_parameter!format_description_with_responses)Context)GETPOSTPUTPATCHDELETEOPTIONSHEADtextstr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-   \/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/fastmcp/server/openapi.py_slugify,   s   
r/   MCPTypeMCPType | Nonez7OpenAPITool | OpenAPIResource | OpenAPIResourceTemplatec                   @      e Zd ZdZdZdZdZdZdS )r0   a  Type of FastMCP component to create from a route.

    Enum values:
        TOOL: Convert the route to a callable Tool
        RESOURCE: Convert the route to a Resource (typically GET endpoints)
        RESOURCE_TEMPLATE: Convert the route to a ResourceTemplate (typically GET with path params)
        EXCLUDE: Exclude the route from being converted to any MCP component
        IGNORE: Deprecated, use EXCLUDE instead
    TOOLRESOURCERESOURCE_TEMPLATEEXCLUDEN)__name__
__module____qualname____doc__r3   r4   r5   r6   r-   r-   r-   r.   r0   N   s    
c                   @  r2   )	RouteTypez
    Deprecated: Use MCPType instead.

    This enum is kept for backward compatibility and will be removed in a future version.
    r3   r4   r5   IGNOREN)r7   r8   r9   r:   r3   r4   r5   r<   r-   r-   r-   r.   r;   a   s    r;   T)kw_onlyc                   @  s   e Zd ZU dZeddZded< eddZded< ed	dZd
ed< ee	ddidZ
ded< ed	ddidZded< ee	ddidZded< dd Zd	S )RouteMapzAMapping configuration for HTTP routes to FastMCP component types.*)defaultzlist[HttpMethod] | Literal['*']methodsz.*zPattern[str] | strpatternNzRouteType | MCPType | None
route_typedescriptionz,A set of tags to match. All tags must match.)default_factorymetadataset[str]tagsz(The type of FastMCP component to create.)r@   rF   r1   mcp_typez:A set of tags to apply to the generated FastMCP component.mcp_tagsc                 C  s   | j du rV| jdurVtjjrtjdtdd t| jt	r(tjjr(tjdtdd | jt	j
kr:tjjr:tjdtdd t| jt	rQ| jj}|dkrJd}tt|| _ n| j| _ n	| j du r_td	| jdu rj| j | _dS dS )
z8Validate and process the route map after initialization.NzThe 'route_type' parameter is deprecated and will be removed in a future version. Use 'mcp_type' instead with the appropriate MCPType value.   )
stacklevelz_The RouteType class is deprecated and will be removed in a future version. Use MCPType instead.zdRouteType.IGNORE is deprecated and will be removed in a future version. Use MCPType.EXCLUDE instead.r<   r6   z`mcp_type` must be provided)rI   rC   fastmcpsettingsdeprecation_warningswarningswarnDeprecationWarning
isinstancer;   r<   namegetattrr0   
ValueError)selfroute_type_namer-   r-   r.   __post_init__   s@   


zRouteMap.__post_init__)r7   r8   r9   r:   r   rA   __annotations__rB   rC   setrH   rI   rJ   rY   r-   r-   r-   r.   r>   n   s&   
 r>   rI   routeopenapi.HTTPRoutemappingslist[RouteMap]c              	   C  s   |D ]S}|j dks| j|j v rUt|jtr|j| j}nt|j| j}|rU|jr8t	| jp/g }|j
|s8q|jdus?J td| j d| j d|jj  |  S qttjdS )a'  
    Determines the FastMCP component type based on the route and mappings.

    Args:
        route: HTTPRoute object
        mappings: List of RouteMap objects in priority order

    Returns:
        The RouteMap that matches the route, or a catchall "Tool" RouteMap if no match is found.
    r?   NRoute  z matched mapping to r\   )rA   methodrS   rB   r   searchpathr)   rH   r[   issubsetrI   loggerdebugrT   r>   r0   r3   )r]   r_   	route_mappattern_matchesroute_tags_setr-   r-   r.   _determine_route_type   s"   rl   c                      sB   e Zd ZdZ					dd  fddZd!ddZd"ddZ  ZS )#OpenAPIToolz*Tool implementation for OpenAPI endpoints.Nclienthttpx.AsyncClientr]   r^   rT   r%   rD   
parametersdict[str, Any]output_schemadict[str, Any] | NonerH   set[str] | Nonetimeoutfloat | Noner   ToolAnnotations | None
serializerCallable[[Any], str] | Nonec              	     s6   t  j|||||pt |	|
d || _|| _|| _d S )N)rT   rD   rp   rr   rH   r   rx   )super__init__r[   _client_route_timeout)rW   rn   r]   rT   rD   rp   rr   rH   ru   r   rx   	__class__r-   r.   r{      s   	
zOpenAPITool.__init__r&   c                 C  s"   d| j d| jj d| jj dS )@Custom representation to prevent recursion errors when printing.zOpenAPITool(name=z	, method=, path=))rT   r}   rc   re   rW   r-   r-   r.   __repr__  s   "zOpenAPITool.__repr__	argumentsr   c           $        sf  i }t  }| jjr)| jjjr)tt| jjj}| jjj| }t |di  }| jjD ]!}|j	}|j	 d|j
 }|j	|v rG||j
f||< ||j
f||< q-| jj}	i }
| jjD ]8}|j
dkr|j	 d|j
 }||v r|||dur||| |
|j	< qY|j	|v r||j	dur||j	 |
|j	< qYdd | jjD }||
  }|rtd| |
 D ]E\ }t fdd	| jjD d}|rt|tr|j}|d
dk}|rt| dd}|	d  dt|}	q|	d  dt|}	qi }| jjD ]}|j
dkr|j	 d|j
 }d}||}||v r5|dur5|dkr5t|ttB r0t|dks5|| }n*||j	}|j	|v r_|dur_|dkr_t|ttB rZt|dks_||j	 }|dur|jpid}|jdurs|jnd}|dkrt|trt|dkr|rt||j	}|| qtd|j	 d t|||j	< qt|tr|jd
dkrt|dkr|r|||j	< qt||j	dd}|||j	< q|||j	< qi }i }| jjD ]H}|j
dkr+|j	 d|j
 }d}||v r	||dur	|| }n|j	|v r||j	dur||j	 }|dur+t|||j	 < q|| t }|| d}| jjr|| jjjr|t  | jjD ]}|j	|v rd |j	 d|j
  qN |j	 qNfdd| D }|r||}zX| j!j"| jj#|	|||| j$dI dH }|%  z/| }d} | j&dur| j&drd|i} n|} nt|tsd|i} n|} t'| dW W S  tj(y   t'|j)d Y W S w  t*j+y }! z;d |!j,j- d!|!j,j. }"z|!j, }#|"d"|# 7 }"W n tj(t/fy   |!j,j)r|"d"|!j,j) 7 }"Y nw t/|"|!d}!~!w t*j0y2 }! zt/d#|!|!d}!~!ww )$z:Execute the HTTP request based on the route configuration.
properties__re   Nc                 S  s"   h | ]}|j d kr|jr|jqS re   locationrequiredrT   .0pr-   r-   r.   	<setcomp>2  s
    z"OpenAPITool.run.<locals>.<setcomp>z"Missing required path parameters: c                 3  s    | ]
}|j  kr|V  qd S N)rT   r   )
param_namer-   r.   	<genexpr>?  s    z"OpenAPITool.run.<locals>.<genexpr>typearrayF)is_query_parameter{}queryr'   r   formT
deepObjectz3deepObject style with explode=false for parameter 'z5' is not standard. Using JSON serialization fallback.headerc                   s   i | ]\}}| vr||qS r-   r-   )r   kv)params_to_excluder-   r.   
<dictcomp>  s    z#OpenAPITool.run.<locals>.<dictcomp>)rc   urlparamsheadersjsonru   zx-fastmcp-wrap-resultresult)structured_content)contentHTTP error :  - Request error: )1r[   r}   request_bodycontent_schemanextitergetkeysrp   rT   r   re   r   itemsrS   listschema_r   replacer%   dictlenstyleexploder   updaterg   warningr   dumpslowerr   addr|   requestrc   r~   raise_for_statusrr   r   JSONDecodeErrorr$   httpxHTTPStatusErrorresponsestatus_codereason_phraserV   RequestError)$rW   r   param_mapping
body_propscontent_typebody_schemaparamoriginal_namesuffixed_namere   path_paramsr   required_path_paramsmissing_paramsparam_value
param_infoschemais_arrayformatted_valuequery_paramssuffixed_value
name_valueparam_styleparam_explodedeep_obj_paramsr   openapi_headersmcp_headers	json_databody_paramsr   r   structured_outputeerror_message
error_datar-   )r   r   r.   run  sJ  


























zOpenAPITool.run)NNNNN)rn   ro   r]   r^   rT   r%   rD   r%   rp   rq   rr   rs   rH   rt   ru   rv   r   rw   rx   ry   r&   r%   )r   rq   r&   r   )r7   r8   r9   r:   r{   r   r   __classcell__r-   r-   r   r.   rm      s    	
rm   c                      s>   e Zd ZdZ			dd fddZdddZdddZ  ZS )OpenAPIResourcez.Resource implementation for OpenAPI endpoints.application/jsonNrn   ro   r]   r^   urir%   rT   rD   	mime_typerH   rt   ru   rv   c	           	        s>   |d u rt  }t jt|||||d || _|| _|| _d S )N)r   rT   rD   r   rH   )r[   rz   r{   r   r|   r}   r~   )	rW   rn   r]   r   rT   rD   r   rH   ru   r   r-   r.   r{     s   
zOpenAPIResource.__init__r&   c                 C      d| j d| jd| jj dS )r   zOpenAPIResource(name=z, uri=r   r   )rT   r   r}   re   r   r-   r-   r.   r   &      zOpenAPIResource.__repr__str | bytesc                   sh  z| j j}t| j}d|v r`d|v r`|d}t|dkr`i }td|}|rK|jdd t|d }t	|D ]\}}||k rJ|d|  }	|	||< q8|
 D ]\}}	|d| dt|	}qOi }
| j jD ]&}|jd	krt| d
|j rt| d
|j }|dur|dkr||
|j< qfi }t }|| | jj| j j||
|| jdI dH }|  |jdd  d v r| }t|W S t fdddD r|jW S |jW S  t j!y } z;d|j"j# d|j"j$ }z|j" }|d| 7 }W n tj%t&fy   |j"jr|d|j"j 7 }Y nw t&||d}~w t j'y3 } zt&d||d}~ww )z2Fetch the resource data by making an HTTP request.r   r   /   z\{([^}]+)\}T)reverser   r(   Nr'   )rc   r   r   r   ru   zcontent-typer   c                 3  s    | ]}| v V  qd S r   r-   )r   ctr   r-   r.   r   l  s    z'OpenAPIResource.read.<locals>.<genexpr>)ztext/zapplication/xmlr   r   r   r   )(r}   re   r%   r   splitr   r)   findallsort	enumerater   r   rp   r   hasattrrT   rU   r   r   r|   r   rc   r~   r   r   r   r   r   r   anyr$   r   r   r   r   r   r   r   rV   r   )rW   re   resource_uripartsr   param_matchesexpected_param_countir   r   r   r   valuer   r   r   r   r   r   r   r-   r   r.   read*  sz   



	


zOpenAPIResource.read)r   NN)rn   ro   r]   r^   r   r%   rT   r%   rD   r%   r   r%   rH   rt   ru   rv   r   )r&   r   )r7   r8   r9   r:   r{   r   r  r   r-   r-   r   r.   r     s    	
r   c                      s@   e Zd ZdZ		dd fddZdddZ	d d!ddZ  ZS )"OpenAPIResourceTemplatez7Resource template implementation for OpenAPI endpoints.Nrn   ro   r]   r^   uri_templater%   rT   rD   rp   rq   rH   rt   ru   rv   c	           	        s:   |d u rt  }t j|||||d || _|| _|| _d S )N)r  rT   rD   rp   rH   )r[   rz   r{   r|   r}   r~   )	rW   rn   r]   r  rT   rD   rp   rH   ru   r   r-   r.   r{     s   
z OpenAPIResourceTemplate.__init__r&   c                 C  r   )r   zOpenAPIResourceTemplate(name=z, uri_template=r   r   )rT   r  r}   re   r   r-   r-   r.   r     r   z OpenAPIResourceTemplate.__repr__r   r   contextContext | Noner   c              
     sx   g }|  D ]\}}|| d|  qt| j| j|| j dd| | jp/d| jj dt	| jj
p6g | jdS )z,Create a resource with the given parameters.=-zResource for r   )rn   r]   r   rT   rD   r   rH   ru   )r   appendr   r|   r}   rT   joinrD   re   r[   rH   r~   )rW   r   r   r  	uri_partskeyr   r-   r-   r.   create_resource  s   z'OpenAPIResourceTemplate.create_resource)NN)rn   ro   r]   r^   r  r%   rT   r%   rD   r%   rp   rq   rH   rt   ru   rv   r   r   )r   r%   r   rq   r  r  r&   r   )r7   r8   r9   r:   r{   r   r  r   r-   r-   r   r.   r    s    

r  c                      sh   e Zd ZdZ							d+d, fddZ	d-d.ddZd/d"d#Zd0d%d&Zd0d'd(Zd0d)d*Z	  Z
S )1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_specrq   rn   ro   rT   
str | None
route_mapslist[RouteMap] | Noneroute_map_fnRouteMapFn | Nonemcp_component_fnComponentFn | None	mcp_namesdict[str, str] | NonerH   rt   ru   rv   rN   r	   c
                   s  t  jdd|pdi|
 || _|	| _|| _t t t t d| _t|}d}|p,g t	 }|D ]}t
||}|jdus?J |j}|durz|||}|durc|}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 q1|tjkr| j|||d q1|tjkr| j|||d q1|tjkrtd|j d|j  |d7 }q1t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
        rT   zOpenAPI FastMCP)toolresourceresource_templatepromptr   Nra   rb   z* mapping customized by route_map_fn: type=zError in route_map_fn for r   z. Using default values.)rH   zExcluding route: r   z$Created FastMCP OpenAPI server with z routesr-   )!rz   r{   r|   r~   _mcp_component_fnr   _used_namesr   parse_openapi_to_http_routesDEFAULT_ROUTE_MAPPINGSrl   rI   rg   rh   rc   re   rT   	Exceptionr   _generate_default_namer[   rH   rJ   r0   r3   _create_openapi_toolr4   _create_openapi_resourcer5   _create_openapi_templater6   infor   )rW   r  rn   rT   r  r  r  r  rH   ru   rN   http_routesnum_excludedr]   ri   rC   r   r   component_name
route_tagsr   r-   r.   r{     s`   %






zFastMCPOpenAPI.__init__r]   r^   mcp_names_mapr&   r%   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   r(   8   N)operation_idr   summaryrc   re   r/   r   )rW   r]   r*  rT   r-   r-   r.   r!  E  s   
z%FastMCPOpenAPI._generate_default_namecomponent_type:Literal['tool', 'resource', 'resource_template', 'prompt']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 Nr   z	. Using 'z
' instead.)r  rg   rh   )rW   rT   r.  new_namer-   r-   r.   _get_unique_name^  s   zFastMCPOpenAPI._get_unique_namerG   c              
   C  s.  t |}t|j|j|j}| |d}|jp"|jp"d|j d|j	 }t
||j|j|jd}t| j|||||t|jp;g |B | jd}	| jdurxz| ||	 td| d W n tyw }
 ztd	| d
|
 d W Y d}
~
nd}
~
ww |	j}|	| jj|< td| d|j d|j	 d|j  dS )z?Creates and registers an OpenAPITool with enhanced description.r  z	Executes rb   base_description	responsesrp   r   )rn   r]   rT   rD   rp   rr   rH   ru   NzTool  customized by component_fnzError in component_fn for tool r   . Using component as-is.zRegistered TOOL:  () with tags: )r   r   r4  schema_definitionsopenapi_versionr1  rD   r-  rc   re   r   rp   r   rm   r|   r[   rH   r~   r  rg   rh   r   r   rT   _tool_manager_tools)rW   r]   rT   rH   combined_schemarr   	tool_namer3  enhanced_descriptionr  r   final_tool_namer-   r-   r.   r"  |  sR   
 z#FastMCPOpenAPI._create_openapi_toolc              
   C  s  |  |d}d| }|jp|jpd|j }t||j|j|jd}t| 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|
< td|
 d|j d|j d|j  dS )zCCreates and registers an OpenAPIResource with enhanced description.r  resource://zRepresents r2  )rn   r]   r   rT   rD   rH   ru   Nz	Resource r5  z#Error in component_fn for resource r   r6  zRegistered RESOURCE: r7  rb   r8  )r1  rD   r-  re   r   r4  rp   r   r   r|   r[   rH   r~   r  rg   rh   r   r   r%   r   _resource_manager
_resourcesrc   )rW   r]   rT   rH   resource_namer   r3  r?  r  r   final_resource_urir-   r-   r.   r#    sD   


 z'FastMCPOpenAPI._create_openapi_resourcec              
   C  sr  |  |d}dd |jD }|  d| }|r'|dddd |D  7 }|jp2|jp2d|j }t||j|j|j	d	}d
dd |jD dd |jD d}	t
| 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|< td| d|j d|j d|j  dS )zKCreates and registers an OpenAPIResourceTemplate with enhanced description.r  c                 S  s   g | ]
}|j d kr|jqS r   )r   rT   r   r-   r-   r.   
<listcomp>  s    z;FastMCPOpenAPI._create_openapi_template.<locals>.<listcomp>rA  r   c                 s  s    | ]	}d | dV  qdS )r   r   Nr-   r   r-   r-   r.   r     s    z:FastMCPOpenAPI._create_openapi_template.<locals>.<genexpr>zTemplate for r2  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 )re   rD   )r   rT   rS   r   r   copyrD   r   r-   r-   r.   r     s    



z;FastMCPOpenAPI._create_openapi_template.<locals>.<dictcomp>c                 S  s"   g | ]}|j d kr|jr|jqS r   r   r   r-   r-   r.   rF    s    )r   r   r   )rn   r]   r  rT   rD   rp   rH   ru   Nz	Template r5  z#Error in component_fn for template r   r6  zRegistered TEMPLATE: r7  rb   r8  )r1  rp   r   r	  rD   r-  re   r   r4  r   r  r|   r[   rH   r~   r  rg   rh   r   r   r  rB  
_templatesrc   )rW   r]   rT   rH   template_namer   uri_template_strr3  r?  template_params_schematemplater   final_template_urir-   r-   r.   r$    s^   

 z'FastMCPOpenAPI._create_openapi_template)NNNNNNN)r  rq   rn   ro   rT   r  r  r  r  r  r  r  r  r  rH   rt   ru   rv   rN   r	   r   )r]   r^   r*  r  r&   r%   )rT   r%   r.  r/  r&   r%   )r]   r^   rT   r%   rH   rG   )r7   r8   r9   r:   r{   r!  r1  r"  r#  r$  r   r-   r-   r   r.   r    s     )d


>5r  )r$   r%   r&   r%   )r]   r^   r_   r`   r&   r>   )Cr:   
__future__r   enumr   r)   rP   collectionsr   collections.abcr   dataclassesr   r   r   typingr   r	   r
   r   	mcp.typesr   pydantic.networksr   rM   fastmcp.exceptionsr   fastmcp.resourcesr   r   fastmcp.server.dependenciesr   fastmcp.server.serverr   fastmcp.tools.toolr   r   fastmcp.utilitiesr   fastmcp.utilities.loggingr   fastmcp.utilities.openapir   r   r   r   r   r   fastmcp.serverr   r7   rg   
HttpMethodr/   
RouteMapFnComponentFnEnumr0   r;   r>   r3   r  rl   rm   r   r  r  r-   r-   r-   r.   <module>   sb     	
	
E
-  (y8