使用说明
mcp线束
TypeScript中MCP服务器的内存测试工具包——MCP的超级测试。
为什么
今天测试MCP服务器意味着将它们作为子进程运行,通过stdio连接,并手动检查JSON。它缓慢、不稳定,很难融入CI。
mcp线束 为您提供了一个快速的内存测试线束,可以直接连接到您的 McpServer 实例——没有子进程,没有端口,没有IO。只需导入服务器,创建一个线束,并对结果进行断言。思考 超级试验 但对于模型上下文协议。
快速开始
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { createHarness } from 'mcp-harness';
import { hasText, getFirstText } from 'mcp-harness/assertions';
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
server.tool('greet', { name: z.string() }, async ({ name }) => ({
content: [{ type: 'text', text: `Hello, ${name}!` }],
}));
const harness = await createHarness(server);
const result = await harness.callTool('greet', { name: 'World' });
console.log(getFirstText(result)); // "Hello, World!"
console.log(hasText(result, 'Hello')); // true
await harness.close();
安装
npm install --save-dev mcp-harness
对等依赖: @modelcontextprotocol/sdk 必须安装在您的项目中。
用法
内存模式
传递您的 McpServer 实例直接。零IO,即时启动:
import { createHarness } from 'mcp-harness';
import { myServer } from './server.js';
const harness = await createHarness(myServer);
// List tools, resources, prompts
const tools = await harness.listTools();
const resources = await harness.listResources();
const templates = await harness.listResourceTemplates();
const prompts = await harness.listPrompts();
// Call a tool
const result = await harness.callTool('my-tool', { arg: 'value' });
// Read a resource
const resource = await harness.readResource('info://version');
// Get a prompt
const prompt = await harness.getPrompt('my-prompt', { name: 'Gab' });
// Server info
const capabilities = harness.getServerCapabilities();
const version = harness.getServerVersion();
// Health check
await harness.ping();
// Always close when done
await harness.close();
子流程模式
通过stdio传输测试编译的服务器,就像真正的MCP客户端一样:
import { createHarness } from 'mcp-harness';
const harness = await createHarness({
command: 'node',
args: ['dist/server.js'],
env: { API_KEY: 'test-key' },
cwd: '/path/to/project',
});
const tools = await harness.listTools();
// Access subprocess stderr for debugging
console.log(harness.stderr);
await harness.close();
断言助手
用于检查MCP结果的框架无关助手。与Vitest、Jest、node:assert或任何测试运行器一起使用:
import {
hasText,
getTexts,
getFirstText,
hasError,
hasErrorMatching,
toolExists,
findTool,
resourceExists,
promptExists,
} from 'mcp-harness/assertions';
// Inspect tool call results
const result = await harness.callTool('echo', { message: 'hi' });
hasText(result, 'hi'); // true
getFirstText(result); // "hi"
getTexts(result); // ["hi"]
// Check for errors
hasError(result); // false
hasErrorMatching(result, /timeout/); // false
// Inspect server capabilities
const tools = await harness.listTools();
toolExists(tools, 'echo'); // true
findTool(tools, 'echo'); // Tool object or undefined
const resources = await harness.listResources();
resourceExists(resources, 'info://version'); // true
const prompts = await harness.listPrompts();
promptExists(prompts, 'greet'); // true
选项
const harness = await createHarness(server, {
timeout: 5000, // Connection/request timeout in ms
clientName: 'my-test', // Client name for MCP handshake
clientVersion: '1.0.0', // Client version
clientCapabilities: {}, // Additional client capabilities
});
API 参考
createHarness(server, options?)
| 参数 | 类型 | 说明 |
|---|---|---|
server |
McpServer | SubprocessConfig |
服务器实例或子流程配置 |
options |
HarnessOptions |
可选连接设置 |
| 退货 | Promise<McpHarness> |
已连接线束实例 |
McpHarness
| 方法 | 签名 | 描述 |
|---|---|---|
listTools() |
() => Promise<Tool[]> |
列出所有已注册的工具 |
callTool() |
(name, args?) => Promise<CallToolResult> |
按名称调用工具 |
listResources() |
() => Promise<Resource[]> |
列出所有已注册的资源 |
readResource() |
(uri) => Promise<ReadResourceResult> |
按URI读取资源 |
listResourceTemplates() |
() => Promise<ResourceTemplate[]> |
列出资源模板 |
listPrompts() |
() => Promise<Prompt[]> |
列出所有已注册的提示 |
getPrompt() |
(name, args?) => Promise<GetPromptResult> |
按名称获取提示 |
ping() |
() => Promise<void> |
Ping服务器 |
getServerCapabilities() |
() => ServerCapabilities | undefined |
获取服务器功能 |
getServerVersion() |
() => { name, version } | undefined |
获取服务器名称和版本 |
close() |
() => Promise<void> |
关闭线束(幂等) |
client |
Client |
用于高级用途的原始MCP客户端 |
stderr |
string | undefined |
子流程stderr输出(仅子流程模式) |
HarnessOptions
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
timeout |
number |
-- | 连接/请求超时(毫秒) |
clientName |
string |
'mcp-harness' |
握手客户端名称 |
clientVersion |
string |
'0.1.0' |
客户端版本 |
clientCapabilities |
object |
-- | 附加功能 |
SubprocessConfig
| 字段 | 类型 | 描述 |
|---|---|---|
command |
string |
要执行的命令('node', 'npx') |
args |
string[] |
命令参数 |
env |
Record<string, string> |
环境变量(已合并 process.env) |
cwd |
string |
工作目录 |
断言助手(mcp-harness/assertions)
| 功能 | 签名 | 描述 |
|---|---|---|
hasText() |
(result, text) => boolean |
检查是否有任何文本块包含子字符串 |
getTexts() |
(result) => string[] |
从结果中提取所有文本字符串 |
getFirstText() |
(result) => string | undefined |
获取第一个文本字符串或未定义 |
hasError() |
(result) => boolean |
检查结果是否为错误 |
hasErrorMatching() |
(result, pattern) => boolean |
检查错误是否与字符串/RegExp匹配 |
toolExists() |
(tools, name) => boolean |
按名称检查工具是否存在 |
findTool() |
(tools, name) => Tool | undefined |
按名称查找工具 |
resourceExists() |
(resources, uri) => boolean |
按URI检查资源是否存在 |
promptExists() |
(prompts, name) => boolean |
按名称检查提示是否存在 |
例子
运作原理
在 内存模式,mcp线束使用mcp SDK InMemoryTransport 以创建一对链接的传输。你的 McpServer 连接到一侧,以及 Client 连接到另一个。消息直接在内存中流动——没有序列化,没有IO,没有子进程。
flowchart LR
client["MCP Client<br/>(harness)"]
server["McpServer<br/>(your code)"]
client <--> |InMemoryTransport<br/>linked pair| server
在 子流程模式,该工具将您的服务器作为子进程生成,并通过以下方式连接 StdioClientTransport,就像真正的MCP主机一样。
贡献
git clone https://github.com/gabry-ts/mcp-harness.git
cd mcp-harness
npm install
npm test
npm run build
许可证
麻省理工学院 © 加布里埃尔 Partiti
