
    a)iv                        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)z6
Lightweight MCP SSE client shared by test utilities.
    )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/tests/mcp_sse_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e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                        | _        t        d       | j                  ddi i ddddd	       d {   }|j                  d
i       | _        |j                  di       | _	        d| _         | j                  j                  dd      }| j                  j                  dd      }t        d| d|        y 7 w)N)r   u    🔗 Connecting to MCP server...
initializez
2024-11-05)rootssamplingzrecommender-data-loaderz0.1.0)nameversion)protocolVersionr    
clientInfo
serverInfor    TrY   unknownrZ   r   u   ✅ Connected to z v)
r"   httpxAsyncClientr   r   printrT   rP   r   r    )r#   rM   serverrZ   s       r   r(   zMCPSSEClient.connectY   s      ,,T\\B01))#/*," ='@WU
 
 "::lB7"JJ~r:!!%%fi8""&&y#6!&G956
s   AC%C# BC%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#   rM   s     r   
list_toolszMCPSSEClient.list_toolsn   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_namerg   s      r   	call_toolzMCPSSEClient.call_toolu   s:      !NOO''yW`6abbbbs   0979c                   K   | j                   r)| j                   j                          d {    d | _         d| _        t        d       y 7 w)NFu"   🔌 Disconnected from MCP server.)r   acloser"   ra   r)   s    r   r,   zMCPSSEClient.disconnectz   sE     ""))+++#D 23 ,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   rm   blockr<   ro   s        r   extract_text_contentz!MCPSSEClient.extract_text_content   s~    **Y''4(EeT*99V$Dyy $66yy(dC(K  r   c                    t         j                  |       }|sy 	 t        j                  |      S # t        j                  $ r Y y w xY wr'   )r   ru   r:   r;   JSONDecodeError)rM   r<   s     r   extract_json_contentz!MCPSSEClient.extract_json_content   sD    008	::d#### 		s   / AA)Ng      >@)r   rs   r   rs   r   Optional[str]r   float)returnint)r<   rs   r{   Optional[Dict[str, Any]]r'   )rD   rs   rE   r}   r{   Dict[str, Any]r{   None)r{   zList[Dict[str, Any]])rh   rs   rg   r~   r{   r~   )rM   r~   r{   ry   )rM   r~   r{   zOptional[Any])r
   r   r   r   r%   r*   r0   r3   staticmethodr@   rT   r(   re   ri   r,   ru   rx   r   r   r   r   r      s    O &*!! ! #	!
 !,  ) )(47*c
4     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(   ri   toolru   ra   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G GT"6 zGKK r   