@@ -17,9 +17,8 @@ public sealed class HttpListenerSseServerTransport : TransportBase, IServerTrans
1717 private readonly string _serverName ;
1818 private readonly HttpListenerServerProvider _httpServerProvider ;
1919 private readonly ILogger < HttpListenerSseServerTransport > _logger ;
20- private readonly JsonSerializerOptions _jsonOptions ;
21- private CancellationTokenSource ? _shutdownCts ;
22-
20+ private SseResponseStreamTransport ? _sseResponseStreamTransport ;
21+
2322 private string EndpointName => $ "Server (SSE) ({ _serverName } )";
2423
2524 /// <summary>
@@ -44,28 +43,23 @@ public HttpListenerSseServerTransport(string serverName, int port, ILoggerFactor
4443 {
4544 _serverName = serverName ;
4645 _logger = loggerFactory . CreateLogger < HttpListenerSseServerTransport > ( ) ;
47- _jsonOptions = McpJsonUtilities . DefaultOptions ;
48- _httpServerProvider = new HttpListenerServerProvider ( port ) ;
46+ _httpServerProvider = new HttpListenerServerProvider ( port )
47+ {
48+ OnSseConnectionAsync = OnSseConnectionAsync ,
49+ OnMessageAsync = OnMessageAsync ,
50+ } ;
4951 }
5052
5153 /// <inheritdoc/>
5254 public Task StartListeningAsync ( CancellationToken cancellationToken = default )
5355 {
54- _shutdownCts = new CancellationTokenSource ( ) ;
55-
56- _httpServerProvider . InitializeMessageHandler ( HttpMessageHandler ) ;
57- _httpServerProvider . StartAsync ( cancellationToken ) ;
58-
59- SetConnected ( true ) ;
60-
61- return Task . CompletedTask ;
56+ return _httpServerProvider . StartAsync ( cancellationToken ) ;
6257 }
6358
64-
6559 /// <inheritdoc/>
6660 public override async Task SendMessageAsync ( IJsonRpcMessage message , CancellationToken cancellationToken = default )
6761 {
68- if ( ! IsConnected )
62+ if ( ! IsConnected || _sseResponseStreamTransport is null )
6963 {
7064 _logger . TransportNotConnected ( EndpointName ) ;
7165 throw new McpTransportException ( "Transport is not connected" ) ;
@@ -79,10 +73,10 @@ public override async Task SendMessageAsync(IJsonRpcMessage message, Cancellatio
7973
8074 try
8175 {
82- var json = JsonSerializer . Serialize ( message , _jsonOptions . GetTypeInfo < IJsonRpcMessage > ( ) ) ;
76+ var json = JsonSerializer . Serialize ( message , McpJsonUtilities . DefaultOptions . GetTypeInfo < IJsonRpcMessage > ( ) ) ;
8377 _logger . TransportSendingMessage ( EndpointName , id , json ) ;
8478
85- await _httpServerProvider . SendEvent ( json , "message" ) . ConfigureAwait ( false ) ;
79+ await _sseResponseStreamTransport . SendMessageAsync ( message , cancellationToken ) . ConfigureAwait ( false ) ;
8680
8781 _logger . TransportSentMessage ( EndpointName , id ) ;
8882 }
@@ -100,49 +94,47 @@ public override async ValueTask DisposeAsync()
10094 GC . SuppressFinalize ( this ) ;
10195 }
10296
103- private async Task CleanupAsync ( CancellationToken cancellationToken )
97+ private Task CleanupAsync ( CancellationToken cancellationToken )
10498 {
10599 _logger . TransportCleaningUp ( EndpointName ) ;
106100
107- if ( _shutdownCts != null )
108- {
109- await _shutdownCts . CancelAsync ( ) . ConfigureAwait ( false ) ;
110- _shutdownCts . Dispose ( ) ;
111- _shutdownCts = null ;
112- }
113-
114101 _httpServerProvider . Dispose ( ) ;
115-
116102 SetConnected ( false ) ;
103+
117104 _logger . TransportCleanedUp ( EndpointName ) ;
105+ return Task . CompletedTask ;
106+ }
107+
108+ private async Task OnSseConnectionAsync ( Stream responseStream , CancellationToken cancellationToken )
109+ {
110+ await using var sseResponseStreamTransport = new SseResponseStreamTransport ( responseStream ) ;
111+ _sseResponseStreamTransport = sseResponseStreamTransport ;
112+ SetConnected ( true ) ;
113+ await sseResponseStreamTransport . RunAsync ( cancellationToken ) ;
118114 }
119115
120116 /// <summary>
121117 /// Handles HTTP messages received by the HTTP server provider.
122118 /// </summary>
123119 /// <returns>true if the message was accepted (return 202), false otherwise (return 400)</returns>
124- private bool HttpMessageHandler ( string request , CancellationToken cancellationToken )
120+ private async Task < bool > OnMessageAsync ( string request , CancellationToken cancellationToken )
125121 {
126122 _logger . TransportReceivedMessage ( EndpointName , request ) ;
127123
128124 try
129125 {
130- var message = JsonSerializer . Deserialize ( request , _jsonOptions . GetTypeInfo < IJsonRpcMessage > ( ) ) ;
126+ var message = JsonSerializer . Deserialize ( request , McpJsonUtilities . DefaultOptions . GetTypeInfo < IJsonRpcMessage > ( ) ) ;
131127 if ( message != null )
132128 {
133- // Fire-and-forget the message to the message channel
134- Task . Run ( async ( ) =>
129+ string messageId = "(no id)" ;
130+ if ( message is IJsonRpcMessageWithId messageWithId )
135131 {
136- string messageId = "(no id)" ;
137- if ( message is IJsonRpcMessageWithId messageWithId )
138- {
139- messageId = messageWithId . Id . ToString ( ) ;
140- }
141-
142- _logger . TransportReceivedMessageParsed ( EndpointName , messageId ) ;
143- await WriteMessageAsync ( message , cancellationToken ) . ConfigureAwait ( false ) ;
144- _logger . TransportMessageWritten ( EndpointName , messageId ) ;
145- } , cancellationToken ) ;
132+ messageId = messageWithId . Id . ToString ( ) ;
133+ }
134+
135+ _logger . TransportReceivedMessageParsed ( EndpointName , messageId ) ;
136+ await WriteMessageAsync ( message , cancellationToken ) . ConfigureAwait ( false ) ;
137+ _logger . TransportMessageWritten ( EndpointName , messageId ) ;
146138
147139 return true ;
148140 }
0 commit comments