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mZmZm	Z	m
Z
 ddlZeddZeddZed	d
ZG dd deZG dd dZdddZedkrVee  dS dS )zE
Reusable SSE MCP client tailored for the remote chatbot data tools.
    )annotationsN)AnyDictListOptionalMCP_URLhttps://api.recomai.one/mcpMCP_AUTH_KEY1+FiDOuHBrVo4X0SfW5KrEQ==:y0R6zQZbj7K6wXN5jxgmTg==MCP_CHATBOT_KEY@c4292acede69fc72e5b06bdea37b2cee45a4ac2190cb8c98e8b2dce6b53f9ceec                   @  s   e Zd ZdZdS )MCPClientErrorz)Generic error raised by the MCPSSEClient.N)__name__
__module____qualname____doc__ r   r   a/Users/divyeshpatel/Desktop/sahana/Recommender/recommender_rl/recommender/data_sync/mcp_client.pyr      s    r   c                   @  s   e Zd ZdZeeedfd/d
dZdd Zdd Z	d0ddZ
ed1ddZd2d3ddZd4dd Zd5d"d#Zd6d&d'Zd6d(d)Zd4d*d+Zed7d-d.ZdS )8MCPSSEClientzEMinimal SSE transport client for MCP servers such as api.recomai.one.g      >@base_urlstrauth_keychatbot_keyOptional[str]timeoutfloatc                 C  sr   | d}d|v rdnd}| | d| | _|| _|| _|p || _|| _d| _d | _i | _i | _	g | _
d| _d S )N/?&zauthKey=r   F)rstripurlr   r   r   r   
request_idhttp_clientserver_infocapabilities	mcp_toolsinitialized)selfr   r   r   r   	separatorr   r   r   __init__   s   


zMCPSSEClient.__init__c                   s   |   I d H  | S N)connectr'   r   r   r   
__aenter__5   s   zMCPSSEClient.__aenter__c                   s   |   I d H  d S r*   )
disconnect)r'   exc_typeexctbr   r   r   	__aexit__9   s   zMCPSSEClient.__aexit__returnintc                 C  s   |  j d7  _ | j S )N   )r!   r,   r   r   r   _next_id<   s   zMCPSSEClient._next_idtextOptional[Dict[str, Any]]c                 C  s0   |    }dd |D }|sd S t|d S )Nc                 S  s$   g | ]}| d r|d ddqS )zdata:  r5   )
startswithreplace).0liner   r   r   
<listcomp>C   s   $ z4MCPSSEClient._parse_sse_response.<locals>.<listcomp>r   )strip
splitlinesjsonloads)r7   linesZ
data_linesr   r   r   _parse_sse_response@   s
   z MCPSSEClient._parse_sse_responseNmethodparamsDict[str, Any]c                   s   | j stdd|  ||pi d}ddd}| j j| j||dI d H }|jdkr6td	|j d
|j | |j}|d u rHtd|j d|v r`|d }td|d d
|d |di S )NzClient is not connectedz2.0)ZjsonrpcidrE   rF   z#application/json, text/event-streamapplication/json)ZAcceptzContent-Type)rA   headers   zHTTP z: zMalformed SSE payload: errorz
MCP error codemessageresult)	r"   r   r6   Zpostr    Zstatus_coder7   rD   get)r'   rE   rF   payloadrJ   ZresponseparsedrL   r   r   r   _send_requestH   s*   
 zMCPSSEClient._send_requestNonec                   sh   | j rd S tj| jd| _| ddi i dddddI d H }|d	i | _|d
i | _d| _ d S )N)r   Z
initializez
2024-11-05)rootsZsamplingzrecommender-data-loaderz0.2.0)nameversion)ZprotocolVersionr$   Z
clientInfoZ
serverInfor$   T)	r&   httpxZAsyncClientr   r"   rS   rP   r#   r$   r'   rO   r   r   r   r+   b   s   

zMCPSSEClient.connectList[Dict[str, Any]]c                   s6   | j std| di I d H }|dg | _| jS )Nz-connect() must be called before listing toolsz
tools/listtools)r&   r   rS   rP   r%   rY   r   r   r   
list_toolss   s   zMCPSSEClient.list_tools	tool_name	argumentsc                   s(   | j std| d||dI d H S )Nz+connect() must be called before using toolsz
tools/call)rV   r^   )r&   r   rS   )r'   r]   r^   r   r   r   	call_toolz   s   zMCPSSEClient.call_toolc              
     sl   |  ||I d H }| |}|s|S zt|W S  tjy5 } ztd| d|d d  |d }~ww )NzTool z returned non-JSON content: rK   )r_   extract_text_contentrA   rB   JSONDecodeErrorr   )r'   r]   r^   rO   r7   r0   r   r   r   call_tool_json   s   
zMCPSSEClient.call_tool_jsonc                   s(   | j r| j  I d H  d | _ d| _d S )NF)r"   acloser&   r,   r   r   r   r.      s
   
zMCPSSEClient.disconnectrO   c                 C  sr   |  d}t|tsd S |D ](}t|tsq| d}|r!|  S | ddkr6| d}t|tr6|  S qd S )Ncontentr7   typerI   data)rP   
isinstancelistdictr   )rO   rd   blockr7   rf   r   r   r   r`      s   





z!MCPSSEClient.extract_text_content)r   r   r   r   r   r   r   r   )r3   r4   )r7   r   r3   r8   r*   )rE   r   rF   r8   r3   rG   r3   rT   )r3   rZ   )r]   r   r^   rG   r3   rG   )rO   rG   r3   r   )r   r   r   r   DEFAULT_MCP_URLDEFAULT_AUTH_KEYDEFAULT_CHATBOT_KEYr)   r-   r2   r6   staticmethodrD   rS   r+   r\   r_   rb   r.   r`   r   r   r   r   r      s(    






r   r3   rT   c                    s   ddl } ddl}| jdd}|jdddd |jd	d
dd | }t|jp)d
}t|	dd|	dd|	ddd}z+|
 I dH  ||j|I dH }||}t|p^tj|dd W | I dH  dS | I dH  w )z$Small CLI helper for manual testing.r   NzCall an MCP SSE tool directly.)descriptionz--toolTzTool name to invoke.)requiredhelpz	--payloadz{}zJSON string payload.)defaultrr   r   r   r	   r
   r   r   )r   r   r      )indent)argparseosArgumentParseradd_argument
parse_argsrA   rB   rQ   r   getenvr+   r_   toolr`   printdumpsr.   )rv   rw   parserargsrQ   clientrO   r7   r   r   r   main   s&   



"r   __main__rk   )r   
__future__r   asynciorA   rw   typingr   r   r   r   rX   r{   rl   rm   rn   RuntimeErrorr   r   r   r   runr   r   r   r   <module>   s(    
