MCP防🛡️
MCProof:用于测试MCP服务器的框架
安装
npm install mcproof快速开始
创建一个 .env.mcproof 项目根目录中的文件:
MCPROOF_BASE_URL=http://localhost:36719
MCPROOF_TIMEOUT_MS=10000
MCPROOF_HEADERS='{ "Authorization": "Bearer integration-token", "x-api-key":"demo-key" }'编写粒度测试文件,无需任何本地客户端设置:
tools.test.ts
import { expectTool, expectToolCallContent, expectToolCallSuccess, getSharedMcpTestClient } from 'mcproof';
describe('get_current_time', () => {
const client = getSharedMcpTestClient();
test('tool is present', async () => {
await expectTool(client, 'get_current_time');
});
test('responds successfully', async () => {
const result = await client.invokeTool({
name: 'get_current_time',
input: { timezone: 'America/New_York' },
});
expectToolCallSuccess(result);
expectToolCallContent(result, expect.objectContaining({
timezone: 'America/New_York',
}));
});
test('fails when required input is missing', async () => {
await expectToolCallError(
client.invokeTool({ name: 'get_current_time', input: {} })
);
});
});resources.test.ts
import {
expectResource,
expectResourceReadContent,
expectResourceReadSuccess,
getSharedMcpTestClient,
} from 'mcproof';
describe('time_tool_app resource', () => {
const client = getSharedMcpTestClient();
test('is available', async () => {
await expectResource(client, 'ui://time-tool/mcp-app.html', {
mimeType: 'text/html;profile=mcp-app',
});
});
test('returns content', async () => {
const result = await client.readResource({ uri: 'ui://time-tool/mcp-app.html' });
expectResourceReadSuccess(result);
expectResourceReadContent(result, expect.any(Array));
});
});prompts.test.ts
import {
expectPrompt,
expectPromptGetContent,
expectPromptGetSuccess,
getSharedMcpTestClient,
} from 'mcproof';
describe('time_expert_prompt', () => {
const client = getSharedMcpTestClient();
test('is available', async () => {
await expectPrompt(client, 'time_expert_prompt', {
argumentCount: 0,
});
});
test('returns messages', async () => {
const result = await client.getPrompt({ name: 'time_expert_prompt' });
expectPromptGetSuccess(result);
expectPromptGetContent(result, expect.any(Array));
});
});使用框架CLI运行套件:
npx mcproof test例如。, MCProof Logging Screenshot
每个CLI测试运行还会在以下目录下编写一个简单的HTML报告 mcproof-reports/ 在您当前的工作目录中。
例如。, MCProof Report Screenshot 1 MCProof Report Screenshot 2
显示已安装的软件包版本:
npx mcproof --version错误测试
错误断言支持两种模式,但 承诺模式 是默认且最安全的选项。
Promise模式 --直接传递promise,无需等待捕获验证错误:
test('fails when required input is missing', async () => {
await expectToolCallError(
client.invokeTool({ name: 'get_current_time', input: {} })
);
});
test('fails for invalid URI', async () => {
await expectResourceReadError(
client.readResource({ uri: 'invalid://uri' })
);
});
test('fails for unknown name', async () => {
await expectPromptGetError(
client.getPrompt({ name: 'unknown_prompt' })
);
});同步结果模式 --仅在SDK返回错误结果对象(不抛出)时使用此选项:
test('tool call returns error', async () => {
const result = await client.invokeTool({ name: 'some_tool', input: { bad: 'input' } });
expectToolCallError(result, 'MCP error -32602: validation failed');
});尝试/捕捉模式 --当您有意直接对抛出的错误进行断言时,请使用此选项:
test('tool throws when required input is missing', async () => {
try {
await client.invokeTool({ name: 'get_current_time', input: {} });
throw new Error('Expected invokeTool to throw');
} catch (error) {
expect(String(error)).toContain('MCP error -32602');
}
});环境配置
MCPROOF_BASE_URL:必需的MCP服务器基本URLMCPROOF_TIMEOUT_MS:可选超时(毫秒)MCPROOF_HEADERS:默认标头的可选JSON对象MCPROOF_HEADER_*:可选的每个标头覆盖,例如。MCPROOF_HEADER_AUTHORIZATIONMCPROOF_ENV_FILE:非默认env文件的可选路径
当两者都 MCPROOF_HEADERS 和 MCPROOF_HEADER_* 如果有人在场,个人头球队获胜。
高级用法
import {McpTestClient, validateMcpToolCall, expectToolCallSuccess} from 'mcproof';
const client = new McpTestClient({ baseUrl: 'http://localhost:36719', timeoutMs: 10000 });
client.setAuthHeaders({ Authorization: 'Bearer token', 'x-api-key': 'key' });
const validation = validateMcpToolCall({ name: 'ping', requestId: '1' });
if (!validation.isValid) {
throw new Error(validation.message);
}
const result = await client.invokeTool({ name: 'ping', requestId: '1' });
expectToolCallSuccess(result);
const resourceResult = await client.readResource({ uri: 'resource://weather/current', requestId: '2' });
const promptResult = await client.getPrompt({
name: 'summarize.weather',
arguments: { city: 'Montreal' },
requestId: '3',
});
console.log('result output', result.output);
console.log('resource output', resourceResult.output);
console.log('prompt output', promptResult.output);API
McpTestClient-具有HTTP MCP集成的核心测试客户端
- connect() - disconnect() - getAuthHeaders() - setAuthHeaders(headers) - clearAuthHeaders() - listTools() - listResources() - listPrompts() - invokeTool(toolCall) - readResource(resourceRead) - getPrompt(promptGet)
installSharedMcpTestClient(config)
configureSharedMcpTestClient(config)
initializeSharedMcpTestClient()
getSharedMcpTestClient()
disconnectSharedMcpTestClient()
resetSharedMcpTestClient()
validateMcpToolCall(call)-退货McpProtocolValidationResult
validateMcpToolResult(result)-退货McpProtocolValidationResult
validateMcpResourceRead(read)-退货McpProtocolValidationResult
validateMcpResourceResult(result)-退货McpProtocolValidationResult
validateMcpPromptGet(get)-退货McpProtocolValidationResult
validateMcpPromptResult(result)-退货McpProtocolValidationResult
expectTool(client, toolName)
expectResource(client, resourceUri, expected?)
expectPrompt(client, promptName, expected?)
expectToolCallSuccess(result)
expectToolCallError(resultOrInvocation[, expectedMessage])
expectToolCallContent(result, expected)
expectToolCallMeta(result, expected?)
expectResourceReadSuccess(result)
expectResourceReadError(resultOrInvocation[, expectedMessage])
expectResourceReadContent(result, expected)
expectResourceReadMeta(result, expected?)
expectPromptGetSuccess(result)
expectPromptGetError(resultOrInvocation[, expectedMessage])
expectPromptGetContent(result, expected)
expectPromptGetMeta(result, expected?)
备注
- 使用官方的MCP TypeScript SDK客户端和可流式传输的HTTP。
- 专为无状态HTTP MCP工具而设计。
- 默认值
mcproof test命令强制共享客户端工作流按顺序执行Jest。 mcproof test将带时间戳的HTML摘要写入mcproof-reports/带有飞行前发现细节和Jest结果。- 手动共享客户端API仍然可用于高级或非标准集成。
