
    Cj&0                        S r SSKrSSKJr  SSKJr  SSKJr  SSKJ	r	J
r
  SSKrSSKJrJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJrJrJr  SSKJr  SSKJrJrJ r   SSK!J"r"J#r#  SSK$J%r%J&r&  \RN                  " \(5      r) " S S5      r*g)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                      ^  \ rS rSr% Sr\\S'   \\\	\
\-     4   \S'   \\\4   \S'   \\S'   SS\S	\S-  S
S4U 4S jjjr\S\S\S\4S j5       rS\S\S\S
S4S jrSrU =r$ )SseServerTransportA   a  
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                 >  > [         TU ]  5         SU;   d"  UR                  S5      (       d  SU;   d  SU;   a  [        SU S35      eUR                  S5      (       d  SU-   nXl        0 U l        0 U l        [        U5      U l        [        R                  SU 35        g	)
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      `/home/rurouni/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/mcp/server/sse.pyr'   SseServerTransport.__init__T   s    . 	 H 3 3D 9 9SH_PSW_P_"8* -B B  ""3''X~H!$&!!45FGEhZPQ    scopereceivesendc                  ^^^^^^^#    US   S:w  a   [         R                  S5        [        S5      e[        X5      nU R                  R                  USS9I S h  vN nU(       a  U" XU5      I S h  vN   [        S5      e[         R                  S5        [        R                  " S	5      u  mn[        R                  " S	5      u  nm[        5       mUR                  S
5      n[        U[        5      (       a  [        U5      U R                  T'   TU R                  T'   [         R                  ST 35        UR                  SS5      n	U	R!                  S5      U R"                  -   n
[%        U
5       STR&                   3m[        R                  [(        [*        [,        4      " S	5      u  mmUUU4S jm [        R.                  " 5        IS h  vN nS[0        S[2        S[4        4UUUUU4S jjn[         R                  S5        UR7                  XX#5        [         R                  S5        Xg47v   S S S 5      IS h  vN   U R                  R9                  TS 5        U R                  R9                  TS 5        g  GN% GN N NE! , IS h  vN  (       d  f       NZ= f! U R                  R9                  TS 5        U R                  R9                  TS 5        f = f7f)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                  B  >#    [         R                  S5        T IS h  vN   T IS h  vN   TR                  STS.5      I S h  vN   [         R                  ST 35        T  S h  vN n [         R                  SU  35        TR                  SU R                  R	                  SSS9S.5      I S h  vN   MW   N N Ny NX N
 S S S 5      IS h  vN    O! , IS h  vN  (       d  f       O= fS S S 5      IS h  vN    g ! , IS h  vN  (       d  f       g = f7f)	NzStarting SSE writerr   )eventdatazSent endpoint event: zSending message via SSE: messageT)by_aliasexclude_none)r*   r+   r3   r?   model_dump_json)session_messageclient_post_uri_datasse_stream_writerwrite_stream_readers    r.   
sse_writer2SseServerTransport.connect_sse.<locals>.sse_writer   s     LL./((*=*=',,zK_-`aaa45I4JKL-@ /LL#<_<M!NO+00%.$3$;$;$K$KUYhl$K$m   )*=a .A	 +>*=*=*=*=*=((((((s   DB<DDB>DCC C%C)C
*C-AC5C
6C<D>D CCCCDCDC0	C" C0	,D3D>D?DDDDDr1   r2   r3   c                   >#    [        TTS9" XU5      I Sh  vN   TR                  5       I Sh  vN   TR                  5       I Sh  vN   TR                  5       I Sh  vN   [        R                  " ST 35        g Nf NP N: N$7f)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+   )r1   r2   r3   read_stream_writer
session_idsse_stream_readerrG   rF   s      r.   response_wrapper8SseServerTransport.connect_sse.<locals>.response_wrapper   s      .6G^hi   -33555-44666+22444MM$@"MN 664sC   BA?BBBB	B B!BBBB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,   r1   r2   r3   requesterror_responseread_streamwrite_streamr9   r:   full_message_path_for_clienttgrQ   rD   rN   rO   rP   rE   rG   rF   s                @@@@@@@r.   connect_sseSseServerTransport.connect_sse~   sv    =F"LL@AHII %)#~~>>wPU>VV 66689901 +0*K*KA*N'K,1,M,Ma,P))W
yy d-../DT/JD  ,0B!!*-4ZLAB IIk2.	 (1'7'7'<t~~'M$ #((D"E!FlS]SaSaRbc/4/P/PQUVY[^V^Q_/`ab/c,,		7..00BO% O' OQU O O 9:.wE>?"11) 102 %%))*d;  $$Z6c W6j 10002 %%))*d;  $$Z6s   AK!J K!3J4EK!9J$ JJ$ A!J
7J$ JJ$ :K!K!J$ J$ 
J!JJ!J$ $:KK!c                 R  #    [         R                  S5        [        X5      nU R                  R	                  USS9I S h  vN nU(       a  U" XU5      I S h  vN $ UR
                  R                  S5      nUc0  [         R                  S5        [        SSS9nU" XU5      I S h  vN $  [        US	9n[         R                  S
U 35        U R                  R                  U5      n	U	(       d3  [         R                  SU 35        [        SSS9nU" XU5      I S h  vN $ UR                  S5      n
[        U
[        5      (       a  [        U
5      OS nXR                  R                  U5      :w  a1  [         R                  SU5        [        SSS9nU" XU5      I S h  vN $ UR!                  5       I S h  vN n[         R                  SU 35         ["        R$                  R'                  U5      n[         R                  SU 35        [/        US9n[1        XS9n[         R                  SU 35        [        SSS9nU" XU5      I S h  vN   U	R-                  U5      I S h  vN   g  GN+ GN GN! [         a7    [         R                  SU 35        [        SSS9nU" XU5      I S h  vN  s $ f = f GN GN GN! [(         aU  n[         R+                  S5        [        SSS9nU" XU5      I S h  vN    U	R-                  U5      I S h  vN     S nAg S nAff = f N N7f)NzHandling POST messageTr7   rO   z#Received request without session_idzsession_id is requiredi  )status_code)rZ   zParsed session ID: zReceived invalid session ID: zInvalid session IDzCould not find session for ID: zCould not find sessioni  r9   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   rT   query_paramsrW   warningr   r   r)   r   rX   r   r   r   bodytypesJSONRPCMessagemodel_validate_jsonr
   	exceptionr3   r   r   )r,   r1   r2   r3   r`   ra   session_id_paramresponserO   writerr9   	requestorrp   r?   errrk   rC   s                    r.   handle_post_message&SseServerTransport.handle_post_message   s    ,-%)  $~~>>wPT>UU'==="//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yy 3=dDU3V3V)$/\`	,,00<< NNXZde 8cJH!%$777\\^#tf-.	**>>tDGLL5gY?@ )A(D:?:KLMJC8ut,,,kk/***i V= 8
  	8NN:;K:LMN 4#FH!%$7777	8 8 8#  	67 9sKH54000++c"""	 	-*s   >L' I+L'I.AL'&I1'L',!I4 AL'J8BL'J; L'7J>8L'7K A L'L#L'%L%&L'.L'1L'48J5,J/-J52L'4J55L';L'>L'
L +L6K97LLLL'L  L'%L')r   r   r   r   )N)__name__
__module____qualname____firstlineno____doc__r\   __annotations__r[   r   r	   r   	Exceptionr   r   r   r'   r   r   r   r   rf   rz   __static_attributes____classcell__)r-   s   @r.   r   r   A   s    	 Nt%;NY<V%WWXX $ 4455**(R (R9RUY9Y (Rei (R (RT X7u X7w X7d X7 X7t9+u 9+w 9+d 9+W[ 9+ 9+r0   r   )+r   rM   
contextlibr   typingr   urllib.parser   uuidr   r   rU   anyio.streams.memoryr   r	   pydanticr
   sse_starletter   starlette.requestsr   starlette.responsesr   starlette.typesr   r   r   	mcp.typesrq   &mcp.server.auth.middleware.bearer_authr   r   r   mcp.server.transport_securityr   r   mcp.shared.messager   r   	getLoggerr|   r*   r    r0   r.   <module>r      sd   %N  *     R $ - & ( 0 0  q q E			8	$Q+ Q+r0   