diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0874fa2..67d3e52 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -35,7 +35,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/ModelContextProtocol.sln b/ModelContextProtocol.sln
index 8bd8f62..4b9250c 100644
--- a/ModelContextProtocol.sln
+++ b/ModelContextProtocol.sln
@@ -31,9 +31,11 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B6FB2B28-D5DE-4654-BE9A-45E305DE4852}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
+ Directory.Packages.props = Directory.Packages.props
global.json = global.json
LICENSE = LICENSE
logo.png = logo.png
+ nuget.config = nuget.config
README.MD = README.MD
version.json = version.json
EndProjectSection
diff --git a/tests/ModelContextProtocol.TestServer/Program.cs b/tests/ModelContextProtocol.TestServer/Program.cs
index 889b53b..ab28ef3 100644
--- a/tests/ModelContextProtocol.TestServer/Program.cs
+++ b/tests/ModelContextProtocol.TestServer/Program.cs
@@ -1,5 +1,4 @@
using System.Text;
-using System.Text.Json;
using ModelContextProtocol.Protocol.Messages;
using ModelContextProtocol.Protocol.Transport;
using ModelContextProtocol.Protocol.Types;
diff --git a/tests/ModelContextProtocol.Tests/Client/McpClientFactoryTests.cs b/tests/ModelContextProtocol.Tests/Client/McpClientFactoryTests.cs
index bf24770..ce4c038 100644
--- a/tests/ModelContextProtocol.Tests/Client/McpClientFactoryTests.cs
+++ b/tests/ModelContextProtocol.Tests/Client/McpClientFactoryTests.cs
@@ -17,34 +17,28 @@ public class McpClientFactoryTests
[Fact]
public async Task CreateAsync_WithInvalidArgs_Throws()
{
- await Assert.ThrowsAsync("serverConfig", () => McpClientFactory.CreateAsync((McpServerConfig)null!, _defaultOptions));
+ await Assert.ThrowsAsync("serverConfig", () => McpClientFactory.CreateAsync((McpServerConfig)null!, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
- await Assert.ThrowsAsync("clientOptions", () => McpClientFactory.CreateAsync(
- new McpServerConfig()
+ await Assert.ThrowsAsync("clientOptions", () => McpClientFactory.CreateAsync(new McpServerConfig()
{
Name = "name",
Id = "id",
TransportType = TransportTypes.StdIo,
- }, (McpClientOptions)null!));
+ }, (McpClientOptions)null!, cancellationToken: TestContext.Current.CancellationToken));
- await Assert.ThrowsAsync("serverConfig", () => McpClientFactory.CreateAsync(
- new McpServerConfig()
+ await Assert.ThrowsAsync("serverConfig", () => McpClientFactory.CreateAsync(new McpServerConfig()
{
Name = "name",
Id = "id",
TransportType = "somethingunsupported",
- },
- _defaultOptions));
+ }, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
- await Assert.ThrowsAsync(() => McpClientFactory.CreateAsync(
- new McpServerConfig()
+ await Assert.ThrowsAsync(() => McpClientFactory.CreateAsync(new McpServerConfig()
{
Name = "name",
Id = "id",
TransportType = TransportTypes.StdIo,
- },
- _defaultOptions,
- (_, __) => null!));
+ }, _defaultOptions, (_, __) => null!, cancellationToken: TestContext.Current.CancellationToken));
}
[Fact]
@@ -68,7 +62,8 @@ public class McpClientFactoryTests
await using var client = await McpClientFactory.CreateAsync(
serverConfig,
_defaultOptions,
- (_, __) => new NopTransport());
+ (_, __) => new NopTransport(),
+ cancellationToken: TestContext.Current.CancellationToken);
// Assert
Assert.NotNull(client);
@@ -91,7 +86,8 @@ public class McpClientFactoryTests
await using var client = await McpClientFactory.CreateAsync(
serverConfig,
_defaultOptions,
- (_, __) => new NopTransport());
+ (_, __) => new NopTransport(),
+ cancellationToken: TestContext.Current.CancellationToken);
// Assert
Assert.NotNull(client);
@@ -114,7 +110,8 @@ public class McpClientFactoryTests
await using var client = await McpClientFactory.CreateAsync(
serverConfig,
_defaultOptions,
- (_, __) => new NopTransport());
+ (_, __) => new NopTransport(),
+ cancellationToken: TestContext.Current.CancellationToken);
// Assert
Assert.NotNull(client);
@@ -144,7 +141,8 @@ public class McpClientFactoryTests
await using var client = await McpClientFactory.CreateAsync(
serverConfig,
_defaultOptions,
- (_, __) => new NopTransport());
+ (_, __) => new NopTransport(),
+ cancellationToken: TestContext.Current.CancellationToken);
// Assert
Assert.NotNull(client);
@@ -171,7 +169,7 @@ public class McpClientFactoryTests
};
// act & assert
- await Assert.ThrowsAsync(() => McpClientFactory.CreateAsync(config, _defaultOptions));
+ await Assert.ThrowsAsync(() => McpClientFactory.CreateAsync(config, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
}
private sealed class NopTransport : IClientTransport
@@ -191,7 +189,7 @@ public class McpClientFactoryTests
{
switch (message)
{
- case JsonRpcRequest request:
+ case JsonRpcRequest:
_channel.Writer.TryWrite(new JsonRpcResponse
{
Id = ((JsonRpcRequest)message).Id,
diff --git a/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs b/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs
index 4fda215..af13cc7 100644
--- a/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs
+++ b/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs
@@ -1,11 +1,12 @@
using ModelContextProtocol.Client;
-using ModelContextProtocol.Configuration;
-using ModelContextProtocol.Protocol.Messages;
-using ModelContextProtocol.Protocol.Transport;
-using ModelContextProtocol.Protocol.Types;
using Microsoft.Extensions.AI;
using OpenAI;
+using ModelContextProtocol.Protocol.Types;
+using ModelContextProtocol.Protocol.Messages;
using System.Text.Json;
+using ModelContextProtocol.Configuration;
+using ModelContextProtocol.Protocol.Transport;
+using Xunit.Sdk;
namespace ModelContextProtocol.Tests;
@@ -61,8 +62,8 @@ public class ClientIntegrationTests : IClassFixture t.Name == "echo");
- var result = await echo.InvokeAsync([new KeyValuePair("message", "Hello MCP!")]);
+ var result = await echo.InvokeAsync([new KeyValuePair("message", "Hello MCP!")], TestContext.Current.CancellationToken);
// assert
Assert.NotNull(result);
@@ -119,7 +120,7 @@ public class ClientIntegrationTests : IClassFixture 0);
@@ -276,17 +277,17 @@ public class ClientIntegrationTests : IClassFixture 0);
@@ -340,7 +341,7 @@ public class ClientIntegrationTests : IClassFixture
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs
index 76616de..e8ca56b 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs
@@ -7,7 +7,6 @@ using ModelContextProtocol.Tests.Utils;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using Moq;
-using System.Diagnostics;
namespace ModelContextProtocol.Tests.Server;
@@ -100,7 +99,7 @@ public class McpServerTests
server.GetType().GetField("_isInitializing", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.SetValue(server, true);
// Act & Assert
- await Assert.ThrowsAsync(() => server.StartAsync());
+ await Assert.ThrowsAsync(() => server.StartAsync(TestContext.Current.CancellationToken));
}
[Fact]
@@ -110,7 +109,7 @@ public class McpServerTests
await using var server = new McpServer(_serverTransport.Object, _options, _loggerFactory.Object, _serviceProvider);
server.IsInitialized = true;
- await server.StartAsync();
+ await server.StartAsync(TestContext.Current.CancellationToken);
// Assert
_serverTransport.Verify(t => t.StartListeningAsync(It.IsAny()), Times.Never);
@@ -123,7 +122,7 @@ public class McpServerTests
await using var server = new McpServer(_serverTransport.Object, _options, _loggerFactory.Object, _serviceProvider);
// Act
- await server.StartAsync();
+ await server.StartAsync(TestContext.Current.CancellationToken);
// Assert
_serverTransport.Verify(t => t.StartListeningAsync(It.IsAny()), Times.Once);
@@ -135,17 +134,16 @@ public class McpServerTests
await using var transport = new TestServerTransport();
await using var server = new McpServer(transport, _options, _loggerFactory.Object, _serviceProvider);
- await server.StartAsync();
+ await server.StartAsync(TestContext.Current.CancellationToken);
// Send initialized notification
- await transport.SendMessageAsync(
- new JsonRpcNotification
+ await transport.SendMessageAsync(new JsonRpcNotification
{
Method = "notifications/initialized"
}
- );
+, TestContext.Current.CancellationToken);
- await Task.Delay(50);
+ await Task.Delay(50, TestContext.Current.CancellationToken);
Assert.True(server.IsInitialized);
}
@@ -171,7 +169,7 @@ public class McpServerTests
await using var server = new McpServer(transport, _options, _loggerFactory.Object, _serviceProvider);
server.ClientCapabilities = new ClientCapabilities { Sampling = new SamplingCapability() };
- await server.StartAsync();
+ await server.StartAsync(TestContext.Current.CancellationToken);
// Act
var result = await server.RequestSamplingAsync(new CreateMessageRequestParams { Messages = [] }, CancellationToken.None);
@@ -200,7 +198,7 @@ public class McpServerTests
await using var transport = new TestServerTransport();
await using var server = new McpServer(transport, _options, _loggerFactory.Object, _serviceProvider);
server.ClientCapabilities = new ClientCapabilities { Roots = new RootsCapability() };
- await server.StartAsync();
+ await server.StartAsync(TestContext.Current.CancellationToken);
// Act
var result = await server.RequestRootsAsync(new ListRootsRequestParams(), CancellationToken.None);
@@ -588,7 +586,7 @@ public class McpServerTests
Temperature = 0.75f,
MaxOutputTokens = 42,
StopSequences = ["."],
- });
+ }, TestContext.Current.CancellationToken);
Assert.Equal("amazingmodel", response.ModelId);
Assert.Equal(ChatFinishReason.Stop, response.FinishReason);
diff --git a/tests/ModelContextProtocol.Tests/SseIntegrationTests.cs b/tests/ModelContextProtocol.Tests/SseIntegrationTests.cs
index 6451e9e..48f91dc 100644
--- a/tests/ModelContextProtocol.Tests/SseIntegrationTests.cs
+++ b/tests/ModelContextProtocol.Tests/SseIntegrationTests.cs
@@ -37,13 +37,17 @@ public class SseIntegrationTests
};
// Act
- await using var client = await McpClientFactory.CreateAsync(defaultConfig, defaultOptions, loggerFactory: loggerFactory);
+ await using var client = await McpClientFactory.CreateAsync(
+ defaultConfig,
+ defaultOptions,
+ loggerFactory: loggerFactory,
+ cancellationToken: TestContext.Current.CancellationToken);
// Wait for SSE connection to be established
await server.WaitForConnectionAsync(TimeSpan.FromSeconds(10));
// Send a test message through POST endpoint
- await client.SendNotificationAsync("test/message", new { message = "Hello, SSE!" });
+ await client.SendNotificationAsync("test/message", new { message = "Hello, SSE!" }, TestContext.Current.CancellationToken);
// Assert
Assert.True(true);
@@ -53,10 +57,7 @@ public class SseIntegrationTests
[Trait("Execution", "Manual")]
public async Task ConnectAndReceiveMessage_EverythingServerWithSse()
{
- if (!EverythingSseServerFixture.IsDockerAvailable)
- {
- return;
- }
+ Assert.SkipWhen(!EverythingSseServerFixture.IsDockerAvailable, "docker is not available");
using var loggerFactory = LoggerFactory.Create(builder =>
builder.AddConsole()
@@ -82,8 +83,12 @@ public class SseIntegrationTests
};
// Create client and run tests
- await using var client = await McpClientFactory.CreateAsync(defaultConfig, defaultOptions, loggerFactory: loggerFactory);
- var tools = await client.ListToolsAsync().ToListAsync();
+ await using var client = await McpClientFactory.CreateAsync(
+ defaultConfig,
+ defaultOptions,
+ loggerFactory: loggerFactory,
+ cancellationToken: TestContext.Current.CancellationToken);
+ var tools = await client.ListToolsAsync(TestContext.Current.CancellationToken).ToListAsync(TestContext.Current.CancellationToken);
// assert
Assert.NotEmpty(tools);
@@ -93,10 +98,7 @@ public class SseIntegrationTests
[Trait("Execution", "Manual")]
public async Task Sampling_Sse_EverythingServer()
{
- if (!EverythingSseServerFixture.IsDockerAvailable)
- {
- return;
- }
+ Assert.SkipWhen(!EverythingSseServerFixture.IsDockerAvailable, "docker is not available");
// arrange
using var loggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(builder =>
@@ -147,17 +149,19 @@ public class SseIntegrationTests
},
};
- await using var client = await McpClientFactory.CreateAsync(defaultConfig, defaultOptions, loggerFactory: loggerFactory);
+ await using var client = await McpClientFactory.CreateAsync(
+ defaultConfig,
+ defaultOptions,
+ loggerFactory: loggerFactory,
+ cancellationToken: TestContext.Current.CancellationToken);
// Call the server's sampleLLM tool which should trigger our sampling handler
- var result = await client.CallToolAsync(
- "sampleLLM",
- new Dictionary
+ var result = await client.CallToolAsync("sampleLLM", new Dictionary
{
["prompt"] = "Test prompt",
["maxTokens"] = 100
}
- );
+, TestContext.Current.CancellationToken);
// assert
Assert.NotNull(result);
@@ -194,13 +198,17 @@ public class SseIntegrationTests
};
// Act
- await using var client = await McpClientFactory.CreateAsync(defaultConfig, defaultOptions, loggerFactory: loggerFactory);
+ await using var client = await McpClientFactory.CreateAsync(
+ defaultConfig,
+ defaultOptions,
+ loggerFactory: loggerFactory,
+ cancellationToken: TestContext.Current.CancellationToken);
// Wait for SSE connection to be established
await server.WaitForConnectionAsync(TimeSpan.FromSeconds(10));
// Send a test message through POST endpoint
- await client.SendNotificationAsync("test/message", new { message = "Hello, SSE!" });
+ await client.SendNotificationAsync("test/message", new { message = "Hello, SSE!" }, TestContext.Current.CancellationToken);
// Assert
Assert.True(true);
@@ -233,7 +241,11 @@ public class SseIntegrationTests
};
// Act
- await using var client = await McpClientFactory.CreateAsync(defaultConfig, defaultOptions, loggerFactory: loggerFactory);
+ await using var client = await McpClientFactory.CreateAsync(
+ defaultConfig,
+ defaultOptions,
+ loggerFactory: loggerFactory,
+ cancellationToken: TestContext.Current.CancellationToken);
// Wait for SSE connection to be established
await server.WaitForConnectionAsync(TimeSpan.FromSeconds(10));
@@ -251,7 +263,7 @@ public class SseIntegrationTests
await server.SendTestNotificationAsync("Hello from server!");
// Assert
- var message = await receivedNotification.Task.WaitAsync(TimeSpan.FromSeconds(10));
+ var message = await receivedNotification.Task.WaitAsync(TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken);
Assert.Equal("Hello from server!", message);
}
@@ -282,7 +294,11 @@ public class SseIntegrationTests
};
// Act
- await using var client = await McpClientFactory.CreateAsync(defaultConfig, defaultOptions, loggerFactory: loggerFactory);
+ await using var client = await McpClientFactory.CreateAsync(
+ defaultConfig,
+ defaultOptions,
+ loggerFactory: loggerFactory,
+ cancellationToken: TestContext.Current.CancellationToken);
var mcpClient = (McpClient)client;
var transport = (SseClientTransport)mcpClient.Transport;
@@ -290,6 +306,6 @@ public class SseIntegrationTests
await server.WaitForConnectionAsync(TimeSpan.FromSeconds(10));
// Assert
- await Assert.ThrowsAsync(async () => await transport.ConnectAsync());
+ await Assert.ThrowsAsync(async () => await transport.ConnectAsync(TestContext.Current.CancellationToken));
}
}
diff --git a/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs b/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs
index 186fee2..97f9348 100644
--- a/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs
+++ b/tests/ModelContextProtocol.Tests/SseServerIntegrationTests.cs
@@ -53,7 +53,7 @@ public class SseServerIntegrationTests : IClassFixture
+ var result = await client.CallToolAsync("sampleLLM", new Dictionary
{
["prompt"] = "Test prompt",
["maxTokens"] = 100
- }
- );
+ },
+ TestContext.Current.CancellationToken);
// assert
Assert.NotNull(result);
diff --git a/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs b/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs
index 67fd84c..26aaecd 100644
--- a/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs
+++ b/tests/ModelContextProtocol.Tests/Transport/SseClientTransportTests.cs
@@ -95,7 +95,7 @@ public class SseClientTransportTests
};
};
- await transport.ConnectAsync();
+ await transport.ConnectAsync(TestContext.Current.CancellationToken);
}
[Fact]
@@ -174,7 +174,7 @@ public class SseClientTransportTests
}
};
- await transport.ConnectAsync();
+ await transport.ConnectAsync(TestContext.Current.CancellationToken);
await transport.SendMessageAsync(new JsonRpcRequest() { Method = "initialize", Id = RequestId.FromNumber(44) }, CancellationToken.None);
Assert.True(true);
@@ -213,7 +213,7 @@ public class SseClientTransportTests
}
};
- await transport.ConnectAsync();
+ await transport.ConnectAsync(TestContext.Current.CancellationToken);
await transport.SendMessageAsync(new JsonRpcRequest() { Method = "initialize", Id = RequestId.FromNumber(44) }, CancellationToken.None);
Assert.True(true);
@@ -251,7 +251,7 @@ public class SseClientTransportTests
throw new IOException("Abort");
};
- await transport.ConnectAsync();
+ await transport.ConnectAsync(TestContext.Current.CancellationToken);
Assert.True(transport.MessageReader.TryRead(out var message));
Assert.NotNull(message);
Assert.IsType(message);
diff --git a/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs b/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs
index 76efb6d..a150650 100644
--- a/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs
+++ b/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs
@@ -52,7 +52,7 @@ public class StdioServerTransportTests
{
await using var transport = new StdioServerTransport(_serverOptions);
- await transport.StartListeningAsync();
+ await transport.StartListeningAsync(TestContext.Current.CancellationToken);
Assert.True(transport.IsConnected);
}
@@ -70,12 +70,12 @@ public class StdioServerTransportTests
Console.SetOut(output);
await using var transport = new StdioServerTransport(_serverOptions, NullLoggerFactory.Instance);
- await transport.StartListeningAsync();
+ await transport.StartListeningAsync(TestContext.Current.CancellationToken);
var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
- await transport.SendMessageAsync(message);
+ await transport.SendMessageAsync(message, TestContext.Current.CancellationToken);
var result = output.ToString()?.Trim();
var expected = JsonSerializer.Serialize(message, McpJsonUtilities.DefaultOptions);
@@ -96,7 +96,7 @@ public class StdioServerTransportTests
var message = new JsonRpcRequest { Method = "test" };
- await Assert.ThrowsAsync(() => transport.SendMessageAsync(message));
+ await Assert.ThrowsAsync(() => transport.SendMessageAsync(message, TestContext.Current.CancellationToken));
}
[Fact]
@@ -123,9 +123,9 @@ public class StdioServerTransportTests
Console.SetOut(new StringWriter());
await using var transport = new StdioServerTransport(_serverOptions);
- await transport.StartListeningAsync();
+ await transport.StartListeningAsync(TestContext.Current.CancellationToken);
- var canRead = await transport.MessageReader.WaitToReadAsync();
+ var canRead = await transport.MessageReader.WaitToReadAsync(TestContext.Current.CancellationToken);
Assert.True(canRead, "Nothing to read here from transport message reader");
Assert.True(transport.MessageReader.TryPeek(out var readMessage));
@@ -144,7 +144,7 @@ public class StdioServerTransportTests
public async Task CleanupAsync_Should_Cleanup_Resources()
{
var transport = new StdioServerTransport(_serverOptions);
- await transport.StartListeningAsync();
+ await transport.StartListeningAsync(TestContext.Current.CancellationToken);
await transport.DisposeAsync();