Skip to content

Commit b19ab58

Browse files
committed
Work around SocketsHttpHandler bug where it doesn't call DispseAsync on the stream returned by the ConnectCallback
- Move workaround to KestrelInMemoryConnection instead of SseClientSessionTransport which is product code
1 parent 575c2bc commit b19ab58

2 files changed

Lines changed: 3 additions & 11 deletions

File tree

src/ModelContextProtocol/Protocol/Transport/SseClientSessionTransport.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,8 @@ private async Task ReceiveMessagesAsync(CancellationToken cancellationToken)
204204

205205
using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
206206

207-
// A lot of methods in HttpClient, including HttpConnection.FillAsync, do not currently respect any
208-
// cancellation tokens so we have to cancel awaiting ourselves.
209-
// I tried disposing the HttpRequestMessage and HttpResponseMessage instead, but neither of these canceled
210-
// the ongoing body read, and we don't want to dispose an HttpClient we may not own.
211-
var sseEventEnumerator = SseParser.Create(stream).EnumerateAsync(cancellationToken).GetAsyncEnumerator();
212-
while (await sseEventEnumerator.MoveNextAsync().AsTask().WaitAsync(cancellationToken).ConfigureAwait(false))
207+
await foreach (SseItem<string> sseEvent in SseParser.Create(stream).EnumerateAsync(cancellationToken).ConfigureAwait(false))
213208
{
214-
SseItem<string> sseEvent = sseEventEnumerator.Current;
215-
216209
switch (sseEvent.EventType)
217210
{
218211
case "endpoint":

tests/ModelContextProtocol.Tests/Utils/KestrelInMemoryConnection.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,12 @@ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationTo
7777
public override Task FlushAsync(CancellationToken cancellationToken)
7878
=> _writeStream.FlushAsync(cancellationToken);
7979

80-
public override async ValueTask DisposeAsync()
80+
protected override void Dispose(bool disposing)
8181
{
8282
// Signal to the server the the client has closed the connection, and dispose the client-half of the Pipes.
83-
await connectionClosedCts.CancelAsync();
83+
connectionClosedCts.Cancel();
8484
duplexPipe.Input.Complete();
8585
duplexPipe.Output.Complete();
86-
await base.DisposeAsync();
8786
}
8887

8988
// Unsupported stuff

0 commit comments

Comments
 (0)