Skip to main content
Glama

whichtool

模型真的能从你的 MCP 服务器中选对工具吗?

Italiano

[!WARNING] 发布已暂时暂停。 自动发布已禁用,npm 包可能不可用,而公共 GitHub 仓库仍保持在线。以下注册表和 Action 说明特意保留,以备将来可能重新发布。要立即使用当前源码:

git clone https://github.com/mattagame/whichtool.git
cd whichtool
bun install
bun run ./src/cli/main.ts inspect ./tools.json

一个 MCP 服务器即使拥有有效的 schema,也可能对模型来说难以理解。如果 list_users 和 search_users 的描述相似,模型就会猜测。Schema 验证仍然通过。集成测试也通过,因为它们按构造调用了正确的工具。

whichtool 将该表面置于真实模型之前,并报告选择了哪个工具以及哪些配对会被混淆。

whichtool 从不执行工具。 它读取 tools/list,记录模型本会调用什么,然后停止。

它刻意设计为单轮路由基准。它衡量模型在一组准备好的意图上的工具选择决策;它不评估多步代理执行、超出浅层 schema 检查的语义参数正确性、工具结果、恢复或最终答案的质量。

该轮中提出的每次调用都保留在 JSON 报告的 trials[].calls 中;首调用字段仍是兼容性视图,而不是丢弃额外调用的理由。

它承担两项工作:

  • inspect — 令牌预算、矛盾注释、几乎相同的描述、无效的 x-mcp-header 值。无需模型调用或模型提供商密钥;实时目标可能仍需要其自身的授权。

  • run — 试验、打乱的工具顺序、混淆矩阵、带 Wilson 95% 区间的比率。

当表面暴露超过 6 个工具时,inspect 会发出警告。真实的 CLI、MCP 和 GitHub Action 运行会在调用模型之前停止,超过该默认值。在审查表面后,操作员可以通过 --max-tools N、trials.maxTools、MCP 启动标志或 Action 的 max-tools 输入来提高限制;1,000 是硬性上限。六是一个谨慎的默认值,而非普遍规则:更多工具可能增加歧义和提示大小,但正确的数量取决于模型、schema、描述和任务。同时设置 --max-context-tokens,以免少量异常大的工具绕过上下文预算。

这些 Wilson 区间描述的是文件中任务在试验层面的稳定性。重复任务衡量的是同一路由决策是否稳定;它不估计模型在未见意图上的表现。

安装

npx whichtool inspect ./tools.json
# or: bunx whichtool inspect ./tools.json
npm install --save-dev whichtool

需要 Node 20.11+ 或 Bun 1.3+。零运行时依赖。

独立二进制文件尚未发布。Bun 编译的可执行文件嵌入了第三方运行时组件,因此分发保持禁用,直到其再分发声明经过审查并能随每个二进制文件一起发布。这与上述临时包发布暂停是分开的;在暂停期间,请使用源码检出。

Related MCP server: mcp-agent-reliability

快速开始

# 1. Look at the surface (no model-provider key)
whichtool inspect ./tools.json
whichtool inspect https://example.com/mcp
whichtool inspect --transport stdio "bun run ./src/server.ts"

# Capture once, work offline afterwards
whichtool inspect --transport stdio "npx -y @modelcontextprotocol/server-filesystem ." \
  --save-snapshot ./tools.json

快照可以是 { "tools": [ … ] }、JSON-RPC tools/list 信封或裸数组。

# 2. Write a task set (whichtool.tasks.yaml)
version: 1
tasks:
  - id: users.list.basic
    prompt: 'Show me all the users in the workspace'
    expected: list_users
  - id: users.search.byname
    prompt: "Find the user whose name contains 'rossi'"
    expected: search_users
  - id: distractor.delete
    prompt: 'Permanently delete the account belonging to Rossi'
    expected: null

即使 expected 为 null,也必须编写。完整格式:docs/task-sets.md。

# Or draft one instead of writing step 2 by hand, then edit and commit the result
# (do not regenerate on every run). It refuses to overwrite without --force.
whichtool tasks generate ./tools.json --provider ollama --model qwen3:4b --out whichtool.tasks.yaml

# Seeded robustness variants, no model
whichtool tasks mutate --out whichtool.tasks.mutated.yaml --seed 0

# 3. Lint before spending anything
whichtool tasks lint ./tools.json --tasks ./whichtool.tasks.yaml

# 4. Preview the workload (no model call)
whichtool run ./tools.json --provider ollama --model qwen3:4b --repeat 5 --dry-run

# 5. Measure
whichtool run ./tools.json --provider ollama --model qwen3:4b --repeat 5
OPENAI_API_KEY=sk-… whichtool run ./tools.json --provider openai --model gpt-4.1-mini

--repeat 默认为每个选定任务 5 次,因此总试验次数是 --only / --skip 之后剩余的任务数乘以 repeat。真实运行默认拒绝超过 50 次总试验。在审查 --dry-run 后,使用 --max-trials N 或 trials.maxTrials 提高该预算;1,000 是绝对且不可覆盖的最大值。

干运行的提示令牌数字是下限,而非价格估算。输出和推理令牌是额外的,可能大得多。内置 HTTP 提供商默认禁用自动重试。

在 whichtool run 期间,按 Ctrl+C 可中止进行中的提供商请求。命令以代码 130 退出,且不写入部分报告。MCP 评估仍可通过 MCP 协议取消。

退出代码:0 执行健康且阈值保持,1 质量阈值失败,2 执行错误(包括不完整运行或提供商失败过多)。默认情况下,运行至少需要一个已评分的试验,并允许最多 10% 的提供商错误率;使用 --min-scored 和 --max-error-rate 覆盖这些值。

# 6. Re-render, gate, compare
whichtool run … --format json --out run.json
whichtool report run.json --format markdown
whichtool report run.json --format html --out report.html
whichtool diff base-run.json head-run.json --max-accuracy-drop 0.05

diff 拒绝减去使用了不同模型、端点、非秘密提供商请求指纹、温度、种子、重复次数、排列设置或任务集的运行。它按任务和试验索引匹配结果,然后使用精确的双侧配对符号检验(p <= 0.05)来判断移动是否可区分。即使首次选择没有移动,意外多调用行为的可区分增加也是回归。

命令

命令

作用

whichtool inspect <target>

表面检查。无需模型调用或模型提供商密钥。

whichtool mcp

通过 MCP 暴露准备好的路由评估操作。

whichtool tasks lint [target]

验证任务集。

whichtool tasks generate <target>

根据工具描述草拟任务集。

whichtool tasks mutate

种子化鲁棒性变体。无需模型。

whichtool run <target>

执行试验并写入报告。

whichtool report <run.json>

重新渲染保存的运行。

whichtool diff <base> <head>

比较两次保存的运行。

whichtool cache info|clear

检查或清除试验缓存。

whichtool <command> --help 列出标志。run 上的主要标志:

--tasks --provider --model --repeat --max-trials --max-tools --concurrency --temperature --seed
--min-scored --max-error-rate
--permute / --no-permute --format --out --min-accuracy --max-over-trigger
--max-context-tokens --only --skip --dry-run --seconds-per-trial --reasoning-effort
--cache / --no-cache --cache-dir

格式:terminal、json、markdown、html、junit、badge。

环境: HTTP 目标凭据需要同时具备 WHICHTOOL_HTTP_AUTHORIZATION 和 WHICHTOOL_HTTP_AUTHORIZATION_ORIGIN 中的确切允许来源(例如 https://mcp.example)。远程凭据需要 HTTPS。提供商密钥来自 ANTHROPIC_API_KEY、OPENAI_API_KEY、OPENROUTER_API_KEY、TOGETHER_API_KEY 和 WHICHTOOL_PROVIDER_API_KEY(用于 openai-compatible 端点)。NO_COLOR / FORCE_COLOR 会被尊重。

传输

说明

snapshot

磁盘上捕获的 tools/list。CI 应使用此方式。

http

流式 HTTP(MCP 2026-07-28)。

stdio

本地启动的服务器。

legacy-sse

已拒绝。自 MCP 2025-03-26 起弃用。

提供商:anthropic、ollama、openai、openai-chat、openrouter、together、vllm、任何 openai-compatible 端点,以及确定性的 mock。openai 使用 OpenAI Responses API。显式选择 openai-chat 以使用 OpenAI Chat Completions;其他 OpenAI 兼容预设继续使用其 chat-completions 端点。

anthropic 使用 Messages API 而非 chat-completions 方言。该提供商不发送温度或种子,并将这些能力记录为不支持,因此其运行依赖 --repeat 和试验级区间。

配置

import { defineConfig } from 'whichtool'

export default defineConfig({
  target: { transport: 'stdio', command: 'bun run ./src/server.ts' },
  tasks: './whichtool.tasks.yaml',
  provider: { name: 'ollama', model: 'qwen3:4b' },
  trials: {
    repeat: 5,
    maxTrials: 50,
    maxTools: 6,
    permute: true,
    temperature: 0,
    concurrency: 4,
  },
  thresholds: {
    minAccuracy: 0.9,
    maxOverTrigger: 0.05,
    maxContextTokens: 4000,
    maxErrorRate: 0.1,
    minScored: 1,
  },
  report: { formats: ['terminal', 'json'], out: './whichtool-report' },
})

whichtool.config.json 也可以。API 密钥绝不是配置字段。普通 CLI 也可以发现 JavaScript 或 TypeScript 配置;MCP 服务器故意不这样做,如下所述。

CI

- uses: mattagame/whichtool@v0.1.0
  with:
    target: ./tools.json
    tasks: ./whichtool.tasks.yaml
    provider: openai
    model: gpt-4.1-mini
    max-trials: '50'
    max-tools: '6'
    min-accuracy: '0.9'
    max-over-trigger: '0.05'

复合操作中的试验缓存默认禁用,因为缓存可能包含提示、工具定义和提供商响应。仅当这些材料不敏感且 GitHub 托管的持久化可接受时,才设置 cache: 'true'。

Action 默认阻止超过 6 个工具的测量调用;max-tools 只能将限制提高到 1,000。其 max-trials 预算适用于每次测量调用。因此,同时测量 head 和 base 修订的比较工作流可以每次运行使用一次试验预算;使用默认值时,head 最多 50 次试验,base 最多 50 次。

省略 provider 以仅运行免费静态检查:inspect,以及存在任务集时的 tasks lint。完整工作流(包括写入作业摘要的 base 分支比较)见 examples/github-action。

作为 MCP 服务器:

{
  "mcpServers": {
    "whichtool": {
      "command": "npx",
      "args": ["-y", "whichtool", "mcp", "--config", "whichtool.config.json"]
    }
  }
}

MCP 服务器故意受其启动参数的能力限制。它不会自动发现或执行 JavaScript/TypeScript 配置:使用 --config 显式传递已审查的 JSON 文件。工具调用使用配置的目标,不能将其替换为任意路径、URL 或子进程。代理选择的任务/报告输入必须位于工作目录中。

预期的代理工作流从您已准备并审查的评估工件开始:inspect_surface、validate_task_file、run_evaluation,然后对保存的运行执行 diff_saved_results。MCP 表面不会生成或修改任务集。它暴露相同的单轮路由基准;它不是完整代理工作流的评估器或执行器。 run_evaluation 始终可以生成干运行计划,但除非操作员使用 --allow-paid-runs 启动服务器,否则无法联系提供商。操作员拥有的真实运行预算默认为 50 次总试验;只有启动 --max-trials 标志或已审查配置中的 trials.maxTrials 可以提高它,最高绝对上限为 1,000。代理无法覆盖该预算。相同的操作员拥有规则适用于 6 工具默认值,通过启动 --max-tools 或 trials.maxTools,绝对上限为 1,000。repeat 和并发也有上限。完整运行返回紧凑摘要。添加 --result-file ./latest-run.json 以将完整报告保留在模型上下文之外。 --allow-dynamic-targets 用于隔离的开发设置,应视为不安全的可选加入。提供商/模型覆盖同样仅限配置,除非操作员添加 --allow-provider-overrides。持久试验缓存在 MCP 模式下关闭;操作员必须在决定提示、调用和响应可以写入磁盘后显式添加 --cache。

示例

示例

展示内容

quickstart

在您可以在本地运行的表面上的完整循环。

ambiguous-server

一个故意难以阅读的表面。

ollama-qwen3

与静态检查不一致的本地模型运行。

github-action

带 base 分支差异的 CI 接线。

在诸如 qwen3 之类的推理模型上,单次试验可能需要数十秒的思考令牌,whichtool 从不读取这些令牌。测量一次试验,然后传递 --dry-run --seconds-per-trial。其提示令牌总数仍是下限,而非价格估算;输出和推理令牌是额外的。

开发

Bun 是工具链;Node 是分发目标。src/core/ 是可移植的 TypeScript(无 Bun/Node 内置模块)。

bun install
bun test
bun run typecheck
bun run lint
bun run build
docker run --rm -v "$PWD:/work" ghcr.io/mattagame/whichtool inspect ./tools.json

欢迎补丁:CONTRIBUTING.md 列出了测试强制执行的约束,而非审查者。

设计记录:SPEC.md。安全:SECURITY.md。JSON 契约:docs/report-schema.md。变更:CHANGELOG.md。

免责声明

软件按原样提供,不提供任何担保。请参阅 LICENSE.md。

  • 在托管提供商上,run 需要付费。工具定义和提示词会发送给您配置的模型。请先使用 --dry-run,但将其提示词 token 数量视为下限,而非价格估算。Ollama 和其他本地端点仍保留在您的机器上。

  • 被测服务器上的工具绝不会被调用。 stdio 确实会以您的权限启动您传入的命令——请将该命令视为代码。

  • 独立二进制文件尚未分发。 在嵌入式运行时的第三方声明经过审查并能够随每个二进制文件一同发布之前,发布功能将保持禁用。

  • 并非安全扫描器。 某个表面可能通过 inspect 检查,但仍然存在危险。详情:SECURITY.md。

许可证

MIT — LICENSE.md。

Related MCP Connectors

Related MCP Servers