返回市场
自动测试

自动测试

作者:strowk2 星标更新:2025-04-09

项目介绍

<h4 align="center">使用语言无关的方式自动测试MCP服务器</h4> <h1 align="center"> <img src="docs/images/logo.png" width="180"/> <br/> mcp-autotest </h1> <p align="center"> <a href="https://github.com/strowk/mcp-autotest/actions/workflows/test.yaml"><img src="https://github.com/strowk/mcp-autotest/actions/workflows/test.yaml/badge.svg"></a> <a href="https://github.com/strowk/mcp-autotest/actions/workflows/golangci-lint.yaml"><img src="https://github.com/strowk/mcp-autotest/actions/workflows/golangci-lint.yaml/badge.svg"/></a> <a href="https://goreportcard.com/report/github.com/strowk/mcp-autotest"><img src="https://goreportcard.com/badge/github.com/strowk/mcp-autotest" alt="Go Report Card"></a> </p> <p align="center"> <a href="#installation">安装</a> ⚙ <a href="#usage">使用</a> ⚙ <a href="#quick-demo">快速演示</a> ⚙ <a href="#dynamic-matching">动态匹配</a> </p>

一个简单的工具,允许您通过定义包含请求和响应的YAML文件来使用MCP协议测试您的MCP服务器。

MCP案例文件是一个多文档YAML文件,它将每个案例定义为一个独立的文档,如下所示:

case: 列出工具
in: { "jsonrpc": "2.0", "method": "tools/list", "id": 1 }
out:
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result":
      {
        "tools":
          [
            {
              "description": "运行只读SQL查询",
              "inputSchema":
                {
                  "type": "object",
                  "properties": { "sql": { "type": "string" } },
                },
              "name": "query",
            },
          ],
      }
  }

---
# 下一个案例...

文件必须以 _test.yaml 后缀命名,以便被识别为测试案例文件。

安装

npm

npm install -g mcp-autotest

Github Releases

发布页面下载预构建二进制文件,并将其放入您的PATH中。

从源代码构建

go install github.com/strowk/mcp-autotest@latest

使用

mcp-autotest [flags] run 路径/到/测试/文件夹 [--] 要运行的服务器命令 [服务器参数]

示例:

# 启动Go MCP服务器并通过stdio传输进行测试
mcp-autotest run testdata go run main.go
# 启动Postgres MCP服务器并通过stdio传输进行测试
mcp-autotest run -v testdata -- npx -y @modelcontextprotocol/server-postgres localhost:5432
# 启动Go MCP服务器并通过Streamable HTTP传输进行测试
mcp-autotest run --url http://localhost:8080/mcp testdata go run main.go

传输方式

默认情况下,mcp-autotest会使用stdio传输,但如果您想使用HTTP传输,可以使用 --url 标志指定MCP服务器的URL。URL必须是以下格式之一:http://主机名:端口/路径https://主机名:端口/路径

目前,Streamable HTTP仅支持 POST 方法,但未来计划支持 GET 方法。

快速演示

在bash shell中运行以下内容:


# 创建测试数据文件夹
mkdir -p testdata

# 创建测试案例文件
cat << EOF > testdata/list_tools_test.yaml
# 这是一个测试案例文件。它包含一系列用YAML格式表示的测试案例。
# 每个测试案例都有可变数量的输入(以'in'开头的键)和输出(以'out'开头的键)。
# 测试案例之间由'---'(三个破折号)分隔,形成一个多文档YAML文件。
# 文件名必须以'_test.yaml'结尾,才能被识别为测试案例文件。

case: 列出工具

# 请求工具列表
in: { "jsonrpc": "2.0", "method": "tools/list", "id": 1 }

# 预期工具列表中有一个工具
out:
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result":
      {
        "tools":
          [
            {
              "description": "运行只读SQL查询",
              "inputSchema":
                {
                  "type": "object",
                  "properties": { "sql": { "type": "string" } },
                },
              "name": "query",
            },
          ],
      }
  }
EOF

# 现在运行自动测试
npx mcp-autotest run testdata -- npx -y @modelcontextprotocol/server-postgres localhost:5432

输出应简单地打印一个单词 PASS

现在,如果您更改了 "description": "运行只读SQL查询", 行中的内容,例如改为 "description": "运行只读SQL查询2",并再次运行最后一个命令,您应该看到如下输出:

2025/03/31 22:23:39 实际json与预期不符,
 得到: '{"id":1,"jsonrpc":"2.0","result":{"tools":[{"description":"运行只读SQL查询","inputSchema":{"properties":{"sql":{"type":"string"}},"type":"object"},"name":"query"}]}}'
 与预期的差异:
  "result": {
    "tools": {
      "0": {
        "description": {
        ^ 值不匹配,
预期字符串: '运行只读SQL查询2',
 得到字符串: '运行只读SQL查询'
FAIL

动态匹配

有时当您的响应中有动态值时,您可能希望使用正则表达式来匹配它们。您可以通过在预期输出中使用 !!re 标签来实现这一点。例如:

case: 列出工具
in_list_tools: {"jsonrpc":"2.0","method":"tools/list","id":1}
out_list_tools: {"jsonrpc":"2.0","result":{"tools":[ { "name": !!re "list-[a-z]+" } ]},"id":1}

这个例子有些过于简化,在实际应用中,您可能会使用 !!re 来处理时间戳、UUID或其他动态值,而不是工具名称。然而,这确实展示了带有 !!re 标签的字符串会被视为正则表达式,并且会使用正则表达式匹配实际值,而不是字符串相等性。

查看测试 Postgres服务器 的工作示例。

嵌入式正则表达式

嵌入式正则表达式只是一个嵌入在字符串中的正则表达式。它用于匹配字符串的一部分。例如:

case: 列出工具
in_list_tools: {"jsonrpc":"2.0","method":"tools/list","id":1}
out_list_tools: {"jsonrpc":"2.0","result":{"tools":[ { "name": !!ere "list-/[a-z]+/-tool" } ]},"id":1}

基本上,!!ere 允许您将大部分字符串视为普通字符串,但让其中一部分(或几部分)被视为正则表达式。 斜杠 / 内部的内容被视为正则表达式,在这里 "list-" 和 "-tool" 是普通字符串,而 [a-z]+ 是一个正则表达式,它可以匹配任何非空的小写字母字符串,因此它可以匹配 "list-abc-tool"、"list-xyz-tool" 等。

这种方法让您不必考虑如何在字符串的其余部分中转义正则表达式语法,只需匹配需要动态的部分即可。

转义斜杠

对于嵌入式正则表达式,您可能需要在字符串中转义斜杠 /,以便在不需要指定正则表达式的地方使用它们。例如:"url": !! "https:\\/\\/github.com\\//[a-z]+/" 可以匹配 "url": "https://github.com/strowk"。 在这里,\\/ 用来变成 /,而 [a-z]+ 用来匹配任何非空的小写字母字符串。之所以有两个反斜杠 \\,是因为在YAML字符串中,反斜杠是转义字符,所以要在字符串中拥有单个反斜杠,需要使用另一个反斜杠来转义它。