§
    öŽ’j81  ã                   ó  — 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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)ÚAuthenticatedUserÚAuthorizationContextÚauthorization_context)Ú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e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Ú_session_ownersÚ	_securityNÚendpointÚsecurity_settingsÚreturnc                 óp  •— t          ¦   «                              ¦   «          d|v s|                     d¦  «        sd|v sd|v rt          d|› d�¦  «        ‚|                     d¦  «        sd|z   }|| _        i | _        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   r   ÚloggerÚdebug)Úselfr   r   Ú	__class__s      €ú<C:\Projects\DSCons\.venv\Lib\site-packages\mcp\server\sse.pyr&   zSseServerTransport.__init__T   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          ¦   «         Š| 
                    d
¦  «        }t          |t          ¦  «        rt          |¦  «        | j        ‰<   ‰| 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t0          dt2          dt4          fˆˆˆˆˆfd„}t                                d¦  «         |                     ||||¦  «         t                                d¦  «         ||fW V — d d d ¦  «        ƒd {V —† n# 1 ƒd {V —†swxY w Y   | j                             ‰d ¦  «         | j                             ‰d ¦  «         d S # | j                             ‰d ¦  «         | j                             ‰d ¦  «         w xY w)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   Úuserz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*   r1   r=   Ú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/   r0   r1   c              “   ó  •K  —  t          ‰‰¬¦  «        | ||¦  «        ƒ d{V —† ‰                     ¦   «         ƒ d{V —† ‰                     ¦   «         ƒ d{V —† ‰                     ¦   «         ƒ d{V —† t          j        d‰› �¦  «         dS )a   
                    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/   r0   r1   Úread_stream_writerÚ
session_idÚsse_stream_readerrE   rD   s      €€€€€r-   Úresponse_wrapperz8SseServerTransport.connect_sse.<locals>.response_wrapper¿   sà   øè è € ð jÕ-Ð6GÐ^hÐiÑiÔiØ˜w¨ñô ð ð ð ð ð ð ð ð -×3Ò3Ñ5Ô5Ð5Ð5Ð5Ð5Ð5Ð5Ð5Ø-×4Ò4Ñ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ø+×2Ò2Ñ4Ô4Ð4Ð4Ð4Ð4Ð4Ð4Ð4Ý”MÐ"MÀÐ"MÐ"MÑNÔNÐNÐNÐNr.   zStarting SSE response taskzYielding read and write streams)r)   Úerrorr(   r   r   Úvalidate_requestr*   ÚanyioÚcreate_memory_object_streamr   ÚgetÚ
isinstancer   r   r   r   Úrstripr   r   ÚhexÚdictÚstrr   Úcreate_task_groupr   r   r   Ú
start_soonÚpop)r+   r/   r0   r1   ÚrequestÚerror_responseÚread_streamÚwrite_streamr7   r8   Úfull_message_path_for_clientÚtgrN   rB   rK   rL   rM   rC   rE   rD   s                @@@@@@@r-   Úconnect_ssezSseServerTransport.connect_sse~   sæ  øøøøøøøè è € à�Œ=˜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ˆ
Ø�yŠy˜Ñ Ô ˆÝ�dÕ-Ñ.Ô.ð 	KÝ/DÀTÑ/JÔ/JˆDÔ  Ñ,Ø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Ñ,ÐÐ,ð	ð 	ð 	ð 	ð 	ð 	ð 	ð	7ÝÔ.Ñ0Ô0ð 2ð 2ð 2ð 2ð 2ð 2ð 2°BðOµ%ð OÅ'ð OÕQUð Oð Oð Oð Oð Oð Oð Oð Oð Oð Oõ —’Ð9Ñ:Ô:Ð:Ø—’Ð.°°wÀÑEÔEÐEå—’Ð>Ñ?Ô?Ð?Ø" LÐ1Ð1Ð1Ð1Ð1ð)2ð 2ð 2ñ 2ô 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2ð 2øøøð 2ð 2ð 2ð 2ð2 Ô%×)Ò)¨*°dÑ;Ô;Ð;ØÔ ×$Ò$ Z°Ñ6Ô6Ð6Ð6Ð6øð Ô%×)Ò)¨*°dÑ;Ô;Ð;ØÔ ×$Ò$ Z°Ñ6Ô6Ð6Ð6øøøs1   ÇK Ç4A3I9É'K É9
JÊK ÊJÊK Ë8K:c              ƒ   ó0  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¦  «        }
t          |
t          ¦  «        rt          |
¦  «        nd }|| j                             |¦  «        k    r?t                                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/          |¬¦  «        }t1          ||¬¦  «        }t                                d|› �¦  «         t          dd¬¦  «        } ||||¦  «        ƒ d {V —† |	                     |¦  «        ƒ d {V —† d S )NzHandling POST messageTr5   rL   z#Received request without session_idzsession_id is requiredi�  )Ústatus_code)rV   zParsed session ID: zReceived invalid session ID: zInvalid session IDzCould not find session for ID: zCould not find sessioni”  r7   z;Rejecting message for session %s: credential does not matchz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   rP   Úquery_paramsrS   Úwarningr   r   r(   r   rT   r   r   r   ÚbodyÚtypesÚJSONRPCMessageÚmodel_validate_jsonr
   Ú	exceptionr1   r   r   )r+   r/   r0   r1   r\   r]   Úsession_id_paramÚresponserL   Úwriterr7   Ú	requestorrk   r=   Úerrrf   rA   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à�yŠy˜Ñ Ô ˆÝ3=¸dÕDUÑ3VÔ3VÐ`Õ)¨$Ñ/Ô/Ð/Ð\`ˆ	Ø˜Ô,×0Ò0°Ñ<Ô<Ò<Ð<õ �NŠNÐXÐZdÑeÔeÐeÝÐ 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;É+<J( Ê(
LÊ2ALÌL)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rX   Ú__annotations__rW   r   r	   r   Ú	Exceptionr   r   r   r&   r   r   r   r   rb   ru   Ú__classcell__)r,   s   @r-   r   r   A   s6  ø€ € € € € € ð	ð 	ð €N€N�NØ˜tÐ%;¸NÈYÑ<VÔ%WÐWÔXÐXÐXÑXð ˜$Ð 4Ð4Ô5Ð5Ð5Ñ5Ø*Ð*Ð*Ñ*ð(Rð (R ð (RÐ9RÐUYÑ9Yð (RÐeið (Rð (Rð (Rð (Rð (Rð (RðT ðX7 uð X7°wð X7Àdð X7ð X7ð X7ñ ÔðX7ðt9+¨uð 9+¸wð 9+Èdð 9+ÐW[ð 9+ð 9+ð 9+ð 9+ð 9+ð 9+ð 9+ð 9+r.   r   )+ry   rJ   Ú
contextlibr   Útypingr   Úurllib.parser   Úuuidr   r   rQ   Úanyio.streams.memoryr   r	   Úpydanticr
   Ússe_starletter   Ústarlette.requestsr   Ústarlette.responsesr   Ústarlette.typesr   r   r   Ú	mcp.typesrl   Ú&mcp.server.auth.middleware.bearer_authr   r   r   Úmcp.server.transport_securityr   r   Úmcp.shared.messager   r   Ú	getLoggerrv   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à Ð Ð Ð Ð Ð Ø qÐ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qÐ qðð ð ð ð ð ð ð ð EÐ DÐ DÐ DÐ DÐ DÐ DÐ Dà	ˆÔ	˜8Ñ	$Ô	$€ðQ+ð Q+ð Q+ð Q+ð Q+ñ Q+ô Q+ð Q+ð Q+ð Q+r.   