o
    W+ i.                     @   s   d 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
mZ e ZdZG dd	 d	eZG d
d deZG dd deZG dd deZdS )z
MCP (Model Context Protocol) API interface for ModelScope Hub.

This module provides a simple interface to interact with
ModelScope MCP plaza (https://www.modelscope.cn/mcp).
    )AnyDictOptionalN)HubApi)raise_for_http_status)
get_loggerz/openapi/v1/mcp/serversc                   @      e Zd ZdZdS )MCPApiErrorz"Base exception for MCP API errors.N__name__
__module____qualname____doc__ r   r   b/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/modelscope/hub/mcp_api.pyr	          r	   c                   @   r   )MCPApiRequestErrorz,Exception raised when MCP API request fails.Nr
   r   r   r   r   r      r   r   c                   @   r   )MCPApiResponseErrorz2Exception raised when MCP API response is invalid.Nr
   r   r   r   r   r   !   r   r   c                       s   e Zd ZdZddee ddf fddZedej	de
eef fdd	Zed
edefddZ				ddee dee
eef  dee dee de
eef f
ddZ	ddede
eef fddZ	dd
edee de
eef fddZ  ZS )MCPApiaU  
    MCP (Model Context Protocol) API interface class.

    This class provides interfaces to interact with ModelScope MCP servers,
    such as to list, deploy and manage MCP servers.

    Note: MCPApi inherits login() from HubApi for authentication.
    Different methods have different token requirements - see individual method docs.
    Nendpointreturnc                    s   t  j|d | jt | _dS )z
        Initialize MCP API.

        Args:
            endpoint: The modelscope server address. Defaults to None (uses default endpoint).
        )r   N)super__init__r   MCP_API_PATHmcp_base_url)selfr   	__class__r   r   r   1   s   zMCPApi.__init__rc              
   C   sh   z|   }W n' tjjy- } ztd|  td| j  td| |d}~ww |di S )a  
        Handle HTTP response with unified error handling and JSON parsing.

        Args:
            r: requests Response object

        Returns:
            Parsed response data dict

        Raises:
            MCPApiResponseError: If JSON parsing fails
        zJSON parsing failed: zResponse content: zInvalid JSON response: Ndata)	jsonrequests
exceptionsJSONDecodeErrorloggererrortextr   get)r   resper   r   r   _handle_response<   s   zMCPApi._handle_response	server_idc                 C   s   d| v r|  ddd S | S )z#Extract server name from server ID./   )split)r+   r   r   r   _get_server_name_from_idS   s   zMCPApi._get_server_name_from_id    tokenfiltertotal_countsearchc              
   C   s   |du s|dk s|dkrt d|pi d||d}z| |}| jj| j| | j||d}t| W n tj	j
yO } ztd| td| |d}~ww | |}	|	d	g }
d
d |
D }|	dd|dS )a  
        List available MCP servers, if (optional) token is presented, this would return private MCP servers as well.

        Args:
            token: Optional access token for authentication
            filter: Optional filters to apply to the search
                - 'category': str, server category, e.g. 'communication'
                - 'tag': str, server tag, e.g. 'social-media'
                - 'is_hosted': bool, server is hosted
                When all three are passed in, the intersection is taken.
            total_count: Number of servers to return, max 100, default 20
            search: Optional search query string,e.g. Chinese service name, English service name, author/owner username
            You can combine `filter` and `search` to retrieve desired MCP servers.

        Returns:
            Dict containing:
                - total_count: Total number of servers
                - servers: List of server dictionaries with name, id, description

        Raises:
            MCPApiRequestError: If API request fails (network, server errors)
            MCPApiResponseError: If response format is invalid or JSON parsing fails

        Authentication:
            Optional, only required if you wish to retrieve private MCP servers.
            You may leverage the token parameter for one-time authentication, or use api.login()

        Returns:
            {
                'total_count': 20,
                'servers': [
                    {'name': 'ServerA', 'id': '@demo/ServerA', 'description': 'This is a demo server for xxx.'},
                    {'name': 'ServerB', 'id': '@demo/ServerB', 'description': 'This is another demo server.'},
                    ...
                ]
            }
        Nr-   d   z%total_count must be between 1 and 100)r3   Zpage_numberZ	page_sizer5   )urlheadersr    cookieszFailed to get MCP servers: %szFailed to get MCP servers: mcp_server_listc                 S   s0   g | ]}| d d| dd| dddqS )namer1   iddescription)r;   r<   r=   )r'   ).0itemr   r   r   
<listcomp>   s    



z+MCPApi.list_mcp_servers.<locals>.<listcomp>r4   r   r4   servers)
ValueErrorget_cookiessessionputr   builder_headersr8   r   r!   r"   RequestExceptionr$   r%   r   r*   r'   )r   r2   r3   r4   r5   bodyr9   r   r)   r   r:   mcp_config_listr   r   r   list_mcp_serversZ   s:   +



zMCPApi.list_mcp_serversc              
   C   sN  | j  d}| | j}z| j|dd}| jj|||d}t| W n tjj	y@ } zt
d|  td| |d}~ww t
d|j  | |}|dg }g }	|D ]D}
i }|
d	d
|d	< |
dd
|d< |
dd
|d< g |d< |
dg D ]}|d |ddd |dd
d q|	| qY|dd|	dS )aQ  
        Get list of operational MCP servers that have been triggered hosting service by the user.

        Returns:
            Dict containing:
                - total_counts: Total number of operational servers
                - servers: List of server info with name, id, description

        Raises:
            MCPApiRequestError: If authentication fails or API request fails
            MCPApiResponseError: If response format is invalid or JSON parsing fails

        Returns:
            {
                'total_count': 10,
                'servers': [
                    {
                        'name': 'ServerA',
                        "id": "@Group1/ServerA",
                        'description': 'This is a demo server for xxx.'
                        'mcp_servers': [
                            {
                                'type': 'sse',
                                'url': 'https://mcp.api-inference.modelscope.net/{uuid}/sse'
                            },
                            {
                                'type': 'streamable_http',
                                'url': 'https://mcp.api-inference.modelscope.net/{uuid}/streamable_http'
                            },
                            ...
                        ]
                    },
                    ...
                ]
            }
        z/operationalT)Zaccess_tokenZcookies_required)r8   r9   z'Failed to get operational MCP servers: NzResponse status code: r:   r;   r1   r<   r=   Zmcp_serversoperational_urlsr7   r,   typer7   r4   r   rA   )r   rG   r8   rD   rE   r'   r   r!   r"   rH   r$   r%   r   debugstatus_coder*   appendr.   )r   r2   r7   r8   r9   r   r)   r   r:   rJ   r?   
mcp_configoperational_urlr   r   r   list_operational_mcp_servers   sH   &



z#MCPApi.list_operational_mcp_serversc              
   C   s>  |st d| j d| }| | j}z| |}| jj||ddi|d}t| W n$ tj	j
yO } ztd| d|  td| d| |d}~ww | |}|d	d
|dd
|dd
d}	|dd
}t|}
|dg }g }|
r|r|D ]}|ddd |dd
d}|| q||	d< |	S )aU  
        Get detailed information for a specific MCP Server,
        a valid token shall be provided if the MCP server is private.

        Args:
            server_id: MCP server ID (e.g., "@amap/amap-maps")
            token: Optional access token for authentication

        Returns:
            Dict containing:
                - name: Server name
                - description: Server description
                - id: Server ID
                - service_config: Connection configuration with type and url

        Raises:
            ValueError: If server_id is empty or None
            MCPApiRequestError: If API request fails or server not found
            MCPApiResponseError: If response format is invalid or JSON parsing fails

        Returns:
            {
                'name': 'ServerA',
                'description': 'This is a demo server for xxx.',
                'id': '@demo/serverA',
                'servers': [
                    {
                        'type': 'sse',
                        'url': 'https://mcp.api-inference.modelscope.net/{uuid}/sse'
                    },
                    {
                        'type': 'streamable_http',
                        'url': 'https://mcp.api-inference.modelscope.net/{uuid}/streamable_http'
                    }
                    ...
                ]
            }
        zserver_id cannot be emptyr,   Zget_operational_urlT)r8   paramsr9   zFailed to get MCP server z: Nr;   r1   r=   r<   )r;   r=   r<   rL   r7   rM   rN   rB   )rC   r   rG   r8   rD   rE   r'   r   r!   r"   rH   r$   r%   r   r*   r   r/   r.   rR   )r   r+   r2   r7   r8   r9   r   r)   r   resultZserver_namerL   rJ   rT   rS   r   r   r   get_mcp_server   sR   )






zMCPApi.get_mcp_server)N)NNr0   r1   )r   r   r   r   r   strr   staticmethodr!   Responser   r   r*   r/   intrK   rU   rX   __classcell__r   r   r   r   r   &   sH    


O

N
r   )r   typingr   r   r   r!   Zmodelscope.hub.apir   Zmodelscope.hub.errorsr   Zmodelscope.utils.loggerr   r$   r   	Exceptionr	   r   r   r   r   r   r   r   <module>   s   