MCP服务器测试工具包

一个用于TypeScript中MCP服务器的内存测试工具包,提供快速、无需子进程或IO的测试解决方案。

  • by gabry-ts
  • TypeScript
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 gabry-ts/mcp-harness

使用说明

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