
    )i                        d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
Z
 G d de      Z G d d      Zdd	Zed
k(  r ej                    e              yy)zE
Reusable SSE MCP client tailored for the remote chatbot data tools.
    )annotationsN)AnyDictListOptionalc                      e Zd ZdZy)MCPClientErrorz)Generic error raised by the MCPSSEClient.N)__name__
__module____qualname____doc__     a/Users/divyeshpatel/Desktop/sahana/Recommender/recommender_rl/recommender/data_sync/mcp_client.pyr	   r	      s    3r   r	   c                      e Zd ZdZ	 	 d	 	 	 	 	 	 	 ddZd Zd ZddZedd       Z	dddZ
dd	Zdd
ZddZddZddZedd       Zy)MCPSSEClientzEMinimal SSE transport client for MCP servers such as api.recomai.one.Nc                    |j                  d      }d|v rdnd}| | d| | _        || _        || _        |xs || _        || _        d| _        d | _        i | _        i | _	        g | _
        d| _        y )N/?&zauthKey=r   F)rstripurlbase_urlauth_keychatbot_keytimeout
request_idhttp_clientserver_infocapabilities	mcp_toolsinitialized)selfr   r   r   r   	separators         r   __init__zMCPSSEClient.__init__   s     ??3'(?C	Z	{(8*=  &2(8<+-,./1 r   c                B   K   | j                          d {    | S 7 wN)connectr#   s    r   
__aenter__zMCPSSEClient.__aenter__,   s     lln 	s   c                @   K   | j                          d {    y 7 wr'   )
disconnect)r#   exc_typeexctbs       r   	__aexit__zMCPSSEClient.__aexit__0   s     oos   c                D    | xj                   dz  c_         | j                   S )N   )r   r)   s    r   _next_idzMCPSSEClient._next_id3   s    1r   c                    | j                         j                         }|D cg c]'  }|j                  d      s|j                  ddd      ) }}|sy t	        j
                  |d         S c c}w )Nzdata:  r2   r   )strip
splitlines
startswithreplacejsonloads)textlinesline
data_liness       r   _parse_sse_responsez MCPSSEClient._parse_sse_response7   sb    

'')@EcYaIbdll8R3
czz*Q-(( ds
   A,A,c                >  K   | j                   st        d      d| j                         ||xs i d}ddd}| j                   j                  | j                  ||       d {   }|j
                  dk7  r%t        d	|j
                   d
|j                         | j                  |j                        }|t        d|j                         d|v r4|d   }t        d|j                  d       d
|j                  d             |j                  di       S 7 w)NzClient is not connectedz2.0)jsonrpcidmethodparamsz#application/json, text/event-streamapplication/json)AcceptzContent-Type)r:   headers   zHTTP z: zMalformed SSE payload: errorz
MCP error codemessageresult)	r   r	   r3   postr   status_coder<   r@   get)r#   rD   rE   payloadrH   responseparsedrJ   s           r   _send_requestzMCPSSEClient._send_request?   s$     !:;; --/l	
 <.
 ))..txxgw.WW3& 5)=)=(>b!PQQ))(--8> #:8==/!JKKf7OE :eii.?-@599YCWBX!YZZzz(B'' Xs   A!D#D$B8Dc                &  K   | j                   ry t        j                  | j                        | _        | j                  ddi i ddddd       d {   }|j                  d	i       | _        |j                  d
i       | _        d| _         y 7 :w)N)r   
initializez
2024-11-05)rootssamplingzrecommender-data-loaderz0.2.0)nameversion)protocolVersionr    
clientInfo
serverInfor    T)	r"   httpxAsyncClientr   r   rT   rP   r   r    r#   rM   s     r   r(   zMCPSSEClient.connectY   s      ,,T\\B))#/*," ='@WU
 
 "::lB7"JJ~r:
s   ABB;Bc                   K   | j                   st        d      | j                  di        d {   }|j                  dg       | _        | j                  S 7 'w)Nz-connect() must be called before listing toolsz
tools/listtools)r"   r	   rT   rP   r!   r`   s     r   
list_toolszMCPSSEClient.list_toolsj   sQ      !PQQ)),;;GR0~~ <s   -AA(Ac                v   K   | j                   st        d      | j                  d||d       d {   S 7 w)Nz+connect() must be called before using toolsz
tools/call)rY   	arguments)r"   r	   rT   )r#   	tool_namere   s      r   	call_toolzMCPSSEClient.call_toolq   s:      !NOO''yW`6abbbbs   0979c           	        K   | j                  ||       d {   }| j                  |      }|s|S 	 t        j                  |      S 7 /# t        j                  $ r}t        d| d|d d        |d }~ww xY ww)NzTool z returned non-JSON content: rI   )rg   extract_text_contentr:   r;   JSONDecodeErrorr	   )r#   rf   re   rM   r<   r.   s         r   call_tool_jsonzMCPSSEClient.call_tool_jsonv   s     ~~i;;((0M	g::d## < ## 	g 53OPTUYVYPZ|!\]cff	gs2   A:AA:A
 A:
A7A22A77A:c                   K   | j                   r)| j                   j                          d {    d | _         d| _        y 7 w)NF)r   acloser"   r)   s    r   r,   zMCPSSEClient.disconnect   s<     ""))+++#D  ,s   *AA Ac                   | j                  d      }t        |t              sy |D ]d  }t        |t              s|j                  d      }|r|c S |j                  d      dk(  s@|j                  d      }t        |t              sb|c S  y )Ncontentr<   typerF   data)rP   
isinstancelistdictstr)rM   ro   blockr<   rq   s        r   ri   z!MCPSSEClient.extract_text_content   s~    **Y''4(EeT*99V$Dyy $66yy(dC(K  r   )Ng      >@)r   ru   r   ru   r   Optional[str]r   float)returnint)r<   ru   ry   Optional[Dict[str, Any]]r'   )rD   ru   rE   r{   ry   Dict[str, Any]ry   None)ry   zList[Dict[str, Any]])rf   ru   re   r|   ry   r|   )rM   r|   ry   rw   )r
   r   r   r   r%   r*   r0   r3   staticmethodr@   rT   r(   rc   rg   rk   r,   ri   r   r   r   r   r      s    O &*!! ! #	!
 !,  ) )(4 "c
g!  r   r   c                   K   ddl } ddl}| j                  d      }|j                  ddd       |j                  d	d
d       |j	                         }t        j                  |j                  xs d
      }t        |j                  dd      |j                  dd      |j                  d            }	 |j                          d{    |j                  |j                  |       d{   }|j                  |      }t        |xs t        j                  |d             |j!                          d{    y7 v7 T7 	# |j!                          d{  7   w xY w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.)defaultr   MCP_URLzhttps://api.recomai.one/mcpMCP_AUTH_KEYr5   MCP_CHATBOT_KEY)r   r   r      )indent)argparseosArgumentParseradd_argument
parse_argsr:   r;   rQ   r   getenvr(   rg   toolri   printdumpsr,   )r   r   parserargsrQ   clientrM   r<   s           r   mainr      s.    $$1Q$RF
46LM
T8NODjj-.G9&CD>2.II/0F"nn''		7;;**62d2djj23!!! 	; 	"f!!!s`   B3E$6E 	E 
#E -E.9E 'E$:E;E$ E E E$E!EE!!E$__main__r}   )r   
__future__r   asyncior:   typingr   r   r   r   r^   RuntimeErrorr	   r   r   r
   runr   r   r   <module>r      s[    #   , , 4\ 4B BJ"6 zGKK r   