From 220a02d78cad0fd5b96f3b84bd51ddc1a725c68f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 19:32:43 +0000
Subject: [PATCH 01/10] Initial plan
From d555fba539bc53ad7e0186fb33bba21a0a26d6dd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 19:39:58 +0000
Subject: [PATCH 02/10] Add private protected constructors to McpClient and
McpServer to prevent external derivation
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../Client/McpClient.cs | 4 +
.../Server/McpServer.cs | 4 +
tests/Common/Utils/TestServerTransport.cs | 9 +-
.../Server/McpServerTests.cs | 97 ++++++++-----------
4 files changed, 55 insertions(+), 59 deletions(-)
diff --git a/src/ModelContextProtocol.Core/Client/McpClient.cs b/src/ModelContextProtocol.Core/Client/McpClient.cs
index 28a37f258..9f8bf4e66 100644
--- a/src/ModelContextProtocol.Core/Client/McpClient.cs
+++ b/src/ModelContextProtocol.Core/Client/McpClient.cs
@@ -7,6 +7,10 @@ namespace ModelContextProtocol.Client;
///
public abstract partial class McpClient : McpSession
{
+ /// Initializes a new instance of the class.
+ private protected McpClient()
+ {
+ }
///
/// Gets the capabilities supported by the connected server.
///
diff --git a/src/ModelContextProtocol.Core/Server/McpServer.cs b/src/ModelContextProtocol.Core/Server/McpServer.cs
index 2d8ea6826..95c605616 100644
--- a/src/ModelContextProtocol.Core/Server/McpServer.cs
+++ b/src/ModelContextProtocol.Core/Server/McpServer.cs
@@ -7,6 +7,10 @@ namespace ModelContextProtocol.Server;
///
public abstract partial class McpServer : McpSession
{
+ /// Initializes a new instance of the class.
+ private protected McpServer()
+ {
+ }
///
/// Gets the capabilities supported by the client.
///
diff --git a/tests/Common/Utils/TestServerTransport.cs b/tests/Common/Utils/TestServerTransport.cs
index 43cd5c262..0fc2b6b4d 100644
--- a/tests/Common/Utils/TestServerTransport.cs
+++ b/tests/Common/Utils/TestServerTransport.cs
@@ -93,10 +93,11 @@ await WriteMessageAsync(new JsonRpcResponse
else
{
// Return a normal sampling response
+ var result = MockSamplingResult ?? new CreateMessageResult { Content = [new TextContentBlock { Text = "" }], Model = "model" };
await WriteMessageAsync(new JsonRpcResponse
{
Id = request.Id,
- Result = JsonSerializer.SerializeToNode(new CreateMessageResult { Content = [new TextContentBlock { Text = "" }], Model = "model" }, McpJsonUtilities.DefaultOptions),
+ Result = JsonSerializer.SerializeToNode(result, McpJsonUtilities.DefaultOptions),
}, cancellationToken);
}
}
@@ -125,6 +126,12 @@ await WriteMessageAsync(new JsonRpcResponse
}
}
+ ///
+ /// Gets or sets the sampling result to return from sampling/createMessage requests.
+ /// When null, a default sampling response is returned.
+ ///
+ public CreateMessageResult? MockSamplingResult { get; set; }
+
///
/// Gets or sets the task to return from tasks/get requests.
///
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs
index 637162962..a10558036 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs
@@ -807,7 +807,8 @@ private async Task Succeeds_Even_If_No_Handler_Assigned(ServerCapabilities serve
[Fact]
public async Task AsSamplingChatClient_NoSamplingSupport_Throws()
{
- await using var server = new TestServerForIChatClient(supportsSampling: false);
+ await using var transport = new TestServerTransport();
+ await using var server = McpServer.Create(transport, _options, LoggerFactory);
Assert.Throws(() => server.AsSamplingChatClient());
}
@@ -815,7 +816,27 @@ public async Task AsSamplingChatClient_NoSamplingSupport_Throws()
[Fact]
public async Task AsSamplingChatClient_HandlesRequestResponse()
{
- await using var server = new TestServerForIChatClient(supportsSampling: true);
+ await using var transport = new TestServerTransport();
+ transport.MockSamplingResult = new CreateMessageResult
+ {
+ Content = [new TextContentBlock { Text = "The Eiffel Tower." }],
+ Model = "amazingmodel",
+ Role = Role.Assistant,
+ StopReason = "endTurn",
+ };
+ await using var server = McpServer.Create(transport, _options, LoggerFactory);
+ var runTask = server.RunAsync(TestContext.Current.CancellationToken);
+ await InitializeServerAsync(transport, new ClientCapabilities { Sampling = new SamplingCapability() }, TestContext.Current.CancellationToken);
+
+ // Capture the sampling request for validation
+ CreateMessageRequestParams? capturedParams = null;
+ transport.OnMessageSent = (message) =>
+ {
+ if (message is JsonRpcRequest request && request.Method == RequestMethods.SamplingCreateMessage)
+ {
+ capturedParams = JsonSerializer.Deserialize(request.Params, McpJsonUtilities.DefaultOptions);
+ }
+ };
IChatClient client = server.AsSamplingChatClient();
@@ -839,6 +860,22 @@ public async Task AsSamplingChatClient_HandlesRequestResponse()
Assert.Single(response.Messages);
Assert.Equal("The Eiffel Tower.", response.Text);
Assert.Equal(ChatRole.Assistant, response.Messages[0].Role);
+
+ // Validate the request parameters
+ Assert.NotNull(capturedParams);
+ Assert.Equal(0.75f, capturedParams.Temperature);
+ Assert.Equal(42, capturedParams.MaxTokens);
+ Assert.Equal(["."], capturedParams.StopSequences);
+ Assert.Null(capturedParams.IncludeContext);
+ Assert.Null(capturedParams.Metadata);
+ Assert.Null(capturedParams.ModelPreferences);
+ Assert.Equal($"You are a helpful assistant.{Environment.NewLine}More system stuff.", capturedParams.SystemPrompt);
+ Assert.Equal(2, capturedParams.Messages.Count);
+ Assert.Equal("I am going to France.", Assert.IsType(Assert.Single(capturedParams.Messages[0].Content)).Text);
+ Assert.Equal("What is the most famous tower in Paris?", Assert.IsType(Assert.Single(capturedParams.Messages[1].Content)).Text);
+
+ await transport.DisposeAsync();
+ await runTask;
}
[Fact]
@@ -890,62 +927,6 @@ private static async Task InitializeServerAsync(TestServerTransport transport, C
await tcs.Task.WaitAsync(TestConstants.DefaultTimeout, cancellationToken);
}
- private sealed class TestServerForIChatClient(bool supportsSampling) : McpServer
- {
- public override ClientCapabilities? ClientCapabilities =>
- supportsSampling ? new ClientCapabilities { Sampling = new SamplingCapability() } :
- null;
-
- public override McpServerOptions ServerOptions => new();
-
- public override Task SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken)
- {
- CreateMessageRequestParams? rp = JsonSerializer.Deserialize(request.Params, McpJsonUtilities.DefaultOptions);
-
- Assert.NotNull(rp);
- Assert.Equal(0.75f, rp.Temperature);
- Assert.Equal(42, rp.MaxTokens);
- Assert.Equal(["."], rp.StopSequences);
- Assert.Null(rp.IncludeContext);
- Assert.Null(rp.Metadata);
- Assert.Null(rp.ModelPreferences);
-
- Assert.Equal($"You are a helpful assistant.{Environment.NewLine}More system stuff.", rp.SystemPrompt);
-
- Assert.Equal(2, rp.Messages.Count);
- Assert.Equal("I am going to France.", Assert.IsType(Assert.Single(rp.Messages[0].Content)).Text);
- Assert.Equal("What is the most famous tower in Paris?", Assert.IsType(Assert.Single(rp.Messages[1].Content)).Text);
-
- CreateMessageResult result = new()
- {
- Content = [new TextContentBlock { Text = "The Eiffel Tower." }],
- Model = "amazingmodel",
- Role = Role.Assistant,
- StopReason = "endTurn",
- };
-
- return Task.FromResult(new JsonRpcResponse
- {
- Id = new RequestId("0"),
- Result = JsonSerializer.SerializeToNode(result, McpJsonUtilities.DefaultOptions),
- });
- }
-
- public override ValueTask DisposeAsync() => default;
-
- public override string? SessionId => throw new NotImplementedException();
- public override string? NegotiatedProtocolVersion => throw new NotImplementedException();
- public override Implementation? ClientInfo => throw new NotImplementedException();
- public override IServiceProvider? Services => throw new NotImplementedException();
- public override LoggingLevel? LoggingLevel => throw new NotImplementedException();
- public override Task SendMessageAsync(JsonRpcMessage message, CancellationToken cancellationToken = default) =>
- throw new NotImplementedException();
- public override Task RunAsync(CancellationToken cancellationToken = default) =>
- throw new NotImplementedException();
- public override IAsyncDisposable RegisterNotificationHandler(string method, Func handler) =>
- throw new NotImplementedException();
- }
-
[Fact]
public async Task NotifyProgress_Should_Be_Handled()
{
From c3e689e7e853b6398a7fefa944a7c42f15f99322 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 19:43:25 +0000
Subject: [PATCH 03/10] Fix formatting: add blank line after constructor
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/ModelContextProtocol.Core/Client/McpClient.cs | 1 +
src/ModelContextProtocol.Core/Server/McpServer.cs | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/ModelContextProtocol.Core/Client/McpClient.cs b/src/ModelContextProtocol.Core/Client/McpClient.cs
index 9f8bf4e66..8d74aaaf2 100644
--- a/src/ModelContextProtocol.Core/Client/McpClient.cs
+++ b/src/ModelContextProtocol.Core/Client/McpClient.cs
@@ -11,6 +11,7 @@ public abstract partial class McpClient : McpSession
private protected McpClient()
{
}
+
///
/// Gets the capabilities supported by the connected server.
///
diff --git a/src/ModelContextProtocol.Core/Server/McpServer.cs b/src/ModelContextProtocol.Core/Server/McpServer.cs
index 95c605616..4f8bf9058 100644
--- a/src/ModelContextProtocol.Core/Server/McpServer.cs
+++ b/src/ModelContextProtocol.Core/Server/McpServer.cs
@@ -11,6 +11,7 @@ public abstract partial class McpServer : McpSession
private protected McpServer()
{
}
+
///
/// Gets the capabilities supported by the client.
///
From 802026ba6f42006daf6de3ce1592f885ba05c7a8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:25:12 +0000
Subject: [PATCH 04/10] Remove InternalsVisibleTo from
ModelContextProtocol.Core.csproj
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../ModelContextProtocol.Core.csproj | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
index 05e732c6f..45ce22d69 100644
--- a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
+++ b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
@@ -55,6 +55,10 @@
+
+
+
+
Date: Mon, 23 Feb 2026 20:32:18 +0000
Subject: [PATCH 05/10] Replace Mock with real McpServer instances
in McpServerToolTests
Replace all Moq-based Mock usages with real McpServer instances
created via McpServer.Create() using TestServerTransport. This removes the
dependency on Moq in this test file.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Server/McpServerToolTests.cs | 118 +++++++++---------
1 file changed, 60 insertions(+), 58 deletions(-)
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs
index 552eaed72..5a147a66e 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs
@@ -3,7 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
-using Moq;
+using ModelContextProtocol.Tests.Utils;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -27,6 +27,9 @@ private static JsonRpcRequest CreateTestJsonRpcRequest()
};
}
+ private static McpServer CreateTestServer(IServiceProvider? services = null) =>
+ McpServer.Create(new TestServerTransport(), new McpServerOptions(), serviceProvider: services);
+
public McpServerToolTests()
{
#if !NET
@@ -51,18 +54,18 @@ public void Create_InvalidArgs_Throws()
[Fact]
public async Task SupportsMcpServer()
{
- Mock mockServer = new();
+ McpServer server = CreateTestServer();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return "42";
});
Assert.DoesNotContain("server", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, McpJsonUtilities.DefaultOptions));
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("42", (result.Content[0] as TextContentBlock)?.Text);
}
@@ -76,8 +79,7 @@ public async Task SupportsCtorInjection()
sc.AddSingleton(expectedMyService);
IServiceProvider services = sc.BuildServiceProvider();
- Mock mockServer = new();
- mockServer.SetupGet(s => s.Services).Returns(services);
+ McpServer server = CreateTestServer(services);
MethodInfo? testMethod = typeof(HasCtorWithSpecialParameters).GetMethod(nameof(HasCtorWithSpecialParameters.TestTool));
Assert.NotNull(testMethod);
@@ -88,7 +90,7 @@ public async Task SupportsCtorInjection()
}, new() { Services = services });
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Content);
@@ -163,16 +165,16 @@ public async Task SupportsServiceFromDI(ServiceLifetime injectedArgumentLifetime
Assert.DoesNotContain("actualMyService", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, McpJsonUtilities.DefaultOptions));
- Mock mockServer = new();
+ McpServer server = CreateTestServer();
var ex = await Assert.ThrowsAsync(async () => await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
- mockServer.SetupGet(s => s.Services).Returns(services);
+ McpServer serverWithServices = CreateTestServer(services);
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Services = services },
+ new RequestContext(serverWithServices, CreateTestJsonRpcRequest()) { Services = services },
TestContext.Current.CancellationToken);
Assert.Equal("42", (result.Content[0] as TextContentBlock)?.Text);
}
@@ -193,7 +195,7 @@ public async Task SupportsOptionalServiceFromDI()
}, new() { Services = services });
var result = await tool.InvokeAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("42", (result.Content[0] as TextContentBlock)?.Text);
}
@@ -208,7 +210,7 @@ public async Task SupportsDisposingInstantiatedDisposableTargets()
options);
var result = await tool1.InvokeAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("""{"disposals":1}""", (result.Content[0] as TextContentBlock)?.Text);
}
@@ -223,7 +225,7 @@ public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableTargets()
options);
var result = await tool1.InvokeAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("""{"asyncDisposals":1}""", (result.Content[0] as TextContentBlock)?.Text);
}
@@ -242,7 +244,7 @@ public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableAndDisposable
options);
var result = await tool1.InvokeAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Services = services },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Services = services },
TestContext.Current.CancellationToken);
Assert.Equal("""{"asyncDisposals":1,"disposals":0}""", (result.Content[0] as TextContentBlock)?.Text);
}
@@ -251,10 +253,10 @@ public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableAndDisposable
[Fact]
public async Task CanReturnCollectionOfAIContent()
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return new List {
new TextContent("text"),
new DataContent("data:image/png;base64,1234"),
@@ -263,7 +265,7 @@ public async Task CanReturnCollectionOfAIContent()
}, new() { SerializerOptions = JsonContext2.Default.Options });
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal(3, result.Content.Count);
@@ -283,10 +285,10 @@ public async Task CanReturnCollectionOfAIContent()
[InlineData("data:audio/wav;base64,1234", "audio")]
public async Task CanReturnSingleAIContent(string data, string type)
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return type switch
{
"text" => (AIContent)new TextContent(data),
@@ -297,7 +299,7 @@ public async Task CanReturnSingleAIContent(string data, string type)
});
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Single(result.Content);
@@ -326,14 +328,14 @@ public async Task CanReturnSingleAIContent(string data, string type)
[Fact]
public async Task CanReturnNullAIContent()
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return (string?)null;
});
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Empty(result.Content);
}
@@ -341,14 +343,14 @@ public async Task CanReturnNullAIContent()
[Fact]
public async Task CanReturnString()
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return "42";
});
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Single(result.Content);
Assert.Equal("42", Assert.IsType(result.Content[0]).Text);
@@ -357,14 +359,14 @@ public async Task CanReturnString()
[Fact]
public async Task CanReturnCollectionOfStrings()
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return new List { "42", "43" };
}, new() { SerializerOptions = JsonContext2.Default.Options });
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Single(result.Content);
Assert.Equal("""["42","43"]""", Assert.IsType(result.Content[0]).Text);
@@ -373,14 +375,14 @@ public async Task CanReturnCollectionOfStrings()
[Fact]
public async Task CanReturnMcpContent()
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return new TextContentBlock { Text = "42" };
});
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Single(result.Content);
Assert.Equal("42", Assert.IsType(result.Content[0]).Text);
@@ -390,10 +392,10 @@ public async Task CanReturnMcpContent()
[Fact]
public async Task CanReturnCollectionOfMcpContent()
{
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return (IList)
[
new TextContentBlock { Text = "42" },
@@ -401,7 +403,7 @@ public async Task CanReturnCollectionOfMcpContent()
];
});
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal(2, result.Content.Count);
Assert.Equal("42", Assert.IsType(result.Content[0]).Text);
@@ -417,14 +419,14 @@ public async Task CanReturnCallToolResult()
Content = [new TextContentBlock { Text = "text" }, ImageContentBlock.FromBytes((byte[])[1, 2, 3, 4], "image/png")]
};
- Mock mockServer = new();
- McpServerTool tool = McpServerTool.Create((McpServer server) =>
+ McpServer server = CreateTestServer();
+ McpServerTool tool = McpServerTool.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return response;
});
var result = await tool.InvokeAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Same(response, result);
@@ -463,8 +465,8 @@ public async Task StructuredOutput_Enabled_ReturnsExpectedSchema(T value)
{
JsonSerializerOptions options = new() { TypeInfoResolver = new DefaultJsonTypeInfoResolver() };
McpServerTool tool = McpServerTool.Create(() => value, new() { Name = "tool", UseStructuredContent = true, SerializerOptions = options });
- var mockServer = new Mock();
- var request = new RequestContext(mockServer.Object, CreateTestJsonRpcRequest())
+ McpServer server = CreateTestServer();
+ var request = new RequestContext(server, CreateTestJsonRpcRequest())
{
Params = new CallToolRequestParams { Name = "tool" },
};
@@ -481,8 +483,8 @@ public async Task StructuredOutput_Enabled_ReturnsExpectedSchema(T value)
public async Task StructuredOutput_Enabled_VoidReturningTools_ReturnsExpectedSchema()
{
McpServerTool tool = McpServerTool.Create(() => { });
- var mockServer = new Mock();
- var request = new RequestContext(mockServer.Object, CreateTestJsonRpcRequest())
+ McpServer server = CreateTestServer();
+ var request = new RequestContext(server, CreateTestJsonRpcRequest())
{
Params = new CallToolRequestParams { Name = "tool" },
};
@@ -493,7 +495,7 @@ public async Task StructuredOutput_Enabled_VoidReturningTools_ReturnsExpectedSch
Assert.Null(result.StructuredContent);
tool = McpServerTool.Create(() => Task.CompletedTask);
- request = new RequestContext(mockServer.Object, CreateTestJsonRpcRequest())
+ request = new RequestContext(server, CreateTestJsonRpcRequest())
{
Params = new CallToolRequestParams { Name = "tool" },
};
@@ -504,7 +506,7 @@ public async Task StructuredOutput_Enabled_VoidReturningTools_ReturnsExpectedSch
Assert.Null(result.StructuredContent);
tool = McpServerTool.Create(() => default(ValueTask));
- request = new RequestContext(mockServer.Object, CreateTestJsonRpcRequest())
+ request = new RequestContext(server, CreateTestJsonRpcRequest())
{
Params = new CallToolRequestParams { Name = "tool" },
};
@@ -521,8 +523,8 @@ public async Task StructuredOutput_Disabled_ReturnsExpectedSchema(T value)
{
JsonSerializerOptions options = new() { TypeInfoResolver = new DefaultJsonTypeInfoResolver() };
McpServerTool tool = McpServerTool.Create(() => value, new() { UseStructuredContent = false, SerializerOptions = options });
- var mockServer = new Mock();
- var request = new RequestContext(mockServer.Object, CreateTestJsonRpcRequest())
+ McpServer server = CreateTestServer();
+ var request = new RequestContext(server, CreateTestJsonRpcRequest())
{
Params = new CallToolRequestParams { Name = "tool" },
};
@@ -819,11 +821,11 @@ public void ReturnDescription_StructuredOutputEnabled_WithExplicitDescription_No
public async Task EnablePollingAsync_ThrowsInvalidOperationException_WhenTransportIsNotStreamableHttpPost()
{
// Arrange
- Mock mockServer = new();
+ McpServer server = CreateTestServer();
var jsonRpcRequest = CreateTestJsonRpcRequest();
// The JsonRpcRequest has no Context, so RelatedTransport will be null
- var requestContext = new RequestContext(mockServer.Object, jsonRpcRequest);
+ var requestContext = new RequestContext(server, jsonRpcRequest);
// Act & Assert
var exception = await Assert.ThrowsAsync(
From 9b23cd06f8bdbc5e8433c99ba7cd2dd4abd1a406 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:38:35 +0000
Subject: [PATCH 06/10] Replace Mock with real McpServer instances
in McpServerPromptTests
Replace all Moq-based Mock usages with real McpServer instances
created via McpServer.Create() using TestServerTransport. This removes the
Moq dependency from this test file and uses concrete implementations instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Server/McpServerPromptTests.cs | 48 ++++++++++---------
1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs
index b463514f9..1a6fab1c7 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs
@@ -2,7 +2,7 @@
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
-using Moq;
+using ModelContextProtocol.Tests.Utils;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -13,6 +13,9 @@ namespace ModelContextProtocol.Tests.Server;
public class McpServerPromptTests
{
+ private static McpServer CreateTestServer(IServiceProvider? services = null) =>
+ McpServer.Create(new TestServerTransport(), new McpServerOptions(), serviceProvider: services);
+
private static JsonRpcRequest CreateTestJsonRpcRequest()
{
return new JsonRpcRequest
@@ -43,18 +46,18 @@ public void Create_InvalidArgs_Throws()
[Fact]
public async Task SupportsMcpServer()
{
- Mock mockServer = new();
+ McpServer server = CreateTestServer();
- McpServerPrompt prompt = McpServerPrompt.Create((McpServer server) =>
+ McpServerPrompt prompt = McpServerPrompt.Create((McpServer s) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(server, s);
return new ChatMessage(ChatRole.User, "Hello");
});
- Assert.DoesNotContain("server", prompt.ProtocolPrompt.Arguments?.Select(a => a.Name) ?? []);
+ Assert.DoesNotContain("s", prompt.ProtocolPrompt.Arguments?.Select(a => a.Name) ?? []);
var result = await prompt.GetAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Messages);
@@ -71,8 +74,7 @@ public async Task SupportsCtorInjection()
sc.AddSingleton(expectedMyService);
IServiceProvider services = sc.BuildServiceProvider();
- Mock mockServer = new();
- mockServer.SetupGet(s => s.Services).Returns(services);
+ McpServer server = CreateTestServer(services);
MethodInfo? testMethod = typeof(HasCtorWithSpecialParameters).GetMethod(nameof(HasCtorWithSpecialParameters.TestPrompt));
Assert.NotNull(testMethod);
@@ -83,7 +85,7 @@ public async Task SupportsCtorInjection()
}, new() { Services = services });
var result = await prompt.GetAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()),
+ new RequestContext(server, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Messages);
@@ -133,11 +135,11 @@ public async Task SupportsServiceFromDI()
Assert.DoesNotContain("actualMyService", prompt.ProtocolPrompt.Arguments?.Select(a => a.Name) ?? []);
await Assert.ThrowsAnyAsync(async () => await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
var result = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Services = services },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Services = services },
TestContext.Current.CancellationToken);
Assert.Equal("Hello", Assert.IsType(result.Messages[0].Content).Text);
}
@@ -158,7 +160,7 @@ public async Task SupportsOptionalServiceFromDI()
}, new() { Services = services });
var result = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("Hello", Assert.IsType(result.Messages[0].Content).Text);
}
@@ -171,7 +173,7 @@ public async Task SupportsDisposingInstantiatedDisposableTargets()
_ => new DisposablePromptType());
var result = await prompt1.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("disposals:1", Assert.IsType(result.Messages[0].Content).Text);
}
@@ -184,7 +186,7 @@ public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableTargets()
_ => new AsyncDisposablePromptType());
var result = await prompt1.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("asyncDisposals:1", Assert.IsType(result.Messages[0].Content).Text);
}
@@ -197,7 +199,7 @@ public async Task SupportsAsyncDisposingInstantiatedAsyncDisposableAndDisposable
_ => new AsyncDisposableAndDisposablePromptType());
var result = await prompt1.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("disposals:0, asyncDisposals:1", Assert.IsType(result.Messages[0].Content).Text);
}
@@ -213,7 +215,7 @@ public async Task CanReturnGetPromptResult()
});
var actual = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Same(expected, actual);
@@ -230,7 +232,7 @@ public async Task CanReturnText()
});
var actual = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@@ -256,7 +258,7 @@ public async Task CanReturnPromptMessage()
});
var actual = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@@ -288,7 +290,7 @@ public async Task CanReturnPromptMessages()
});
var actual = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@@ -315,7 +317,7 @@ public async Task CanReturnChatMessage()
});
var actual = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@@ -347,7 +349,7 @@ public async Task CanReturnChatMessages()
});
var actual = await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@@ -368,7 +370,7 @@ public async Task ThrowsForNullReturn()
});
await Assert.ThrowsAsync(async () => await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
}
@@ -381,7 +383,7 @@ public async Task ThrowsForUnexpectedTypeReturn()
});
await Assert.ThrowsAsync(async () => await prompt.GetAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()),
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
}
From 5546543ab438194aa67930e63915a5e01cbf8073 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:44:18 +0000
Subject: [PATCH 07/10] Replace Mock with real McpServer instances
in McpServerResourceTests
Remove Moq dependency and use McpServer.Create() with TestServerTransport
to create real server instances instead of mocks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Server/McpServerResourceTests.cs | 84 ++++++++++---------
1 file changed, 43 insertions(+), 41 deletions(-)
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerResourceTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerResourceTests.cs
index 695bbf39d..99851b4ec 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerResourceTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerResourceTests.cs
@@ -2,7 +2,7 @@
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
-using Moq;
+using ModelContextProtocol.Tests.Utils;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.Json.Serialization;
@@ -21,6 +21,9 @@ private static JsonRpcRequest CreateTestJsonRpcRequest()
};
}
+ private static McpServer CreateTestServer(IServiceProvider? services = null) =>
+ McpServer.Create(new TestServerTransport(), new McpServerOptions(), serviceProvider: services);
+
public McpServerResourceTests()
{
#if !NET
@@ -143,7 +146,7 @@ public async Task UriTemplate_CreatedFromParameters_LotsOfTypesSupported()
McpServerResource t;
ReadResourceResult result;
- McpServer server = new Mock().Object;
+ McpServer server = CreateTestServer();
t = McpServerResource.Create(() => "42", new() { Name = Name });
Assert.Equal("resource://mcp/Hello", t.ProtocolResourceTemplate.UriTemplate);
@@ -288,7 +291,7 @@ public async Task UriTemplate_NonMatchingUri_DoesNotMatch(string uri)
Assert.Equal("resource://mcp/Hello{?arg1}", t.ProtocolResourceTemplate.UriTemplate);
Assert.False(t.IsMatch(uri));
await Assert.ThrowsAsync(async () => await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = uri } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = uri } },
TestContext.Current.CancellationToken));
}
@@ -299,7 +302,7 @@ public async Task UriTemplate_IsHostCaseInsensitive(string actualUri, string que
{
McpServerResource t = McpServerResource.Create(() => "resource", new() { UriTemplate = actualUri });
Assert.NotNull(await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = queriedUri } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = queriedUri } },
TestContext.Current.CancellationToken));
}
@@ -328,7 +331,7 @@ public async Task UriTemplate_MissingParameter_Throws(string uri)
McpServerResource t = McpServerResource.Create((string arg1, int arg2) => arg1, new() { Name = "Hello" });
Assert.Equal("resource://mcp/Hello{?arg1,arg2}", t.ProtocolResourceTemplate.UriTemplate);
await Assert.ThrowsAsync(async () => await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = uri } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = uri } },
TestContext.Current.CancellationToken));
}
@@ -341,25 +344,25 @@ public async Task UriTemplate_MissingOptionalParameter_Succeeds()
ReadResourceResult result;
result = await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello" } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("", ((TextResourceContents)result.Contents[0]).Text);
result = await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello?arg1=first" } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello?arg1=first" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("first", ((TextResourceContents)result.Contents[0]).Text);
result = await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello?arg2=42" } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello?arg2=42" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("42", ((TextResourceContents)result.Contents[0]).Text);
result = await t.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello?arg1=first&arg2=42" } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Hello?arg1=first&arg2=42" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("first42", ((TextResourceContents)result.Contents[0]).Text);
@@ -368,16 +371,16 @@ public async Task UriTemplate_MissingOptionalParameter_Succeeds()
[Fact]
public async Task SupportsMcpServer()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return "42";
}, new() { Name = "Test" });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("42", ((TextResourceContents)result.Contents[0]).Text);
@@ -392,8 +395,7 @@ public async Task SupportsCtorInjection()
sc.AddSingleton(expectedMyService);
IServiceProvider services = sc.BuildServiceProvider();
- Mock mockServer = new();
- mockServer.SetupGet(s => s.Services).Returns(services);
+ McpServer testServer = CreateTestServer(services);
MethodInfo? testMethod = typeof(HasCtorWithSpecialParameters).GetMethod(nameof(HasCtorWithSpecialParameters.TestResource));
Assert.NotNull(testMethod);
@@ -404,7 +406,7 @@ public async Task SupportsCtorInjection()
}, new() { Services = services });
var result = await tool.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "https://something" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "https://something" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Contents);
@@ -478,14 +480,14 @@ public async Task SupportsServiceFromDI(ServiceLifetime injectedArgumentLifetime
McpServerResource resource = services.GetRequiredService();
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
await Assert.ThrowsAnyAsync(async () => await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken));
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Services = services, Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Services = services, Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("42", ((TextResourceContents)result.Contents[0]).Text);
@@ -507,7 +509,7 @@ public async Task SupportsOptionalServiceFromDI()
}, new() { Services = services, Name = "Test" });
var result = await resource.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("42", ((TextResourceContents)result.Contents[0]).Text);
@@ -523,7 +525,7 @@ public async Task SupportsDisposingInstantiatedDisposableTargets()
_ => new DisposableResourceType());
var result = await resource1.ReadAsync(
- new RequestContext(new Mock().Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "test://static/resource/instanceMethod" } },
+ new RequestContext(CreateTestServer(), CreateTestJsonRpcRequest()) { Params = new() { Uri = "test://static/resource/instanceMethod" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal("0", ((TextResourceContents)result.Contents[0]).Text);
@@ -534,14 +536,14 @@ public async Task SupportsDisposingInstantiatedDisposableTargets()
[Fact]
public async Task CanReturnReadResult()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return new ReadResourceResult { Contents = [new TextResourceContents { Text = "hello", Uri = "" }] };
}, new() { Name = "Test" });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Single(result.Contents);
@@ -551,14 +553,14 @@ public async Task CanReturnReadResult()
[Fact]
public async Task CanReturnResourceContents()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return new TextResourceContents { Text = "hello", Uri = "" };
}, new() { Name = "Test", SerializerOptions = JsonContext6.Default.Options });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Single(result.Contents);
@@ -568,10 +570,10 @@ public async Task CanReturnResourceContents()
[Fact]
public async Task CanReturnCollectionOfResourceContents()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return (IList)
[
new TextResourceContents { Text = "hello", Uri = "" },
@@ -579,7 +581,7 @@ public async Task CanReturnCollectionOfResourceContents()
];
}, new() { Name = "Test" });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal(2, result.Contents.Count);
@@ -590,14 +592,14 @@ public async Task CanReturnCollectionOfResourceContents()
[Fact]
public async Task CanReturnString()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return "42";
}, new() { Name = "Test" });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Single(result.Contents);
@@ -607,14 +609,14 @@ public async Task CanReturnString()
[Fact]
public async Task CanReturnCollectionOfStrings()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return new List { "42", "43" };
}, new() { Name = "Test", SerializerOptions = JsonContext6.Default.Options });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal(2, result.Contents.Count);
@@ -625,14 +627,14 @@ public async Task CanReturnCollectionOfStrings()
[Fact]
public async Task CanReturnDataContent()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return new DataContent(new byte[] { 0, 1, 2 }, "application/octet-stream");
}, new() { Name = "Test" });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Single(result.Contents);
@@ -643,10 +645,10 @@ public async Task CanReturnDataContent()
[Fact]
public async Task CanReturnCollectionOfAIContent()
{
- Mock mockServer = new();
+ McpServer testServer = CreateTestServer();
McpServerResource resource = McpServerResource.Create((McpServer server) =>
{
- Assert.Same(mockServer.Object, server);
+ Assert.Same(testServer, server);
return new List
{
new TextContent("hello!"),
@@ -654,7 +656,7 @@ public async Task CanReturnCollectionOfAIContent()
};
}, new() { Name = "Test", SerializerOptions = JsonContext6.Default.Options });
var result = await resource.ReadAsync(
- new RequestContext(mockServer.Object, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
+ new RequestContext(testServer, CreateTestJsonRpcRequest()) { Params = new() { Uri = "resource://mcp/Test" } },
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.Equal(2, result.Contents.Count);
From 8abd2e9d29f6bb8460565b4f654b453a4e06124c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:48:00 +0000
Subject: [PATCH 08/10] Replace all Mock usages with
McpServer.Create() + TestServerTransport
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../Configuration/McpServerBuilderExtensionsPromptsTests.cs | 4 ++--
.../Configuration/McpServerBuilderExtensionsResourcesTests.cs | 4 ++--
.../Configuration/McpServerBuilderExtensionsToolsTests.cs | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsPromptsTests.cs b/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsPromptsTests.cs
index 69405e16c..f8fde1387 100644
--- a/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsPromptsTests.cs
+++ b/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsPromptsTests.cs
@@ -5,7 +5,7 @@
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
-using Moq;
+using ModelContextProtocol.Tests.Utils;
using System.Collections;
using System.ComponentModel;
using System.Text.Json;
@@ -314,7 +314,7 @@ public async Task WithPrompts_TargetInstance_UsesTarget()
sc.AddMcpServer().WithPrompts(target);
McpServerPrompt prompt = sc.BuildServiceProvider().GetServices().First(t => t.ProtocolPrompt.Name == "returns_string");
- var result = await prompt.GetAsync(new RequestContext(new Mock().Object, new JsonRpcRequest { Method = "test", Id = new RequestId("1") })
+ var result = await prompt.GetAsync(new RequestContext(McpServer.Create(new TestServerTransport(), new McpServerOptions()), new JsonRpcRequest { Method = "test", Id = new RequestId("1") })
{
Params = new GetPromptRequestParams
{
diff --git a/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsResourcesTests.cs b/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsResourcesTests.cs
index 545384a7c..b066f7d5a 100644
--- a/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsResourcesTests.cs
+++ b/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsResourcesTests.cs
@@ -5,7 +5,7 @@
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
-using Moq;
+using ModelContextProtocol.Tests.Utils;
using System.Collections;
using System.ComponentModel;
using System.Threading.Channels;
@@ -345,7 +345,7 @@ public async Task WithResources_TargetInstance_UsesTarget()
sc.AddMcpServer().WithResources(target);
McpServerResource resource = sc.BuildServiceProvider().GetServices().First(t => t.ProtocolResource?.Name == "returns_string");
- var result = await resource.ReadAsync(new RequestContext(new Mock().Object, new JsonRpcRequest { Method = "test", Id = new RequestId("1") })
+ var result = await resource.ReadAsync(new RequestContext(McpServer.Create(new TestServerTransport(), new McpServerOptions()), new JsonRpcRequest { Method = "test", Id = new RequestId("1") })
{
Params = new()
{
diff --git a/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs b/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs
index 518b70f00..b3abb111f 100644
--- a/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs
+++ b/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsToolsTests.cs
@@ -5,7 +5,7 @@
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
-using Moq;
+using ModelContextProtocol.Tests.Utils;
using System.Collections;
using System.Collections.Concurrent;
using System.ComponentModel;
@@ -594,7 +594,7 @@ public async Task WithTools_TargetInstance_UsesTarget()
sc.AddMcpServer().WithTools(target, BuilderToolsJsonContext.Default.Options);
McpServerTool tool = sc.BuildServiceProvider().GetServices().First(t => t.ProtocolTool.Name == "get_ctor_parameter");
- var result = await tool.InvokeAsync(new RequestContext(new Mock().Object, new JsonRpcRequest { Method = "test", Id = new RequestId("1") }), TestContext.Current.CancellationToken);
+ var result = await tool.InvokeAsync(new RequestContext(McpServer.Create(new TestServerTransport(), new McpServerOptions()), new JsonRpcRequest { Method = "test", Id = new RequestId("1") }), TestContext.Current.CancellationToken);
Assert.Equal(target.GetCtorParameter(), (result.Content[0] as TextContentBlock)?.Text);
}
From f6af40fc2b1339ea6ca444d97e874009223d2c77 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:53:21 +0000
Subject: [PATCH 09/10] Fix SupportsMcpServer test assertions to preserve
original lambda parameter names
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../Server/McpServerPromptTests.cs | 10 +++++-----
.../Server/McpServerToolTests.cs | 8 ++++----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs
index 1a6fab1c7..ae6178109 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerPromptTests.cs
@@ -46,18 +46,18 @@ public void Create_InvalidArgs_Throws()
[Fact]
public async Task SupportsMcpServer()
{
- McpServer server = CreateTestServer();
+ McpServer testServer = CreateTestServer();
- McpServerPrompt prompt = McpServerPrompt.Create((McpServer s) =>
+ McpServerPrompt prompt = McpServerPrompt.Create((McpServer server) =>
{
- Assert.Same(server, s);
+ Assert.Same(testServer, server);
return new ChatMessage(ChatRole.User, "Hello");
});
- Assert.DoesNotContain("s", prompt.ProtocolPrompt.Arguments?.Select(a => a.Name) ?? []);
+ Assert.DoesNotContain("server", prompt.ProtocolPrompt.Arguments?.Select(a => a.Name) ?? []);
var result = await prompt.GetAsync(
- new RequestContext(server, CreateTestJsonRpcRequest()),
+ new RequestContext(testServer, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Messages);
diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs
index 5a147a66e..7634862d4 100644
--- a/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs
+++ b/tests/ModelContextProtocol.Tests/Server/McpServerToolTests.cs
@@ -54,18 +54,18 @@ public void Create_InvalidArgs_Throws()
[Fact]
public async Task SupportsMcpServer()
{
- McpServer server = CreateTestServer();
+ McpServer testServer = CreateTestServer();
- McpServerTool tool = McpServerTool.Create((McpServer s) =>
+ McpServerTool tool = McpServerTool.Create((McpServer server) =>
{
- Assert.Same(server, s);
+ Assert.Same(testServer, server);
return "42";
});
Assert.DoesNotContain("server", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, McpJsonUtilities.DefaultOptions));
var result = await tool.InvokeAsync(
- new RequestContext(server, CreateTestJsonRpcRequest()),
+ new RequestContext(testServer, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("42", (result.Content[0] as TextContentBlock)?.Text);
}
From adb6f59ae8e2bba8d6cdc1bcff94f964b3f302ec Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:55:46 +0000
Subject: [PATCH 10/10] Remove InternalsVisibleTo from
ModelContextProtocol.Core.csproj
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../ModelContextProtocol.Core.csproj | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
index 45ce22d69..05e732c6f 100644
--- a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
+++ b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
@@ -55,10 +55,6 @@
-
-
-
-