2026年7月8日 3 分钟阅读

mcp-recorder 实战教程:用 VCR 模式锁定 MCP 服务器回归测试

tinyash 0 条评论

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 的工作流非常直观,就三个步骤:

  1. Record:代理到真实 MCP 服务器,把完整的 JSON-RPC 对话录成 cassette 文件
  2. Replay:用 cassette 模拟服务器响应,测试你的 Agent 客户端——不需要真实服务器,不需要网络,不需要凭据
  3. 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,可以省下大量事后排查的时间。


相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。