为什么我QA
用于代码生成MCP服务器的可重用QA平台。使用以下命令评估生成的代码 可执行证明:如果它编译并通过测试,那么它在客观上是可用的。
快速开始
# Install
pnpm install
pnpm build
# Configure environment (copy and edit with your values)
cp .env.example .env
# List available scenarios
npx whyme-qa list -d scenarios/
# Run a scenario against an MCP server
npx whyme-qa run -s scenarios/counter.yaml
# Run with workspace preserved for debugging
npx whyme-qa run -s scenarios/counter.yaml --keep-workspace运作原理
- 场景YAML 定义MCP服务器、工具调用、预期输出和验证门
- 跑者 连接到MCP服务器,执行工具调用,实现生成的代码
- 关卡脚本 验证代码:编译、lint、测试、WASM构建、激活检查
- 代理循环 (可选)--如果门失败,LLM会检查错误并修复代码,重新运行门最多N次迭代
- 记者 生成带有迭代历史的分数、JUnitXML和Markdown报告
建筑
whyme-qa/
├── packages/
│ ├── runner/ # CLI + scenario orchestrator + agent loop
│ ├── adapters/ # MCP client + gate execution + LLM client
│ ├── reporter/ # Scoring, JUnit, Markdown reports
│ └── schemas/ # TypeScript type definitions
├── gates/
│ └── stylus/ # Shell scripts for Stylus verification
├── scenarios/ # YAML scenario definitions
├── .gitlab/
│ └── duo/flows/ # GitLab Duo flow definitions
└── .gitlab-ci.yml # CI pipeline configuration数据流
MCP Server → File Extraction → Workspace → Gates → [Agent Loop] → Score → Report
│
LLM (via OpenRouter)
Read files + gate errors
Return fixed files
Re-run all gates
Repeat until pass or max iterations验证门(触控笔)
| 门 | 命令 | 点 |
|---|---|---|
| 格式 | cargo fmt --check | 5 |
| Clippy | cargo clippy -- -D warnings | 10 |
| 编译 | cargo build --release | 10 |
| 单元测试 | cargo test --all | 30 |
| WASM构建 | cargo build --target wasm32-unknown-unknown | 10 |
| 触控笔检查 | cargo stylus check | 20 |
| 安全 | cargo audit | 15 |
MCP响应格式
跑步者的 extractFilesFromResponse 支持三种响应格式:
- 通用的
{files: {path: content}}--一个JSON对象files将文件路径映射到内容字符串的键 - ARBuilder风格 --带顶级键的JSON
code,cargo_toml,main_rs,stylus_toml,rust_toolchain_toml映射到Stylus项目文件。还处理atests附加到的密钥src/lib.rs(或放置在tests/mod.rs如果不code密钥存在) --- FILE: path ---分隔块 --带有文件边界标记的纯文本 `--- FILE:
---` 标头
| ARBuilder密钥 | 映射文件 |
|---|---|
code | src/lib.rs |
cargo_toml | Cargo.toml |
main_rs | src/main.rs |
stylus_toml | Stylus.toml |
rust_toolchain_toml | rust-toolchain.toml |
写作场景
看 scenarios/counter.yaml 举个例子。关键字段:
sut.mcp_server--如何启动被测MCP服务器plan.steps--要执行的有序工具调用(使用ARBuilder的prompt参数,不是description)workspace.required_files--生成后必须存在的文件gates--运行哪些验证门agent--(可选)代理循环配置:模型、max_iteractions、api_key_env
环境变量替换
场景YAML文件支持 ${VAR} 和 ${VAR:-default} 从以下位置解析的占位符 process.env 在加载时。这使得机密和特定于机器的路径不会出现在已提交的文件中:
sut:
mcp_server:
command: "${ARBBUILDER_PYTHON:-python3}"
cwd: "${ARBBUILDER_DIR}"
env:
OPENROUTER_API_KEY: "${OPENROUTER_API_KEY}"代理循环
配置后,代理循环使用LLM迭代修复验证门失败的代码。在测试了初始MCP生成的代码后,如果任何门失败,则代理:
- 读取所有工作区文件和门错误输出
- 将它们发送到LLM(通过OpenRouter),要求其解决问题
- 将LLM返回的文件更改应用于工作区
- 重新运行所有启用的门
- 重复直到所有门都通过或
max_iterations已达到
在YAML中按场景配置:
agent:
enabled: true
model: "anthropic/claude-sonnet-4"
max_iterations: 5
api_key_env: OPENROUTER_API_KEY
temperature: 0.2CLI参考
# Run a scenario
whyme-qa run -s [-o ] [-g ] [--keep-workspace]
# Run without agent loop (even if configured in scenario)
whyme-qa run -s --no-agent
# Override agent model and iterations
whyme-qa run -s --agent-model "anthropic/claude-sonnet-4" --max-iterations 10
# List scenarios
whyme-qa list [-d ]CI/CD管道
这 .gitlab-ci.yml 定义了四个阶段:
| 阶段 | 职位 | 描述 |
|---|---|---|
lint | lint | 构建所有包并运行类型检查 |
test | unit_tests | 运行单元测试,将报告作为工件上传 |
verify | e2e_counter | 端到端运行计数器场景(手动触发) |
report | _(保留)_ | 未来的报告工作 |
这 e2e_counter 工作是手动的(when: manual)以及 allow_failure: true,因此不会堵塞管道。JUnitXML报告作为GitLab测试报告工件收集。
GitLab Duo流定义也提供在 .gitlab/duo/flows/whyme_qa.yaml 与GitLab Duo工作流自动化一起使用。
许可证
阿帕奇-2.0
