Skip to content

Add client completion notification and details#1368

Open
stephentoub wants to merge 5 commits intomodelcontextprotocol:mainfrom
stephentoub:completiondetails
Open

Add client completion notification and details#1368
stephentoub wants to merge 5 commits intomodelcontextprotocol:mainfrom
stephentoub:completiondetails

Conversation

@stephentoub
Copy link
Contributor

Introduce a new mechanism for reporting MCP client session completion details, including both graceful and error terminations. Add a Completion property to McpClient, exposing a Task<ClientCompletionDetails> that completes with details about session closure. Implement extensible completion details (including StdioClientCompletionDetails for stdio transports) and propagate them via a new internal TransportClosedException.

Closes #1332
Closes #438

eiriktsarpalis
eiriktsarpalis previously approved these changes Feb 24, 2026
halter73
halter73 previously approved these changes Feb 24, 2026
Copy link
Contributor

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see this implemented for stateful Streamable HTTP when there are 404s as well, but I think this is already a nice improvement even without that part. I have a small preference for the abstract Completion property over the method, but I don't care too much either way on that.

stephentoub and others added 3 commits February 25, 2026 15:40
Introduce a new mechanism for reporting MCP client session completion details, including both graceful and error terminations. Add a Completion property to McpClient, exposing a `Task<ClientCompletionDetails>` that completes with details about session closure. Implement extensible completion details (including StdioClientCompletionDetails for stdio transports) and propagate them via a new internal TransportClosedException.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
halter73
halter73 previously approved these changes Feb 26, 2026
Copy link
Contributor

@halter73 halter73 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out 10x wasn't enough 😭

 Failed Checks:
  - ClientRespectsRetryField: Client MUST respect the retry field, waiting the given number of milliseconds before attempting to reconnect
    Error: Client reconnected very late (5355ms instead of 500ms). Client appears to be ignoring the retry field and using its own backoff strategy.

https://github.com/modelcontextprotocol/csharp-sdk/actions/runs/22415043174/job/64898373590?pr=1368

// after the call to Cancel below, to invoke SetDisconnected.
_disconnectError = new TransportClosedException(new HttpClientCompletionDetails
{
HttpStatusCode = statusCode,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Can you please remove the HttpStatusCode parameter from SetSessionExpired and replace this line with just HttpStatusCode = HttpStatusCode.NotFound? That's only assuming that this is only called given a 404 status code which appears to be that case.

if (_options.TransportMode is not HttpTransportMode.AutoDetect || _getReceiveTask is not null)
{
SetDisconnected();
SetDisconnected(_disconnectError ?? new TransportClosedException(new HttpClientCompletionDetails()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Assuming that the ?? new TransportClosedException(new HttpClientCompletionDetails() logic should be unreachable, can use configure the HttpClientCompletionDetails with an exception stating as much? If not, can you configure the HttpClientCompletionDetails with an exception describing how the client might have disconnected?

@stephentoub
Copy link
Contributor Author

stephentoub commented Feb 27, 2026

It turns out 10x wasn't enough 😭

 Failed Checks:
  - ClientRespectsRetryField: Client MUST respect the retry field, waiting the given number of milliseconds before attempting to reconnect
    Error: Client reconnected very late (5355ms instead of 500ms). Client appears to be ignoring the retry field and using its own backoff strategy.

https://github.com/modelcontextprotocol/csharp-sdk/actions/runs/22415043174/job/64898373590?pr=1368

I think there's a real pre-existing bug lurking.

@halter73
Copy link
Contributor

This appears to be failing the API check due to adding an abstract member even though the McpClient constructor is experimental.

Error: /Users/runner/.dotnet/sdk/10.0.103/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.ApiCompat.ValidatePackage.targets(39,5): error CP0005: Cannot add abstract member 'System.Threading.Tasks.Task<ModelContextProtocol.Client.ClientCompletionDetails> ModelContextProtocol.Client.McpClient.Completion.get' to lib/netstandard2.0/ModelContextProtocol.Core.dll because it does not exist on [Baseline] lib/netstandard2.0/ModelContextProtocol.Core.dll [/Users/runner/work/csharp-sdk/csharp-sdk/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj]

Should we suppress this?

@halter73
Copy link
Contributor

halter73 commented Feb 27, 2026

I think there's a real pre-existing bug lurking.

Maybe, but then why would the retry happen after 5 seconds? The DefaultReconnectionInterval is 1 second, so it definitely could be falling back to that. But even if that were happening (which I kinda doubt), that wouldn't account for most of the delay.

To me, this seems like the main issue is likely with the tests. It might be caused by a low core count CI machine and too much test parallelism causing thread pool starvation. Or maybe some tests not properly cleaning up after themselves causing similar results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stdio transport does not expose process exit code on server launch failure Provide notification of server connection loss

4 participants