§
    ­eî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      €úR/home/div/.hermes/hermes-agent/venv/lib/python3.11/site-packages/mcp/server/sse.pyr"   zSseServerTransport.__init__P   sÜ   ø€ õ. 	‰Œ×ÒÑÔÐð �HÐÐ × 3Ò 3°DÑ 9Ô 9Ð¸SÀH¸_¸_ÐPSÐW_ÐP_ÐP_ÝðB 8ð Bð Bð Bñô ð ð ×"Ò" 3Ñ'Ô'ð 	&Ø˜X‘~ˆHà!ˆŒØ$&ˆÔ!Ý4Ð5FÑGÔGˆŒÝ�ŠÐPÀhÐ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�  øè è € Ý�LŠLÐ.Ñ/Ô/Ð/Ø(ð ð ð ð ð ð ð ð Ð*=ð ð ð ð ð ð ð ð Ø'×,Ò,°zÐK_Ð-`Ð-`ÑaÔaÐaÐaÐaÐaÐaÐaÐaÝ—’ÐKÐ5IÐKÐKÑLÔLÐLà-@ð ð ð ð ð ð ð ˜/Ý—L’LÐ!N¸_Ð!NÐ!NÑOÔOÐOØ+×0Ò0à%.Ø$3Ô$;×$KÒ$KÐUYÐhlÐ$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Õ)Ð2CÐZdÐeÑeÔeØ˜7 Dñô ð ð ð ð ð ð ð ð )×/Ò/Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ø)×0Ò0Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Ð2Ð2Ý”ÐI¸ZÐ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Ò"Ð"Ý�LŠLÐ@ÑAÔAÐAÝÐHÑIÔIÐIõ ˜% Ñ)Ô)ˆØ#œ~×>Ò>¸wÐPUÐ>Ñ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Ô*KÈAÑ*NÔ*NÑ'Ð˜KÝ,1Ô,MÈaÑ,PÔ,PÑ)ˆÐ)å‘W”Wˆ
Ø0BˆÔ! *Ñ-Ý�ŠÐA°ZÐAÐAÑBÔBÐBð —I’I˜k¨2Ñ.Ô.ˆ	ð (1×'7Ò'7¸Ñ'<Ô'<¸t¼~Ñ'MÐ$õ #(Ð(DÑ"EÔ"EÐcÐcÐS]ÔSaÐcÐcÐå/4Ô/PÕQUÕVYÕ[^ÐV^ÔQ_Ô/`ÐabÑ/cÔ/cÑ,ÐÐ,ð	ð 	ð 	ð 	ð 	ð 	ð 	õ Ô*Ñ,Ô,ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.°ðK­eð K½gð KÍTð Kð Kð Kð Kð Kð Kð Kð Kð Kð Kõ �LŠLÐ5Ñ6Ô6Ð6Ø�MŠMÐ*¨E°7¸DÑAÔAÐAå�LŠLÐ:Ñ;Ô;Ð;Ø Ð-Ð-Ð-Ð-Ð-ð'	.ð 	.ð 	.ñ 	.ô 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.ð 	.øøøð 	.ð 	.ð 	.ð 	.ð 	.ð 	.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¾  è è € Ý�ŠÐ,Ñ-Ô-Ð-Ý˜% Ñ)Ô)ˆð  $œ~×>Ò>¸wÐPTÐ>ÑUÔUÐUÐUÐUÐUÐUÐUˆØð 	>Ø'˜¨¨w¸Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=Ð=à"Ô/×3Ò3°LÑAÔAÐØÐ#Ý�NŠNÐ@ÑAÔAÐAÝÐ 8ÀcÐJÑJÔJˆHØ!˜ %¨°$Ñ7Ô7Ð7Ð7Ð7Ð7Ð7Ð7Ð7ð	8ÝÐ"2Ð3Ñ3Ô3ˆJÝ�LŠLÐ;¨zÐ;Ð;Ñ<Ô<Ð<Ð<øÝð 	8ð 	8ð 	8Ý�NŠNÐMÐ;KÐMÐMÑNÔNÐNÝÐ 4À#ÐFÑFÔFˆHØ!˜ %¨°$Ñ7Ô7Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ð7ð	8øøøð
 Ô*×.Ò.¨zÑ:Ô:ˆØð 	8Ý�NŠNÐI¸ZÐIÐIÑJÔJÐJÝÐ 8ÀcÐJÑJÔJˆHØ!˜ %¨°$Ñ7Ô7Ð7Ð7Ð7Ð7Ð7Ð7Ð7à—\’\‘^”^Ð#Ð#Ð#Ð#Ð#Ð#ˆÝ�ŠÐ- tÐ-Ð-Ñ.Ô.Ð.ð	ÝÔ*×>Ò>¸tÑDÔDˆGÝ�LŠLÐ?°gÐ?Ð?Ñ@Ô@Ð@Ð@øÝð 	ð 	ð 	Ý×ÒÐ6Ñ7Ô7Ð7ÝÐ 9ÀsÐKÑKÔKˆHØ�(˜5 '¨4Ñ0Ô0Ð0Ð0Ð0Ð0Ð0Ð0Ð0Ø—+’+˜cÑ"Ô"Ð"Ð"Ð"Ð"Ð"Ð"Ð"ØˆFˆFˆFˆFˆFøøøøð	øøøõ )¸ÐAÑAÔAˆÝ(¨¸8ÐDÑDÔDˆÝ�ŠÐL¸?ÐLÐLÑMÔMÐMÝ˜J°CÐ8Ñ8Ô8ˆØˆh�u˜g tÑ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ø�kŠk˜/Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*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  ø€ € € € € € ð	ð 	ð €N€N�NØ˜tÐ%;¸NÈYÑ<VÔ%WÐWÔXÐXÐXÑXØ*Ð*Ð*Ñ*ð'Rð 'R ð 'RÐ9RÐUYÑ9Yð '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*   