From b39de2bb7aed52b54a81e8e3b776b8dfb3d9b09e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:44:05 +0000 Subject: [PATCH 1/4] Initial plan From f767597f42b6c7464aa8fadd63bcc4230a54d231 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:49:28 +0000 Subject: [PATCH 2/4] Add Microsoft Learn MCP server integration tests via Streamable HTTP Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../MicrosoftLearnMcpServerTests.cs | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs diff --git a/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs b/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs new file mode 100644 index 000000000..01eb10541 --- /dev/null +++ b/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs @@ -0,0 +1,168 @@ +using ModelContextProtocol.Client; +using ModelContextProtocol.Protocol; +using ModelContextProtocol.Tests.Utils; + +namespace ModelContextProtocol.Tests; + +/// +/// Integration tests for connecting to the Microsoft Learn MCP server. +/// These tests connect to a live external service and are marked as Manual execution. +/// +public class MicrosoftLearnMcpServerTests(ITestOutputHelper testOutputHelper) : LoggedTest(testOutputHelper) +{ + private const string MicrosoftLearnMcpEndpoint = "https://learn.microsoft.com/api/mcp"; + + [Fact] + [Trait("Execution", "Manual")] + public async Task ConnectAndInitialize_MicrosoftLearnServer_WithStreamableHttp() + { + // Arrange + var transportOptions = new HttpClientTransportOptions + { + Endpoint = new Uri(MicrosoftLearnMcpEndpoint), + Name = "Microsoft Learn MCP Server", + TransportMode = HttpTransportMode.StreamableHttp, + }; + + var clientOptions = new McpClientOptions + { + ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } + }; + + // Act + await using var client = await McpClient.CreateAsync( + new HttpClientTransport(transportOptions), + clientOptions, + loggerFactory: LoggerFactory, + cancellationToken: TestContext.Current.CancellationToken); + + // Assert + Assert.NotNull(client); + Assert.NotNull(client.ServerCapabilities); + Assert.NotNull(client.ServerInfo); + Assert.NotNull(client.NegotiatedProtocolVersion); + } + + [Fact] + [Trait("Execution", "Manual")] + public async Task ListTools_MicrosoftLearnServer() + { + // Arrange + var transportOptions = new HttpClientTransportOptions + { + Endpoint = new Uri(MicrosoftLearnMcpEndpoint), + Name = "Microsoft Learn MCP Server", + TransportMode = HttpTransportMode.StreamableHttp, + }; + + var clientOptions = new McpClientOptions + { + ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } + }; + + // Act + await using var client = await McpClient.CreateAsync( + new HttpClientTransport(transportOptions), + clientOptions, + loggerFactory: LoggerFactory, + cancellationToken: TestContext.Current.CancellationToken); + + var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken); + + // Assert + Assert.NotNull(tools); + Assert.NotEmpty(tools); + } + + [Fact] + [Trait("Execution", "Manual")] + public async Task ListResources_MicrosoftLearnServer() + { + // Arrange + var transportOptions = new HttpClientTransportOptions + { + Endpoint = new Uri(MicrosoftLearnMcpEndpoint), + Name = "Microsoft Learn MCP Server", + TransportMode = HttpTransportMode.StreamableHttp, + }; + + var clientOptions = new McpClientOptions + { + ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } + }; + + // Act + await using var client = await McpClient.CreateAsync( + new HttpClientTransport(transportOptions), + clientOptions, + loggerFactory: LoggerFactory, + cancellationToken: TestContext.Current.CancellationToken); + + var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken); + + // Assert + Assert.NotNull(resources); + // Microsoft Learn server may or may not have resources, so we don't assert NotEmpty + } + + [Fact] + [Trait("Execution", "Manual")] + public async Task ListPrompts_MicrosoftLearnServer() + { + // Arrange + var transportOptions = new HttpClientTransportOptions + { + Endpoint = new Uri(MicrosoftLearnMcpEndpoint), + Name = "Microsoft Learn MCP Server", + TransportMode = HttpTransportMode.StreamableHttp, + }; + + var clientOptions = new McpClientOptions + { + ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } + }; + + // Act + await using var client = await McpClient.CreateAsync( + new HttpClientTransport(transportOptions), + clientOptions, + loggerFactory: LoggerFactory, + cancellationToken: TestContext.Current.CancellationToken); + + var prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken); + + // Assert + Assert.NotNull(prompts); + // Microsoft Learn server may or may not have prompts, so we don't assert NotEmpty + } + + [Fact] + [Trait("Execution", "Manual")] + public async Task PingServer_MicrosoftLearnServer() + { + // Arrange + var transportOptions = new HttpClientTransportOptions + { + Endpoint = new Uri(MicrosoftLearnMcpEndpoint), + Name = "Microsoft Learn MCP Server", + TransportMode = HttpTransportMode.StreamableHttp, + }; + + var clientOptions = new McpClientOptions + { + ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } + }; + + // Act + await using var client = await McpClient.CreateAsync( + new HttpClientTransport(transportOptions), + clientOptions, + loggerFactory: LoggerFactory, + cancellationToken: TestContext.Current.CancellationToken); + + await client.PingAsync(TestContext.Current.CancellationToken); + + // Assert - if we get here without exception, ping was successful + Assert.True(true); + } +} From 69723c3fd9f60e31caae7eba7b30b7d6837400c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:50:35 +0000 Subject: [PATCH 3/4] Add documentation for running manual tests Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- tests/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/README.md diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..de5119508 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,40 @@ +# Running Tests + +## Manual Tests + +Some tests in this repository are marked with the `[Trait("Execution", "Manual")]` attribute. These tests require external dependencies or network connectivity and are not run by default in CI/CD pipelines. + +### Microsoft Learn MCP Server Tests + +The `MicrosoftLearnMcpServerTests` class contains integration tests that connect to the Microsoft Learn MCP server at `https://learn.microsoft.com/api/mcp` using Streamable HTTP transport. + +These tests: +- Require network connectivity to Microsoft Learn services +- Test real-world integration with a production MCP server +- Validate the Streamable HTTP transport implementation + +#### Running the Microsoft Learn tests + +To run these tests, use the following command: + +```bash +dotnet test --filter "(FullyQualifiedName~MicrosoftLearnMcpServerTests)" +``` + +Or to run all manual tests: + +```bash +dotnet test --filter "(Execution=Manual)" +``` + +To exclude manual tests from a test run: + +```bash +dotnet test --filter "(Execution!=Manual)" +``` + +### Requirements + +- .NET 10.0 SDK (as specified in `global.json`) +- Internet connectivity +- Access to https://learn.microsoft.com/api/mcp (ensure no firewall restrictions) From 171a7862b193f9836fad213b67b3d2c7902ccbb4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:51:48 +0000 Subject: [PATCH 4/4] Refactor Microsoft Learn MCP server tests to reduce duplication Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../MicrosoftLearnMcpServerTests.cs | 98 +++---------------- 1 file changed, 15 insertions(+), 83 deletions(-) diff --git a/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs b/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs index 01eb10541..845621703 100644 --- a/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs +++ b/tests/ModelContextProtocol.Tests/MicrosoftLearnMcpServerTests.cs @@ -12,11 +12,8 @@ public class MicrosoftLearnMcpServerTests(ITestOutputHelper testOutputHelper) : { private const string MicrosoftLearnMcpEndpoint = "https://learn.microsoft.com/api/mcp"; - [Fact] - [Trait("Execution", "Manual")] - public async Task ConnectAndInitialize_MicrosoftLearnServer_WithStreamableHttp() + private Task CreateClientAsync(CancellationToken cancellationToken = default) { - // Arrange var transportOptions = new HttpClientTransportOptions { Endpoint = new Uri(MicrosoftLearnMcpEndpoint), @@ -29,12 +26,19 @@ public async Task ConnectAndInitialize_MicrosoftLearnServer_WithStreamableHttp() ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } }; - // Act - await using var client = await McpClient.CreateAsync( + return McpClient.CreateAsync( new HttpClientTransport(transportOptions), clientOptions, loggerFactory: LoggerFactory, - cancellationToken: TestContext.Current.CancellationToken); + cancellationToken: cancellationToken); + } + + [Fact] + [Trait("Execution", "Manual")] + public async Task ConnectAndInitialize_MicrosoftLearnServer_WithStreamableHttp() + { + // Act + await using var client = await CreateClientAsync(TestContext.Current.CancellationToken); // Assert Assert.NotNull(client); @@ -47,26 +51,8 @@ public async Task ConnectAndInitialize_MicrosoftLearnServer_WithStreamableHttp() [Trait("Execution", "Manual")] public async Task ListTools_MicrosoftLearnServer() { - // Arrange - var transportOptions = new HttpClientTransportOptions - { - Endpoint = new Uri(MicrosoftLearnMcpEndpoint), - Name = "Microsoft Learn MCP Server", - TransportMode = HttpTransportMode.StreamableHttp, - }; - - var clientOptions = new McpClientOptions - { - ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } - }; - // Act - await using var client = await McpClient.CreateAsync( - new HttpClientTransport(transportOptions), - clientOptions, - loggerFactory: LoggerFactory, - cancellationToken: TestContext.Current.CancellationToken); - + await using var client = await CreateClientAsync(TestContext.Current.CancellationToken); var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken); // Assert @@ -78,26 +64,8 @@ public async Task ListTools_MicrosoftLearnServer() [Trait("Execution", "Manual")] public async Task ListResources_MicrosoftLearnServer() { - // Arrange - var transportOptions = new HttpClientTransportOptions - { - Endpoint = new Uri(MicrosoftLearnMcpEndpoint), - Name = "Microsoft Learn MCP Server", - TransportMode = HttpTransportMode.StreamableHttp, - }; - - var clientOptions = new McpClientOptions - { - ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } - }; - // Act - await using var client = await McpClient.CreateAsync( - new HttpClientTransport(transportOptions), - clientOptions, - loggerFactory: LoggerFactory, - cancellationToken: TestContext.Current.CancellationToken); - + await using var client = await CreateClientAsync(TestContext.Current.CancellationToken); var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken); // Assert @@ -109,26 +77,8 @@ public async Task ListResources_MicrosoftLearnServer() [Trait("Execution", "Manual")] public async Task ListPrompts_MicrosoftLearnServer() { - // Arrange - var transportOptions = new HttpClientTransportOptions - { - Endpoint = new Uri(MicrosoftLearnMcpEndpoint), - Name = "Microsoft Learn MCP Server", - TransportMode = HttpTransportMode.StreamableHttp, - }; - - var clientOptions = new McpClientOptions - { - ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } - }; - // Act - await using var client = await McpClient.CreateAsync( - new HttpClientTransport(transportOptions), - clientOptions, - loggerFactory: LoggerFactory, - cancellationToken: TestContext.Current.CancellationToken); - + await using var client = await CreateClientAsync(TestContext.Current.CancellationToken); var prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken); // Assert @@ -140,26 +90,8 @@ public async Task ListPrompts_MicrosoftLearnServer() [Trait("Execution", "Manual")] public async Task PingServer_MicrosoftLearnServer() { - // Arrange - var transportOptions = new HttpClientTransportOptions - { - Endpoint = new Uri(MicrosoftLearnMcpEndpoint), - Name = "Microsoft Learn MCP Server", - TransportMode = HttpTransportMode.StreamableHttp, - }; - - var clientOptions = new McpClientOptions - { - ClientInfo = new() { Name = "CSharpSdkIntegrationTest", Version = "1.0.0" } - }; - // Act - await using var client = await McpClient.CreateAsync( - new HttpClientTransport(transportOptions), - clientOptions, - loggerFactory: LoggerFactory, - cancellationToken: TestContext.Current.CancellationToken); - + await using var client = await CreateClientAsync(TestContext.Current.CancellationToken); await client.PingAsync(TestContext.Current.CancellationToken); // Assert - if we get here without exception, ping was successful