mcp-recorder 实战教程:用 VCR 模式锁定 MCP 服务器回归测试
MCP(Model Context Protocol)让 AI Agent 可以调用外部工具和获取外部数据,但有一个现实问题:MCP 服务器可能在你不注意的时候静默变更。工具 Schema 变了、Prompt 调整了、响应格式变了——你的 Agent 代码没动,但行为突然出了问题。
更麻烦的是,这种「静默变更」往往不会在部署时报错。你更新了某个 MCP 服务器的配置,表面上一切正常,但某个工具调用的返回格式变了。Agent 尝试解析旧格式,失败。用户第一个发现。
本文介绍的 mcp-recorder 正是为了解决这个问题——它采用 VCR(录播)模式,把 MCP 交互录制成 cassette 文件,然后通过回放和验证来检测回归。
安装:一行命令
mcp-recorder 是一个纯 Python CLI 工具,支持 Python 3.11+:
pip install mcp-recorder
或者用 uv:
uv add mcp-recorder
装完之后你就有 mcp-recorder 这个 CLI 命令了。它还有 pytest 插件,装完即用。
核心概念:Record → Replay → Verify
mcp-recorder 的工作流非常直观,就三个步骤:
- Record:代理到真实 MCP 服务器,把完整的 JSON-RPC 对话录成 cassette 文件
- Replay:用 cassette 模拟服务器响应,测试你的 Agent 客户端——不需要真实服务器,不需要网络,不需要凭据
- Verify:把 cassette 中的请求重放给更新后的 MCP 服务器,对比新响应和 golden 记录——有差异就是回归
这三个模式共享同一种 cassette 格式,所以录制一次,后续可以任意回放和验证。
来看看具体的 CLI 使用。
交互式录制
最简单的录制方式:启动代理,指向你的 MCP 服务器。
对 HTTP 协议的 MCP 服务器:
mcp-recorder record \ --target http://localhost:8000 \ --port 5555 \ --output golden.json
对 stdio 协议的 MCP 服务器(通过子进程启动):
mcp-recorder record \ --target-stdio "node dist/index.js" \ --target-env "API_KEY=$API_KEY" \ --output golden.json
代理启动后,把你的 MCP 客户端指向 http://localhost:5555,正常交互即可。按 Ctrl+C 结束录制,cassette 自动保存。
Scenarios 文件:零代码录制方案
交互式录制依赖你手动操作客户端,而 scenarios 文件可以完全自动化。创建一个 YAML 文件,定义要测试的场景:
schema_version: "1.0"
target: http://localhost:3000
redact:
server_url: true
env:
- API_KEY
patterns:
- "sk-[a-zA-Z0-9]+"
scenarios:
tools_and_schemas:
description: "列出工具并调用 search"
actions:
- list_tools
- call_tool:
name: search
arguments:
query: "test"
error_handling:
description: "空参数返回正确错误"
actions:
- call_tool:
name: search
arguments: {}
然后一条命令录制全部场景:
mcp-recorder record-scenarios scenarios.yml
每条场景会生成独立的 cassette 文件。也支持 --scenario tools_and_schemas 录制单个场景。
对于 stdio 服务器,target 换成对象格式:
target:
command: "node"
args: ["dist/index.js"]
env:
API_KEY: "${API_KEY}"
cwd: "./server"
环境变量支持 ${VAR:-default} 缺省值语法,配合 CI 非常自然。
验证回归
修改 MCP 服务器之后,验证回归只需一条命令:
mcp-recorder verify \ --cassette golden.json \ --target http://localhost:8000
输出示例:
Verifying golden.json against http://localhost:8000
1. initialize [PASS]
2. tools/list [PASS]
3. tools/call [search] [FAIL]
$.result.content[0].text: "old output" != "new output"
4. tools/call [analyze] [PASS]
Result: 3/4 passed, 1 failed
如果有意修改了行为,用 --update 更新 cassette 即可。支持 --ignore-fields timestamp 和 --ignore-paths '$.result.metadata.requestId' 忽略易变字段。
回放测试
在没有真实服务器的情况下测试客户端:
mcp-recorder replay --cassette golden.json
然后你的 Agent 可以在 http://localhost:5555 连接 mock 服务器。无网络、无凭据、每次返回相同的响应——对单元测试和集成测试来说非常可靠。
pytest 集成:一行标记
mcp-recorder 安装后自动激活 pytest 插件。在测试中通过标记绑定 cassette:
import pytest
from fastmcp import Client
@pytest.mark.mcp_cassette("cassettes/golden.json")
async def test_tool_call(mcp_replay_url):
async with Client(mcp_replay_url) as client:
result = await client.call_tool("add", {"a": 2, "b": 3})
assert result.content[0].text == "5"
运行测试:
pytest # 从 cassette 回放(默认) pytest --mcp-target http://localhost:8000 # 验证真实服务器 pytest --mcp-target-stdio "node dist/index.js" # 验证 stdio 服务器
每个测试获得独立服务器 + 随机端口,不需要手动管理服务器生命周期。
CI 集成:GitHub Actions
在 CI 中自动验证 MCP 服务器回归:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install mcp-recorder
# 启动 MCP 服务器
- run: npm start &
- run: sleep 5
# 验证 cassette 与真实服务器一致性
- run: |
mcp-recorder verify \
--cassette integration/cassettes/tools_and_schemas.json \
--target http://localhost:3000
Cassette 文件提交到仓库后,在 replay 模式下直接跑 pytest,CI 甚至不需要启动真实服务器。
录制时做好密钥脱敏
cassette 文件中可能包含 API 密钥等敏感信息。mcp-recorder 提供三层脱敏机制:
mcp-recorder record \ --target https://mcp.firecrawl.dev/"$FIRECRAWL_KEY"/mcp \ --redact-env FIRECRAWL_KEY \ --redact-patterns "sk-[a-zA-Z0-9]+"
默认 --redact-server-url 已启用,自动剥离 URL 中的路径部分。API 密钥不会出现在请求体中(request body 从不修改),只在 metadata 和 response 中被替换。
深入一下:cassette 格式
Cassette 文件是标准 JSON,记录了完整的 JSON-RPC 协议层交互:
{
"version": "1.0",
"metadata": {
"recorded_at": "2026-02-17T20:25:23Z",
"server_url": "http://127.0.0.1:8000",
"transport_type": "http",
"protocol_version": "2025-11-25",
"server_info": { "name": "Test Calculator", "version": "2.14.5" }
},
"interactions": [
{
"type": "jsonrpc_request",
"request": {
"jsonrpc": "2.0", "id": 0,
"method": "tools/call",
"params": { "name": "add", "arguments": { "a": 2, "b": 3 } }
},
"response": {
"jsonrpc": "2.0", "id": 0,
"result": { "content": [{ "type": "text", "text": "5" }] }
},
"latency_ms": 18
}
]
}
可以和 mcp-recorder inspect golden.json 查看摘要信息——交互数量、每步耗时、协议版本等。
适用场景总结
| 场景 | 推荐模式 | 优势 |
|---|---|---|
| 本地开发测试客户端 | Replay | 无网络依赖,确定性响应 |
| PR 前验证服务器变更 | Verify | 自动检测回归,CI 集成 |
| 多版本兼容性测试 | Verify + 多个 cassette | 覆盖不同协议版本的差异 |
| 团队协作 | Scenario 文件提交仓库 | 新人上手直接 pip install + 运行 |
mcp-recorder 目前支持 HTTP(Streamable HTTP / SSE)和 stdio 两种传输协议,规划中还有 WebSocket、TypeScript 插件和 cassette diff 比较等特性。
如果你在开发或维护 MCP 服务器,或者你构建的 AI Agent 依赖于外部 MCP 工具,给 mcp-recorder 一个机会——花 10 分钟录制第一组 cassette,之后每次变更都跑一遍 verify,可以省下大量事后排查的时间。
相关链接