
    ^sj                         d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	m
Z
 ddlZddlmZmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZ ddlmZ  ej:                  e      Z G d d      Z y)a  
SSE Server Transport Module

This module implements a Server-Sent Events (SSE) transport layer for MCP servers.

Example usage:
```
    # Create an SSE transport at an endpoint
    sse = SseServerTransport("/messages")

    # Create Starlette routes for SSE and message handling
    routes = [
        Route("/sse", endpoint=handle_sse),
        Route("/messages", endpoint=handle_messages, methods=["POST"])
    ]

    # Define handler functions
    async def handle_sse(request):
        async with sse.connect_sse(
            request.scope, request.receive, request._send
        ) as streams:
            await app.run(
                streams[0], streams[1], app.create_initialization_options()
            )

    async def handle_messages(request):
        await sse.handle_post_message(request.scope, request.receive, request._send)

    # Create and run Starlette app
    starlette_app = Starlette(routes=routes)
    uvicorn.run(starlette_app, host="0.0.0.0", port=port)
```

See SseServerTransport class documentation for more details.
    N)asynccontextmanager)Any)quote)UUIDuuid4)MemoryObjectReceiveStreamMemoryObjectSendStream)ValidationError)EventSourceResponse)Request)Response)ReceiveScopeSendc                        e Zd ZU dZeed<   eeee	j                  ez     f   ed<   deddf fdZeded	ed
efd       Zded	ed
eddfdZ xZS )SseServerTransporta  
    SSE server transport for MCP. This class provides _two_ ASGI applications,
    suitable to be used with a framework like Starlette and a server like Hypercorn:

        1. connect_sse() is an ASGI application which receives incoming GET requests,
           and sets up a new SSE stream to send server messages to the client.
        2. handle_post_message() is an ASGI application which receives incoming POST
           requests, which should contain client messages that link to a
           previously-established SSE session.
    	_endpoint_read_stream_writersendpointreturnNc                 n    t         |           || _        i | _        t        j                  d|        y)z
        Creates a new SSE server transport, which will direct the client to POST
        messages to the relative or absolute URL given.
        z.SseServerTransport initialized with endpoint: N)super__init__r   r   loggerdebug)selfr   	__class__s     A/root/.hermes/venv/lib/python3.12/site-packages/mcp/server/sse.pyr   zSseServerTransport.__init__I   s3     	!$&!EhZPQ    scopereceivesendc                (  K   |d   dk7  r t         j                  d       t        d      t         j                  d       t	        j
                  d      \  }}t	        j
                  d      \  }t               }t        | j                         d|j                   || j                  |<   t         j                  d|        t	        j
                  dt        t        t        f         \  }fd	}	t	        j                         4 d {   }
t        ||	
      }t         j                  d       |
j!                  ||||       t         j                  d       ||f d d d       d {    y 7 g7 # 1 d {  7  sw Y   y xY ww)Ntypehttpz%connect_sse received non-HTTP requestz)connect_sse can only handle HTTP requestszSetting up SSE connectionr   z?session_id=zCreated new session with ID: c            
        K   t         j                  d       4 d {    4 d {    j                  dd       d {    t         j                  d        2 3 d {   } t         j                  d|         j                  d| j                  dd      d       d {    O7 7 7 q7 P7 6 d d d       d {  7   n# 1 d {  7  sw Y   nxY wd d d       d {  7   y # 1 d {  7  sw Y   y xY ww)	NzStarting SSE writerr   )eventdatazSent endpoint event: zSending message via SSE: messageT)by_aliasexclude_none)r   r   r"   model_dump_json)r)   session_urisse_stream_writerwrite_stream_readers    r   
sse_writerz2SseServerTransport.connect_sse.<locals>.sse_writerm   s
    LL./(  *=  ',,z;-WXXX4[MBC%8 	 	'LL#<WI!FG+00%.$+$;$;)-D %< %   X	 &9	         s   DB4DC8B6C8CB8C%B>)B:
*B>-AC.B<
/C4D6C88C:B><C>C?C8
CC8C#	CC#	C8&D1C42D8D
>D?D
D)contentdata_sender_callablezStarting SSE response taskzYielding read and write streams)r   error
ValueErrorr   anyiocreate_memory_object_streamr   r   r   hexr   dictstrr   create_task_groupr   
start_soon)r   r    r!   r"   read_stream_writerread_streamwrite_stream
session_idsse_stream_readerr0   tgresponser-   r.   r/   s               @@@r   connect_ssezSseServerTransport.connect_sseT   sa    =F"LL@AHII01 +0*K*KA*N'K,1,M,Ma,P))W
t~~./|JNN;KL0B!!*-4ZLAB/4/P/PtCH~0
,,	" **, 	. 	.*)
H LL56MM(E7D9LL:;--	. 	. 	. 	. 	. 	. 	.sI   DFE9FAE=(F3E;4F;F=FFFFc                   K   t         j                  d       t        ||      }|j                  j	                  d      }|4t         j                  d       t        dd      } ||||       d {   S 	 t        |      }t         j                  d|        | j                  j	                  |      }|s7t         j                  d|        t        dd      } ||||       d {   S |j                          d {   }	t         j                  d|	        	 t        j                  j                  |	      }
t         j                  d|
        t         j                  d|
        t        dd      } ||||       d {    |j!                  |
       d {    y 7 7# t        $ r; t         j                  d	|        t        d
d      } ||||       d {  7  cY S w xY w7 7 # t        $ r\}t         j                  d|        t        dd      } ||||       d {  7   |j!                  |       d {  7   Y d }~y d }~ww xY w7 7 w)NzHandling POST messager?   z#Received request without session_idzsession_id is requiredi  )status_code)r7   zParsed session ID: zReceived invalid session ID: zInvalid session IDzCould not find session for ID: zCould not find sessioni  zReceived JSON: zValidated client message: zFailed to parse message: zCould not parse messagezSending message to writer: Accepted   )r   r   r   query_paramsgetwarningr   r   r4   r   jsontypesJSONRPCMessagemodel_validater
   r3   r"   )r   r    r!   r"   requestsession_id_paramrB   r?   writerrK   r)   errs               r   handle_post_messagez&SseServerTransport.handle_post_message   s-     	,-%)"//33LA#NN@A 8cJH!%$777	8"23JLL.zl;< **..z:NN<ZLIJ 8cJH!%$777\\^#tf-.	**99$?GLL5gY?@ 	27)<=JC8ugt,,,kk'"""A 8
  	8NN:;K:LMN 4#FH!%$7777	8 8#  	LL4SE:; 9sKH5'4000++c"""	 	-"s   A.I"0F'1I"6$F* AI")G1*I"G4I"7G6 2I"I	I"!I "I"*;G.%G(&G.+I"-G..I"4I"6	I?2I1H42IIII"II" I")__name__
__module____qualname____doc__r9   __annotations__r8   r   r	   rL   rM   	Exceptionr   r   r   r   r   rC   rS   __classcell__)r   s   @r   r   r   8   s    	 N$U%9%9I%EFF 	R 	R 	R 1.u 1.w 1.d 1. 1.f*#*#%,*#48*#	*#r   r   )!rW   logging
contextlibr   typingr   urllib.parser   uuidr   r   r5   anyio.streams.memoryr   r	   pydanticr
   sse_starletter   starlette.requestsr   starlette.responsesr   starlette.typesr   r   r   	mcp.typesrL   	getLoggerrT   r   r    r   r   <module>ri      sU   "H  *     R $ - & ( 0 0 			8	$z# z#r   