使用说明
McpServerFactory
内存集成 测试框架 为。NET模型上下文协议(MCP)服务器。
MCP服务器的真正契约不是与代码的契约,而是与模型的契约。 工具名称
JSON模式、代理读取的描述、它看到的错误文本、采样
它引发的往返旅行。McpServerFactory启动您的服务器 过程中的 并连接a 真实的
McpClient 通过内存管道,您可以在简单的单元测试中对该合约进行断言:
两边都有断点,依赖关系被替换为假货,没有子进程,没有端口,没有Docker,
没有现场模特。
思考 WebApplicationFactory<T> --但对于MCP来说。
// one process: a real client ⇄ your real server, over in-memory pipes
McpTestClient client = await factory.CreateTestClientAsync();
Assert.Equal("hello", await client.CallToolForTextAsync(
"echo", new Dictionary<string, object?> { ["message"] = "hello" }));
您可以实际验证的内容
- 一个工具 存在,它的输入模式/描述就是你所想的(
GetToolAsync,McpAssert.ToolExistsAsync). - 工具返回右侧 文本 或 键入JSON (
CallToolForTextAsync,CallToolForJsonAsync<T>). - 一个工具 未能如愿 —
IsError结果抛出而不是悄悄通过测试(CallToolExpectingErrorAsync). - 服务器启动采样 做正确的事,用你控制的假模型来回答(
FakeSamplingHandler). - 预期 通知 火灾——记录、进度、列表已更改(
NotificationRecorder). - 你的 真实DI图 连接起来,模拟慢速/外部比特(
configureServices/ConfigureHost).
范围: 默认情况下,工厂托管 您注册的工具/资源/提示类 通过内存传输。它不会自动运行您的服务器
Program.cs.锻炼 您的真实组合根(配置、选项、托管服务),请使用ConfigureHost钩子。
安装
dotnet add package McpServerFactory
模板脚手架
安装模板包以引导MCP集成测试项目:
dotnet new install McpServerFactory.Templates
dotnet new mcp-itest -n MyServer.Tests
这 mcp-itest 模板接受 --McpServerFactoryVersion 以覆盖
McpServerFactory 包版本;默认跟踪的版本
您安装的模板包。
快速开始
using McpServerFactory.Testing;
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Server;
using Xunit;
[McpServerToolType]
public sealed class EchoTools
{
[McpServerTool(Name = "echo")]
public string Echo(string message) => message;
}
public class EchoTests
{
[Fact]
public async Task Echo_ReturnsInput()
{
await using McpServerIntegrationFactory factory = new(
configureMcpServer: builder => builder.WithTools<EchoTools>());
// The factory owns the client; you do not dispose it yourself.
McpTestClient client = await factory.CreateTestClientAsync();
string text = await client.CallToolForTextAsync(
"echo",
new Dictionary<string, object?> { ["message"] = "hello" });
Assert.Equal("hello", text);
}
}
使用xUnit?同伴 McpServerFactory.Xunit 包裹
每个测试类通过以下方式启动服务器一次 IClassFixture<T>.
为什么使用这个库
- 快速且正在处理中 --没有子进程、端口、Docker或stdio管道。
- 真实协议流 --一个真实的
McpClient通过真实(内存中)传输:tools/list,tools/call、资源、提示和服务器启动的采样都是端到端运行的。 - 易依赖性覆盖 --替代服务通过
configureServices. - 可调试 --在两侧设置断点;这都是一个过程。
- 与框架无关的核心 --与xUnit、NUnit和MSTest配合使用。
如何比较
| 方法 | 速度 | 无进程/端口 | 两侧断点 | DI替换 | 练习真实 Program.cs |
|---|---|---|---|---|---|
| McpServerFactory | 快 | ✅ | ✅ | ✅ | 通过 ConfigureHost |
stdio子流程+ McpClient |
缓慢 | ❌ | 仅限服务器 | ❌ | ✅ |
未加工管道+ StreamClientTransport |
快 | ✅ | ✅ | ✅ (手动) | ❌ |
| MCP检查员(手动) | n/a | ❌ | ❌ | ❌ | ✅ |
使用它时 您希望对您的工具/资源/提示进行快速、自动化、过程中的测试,以及 具有依赖替换的处理程序。 改用stdio子流程 当你必须 验证实际发布的二进制文件、其实际传输配置或进程级启动。
在野外使用
stash-mcp --用于Bitbucket的40工具MCP服务器
服务器——使用McpServerFactory测试其工具。它对工厂进行子类化,注册其真正的工具
组装,并将实时Bitbucket客户端、缓存和弹性服务替换为假货,因此
整个工具表面在过程中进行锻炼,而无需接触Bitbucket实例:
public sealed class StashMcpTestFactory(Action<StashMcpTestFactory>? configureMocks = null)
: McpServerFactory.Testing.McpServerFactory
{
public IBitbucketClient BitbucketClient { get; } = Substitute.For<IBitbucketClient>();
protected override void ConfigureMcpServer(IMcpServerBuilder builder) =>
builder.WithToolsFromAssembly(typeof(ProjectTools).Assembly);
protected override void ConfigureServices(IServiceCollection services) =>
services.AddSingleton(BitbucketClient); // ...plus cache, settings, resilience fakes
}
测试工具、资源、提示和结构化输出
McpTestClient 包裹真实 McpClient 使用测试形状的助手(所有分页都是安全的):
McpTestClient client = await factory.CreateTestClientAsync();
string[] tools = await client.GetToolNamesAsync();
string greeting = await client.CallToolForTextAsync("greet");
MyDto result = await client.CallToolForJsonAsync<MyDto>("compute", args); // structured or JSON-text
string contents = await client.ReadResourceTextAsync("resource://config");
string[] prompts = await client.GetPromptNamesAsync();
工具故障(IsError)不再默默地流逝: CallToolForTextAsync 投掷
McpToolCallException,以及 CallToolExpectingErrorAsync 断言负路径。这
框架无关 McpAssert 助手(ToolExistsAsync, Succeeded, IsError, TextEquals)
在任何测试框架下工作。
测试服务器启动采样
如果您的服务器调用模型(服务器发起的采样),则连接一个确定性的假模型进行测试 永远不需要真正的法学硕士:
FakeSamplingHandler sampling = FakeSamplingHandler.Returning("42");
await using McpServerIntegrationFactory factory = new(
configureMcpServer: builder => builder.WithTools<AskTools>(),
options: new McpServerFactoryOptions
{
ConfigureClient = client => client.UseSamplingHandler(sampling),
});
McpTestClient client = await factory.CreateTestClientAsync();
string answer = await client.CallToolForTextAsync(
"ask", new Dictionary<string, object?> { ["question"] = "..." });
Assert.Single(sampling.ReceivedRequests); // assert what the server asked the model
ConfigureClient 暴露全部 McpClientOptions,所以你也可以声明启发、根、,
或通知处理程序。捕获服务器发送的通知(日志记录、进度、列表更改)
NotificationRecorder.Attach(client.Inner) 和 await recorder.WaitForMethodAsync(...).
测试你的真实作文根
默认情况下,工厂托管您注册的类。要执行相同的注册,请
服务器的 Program.cs 使用--实际配置绑定、选项和托管服务--供应
ConfigureHost工厂始终拥有MCP服务器注册和内存传输,
所以配置一切 除了 运输;通过注册工具/资源/提示
configureMcpServer:
await using McpServerIntegrationFactory factory = new(
configureMcpServer: builder => builder.WithTools<MyTools>(),
options: new McpServerFactoryOptions
{
ConfigureHost = builder =>
{
builder.Configuration.AddInMemoryCollection(/* test config */);
builder.Services.AddMyDomainServices(); // your real registration, minus the transport
},
});
使用xUnit每类启动一次
安装配套包并衍生夹具:
dotnet add package McpServerFactory.Xunit
using McpServerFactory.Testing.Xunit;
public sealed class EchoFixture : McpServerFixture
{
protected override void ConfigureMcpServer(IMcpServerBuilder builder) => builder.WithTools<EchoTools>();
}
public sealed class EchoTests(EchoFixture fixture) : IClassFixture<EchoFixture>
{
[Fact]
public async Task Echoes() =>
Assert.Equal("hi", await fixture.TestClient.CallToolForTextAsync(
"echo", new Dictionary<string, object?> { ["message"] = "hi" }));
}
行为保证
CreateClientAsync/CreateTestClientAsync每个工厂实例都是线程安全和幂等的。- 并发呼叫返回相同的已连接客户端; 工厂拥有并处置它 --你知道 不需要自己处理退回的客户。
- 启动失败不会泄漏临时主机实例或其管道。
DisposeAsync多次调用是安全的,并且受以下限制ShutdownTimeout(它不会挂起来 拆卸)。CreateClientAsync投掷ObjectDisposedException处置后。- 需要独立的服务器实例(隔离)?创建多个工厂实例——每个实例都有自己的 自己的主人。单个工厂公开一个内存会话。
兼容性和支持
- 目标框架:
net8.0,net9.0,net10.0. - MCP SDK依赖关系:
ModelContextProtocol0.4.0-preview.3. - 兼容性承诺:每个软件包版本都会根据所有固定的MCP SDK版本进行验证 目标框架。
- 升级策略:MCP SDK凸起是明确的,并在 更改日志.md.虽然
MCP SDK正在预览中,
McpServerFactory停留0.x步调一致地颠簸着。
| McpServerFactory | MCP SDK | 目标框架 |
|---|---|---|
| 0.2.x | 0.4.0-评论.3 | 净8.0,净9.0,净10.0 |
| 0.1.x | 0.4.0-评论.3 | 净值10.0 |
API概述
McpServerFactory/McpServerIntegrationFactory- 启动进程内服务器主机;通过以下方式创建连接的客户端
CreateClientAsync()或一个 工厂自有包装CreateTestClientAsync(). - 暴露
Services用于启动后的DI验证。
- 启动进程内服务器主机;通过以下方式创建连接的客户端
McpServerFactoryOptions- 配置服务器标识、超时、指令、日志记录、客户端(
ConfigureClient),以及 宿主组成根(ConfigureHost).
- 配置服务器标识、超时、指令、日志记录、客户端(
McpTestClient- 带有工具、资源、提示、结构化输出和服务器元数据帮助程序的包装器。
FakeSamplingHandler/NotificationRecorder/McpAssert- 确定性采样、通知捕获和框架无关断言。
McpServerFactory.Xunit(单独包装)McpServerFixture为了IClassFixture<T>每节课开机一次。
登录测试输出
默认情况下,主机日志记录提供程序被抑制,以保持测试输出的干净。 要在测试期间启用自定义日志记录,请执行以下操作:
using Microsoft.Extensions.Logging;
var options = new McpServerFactoryOptions
{
SuppressHostLogging = false,
ConfigureLogging = logging => logging.SetMinimumLevel(LogLevel.Debug),
};
发行说明
看 更改日志.md 查看发布历史和即将发生的更改。
样品
- 最小可运行样本:
samples/MinimalSmoke
存储库布局
src/McpServerFactory--可重用工厂库(与框架无关的核心)。src/McpServerFactory.Xunit— xUnit 设备 (McpServerFixture).tests/McpServerFactory.Tests--以单元/集成为重点的库测试。templates/McpServerFactory.Templates—dotnet new模板包。samples/MinimalSmoke--可运行的示例控制台应用程序。docs--架构说明和使用指南。