Skip to content

Commit 733f317

Browse files
committed
Fix InvalidOperationException thrown from PipeReader in new Server_ShutsDownQuickly_WhenClientIsConnected test
Example Error: System.InvalidOperationException : Reading is not allowed after reader was completed. Failed ModelContextProtocol.AspNetCore.Tests.MapMcpStatelessTests.Server_ShutsDownQuickly_WhenClientIsConnected [210 ms] Error Message: System.InvalidOperationException : Reading is not allowed after reader was completed. Stack Trace: at System.IO.Pipelines.ThrowHelper.ThrowInvalidOperationException_NoReadingAllowed() at System.IO.Pipelines.Pipe.AdvanceReader(SequencePosition& consumed, SequencePosition& examined) at System.IO.Pipelines.Pipe.DefaultPipeReader.AdvanceTo(SequencePosition consumed) at System.IO.Pipelines.PipeReaderStream.HandleReadResult(ReadResult result, Span`1 buffer) at System.IO.Pipelines.PipeReaderStream.HandleReadResult(ReadResult result, Span`1 buffer) at System.IO.Pipelines.PipeReaderStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken) at ModelContextProtocol.AspNetCore.Tests.Utils.KestrelInMemoryConnection.DuplexStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken) in /_/tests/ModelContextProtocol.AspNetCore.Tests/Utils/KestrelInMemoryConnection.cs:line 81 at System.Net.Http.HttpConnection.FillAsync(Boolean async) at System.Net.Http.HttpConnection.ChunkedEncodingReadStream.ReadAsyncCore(Memory`1 buffer, CancellationToken cancellationToken) at System.Net.ServerSentEvents.SseParser`1.FillLineBufferAsync(CancellationToken cancellationToken) at System.Net.ServerSentEvents.SseParser`1.EnumerateAsync(CancellationToken cancellationToken)+MoveNext() at System.Net.ServerSentEvents.SseParser`1.EnumerateAsync(CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() at ModelContextProtocol.Client.StreamableHttpClientSessionTransport.ProcessSseResponseAsync(Stream responseStream, JsonRpcRequest relatedRpcRequest, CancellationToken cancellationToken) in /_/src/ModelContextProtocol.Core/Client/StreamableHttpClientSessionTransport.cs:line 192 at ModelContextProtocol.Client.StreamableHttpClientSessionTransport.ProcessSseResponseAsync(Stream responseStream, JsonRpcRequest relatedRpcRequest, CancellationToken cancellationToken) in /_/src/ModelContextProtocol.Core/Client/StreamableHttpClientSessionTransport.cs:line 192 at ModelContextProtocol.Client.StreamableHttpClientSessionTransport.ReceiveUnsolicitedMessagesAsync() in /_/src/ModelContextProtocol.Core/Client/StreamableHttpClientSessionTransport.cs:line 187 at ModelContextProtocol.Client.StreamableHttpClientSessionTransport.DisposeAsync() in /_/src/ModelContextProtocol.Core/Client/StreamableHttpClientSessionTransport.cs:line 149 at ModelContextProtocol.Client.McpClientImpl.DisposeAsync() in /_/src/ModelContextProtocol.Core/Client/McpClientImpl.cs:line 235 at ModelContextProtocol.AspNetCore.Tests.MapMcpTests.Server_ShutsDownQuickly_WhenClientIsConnected() in /_/tests/ModelContextProtocol.AspNetCore.Tests/MapMcpTests.cs:line 238 at ModelContextProtocol.AspNetCore.Tests.MapMcpTests.Server_ShutsDownQuickly_WhenClientIsConnected() in /_/tests/ModelContextProtocol.AspNetCore.Tests/MapMcpTests.cs:line 238 --- End of stack trace from previous location --- Standard Output Messages: | [2025-10-10T23:37:09] Microsoft.Hosting.Lifetime Information: Now listening on: http://localhost:5000 | [2025-10-10T23:37:09] Microsoft.Hosting.Lifetime Information: Application started. Press Ctrl+C to shut down. | [2025-10-10T23:37:09] Microsoft.Hosting.Lifetime Information: Hosting environment: Production | [2025-10-10T23:37:09] Microsoft.Hosting.Lifetime Information: Content root path: /home/runner/work/csharp-sdk/csharp-sdk/artifacts/bin/ModelContextProtocol.AspNetCore.Tests/Debug/net9.0 | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request starting HTTP/1.1 POST http://localhost:5000/ - application/json;+charset=utf-8 - | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executing endpoint 'MCP Streamable HTTP | HTTP: POST /' | [2025-10-10T23:37:09] ModelContextProtocol.Server.McpServer Information: Server (ModelContextProtocol.AspNetCore.Tests 1.0.0.0) method 'initialize' request handler called. | [2025-10-10T23:37:09] ModelContextProtocol.Server.McpServer Information: Server (ModelContextProtocol.AspNetCore.Tests 1.0.0.0), Client (ModelContextProtocol.AspNetCore.Tests 1.0.0.0) method 'initialize' request handler completed. | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executed endpoint 'MCP Streamable HTTP | HTTP: POST /' | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request finished HTTP/1.1 POST http://localhost:5000/ - 200 - text/event-stream 1.4557ms | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request starting HTTP/1.1 GET http://localhost:5000/ - - - | [2025-10-10T23:37:09] ModelContextProtocol.Client.McpClient Information: Client (ModelContextProtocol.AspNetCore.Tests 1.0.0.0) client received server '{"name":"ModelContextProtocol.AspNetCore.Tests","version":"1.0.0.0"}' capabilities: '{"logging":{},"tools":{"listChanged":true}}'. | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executing endpoint 'MCP Streamable HTTP | HTTP: GET /' | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request starting HTTP/1.1 POST http://localhost:5000/ - application/json;+charset=utf-8 - | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executing endpoint 'MCP Streamable HTTP | HTTP: POST /' | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executed endpoint 'MCP Streamable HTTP | HTTP: POST /' | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request finished HTTP/1.1 POST http://localhost:5000/ - 202 0 - 0.4372ms | [2025-10-10T23:37:09] ModelContextProtocol.Client.McpClient Information: Client (ModelContextProtocol.AspNetCore.Tests 1.0.0.0) client created and connected. | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request starting HTTP/1.1 POST http://localhost:5000/ - application/json;+charset=utf-8 - | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executing endpoint 'MCP Streamable HTTP | HTTP: POST /' | [2025-10-10T23:37:09] ModelContextProtocol.Server.McpServer Information: Server (ModelContextProtocol.AspNetCore.Tests 1.0.0.0), Client (ModelContextProtocol.AspNetCore.Tests 1.0.0.0) method 'tools/list' request handler called. | [2025-10-10T23:37:09] ModelContextProtocol.Server.McpServer Information: Server (ModelContextProtocol.AspNetCore.Tests 1.0.0.0), Client (ModelContextProtocol.AspNetCore.Tests 1.0.0.0) method 'tools/list' request handler completed. | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executed endpoint 'MCP Streamable HTTP | HTTP: POST /' | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request finished HTTP/1.1 POST http://localhost:5000/ - 200 - text/event-stream 0.6495ms | [2025-10-10T23:37:09] Microsoft.Hosting.Lifetime Information: Application is shutting down... | [2025-10-10T23:37:09] Microsoft.AspNetCore.Routing.EndpointMiddleware Information: Executed endpoint 'MCP Streamable HTTP | HTTP: GET /' | [2025-10-10T23:37:09] Microsoft.AspNetCore.Hosting.Diagnostics Information: Request finished HTTP/1.1 GET http://localhost:5000/ - 200 - text/event-stream 16.9226ms | [2025-10-10T23:37:09] ModelContextProtocol.Client.McpClient Information: http://localhost:5000/ message processing canceled. | [2025-10-10T23:37:09] ModelContextProtocol.Client.StreamableHttpClientSessionTransport Warning: http://localhost:5000/ shutdown failed. System.Net.Http.HttpRequestException: The KestrelInMemoryTransport has been shut down. (localhost:5000) ---> System.IO.IOException: The KestrelInMemoryTransport has been shut down. at ModelContextProtocol.AspNetCore.Tests.Utils.KestrelInMemoryTransport.CreateConnection(EndPoint endpoint) in /_/tests/ModelContextProtocol.AspNetCore.Tests/Utils/KestrelInMemoryTransport.cs:line 18 at ModelContextProtocol.AspNetCore.Tests.Utils.KestrelInMemoryTest.<.ctor>b__0_0(SocketsHttpConnectionContext context, CancellationToken token) in /_/tests/ModelContextProtocol.AspNetCore.Tests/Utils/KestrelInMemoryTest.cs:line 23 at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.InjectNewHttp11ConnectionAsync(QueueItem queueItem) at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at ModelContextProtocol.Client.McpHttpClient.SendAsync(HttpRequestMessage request, JsonRpcMessage message, CancellationToken cancellationToken) in /_/src/ModelContextProtocol.Core/Client/McpHttpClient.cs:line 22 at ModelContextProtocol.Client.StreamableHttpClientSessionTransport.SendDeleteRequest() in /_/src/ModelContextProtocol.Core/Client/StreamableHttpClientSessionTransport.cs:line 249
1 parent 2c9c85e commit 733f317

File tree

1 file changed

+3
-1
lines changed

1 file changed

+3
-1
lines changed

tests/ModelContextProtocol.AspNetCore.Tests/Utils/KestrelInMemoryConnection.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ protected override void Dispose(bool disposing)
9393
{
9494
// Signal to the server the the client has closed the connection, and dispose the client-half of the Pipes.
9595
ThreadPool.UnsafeQueueUserWorkItem(static cts => ((CancellationTokenSource)cts!).Cancel(), connectionClosedCts);
96-
duplexPipe.Input.Complete();
96+
// We could also call duplexPipe.Input.Complete(), but it's not necessary. It can cause issues with the
97+
// Server_ShutsDownQuickly_WhenClientIsConnected test where the HttpClient calls Dispose on the Stream underlying
98+
// a GET SSE response while still reading from it, resulting in an InvalidOperationException from the PipeReader.
9799
duplexPipe.Output.Complete();
98100
}
99101

0 commit comments

Comments
 (0)