diff --git a/src/mcpdotnet/Client/McpClient.cs b/src/mcpdotnet/Client/McpClient.cs
index 4195f5d..c806d91 100644
--- a/src/mcpdotnet/Client/McpClient.cs
+++ b/src/mcpdotnet/Client/McpClient.cs
@@ -1,13 +1,15 @@
-using System.Text.Json;
-using McpDotNet.Configuration;
+using McpDotNet.Configuration;
using McpDotNet.Logging;
using McpDotNet.Protocol.Messages;
using McpDotNet.Protocol.Transport;
using McpDotNet.Protocol.Types;
using McpDotNet.Shared;
+
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
+using System.Text.Json;
+
namespace McpDotNet.Client;
///
@@ -16,7 +18,7 @@ internal sealed class McpClient : McpJsonRpcEndpoint, IMcpClient
private readonly McpClientOptions _options;
private readonly ILogger _logger;
private readonly IClientTransport _clientTransport;
-
+
private volatile bool _isInitializing;
///
@@ -44,7 +46,7 @@ internal sealed class McpClient : McpJsonRpcEndpoint, IMcpClient
SetRequestHandler(
"sampling/createMessage",
- request => samplingHandler(request, CancellationTokenSource?.Token ?? default));
+ (request, ct) => samplingHandler(request, ct));
}
if (options.Capabilities?.Roots is { } rootsCapability)
@@ -56,7 +58,7 @@ internal sealed class McpClient : McpJsonRpcEndpoint, IMcpClient
SetRequestHandler(
"roots/list",
- request => rootsHandler(request, CancellationTokenSource?.Token ?? default));
+ (request, ct) => rootsHandler(request, ct));
}
}
diff --git a/src/mcpdotnet/Configuration/McpServerBuilderExtensions.Tools.cs b/src/mcpdotnet/Configuration/McpServerBuilderExtensions.Tools.cs
index c12f0ed..872c550 100644
--- a/src/mcpdotnet/Configuration/McpServerBuilderExtensions.Tools.cs
+++ b/src/mcpdotnet/Configuration/McpServerBuilderExtensions.Tools.cs
@@ -1,11 +1,13 @@
-using System.Reflection;
-using System.Text.Json;
-using McpDotNet.Configuration;
+using McpDotNet.Configuration;
using McpDotNet.Protocol.Types;
using McpDotNet.Server;
using McpDotNet.Utils;
+
using Microsoft.Extensions.AI;
+using System.Reflection;
+using System.Text.Json;
+
namespace McpDotNet;
///
diff --git a/src/mcpdotnet/Server/McpServer.cs b/src/mcpdotnet/Server/McpServer.cs
index b1308bb..764e24e 100644
--- a/src/mcpdotnet/Server/McpServer.cs
+++ b/src/mcpdotnet/Server/McpServer.cs
@@ -1,12 +1,14 @@
-using System.Text.Json.Nodes;
-using McpDotNet.Logging;
+using McpDotNet.Logging;
using McpDotNet.Protocol.Transport;
using McpDotNet.Protocol.Types;
using McpDotNet.Shared;
using McpDotNet.Utils;
+
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
+using System.Text.Json.Nodes;
+
namespace McpDotNet.Server;
///
@@ -107,14 +109,14 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
private void SetPingHandler()
{
- SetRequestHandler("ping",
- request => Task.FromResult(new PingResult()));
+ SetRequestHandler("ping",
+ (request, _) => Task.FromResult(new PingResult()));
}
private void SetInitializeHandler(McpServerOptions options)
{
SetRequestHandler("initialize",
- request =>
+ (request, _) =>
{
ClientCapabilities = request?.Capabilities ?? new();
ClientInfo = request?.ClientInfo;
@@ -133,8 +135,8 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
// This capability is not optional, so return an empty result if there is no handler.
SetRequestHandler("completion/complete",
options.GetCompletionHandler is { } handler ?
- request => handler(new(this, request), CancellationTokenSource?.Token ?? default) :
- request => Task.FromResult(new CompleteResult() { Completion = new() { Values = [], Total = 0, HasMore = false } }));
+ (request, ct) => handler(new(this, request), ct) :
+ (request, ct) => Task.FromResult(new CompleteResult() { Completion = new() { Values = [], Total = 0, HasMore = false } }));
}
private void SetResourcesHandler(McpServerOptions options)
@@ -150,9 +152,8 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
throw new McpServerException("Resources capability was enabled, but ListResources and/or ReadResource handlers were not specified.");
}
- CancellationToken cancellationToken = CancellationTokenSource?.Token ?? default;
- SetRequestHandler("resources/list", request => listResourcesHandler(new(this, request), cancellationToken));
- SetRequestHandler("resources/read", request => readResourceHandler(new(this, request), cancellationToken));
+ SetRequestHandler("resources/list", (request, ct) => listResourcesHandler(new(this, request), ct));
+ SetRequestHandler("resources/read", (request, ct) => readResourceHandler(new(this, request), ct));
if (resourcesCapability.Subscribe is not true)
{
@@ -166,8 +167,8 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
throw new McpServerException("Resources capability was enabled with subscribe support, but SubscribeToResources and/or UnsubscribeFromResources handlers were not specified.");
}
- SetRequestHandler("resources/subscribe", request => subscribeHandler(new(this, request), cancellationToken));
- SetRequestHandler("resources/unsubscribe", request => unsubscribeHandler(new(this, request), cancellationToken));
+ SetRequestHandler("resources/subscribe", (request, ct) => subscribeHandler(new(this, request), ct));
+ SetRequestHandler("resources/unsubscribe", (request, ct) => unsubscribeHandler(new(this, request), ct));
}
private void SetPromptsHandler(McpServerOptions options)
@@ -183,9 +184,8 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
throw new McpServerException("Prompts capability was enabled, but ListPrompts and/or GetPrompt handlers were not specified.");
}
- CancellationToken cancellationToken = CancellationTokenSource?.Token ?? default;
- SetRequestHandler("prompts/list", request => listPromptsHandler(new(this, request), cancellationToken));
- SetRequestHandler("prompts/get", request => getPromptHandler(new(this, request), cancellationToken));
+ SetRequestHandler("prompts/list", (request, ct) => listPromptsHandler(new(this, request), ct));
+ SetRequestHandler("prompts/get", (request, ct) => getPromptHandler(new(this, request), ct));
}
private void SetToolsHandler(McpServerOptions options)
@@ -201,8 +201,7 @@ internal sealed class McpServer : McpJsonRpcEndpoint, IMcpServer
throw new McpServerException("ListTools and/or CallTool handlers were specified but the Tools capability was not enabled.");
}
- CancellationToken cancellationToken = CancellationTokenSource?.Token ?? default;
- SetRequestHandler("tools/list", request => listToolsHandler(new(this, request), cancellationToken));
- SetRequestHandler("tools/call", request => callToolHandler(new(this, request), cancellationToken));
+ SetRequestHandler("tools/list", (request, ct) => listToolsHandler(new(this, request), ct));
+ SetRequestHandler("tools/call", (request, ct) => callToolHandler(new(this, request), ct));
}
}
diff --git a/src/mcpdotnet/Shared/McpJsonRpcEndpoint.cs b/src/mcpdotnet/Shared/McpJsonRpcEndpoint.cs
index 880668b..cd7647f 100644
--- a/src/mcpdotnet/Shared/McpJsonRpcEndpoint.cs
+++ b/src/mcpdotnet/Shared/McpJsonRpcEndpoint.cs
@@ -1,14 +1,16 @@
-using System.Collections.Concurrent;
-using System.Text.Json;
-using McpDotNet.Client;
+using McpDotNet.Client;
using McpDotNet.Logging;
using McpDotNet.Protocol.Messages;
using McpDotNet.Protocol.Transport;
using McpDotNet.Utils;
using McpDotNet.Utils.Json;
+
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
+using System.Collections.Concurrent;
+using System.Text.Json;
+
namespace McpDotNet.Shared;
///
@@ -23,7 +25,7 @@ internal abstract class McpJsonRpcEndpoint : IAsyncDisposable
private readonly ITransport _transport;
private readonly ConcurrentDictionary> _pendingRequests;
private readonly ConcurrentDictionary>> _notificationHandlers;
- private readonly Dictionary>> _requestHandlers = [];
+ private readonly Dictionary>> _requestHandlers = [];
private int _nextRequestId;
private readonly JsonSerializerOptions _jsonOptions;
private readonly ILogger _logger;
@@ -175,7 +177,7 @@ internal abstract class McpJsonRpcEndpoint : IAsyncDisposable
try
{
_logger.RequestHandlerCalled(EndpointName, request.Method);
- var result = await handler(request).ConfigureAwait(false);
+ var result = await handler(request, cancellationToken).ConfigureAwait(false);
_logger.RequestHandlerCompleted(EndpointName, request.Method);
await _transport.SendMessageAsync(new JsonRpcResponse
{
@@ -329,18 +331,18 @@ internal abstract class McpJsonRpcEndpoint : IAsyncDisposable
/// Type of response payload (not full RPC response
/// Method identifier to register for
/// Handler to be called when a request with specified method identifier is received
- protected void SetRequestHandler(string method, Func> handler)
+ protected void SetRequestHandler(string method, Func> handler)
{
Throw.IfNull(method);
Throw.IfNull(handler);
- _requestHandlers[method] = async (request) =>
+ _requestHandlers[method] = async (request, cancellationToken) =>
{
// Convert the params JsonElement to our type using the same options
var jsonString = JsonSerializer.Serialize(request.Params);
var typedRequest = JsonSerializer.Deserialize(jsonString, _jsonOptions);
- return await handler(typedRequest).ConfigureAwait(false);
+ return await handler(typedRequest, cancellationToken).ConfigureAwait(false);
};
}