Improve progress reporting (#145)

* Improve progress reporting

- Enable injecting an `IProgress<>` into a tool call to report progress when the client has supplied a progress token
- Add a custom type for ProgressToken and ProgressNotification to map to the schema
- Simplify RequestId to match ProgressToken's shape
- Serialize StdioClientTransport's SendMessageAsync implementation
- Add strongly-typed names for all request methods
- Change all request IDs created by McpJsonRpcEndpoint to include a guid for that endpoint

* Address PR feedback
This commit is contained in:
Stephen Toub 2025-03-31 09:33:16 -04:00 • committed by GitHub
commit 2c75acded8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 627 additions and 228 deletions

View file

@ -118,7 +118,7 @@ internal sealed class SseClientSessionTransport : TransportBase
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
// Check if the message was an initialize request
if (message is JsonRpcRequest request && request.Method == "initialize")
if (message is JsonRpcRequest request && request.Method == RequestMethods.Initialize)
{
// If the response is not a JSON-RPC response, it is an SSE message
if (responseContent.Equals("accepted", StringComparison.OrdinalIgnoreCase))

View file

@ -21,6 +21,7 @@ internal sealed class StdioClientStreamTransport : TransportBase
private readonly ILogger _logger;
private readonly JsonSerializerOptions _jsonOptions;
private readonly DataReceivedEventHandler _logProcessErrors;
private readonly SemaphoreSlim _sendLock = new(1, 1);
private Process? _process;
private Task? _readTask;
private CancellationTokenSource? _shutdownCts;
@ -150,6 +151,8 @@ internal sealed class StdioClientStreamTransport : TransportBase
/// <inheritdoc/>
public override async Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
{
using var _ = await _sendLock.LockAsync(cancellationToken).ConfigureAwait(false);
if (!IsConnected || _process?.HasExited == true)
{
_logger.TransportNotConnected(EndpointName);