diff --git a/Directory.Packages.props b/Directory.Packages.props index 3f5540f9d..46180d362 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,10 +5,11 @@ 9.0.11 10.0.3 10.3.0 + 9.10.2 - - + + @@ -17,6 +18,16 @@ + + + + + + + + + + @@ -34,6 +45,7 @@ + @@ -67,13 +79,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - - - - - - @@ -82,8 +87,10 @@ - - + + + + @@ -94,4 +101,25 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index d282e9af3..06879025f 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,13 @@ For more information about MCP: - [Protocol Specification](https://modelcontextprotocol.io/specification/) - [GitHub Organization](https://github.com/modelcontextprotocol) +## Prerequisites + +The SDK targets .NET Standard 2.0, .NET 8.0, .NET 9.0, and .NET 10.0. When targeting .NET 8.0, the SDK uses 8.x versions of `Microsoft.Extensions.*` dependencies for runtime compatibility. + +> [!IMPORTANT] +> The SDK depends on `System.Text.Json` 10.x on all target frameworks, including .NET 8.0. If your application pins `System.Text.Json` to an 8.x version, you will need to allow the upgrade to 10.x for the SDK to function correctly. + ## Installation To get started, install the package from NuGet diff --git a/samples/AspNetCoreMcpServer/AspNetCoreMcpServer.csproj b/samples/AspNetCoreMcpServer/AspNetCoreMcpServer.csproj index 59ab49828..39ea74a97 100644 --- a/samples/AspNetCoreMcpServer/AspNetCoreMcpServer.csproj +++ b/samples/AspNetCoreMcpServer/AspNetCoreMcpServer.csproj @@ -1,7 +1,7 @@ - net9.0 + net8.0 enable enable true diff --git a/samples/ChatWithTools/ChatWithTools.csproj b/samples/ChatWithTools/ChatWithTools.csproj index 3723185fe..901e1ad7d 100644 --- a/samples/ChatWithTools/ChatWithTools.csproj +++ b/samples/ChatWithTools/ChatWithTools.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable + + + + diff --git a/src/ModelContextProtocol.Core/README.md b/src/ModelContextProtocol.Core/README.md index 69913a150..1414a5263 100644 --- a/src/ModelContextProtocol.Core/README.md +++ b/src/ModelContextProtocol.Core/README.md @@ -17,6 +17,13 @@ For more information about MCP: - [Protocol Specification](https://modelcontextprotocol.io/specification/) - [GitHub Organization](https://github.com/modelcontextprotocol) +## Prerequisites + +The SDK targets .NET Standard 2.0, .NET 8.0, .NET 9.0, and .NET 10.0. When targeting .NET 8.0, the SDK uses 8.x versions of `Microsoft.Extensions.*` dependencies for runtime compatibility. + +> [!IMPORTANT] +> The SDK depends on `System.Text.Json` 10.x on all target frameworks, including .NET 8.0. If your application pins `System.Text.Json` to an 8.x version, you will need to allow the upgrade to 10.x for the SDK to function correctly. + ## Installation To get started, install the core package from NuGet diff --git a/src/ModelContextProtocol.Core/Server/StreamableHttpPostTransport.cs b/src/ModelContextProtocol.Core/Server/StreamableHttpPostTransport.cs index 7f399bab3..6a69cf440 100644 --- a/src/ModelContextProtocol.Core/Server/StreamableHttpPostTransport.cs +++ b/src/ModelContextProtocol.Core/Server/StreamableHttpPostTransport.cs @@ -17,6 +17,7 @@ internal sealed partial class StreamableHttpPostTransport( CancellationToken sessionCancellationToken, ILogger logger) : ITransport { + private readonly ILogger _logger = logger; private readonly SemaphoreSlim _messageLock = new(1, 1); private readonly TaskCompletionSource _httpResponseTcs = new(TaskCreationOptions.RunContinuationsAsynchronously); private readonly SseEventWriter _httpSseWriter = new(responseStream); diff --git a/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj b/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj index 384e8fcdd..38032f8e8 100644 --- a/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj +++ b/tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj @@ -33,7 +33,7 @@ - + diff --git a/tests/ModelContextProtocol.AspNetCore.Tests/ServerConformanceTests.cs b/tests/ModelContextProtocol.AspNetCore.Tests/ServerConformanceTests.cs index d2501456c..c00f8c117 100644 --- a/tests/ModelContextProtocol.AspNetCore.Tests/ServerConformanceTests.cs +++ b/tests/ModelContextProtocol.AspNetCore.Tests/ServerConformanceTests.cs @@ -173,10 +173,19 @@ public async Task RunPendingConformanceTest_ServerSsePolling() ); } + var stdOut = outputBuilder.ToString(); + var stdErr = errorBuilder.ToString(); + + // On Windows, the Node.js conformance runner can crash during shutdown due to a libuv assertion + // (UV_HANDLE_CLOSING), producing a non-zero exit code even when all tests pass. Fall back to + // checking the output for "0 failed" when the exit code is non-zero. + bool success = process.ExitCode == 0 || + (stdOut.Contains("0 failed") && !stdOut.Contains("FAILURE")); + return ( - Success: process.ExitCode == 0, - Output: outputBuilder.ToString(), - Error: errorBuilder.ToString() + Success: success, + Output: stdOut, + Error: stdErr ); } } diff --git a/tests/ModelContextProtocol.Tests/ClientIntegrationTestFixture.cs b/tests/ModelContextProtocol.Tests/ClientIntegrationTestFixture.cs index 049d72d60..faf83814d 100644 --- a/tests/ModelContextProtocol.Tests/ClientIntegrationTestFixture.cs +++ b/tests/ModelContextProtocol.Tests/ClientIntegrationTestFixture.cs @@ -27,8 +27,9 @@ public ClientIntegrationTestFixture() TestServerTransportOptions = new() { - Command = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "TestServer.exe" : PlatformDetection.IsMonoRuntime ? "mono" : "dotnet", + Command = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Path.Combine(AppContext.BaseDirectory, "TestServer.exe") : PlatformDetection.IsMonoRuntime ? "mono" : "dotnet", Name = "TestServer", + WorkingDirectory = AppContext.BaseDirectory, }; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs b/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs index 018e12dbe..a048362ca 100644 --- a/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs +++ b/tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs @@ -2,7 +2,9 @@ using ModelContextProtocol.Client; using ModelContextProtocol.Protocol; using ModelContextProtocol.Tests.Utils; +#if !NET8_0 using OpenAI; +#endif using System.Text.Json; using System.Text.Json.Serialization; @@ -10,9 +12,11 @@ namespace ModelContextProtocol.Tests; public partial class ClientIntegrationTests : LoggedTest, IClassFixture { +#if !NET8_0 private static readonly string? s_openAIKey = Environment.GetEnvironmentVariable("AI:OpenAI:ApiKey"); public static bool NoOpenAIKeySet => string.IsNullOrWhiteSpace(s_openAIKey); +#endif private readonly ClientIntegrationTestFixture _fixture; @@ -492,6 +496,7 @@ public async Task CallTool_Stdio_MemoryServer() await client.DisposeAsync(); } +#if !NET8_0 [Fact(Skip = "Requires OpenAI API Key", SkipWhen = nameof(NoOpenAIKeySet))] public async Task ListToolsAsync_UsingEverythingServer_ToolsAreProperlyCalled() { @@ -547,6 +552,7 @@ public async Task SamplingViaChatClient_RequestResponseProperlyPropagated() Assert.Contains("LLM sampling result:", content.Text); Assert.Contains("Eiffel", content.Text); } +#endif [Theory] [MemberData(nameof(GetClients))] diff --git a/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj b/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj index 0985f4cd7..3968cbaf2 100644 --- a/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj +++ b/tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj @@ -60,7 +60,7 @@ all - + diff --git a/tests/ModelContextProtocol.Tests/Transport/StdioClientTransportTests.cs b/tests/ModelContextProtocol.Tests/Transport/StdioClientTransportTests.cs index c33ed7f72..6f1817f2f 100644 --- a/tests/ModelContextProtocol.Tests/Transport/StdioClientTransportTests.cs +++ b/tests/ModelContextProtocol.Tests/Transport/StdioClientTransportTests.cs @@ -111,7 +111,7 @@ public async Task EscapesCliArgumentsCorrectly(string? cliArgumentValue) Command = (PlatformDetection.IsMonoRuntime, PlatformDetection.IsWindows) switch { (true, _) => "mono", - (_, true) => "TestServer.exe", + (_, true) => Path.Combine(AppContext.BaseDirectory, "TestServer.exe"), _ => "dotnet", }, Arguments = (PlatformDetection.IsMonoRuntime, PlatformDetection.IsWindows) switch @@ -120,6 +120,7 @@ public async Task EscapesCliArgumentsCorrectly(string? cliArgumentValue) (_, true) => [cliArgument], _ => ["TestServer.dll", cliArgument], }, + WorkingDirectory = AppContext.BaseDirectory, }; var transport = new StdioClientTransport(options, LoggerFactory);