mcpField
G
Gaffer

Gaffer

本地服务
gaffer.sh开发工具111 周前更新

关于 Gaffer

Gaffer 是面向 AI 编码 Agent 的 MCP 服务,可连接项目的测试历史、失败记录和覆盖率数据。它通过代码模式支持串联分析调用,并提供单一的测试结果上传操作。

主要功能

  1. 01项目健康度、通过率与趋势分析
  2. 02测试历史与不稳定测试检测
  3. 03失败搜索与根因聚类
  4. 04覆盖率指标与未测试文件发现
  5. 05测试运行报告与性能比较
  6. 06测试结果上传及处理状态查询

适用场景

  1. 01排查近期 CI 运行中的失败
  2. 02确认测试是否不稳定或新近失败
  3. 03查找与失败相关的低覆盖率文件
  4. 04比较不同提交间的测试耗时

MCP 相关

它通过 3 个 MCP 工具和 JavaScript codemode 命名空间提供 17 个函数,涵盖测试分析、覆盖率、报告和上传。除 upload_test_results 外,其余函数均为只读。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"sh-gaffer": {
"command": "npx",
"args": [
"-y",
"@gaffer-sh/mcp"
],
"env": {
"GAFFER_API_KEY": "<GAFFER_API_KEY>",
"GAFFER_API_URL": "<GAFFER_API_URL>"
}
}
}
}
启动命令npx -y @gaffer-sh/mcp
需要配置的环境变量
GAFFER_API_KEY密钥API key from Account Settings > API Keys. gaf_ user key or gfr_ project token.
GAFFER_API_URLOverride the Gaffer API base URL. Defaults to https://app.gaffer.sh

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@gaffer-sh/mcp0.9.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

@gaffer-sh/mcp

Gaffer 的 MCP(Model Context Protocol)服务——让你的 AI 助手记住测试情况。

这是什么?

此 MCP 服务将 Claude Code 和 Cursor 等 AI 编码助手连接到你的 Gaffer 测试历史记录和覆盖率数据。它以代码模式运行:通过一个包含 17 个函数的命名空间提供 3 个 MCP 工具——其中 16 个是只读分析函数,另一个是 upload_test_results。它允许 AI:

  • 检查项目的测试状况(通过率、不稳定测试、趋势)
  • 查询特定测试的历史记录,以了解其稳定性
  • 在调试时获取测试失败的上下文
  • 分析代码覆盖率并找出未经测试的区域
  • 浏览所有项目(使用用户 API Keys)
  • 访问测试报告文件(HTML 报告、覆盖率等)

前提条件

  1. 一个已上传测试结果的 Gaffer 账户
  2. 在「Account Settings > API Keys」中获取的 API Key

设置

Claude Code(CLI)

通过 Claude Code CLI 添加 Gaffer MCP 服务是最简单的方法:

claude mcp add gaffer -e GAFFER_API_KEY=gaf_your_api_key_here -- npx -y @gaffer-sh/mcp
Claude Code(手动)

或者,将其添加到 Claude Code 设置中(~/.claude.json 或项目的 .claude/settings.json):

{
  "mcpServers": {
    "gaffer": {
      "command": "npx",
      "args": ["-y", "@gaffer-sh/mcp"],
      "env": {
        "GAFFER_API_KEY": "gaf_your_api_key_here"
      }
    }
  }
}
Cursor

将其添加到项目中的 .cursor/mcp.json:

{
  "mcpServers": {
    "gaffer": {
      "command": "npx",
      "args": ["-y", "@gaffer-sh/mcp"],
      "env": {
        "GAFFER_API_KEY": "gaf_your_api_key_here"
      }
    }
  }
}

此服务的工作方式

此服务使用代码模式。它不会为每个 API 调用单独提供一个 MCP 工具,而是提供 3 个工具,以及一个通过 JavaScript 调用的 codemode 命名空间。较少的工具定义占用的上下文窗口更少,单次执行还可以串联多个调用。

MCP 工具功能
execute_code针对 codemode.<function>() 运行 JavaScript。最多 20 次 API 调用,超时为 30s。
search_tools按关键词查找可用函数。查询为空时会列出所有函数。
list_projects列出项目。仅当令牌是用户 API Key(gaf_)时才会注册。
const health = await codemode.get_project_health({ projectId: "proj_abc" });
if (health.flakyTestCount > 0) {
  const flaky = await codemode.get_flaky_tests({ projectId: "proj_abc" });
  return { health, flaky };
}
return { health };

可通过 execute_code 使用的函数

函数类别描述
get_project_healthhealth健康评分、通过率、不稳定测试数量、趋势
get_test_historytesting特定测试的通过/失败历史记录
get_flaky_teststesting翻转率(通过↔失败)较高的测试
list_test_runstesting最近的测试运行,可按提交/分支/状态筛选
get_test_run_detailstesting某次运行中解析后的单项测试结果
get_failure_clusterstesting按根本原因分组的失败测试
get_slowest_teststesting按 P95 耗时排列的最慢测试
compare_test_metricstesting比较不同提交或运行之间的测试性能
search_failurestesting按错误或测试名称模式搜索失败记录,或列出所有近期失败记录
get_coverage_summarycoverage整体覆盖率指标及趋势
get_coverage_for_filecoverage特定文件或路径的覆盖率
get_untested_filescoverage低于覆盖率阈值的文件
find_uncovered_failure_areascoverage覆盖率低且测试失败的文件
get_reportreports测试运行的报告文件 URL
get_report_browser_urlreports可通过浏览器访问的签名报告 URL(30 分钟)
get_upload_statusuploadsCI 结果是否已上传并处理
upload_test_resultsuploads上传测试结果(写入)——受速率限制并记录审计日志

除 upload_test_results 外,所有函数均为只读。

函数参考

list_projects

列出你有权访问的所有项目。

  • 输入: organizationId(可选)、limit(可选,默认值:50)
  • 返回: 包含 ID、名称和组织信息的项目列表
  • 示例:「我在 Gaffer 中有哪些项目?」
get_project_health

获取项目的健康指标。

  • 输入: projectId(必填)、days(可选,默认值:30)
  • 返回: 健康评分(0-100)、通过率、测试运行次数、不稳定测试数量、趋势
  • 示例:「我的测试套件状况如何?」
get_test_history

获取特定测试的通过/失败历史记录。

  • 输入: projectId(必填)、testName 或 filePath(二选一,必填)、limit(可选)
  • 返回: 运行历史记录,包含状态、耗时、分支、提交和错误
  • 示例:“登录测试是否不稳定?查看它的历史记录”
get_flaky_tests

获取项目中的不稳定测试列表。

  • 输入: projectId(必填)、threshold(可选,默认值:0.1)、days(可选)、limit(可选)
  • 返回: 不稳定测试列表,包含翻转率、状态转换次数和运行次数
  • 示例:“我的项目中哪些测试不稳定?”
list_test_runs

列出最近的测试运行记录,支持可选筛选条件。

  • 输入: projectId(必填)、commitSha(可选)、branch(可选)、status(可选)、limit(可选)
  • 返回: 测试运行记录列表,包含通过/失败/跳过数量以及提交和分支信息
  • 示例:“最近一次提交中有哪些测试失败了?”
get_test_run_details

获取特定测试运行的解析结果。

  • 输入: testRunId(必填)、projectId(必填)、status(可选筛选条件)、limit(可选)
  • 返回: 单项测试结果,包含名称、状态、耗时、文件路径和错误
  • 示例:“显示此测试运行中的所有失败测试”
get_report

获取随测试运行上传的报告文件 URL。

  • 输入: testRunId(必填)
  • 返回: 文件列表,包含文件名、大小、内容类型和下载 URL
  • 示例:“获取最新测试运行的 Playwright 报告”
get_report_browser_url

获取可在浏览器中打开以查看测试报告的 URL。

  • 输入: projectId(必填)、testRunId(必填)、filename(可选)
  • 返回: 有效期为 30 分钟的签名 URL
  • 示例:“给我一个查看测试报告的链接”
get_slowest_tests

获取项目中最慢的测试,按 P95 耗时排序。

  • 输入: projectId(必填)、days(可选)、limit(可选)、framework(可选)、branch(可选)
  • 返回: 测试列表,包含平均耗时、P95 耗时和运行次数
  • 示例:“哪些测试正在拖慢我的 CI 流水线?”
compare_test_metrics

比较两个提交或测试运行之间的测试指标。

  • 输入: projectId(必填)、testName(必填)、beforeCommit/afterCommit 或 beforeRunId/afterRunId
  • 返回: 比较前后的指标,包含耗时变化和变化百分比
  • 示例:“我的修复让这个测试变快了吗?”
get_coverage_summary

获取项目的覆盖率指标摘要。

  • 输入: projectId(必填)、days(可选,默认值:30)
  • 返回: 行/分支/函数覆盖率百分比、趋势、报告数量和覆盖率最低的文件
  • 示例:“我们的测试覆盖率是多少?”
get_coverage_for_file

获取特定文件或路径的覆盖率指标。

  • 输入: projectId(必填)、filePath(必填——精确或部分匹配)
  • 返回: 匹配文件列表,包含行/分支/函数覆盖率
  • 示例:“我们的 API 路由覆盖率是多少?”
get_untested_files

获取测试覆盖率很低或没有覆盖率的文件。

  • 输入: projectId(必填)、maxCoverage(可选,默认值:10%)、limit(可选)
  • 返回: 低于阈值的文件列表,按覆盖率排序(最低的排在最前)
  • 示例:“哪些文件没有测试?”
find_uncovered_failure_areas

查找覆盖率低且存在测试失败的代码区域(高风险)。

  • 输入: projectId(必填)、days(可选)、coverageThreshold(可选,默认值:80%)
  • 返回: 按评分排序的风险区域,包含文件路径、覆盖率百分比和失败次数
  • 示例:“我们应该重点测试哪些地方?”
get_failure_clusters

根据错误消息相似度,按根因对失败的测试进行分组。

  • 输入: projectId(必需)、testRunId(必需)
  • 返回: 按相似错误消息分组的失败测试集群,包含代表性错误和测试数量
  • 示例:“这 15 个失败是否来自同一个 Bug?”
search_failures

根据错误消息、堆栈跟踪或测试名称搜索以往的失败,也可以列出时间窗口内的所有失败。

  • 输入: query(可选——省略则返回所有失败)、projectId(gaf_ 密钥必需)、searchIn(可选:errors/names/all,默认值:all)、days(可选,默认值:30)、branch(可选)、limit(可选,默认值:20)
  • 返回: 匹配的失败,包含测试名称、错误消息、运行和提交上下文;当扫描上限导致列表被截短时,还会包含 truncated
  • 示例:“以前遇到过这种连接被拒绝错误吗?”/“过去 7 天有哪些失败?”
get_upload_status

检查 CI 结果是否已上传并处理。

  • 输入: projectId(必需)、sessionId(可选)、commitSha(可选)、branch(可选)
  • 返回: 上传会话(一个或多个),包含处理状态、关联的测试运行和覆盖率报告
  • 示例:“提交 abc123 的测试结果准备好了吗?”
upload_test_results

上传结构化的测试结果。这是唯一会写入数据的函数。

当你手头已有结果(从 CI 输出或运行器的 JSON 报告中解析而来),且没有可用于上传结果的 Gaffer CLI 时,请使用此函数。

  • 输入: projectId(gaf_ 密钥必需)、framework(必需)、tests(必需)、branch、commitSha、ciProvider、startedAt、finishedAt、coverage
  • 返回: uploadSessionId、生成的 runId,以及派生出的通过/失败/跳过汇总
  • 示例:“上传这 42 条已解析的 pytest 结果,以便我们跟踪它们”

runId、运行时间戳和汇总均根据 tests 派生——只有在你知道真实的实际时间范围时,才传入 startedAt/finishedAt。

需要了解的两项限制:

  • 不具备幂等性。 每次调用都会创建一次新的运行,因此在结果不确定的失败后重试会产生重复项。请改为检查 get_upload_status,不要重试。
  • 每个项目都有调用频率限制,且每次调用都会连同发起调用的凭证 ID 一起写入项目审计日志。

处理是异步的:结果需要几秒钟才会在读取函数中显示。

Agentic CI 工作流

这些工作流展示了 AI Agent 如何诊断 CI 失败、等待结果并查找覆盖率缺口。每个步骤都是一个 codemode 函数,因此整个调用链会在一次 execute_code 调用中运行,而不是每个步骤各进行一次往返。

工作流:诊断 CI 失败
list_test_runs(projectId, status="failed")
  → get_test_run_details(projectId, testRunId, status="failed")
  → get_failure_clusters(projectId, testRunId)
  → get_test_history(projectId, testName="...")
  → compare_test_metrics(projectId, testName, beforeCommit, afterCommit)
  1. 查找失败的测试运行
  2. 获取包含堆栈跟踪的单项失败详情
  3. 按根因对失败进行分组——15 个失败通常只对应 2-3 个 Bug
  4. 检查每项失败是新出现的(回归)还是反复出现的
  5. 通过比较修复前后的情况来验证修复
工作流:等待结果
get_upload_status(projectId, commitSha="abc123")
  → poll until processingStatus="completed"
  → get_test_run_details(projectId, testRunId)
  1. 检查提交的结果是否已上传
  2. 等待处理完成
  3. 使用关联的测试运行 ID 获取结果
工作流:查找覆盖率缺口
find_uncovered_failure_areas(projectId)
  → get_untested_files(projectId)
  → get_coverage_for_file(projectId, filePath="src/critical/")
  1. 查找覆盖率低且测试失败的文件(风险最高)
  2. 查找完全没有覆盖率的文件
  3. 深入查看特定目录,进行有针对性的分析
函数快速参考
Agent 问题函数
“哪些测试失败了?”get_test_run_details
“是否有相同的根因?”get_failure_clusters
“以前见过这个错误吗?”search_failures
“这是间歇性失败吗?”get_flaky_tests
“这是新出现的吗?”get_test_history
“我的修复生效了吗?”compare_test_metrics
“结果准备好了吗?”get_upload_status
“哪些内容尚未测试?”find_uncovered_failure_areas
“哪些测试耗时较长?”get_slowest_tests

优先改进覆盖率

使用覆盖率工具改进测试套件时,将覆盖率数据与代码库探索相结合,可获得最佳效果:

1. 了解代码使用情况

在单纯根据覆盖率百分比选择文件之前,先探索哪些代码真正关键:

  • 查找入口点: 查看路由定义、事件处理程序和导出函数——这些能揭示哪些代码在生产环境中实际执行
  • 查找被大量导入的文件: 被许多其他文件导入的文件具有较高价值
  • 识别关键业务逻辑: 查找处理身份验证、支付、数据变更或核心领域逻辑的文件
2. 按影响排序

覆盖率低并不意味着优先级高。请考虑:

  • 高使用率 + 低覆盖率 = 最高优先级——频繁运行但缺少测试的代码
  • 覆盖率为 0% 的大型文件——未覆盖行数越多,对整体覆盖率的影响越大
  • 同时存在失败和低覆盖率的文件——对此使用 find_uncovered_failure_areas
3. 使用基于路径的查询

get_untested_files 工具可能会返回许多前端组件。对于后端或特定区域:

# Query specific paths with get_coverage_for_file
get_coverage_for_file(filePath="server/services")
get_coverage_for_file(filePath="src/api")
get_coverage_for_file(filePath="lib/core")
4. 迭代改进
  1. 使用 get_coverage_summary 获取基线
  2. 使用 get_coverage_for_file 检查关键路径上的目标
  3. 为影响最大的文件编写测试
  4. CI 上传新结果后重新检查覆盖率
  5. 重复上述步骤

身份验证

用户 API 密钥(推荐)

用户 API 密钥(前缀为 gaf_)可对组织中的所有项目提供只读访问权限。请从此处获取 API 密钥:账户设置 > API 密钥

项目令牌

项目令牌(前缀为 gfr_)专为上传测试结果设计,且只能访问单个项目。使用项目令牌时,请省略 projectId——系统会自动解析。MCP 服务推荐使用用户 API 密钥,因为它们支持 list_projects 并可跨项目读取。

环境变量

变量必需说明
GAFFER_API_KEY是你的 Gaffer API 密钥(以 gaf_ 开头)
GAFFER_API_URL否API 基础 URL(默认值:https://app.gaffer.sh)

本地开发

pnpm install
pnpm build

使用 Claude Code 在本地测试(使用构建文件的绝对路径):

{
  "mcpServers": {
    "gaffer": {
      "command": "node",
      "args": ["/absolute/path/to/dist/index.js"],
      "env": {
        "GAFFER_API_KEY": "gaf_..."
      }
    }
  }
}

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。