
    )`iJ*                        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 ddlmZmZ ddl m!Z!m"Z"  ej#        e$          Z% G d d          Z&dS )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, methods=["GET"]),
        Mount("/messages/", app=sse.handle_post_message),
    ]

    # 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()
            )
        # Return empty response to avoid NoneType error
        return Response()

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

Note: The handle_sse function must return a Response to avoid a "TypeError: 'NoneType'
object is not callable" error when client disconnects. The example above returns
an empty Response() after the SSE connection ends to fix this.

See SseServerTransport class documentation for more details.
    N)asynccontextmanager)Any)quote)UUIDuuid4)MemoryObjectReceiveStreamMemoryObjectSendStream)ValidationError)EventSourceResponse)Request)Response)ReceiveScopeSend)TransportSecurityMiddlewareTransportSecuritySettings)ServerMessageMetadataSessionMessagec                        e Zd ZU dZeed<   eeee	e
z           f         ed<   eed<   ddededz  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	_securityNendpointsecurity_settingsreturnc                 b   t                                                       d|v s|                    d          sd|v sd|v rt          d| d          |                    d          sd|z   }|| _        i | _        t          |          | _        t          	                    d|            d	S )
a  
        Creates a new SSE server transport, which will direct the client to POST
        messages to the relative path given.

        Args:
            endpoint: A relative path where messages should be posted
                    (e.g., "/messages/").
            security_settings: Optional security settings for DNS rebinding protection.

        Note:
            We use relative paths instead of full URLs for several reasons:
            1. Security: Prevents cross-origin requests by ensuring clients only connect
               to the same origin they established the SSE connection with
            2. Flexibility: The server can be mounted at any path without needing to
               know its full URL
            3. Portability: The same endpoint configuration works across different
               environments (development, staging, production)

        Raises:
            ValueError: If the endpoint is a full URL instead of a relative path
        z://z//?#zGiven endpoint: z] is not a relative path (e.g., '/messages/'), expecting a relative path (e.g., '/messages/')./z.SseServerTransport initialized with endpoint: N)
super__init__
startswith
ValueErrorr   r   r   r   loggerdebug)selfr   r   	__class__s      b/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/mcp/server/sse.pyr"   zSseServerTransport.__init__P   s    . 	 H 3 3D 9 9SH__PSW_P_P_B8 B B B   ""3'' 	&X~H!$&!45FGGPhPPQQQQQ    scopereceivesendc                  K   |d         dk    r)t                               d           t          d          t          ||          }| j                            |d           d {V }|r" ||||           d {V  t          d          t                               d           t          j        d	          \  }t          j        d	          \  }t                      | j
        <   t                               d
            |                    dd          }|                    d          | j        z   }	t          |	           dj         t          j        t           t"          t$          f                  d	          \  fdt          j                    4 d {V }
dt(          dt*          dt,          ffd}t                               d           |
                    ||||           t                               d           ||fW V  d d d           d {V  d S # 1 d {V swxY w Y   d S )Ntypehttpz%connect_sse received non-HTTP requestz)connect_sse can only handle HTTP requestsFis_postzRequest validation failedzSetting up SSE connectionr   zCreated new session with ID: 	root_path r    z?session_id=c            
      *  K   t                               d           4 d {V  4 d {V                      dd           d {V  t                               d            2 3 d {V } t                               d|                                 d| j                            dd          d           d {V  ]6 	 d d d           d {V  n# 1 d {V swxY w Y   d d d           d {V  d S # 1 d {V swxY w Y   d S )	NzStarting SSE writerr   )eventdatazSent endpoint event: zSending message via SSE: messageT)by_aliasexclude_none)r%   r&   r-   r8   model_dump_json)session_messageclient_post_uri_datasse_stream_writerwrite_stream_readers    r)   
sse_writerz2SseServerTransport.connect_sse.<locals>.sse_writer   s     LL.///(        *=        ',,zK_-`-`aaaaaaaaaK5IKKLLL-@       /LL!N_!N!NOOO+00%.$3$;$K$KUYhl$K$m$m           .A-@	                                                        sA   	D>C-C
3ACD
C(	(D+C(	,D
DDr+   r,   r-   c                    K    t                    | ||           d{V                                   d{V                                   d{V  t          j        d            dS )z
                The EventSourceResponse returning signals a client close / disconnect.
                In this case we close our side of the streams to signal the client that
                the connection has been closed.
                )contentdata_sender_callableNzClient session disconnected )r   acloseloggingr&   )r+   r,   r-   read_stream_writer
session_idsse_stream_readerr@   r?   s      r)   response_wrapperz8SseServerTransport.connect_sse.<locals>.response_wrapper   s       f)2CZdeee7D         )//111111111)00222222222IZIIJJJJJr*   zStarting SSE response taskzYielding read and write streams)r%   errorr$   r   r   validate_requestr&   anyiocreate_memory_object_streamr   r   getrstripr   r   hexdictstrr   create_task_groupr   r   r   
start_soon)r'   r+   r,   r-   requesterror_responseread_streamwrite_streamr3   full_message_path_for_clienttgrI   r=   rF   rG   rH   r>   r@   r?   s               @@@@@@@r)   connect_ssezSseServerTransport.connect_ssey   sB     =F""LL@AAAHIII %))#~>>wPU>VVVVVVVV 	: .66666666689990111 +0*KA*N*N'K,1,Ma,P,P))WW
0B!*-AZAABBB IIk2..	 (1'7'7'<'<t~'M$ #((D"E"EccS]Sacc/4/PQUVY[^V^Q_/`ab/c/c,,	 	 	 	 	 	 	 *,, 	. 	. 	. 	. 	. 	. 	.Ke Kg KT K K K K K K K K K K LL5666MM*E7DAAALL:;;;-----'	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	.s   2A3H88
IIc                    K   t                               d           t          ||          }| j                            |d           d {V }|r ||||           d {V S |j                            d          }|>t                               d           t          dd          } ||||           d {V S 	 t          |	          }t                               d
|            nQ# t          $ rD t                               d|            t          dd          } ||||           d {V cY S w xY w| j                            |          }	|	sAt                               d|            t          dd          } ||||           d {V S |                                 d {V }
t                               d|
            	 t          j                            |
          }t                               d|            nq# t           $ rd}t                               d           t          dd          } ||||           d {V  |	                    |           d {V  Y d }~d S d }~ww xY wt'          |          }t)          ||          }t                               d|            t          dd          } ||||           d {V  |	                    |           d {V  d S )NzHandling POST messageTr1   rG   z#Received request without session_idzsession_id is requiredi  )status_code)rP   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 messagezCould not parse message)request_context)metadataz#Sending session message to writer: Accepted   )r%   r&   r   r   rK   query_paramsrN   warningr   r   r$   r   bodytypesJSONRPCMessagemodel_validate_jsonr
   	exceptionr-   r   r   )r'   r+   r,   r-   rU   rV   session_id_paramresponserG   writerrd   r8   errr_   r<   s                  r)   handle_post_messagez&SseServerTransport.handle_post_message   s     ,---%))  $~>>wPT>UUUUUUUU 	>'w========="/33LAA#NN@AAA 8cJJJH!%$777777777	8"2333JLL;z;;<<<< 	8 	8 	8NNM;KMMNNN 4#FFFH!%$77777777777	8
 *..z:: 	8NNIZIIJJJ 8cJJJH!%$777777777\\^^######-t--...	*>>tDDGLL?g??@@@@ 	 	 	6777 9sKKKH(5'4000000000++c"""""""""FFFFF	 )AAA(8DDDL?LLMMMJC888hugt,,,,,,,,,kk/***********s,   ?-C- -AD;:D;<H 
I>AI99I>)N)__name__
__module____qualname____doc__rR   __annotations__rQ   r   r	   r   	Exceptionr   r   r"   r   r   r   r   r[   rm   __classcell__)r(   s   @r)   r   r   @   s        	 	 NNNt%;NY<V%WWXXXX****'R 'R 'R9RUY9Y 'Rei 'R 'R 'R 'R 'R 'RR M.u M.w M.d M. M. M. M.^0+u 0+w 0+d 0+W[ 0+ 0+ 0+ 0+ 0+ 0+ 0+ 0+r*   r   )'rq   rE   
contextlibr   typingr   urllib.parser   uuidr   r   rL   anyio.streams.memoryr   r	   pydanticr
   sse_starletter   starlette.requestsr   starlette.responsesr   starlette.typesr   r   r   	mcp.typesre   mcp.server.transport_securityr   r   mcp.shared.messager   r   	getLoggerrn   r%   r    r*   r)   <module>r      s  % %N  * * * * * *                      R R R R R R R R $ $ $ $ $ $ - - - - - - & & & & & & ( ( ( ( ( ( 0 0 0 0 0 0 0 0 0 0              E D D D D D D D		8	$	$y+ y+ y+ y+ y+ y+ y+ y+ y+ y+r*   