
    uj-                         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	m
Z
 ddlmZ  e            ZdZ G d d	e          Z G d
 de          Z G d de          Z G 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)RequestError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__     f/lsinfo/ai/hellotax_ai/data_center/backend/venv/lib/python3.11/site-packages/modelscope/hub/mcp_api.pyr   r      s        ,,Dr   r   c                       e Zd ZdZdS )MCPApiRequestErrorz,Exception raised when MCP API request fails.Nr   r   r   r   r   r      s        66Dr   r   c                       e Zd ZdZdS )MCPApiResponseErrorz2Exception raised when MCP API response is invalid.Nr   r   r   r   r   r   !   s        <<Dr   r   c                   <    e Zd ZdZ	 	 ddee         dee         ddf fdZededef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Z	 ddede	ee
f         fdZ	 ddedee         de	ee
f         fdZ x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tokenreturnc                 v    t                                          ||           | j        t          z   | _        dS )z
        Initialize MCP API.

        Args:
            endpoint: The modelscope server address. Defaults to None (uses default endpoint).
            token: Optional access token for Bearer authentication.
        )r   r   N)super__init__r   MCP_API_PATHmcp_base_url)selfr   r   	__class__s      r   r   zMCPApi.__init__1   s7     	(%888 ML8r   	server_idc                 F    d| v r|                      dd          d         S | S )z#Extract server name from server ID./   )split)r$   s    r   _get_server_name_from_idzMCPApi._get_server_name_from_id?   s.     )??3**1--r       filtertotal_countsearchc                 d   ||dk     s|dk    rt          d          |pi d||d}	 |                     |d          }| j                            | j        ||          }t          |           nJ# t          j        j        $ r3}t          
                    d	|           t          d
|           |d}~ww xY w	 |                     |          }	n%# t          $ r}t          d|           |d}~ww xY w|	                    dg           }
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)r,   page_number	page_sizer.   Fr   token_required)urlheadersjsonzFailed to get MCP servers: %szFailed to get MCP servers: z(Invalid response from MCP servers list: mcp_server_listc                     g | ]D}|                     d d          |                     dd          |                     dd          dES )namer+   iddescription)r:   r;   r<   )get).0items     r   
<listcomp>z+MCPApi.list_mcp_servers.<locals>.<listcomp>   sd     ' ' '  HHVR((((4$$88M266
 
 ' ' 'r   r-   r   r-   servers)
ValueError_build_bearer_headerssessionputr!   r   requests
exceptionsRequestExceptionloggererrorr   _parse_openapi_responser   r   r=   )r"   r   r,   r-   r.   bodyr6   redatar8   mcp_config_lists               r   list_mcp_serverszMCPApi.list_mcp_serversF   s   V +//[35F5FDEEE l$	
 
	O00E 1 3 3G  %wT ! C CA!!$$$$"3 	O 	O 	OLL8!<<<$%F1%F%FGGQN	O	G//22DD 	G 	G 	G%>1>>@ @EFG	G ((#4b99' ' &	' ' '  88M155&
 
 	
s0   AA1 1B8.B33B8<C 
C4C//C4c           	         | j          d}	 |                     |d          }| j                            ||          }t	          |           nL# t
          j        j        $ r5}t          	                    d|            t          d|           |d}~ww xY wt                              d|j                    	 |                     |          }n%# t          $ r}t          d|           |d}~ww xY w|                    d	g           }g }|D ]}	i }
|	                    d
d          |
d
<   |	                    dd          |
d<   |	                    dd          |
d<   g |
d<   |	                    dg           D ]b}|
d                             |                    d          pd                    d          d         |                    dd          d           c|                    |
           |                    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/operationalTr3   )r6   z'Failed to get operational MCP servers: NzResponse status code: z/Invalid response from operational MCP servers: r8   r:   r+   r;   r<   mcp_serversoperational_urlsr5   r&   typer5   r-   r   rA   )r!   rD   rE   r=   r   rG   rH   rI   rJ   rK   r   debugstatus_coderL   r   r   appendr(   )r"   r   r5   r6   rN   rO   rP   r8   rQ   r?   
mcp_configoperational_urls               r   list_operational_mcp_serversz#MCPApi.list_operational_mcp_servers   s   L "000	F00D 1 2 2G  g 66A!!$$$$"3 	F 	F 	FLLF1FFGGG$=!==? ?DEF	F
 	=am==>>>	N//22DD 	N 	N 	N%E!EEG GLMN	N ((#4b99# 	/ 	/DJ!%&"!5!5Jv#xxb11Jt(,(C(CJ}%(*J}%#'88,>#C#C  =)00,0077=2DDSII"M#''r222 2    
 "":....88M155&
 
 	
s0   AA B#0BB>C 
C6C11C6c                    |st          d          | j         d| }	 |                     |d          }| j                            ||ddi          }t          |           nR# t          j        j        $ r;}t          
                    d| d	|            t          d| d	|           |d
}~ww xY w	 |                     |          }n(# t          $ r}t          d| d	|           |d
}~ww xY w|                    dd          |                    dd          |                    dd          d}|                    dd          }t                              |          }	|                    dg           }
g }|	rc|
ra|
D ]^}|                    d          pd                    d          d         |                    dd          d}|                    |           _||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&   Fr3   get_operational_urlT)r6   paramszFailed to get MCP server z: Nz!Invalid response from MCP server r:   r+   r<   r;   )r:   r<   r;   rU   r5   rV   rW   rB   )rC   r!   rD   rE   r=   r   rG   rH   rI   rJ   rK   r   rL   r   r   r   r)   r(   r[   )r"   r$   r   r5   r6   rN   rO   rP   resultserver_namerU   rQ   r]   r\   s                 r   get_mcp_serverzMCPApi.get_mcp_server   s   R  	:8999"00Y00		E00E 1 3 3G  W.CT-J ! L LA!!$$$$"3 	E 	E 	ELLEYEE!EEFFF$<I<<<<> >CDE	E
	M//22DD 	M 	M 	M%DIDDDDF FKLM	M
 HHVR((88M266((4$$
 
 HHT2&&	55i@@88$6;; 	3+ 	3#3 3 3,0077=2DDSII"M*..ub99 
  &&z2222+ys0   AA% %B496B//B48C 
C3C..C3)NN)NNr*   r+   )N)r   r   r   r   r   strr   staticmethodr)   r   r   intrR   r^   rd   __classcell__)r#   s   @r   r   r   &   s         ,0(,9 9#C=9 9159 9 9 9 9 9 C C    \ 15<@6813	O
 O
 (O
!)$sCx.!9O
 '/smO
 "*#	O
 9=S#X	O
 O
 O
 O
d 37M
 M
,/M
;?S>M
 M
 M
 M
b /3S S"%S&smS7;CH~S S S S S S S Sr   r   )r   typingr   r   r   rG   modelscope.hub.apir   modelscope.hub.errorsr   r   modelscope.utils.loggerr	   rJ   r    	Exceptionr   r   r   r   r   r   r   <module>rn      sD    ' & & & & & & & & &  % % % % % % E E E E E E E E . . . . . . 
 )	 	 	 	 	) 	 	 	
	 	 	 	 	 	 	 	
	 	 	 	 	+ 	 	 	
S S S S SV S S S S Sr   