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-сервер может иметь валидные схемы и при этом оставаться нечитаемым для модели. Отправьте list_users и search_users с похожими описаниями — и модель начнёт угадывать. Проверка схемы всё равно проходит. Интеграционные тесты тоже проходят, потому что они вызывают правильный инструмент по построению.

whichtool помещает эту поверхность перед реальной моделью и сообщает, какой инструмент выбирается и какие пары путаются.

whichtool никогда не выполняет инструмент. Он читает tools/list, записывает, что модель вызвала бы, и останавливается.

Это намеренно одношаговый бенчмарк маршрутизации. Он измеряет решение модели о выборе инструмента на подготовленном наборе интентов; он не оценивает многошаговое выполнение агента, семантическую корректность аргументов сверх поверхностной проверки схемы, результаты инструментов, восстановление после ошибок или качество финального ответа.

Каждый вызов, предложенный в этом ходе, сохраняется в trials[].calls JSON-отчёта; поля первого вызова остаются представлением для совместимости, а не причиной отбрасывать дополнительные вызовы.

Он выполняет две задачи:

  • inspect — бюджет токенов, противоречивые аннотации, почти идентичные описания, недопустимые значения x-mcp-header. Без вызова модели или ключа провайдера; живая цель может по-прежнему требовать собственной авторизации.

  • run — испытания, перемешанный порядок инструментов, матрица путаницы, показатели с 95% интервалами Уилсона.

inspect предупреждает, когда поверхность содержит более 6 инструментов. Реальные запуски CLI, MCP и GitHub Action останавливаются до вызова модели выше этого значения по умолчанию. После проверки поверхности оператор может поднять лимит с помощью --max-tools N, trials.maxTools, флага запуска MCP или входа max-tools в Action; 1000 — жёсткий максимум. Шесть — осторожное значение по умолчанию, а не универсальное правило: больше инструментов может увеличить неоднозначность и размер промпта, но правильное число зависит от модели, схем, описаний и задач. Также установите --max-context-tokens, чтобы небольшое количество необычно больших инструментов не могло обойти бюджет контекста.

Эти интервалы Уилсона описывают стабильность на уровне испытаний для задач в файле. Повторение задачи измеряет, стабильно ли одно и то же решение о маршрутизации; это не оценивает, как модель будет работать на невиданных интентах.

Установка

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; 1000 — абсолютный, не переопределяемый максимум.

Цифра токенов промпта при --dry-run — это нижняя граница, а не оценка стоимости. Токены вывода и рассуждений добавляются дополнительно и могут быть намного больше. Автоматические повторные попытки отключены по умолчанию для встроенных 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 отказывается вычитать запуски, которые использовали другую модель, конечную точку, несекретный отпечаток запроса провайдера, температуру, seed, количество повторов, настройку перестановки или набор задач. Он сопоставляет результаты по задаче и индексу испытания, затем использует точный двусторонний парный знаковый тест (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. Этот провайдер не отправляет температуру или seed и записывает эти возможности как неподдерживаемые, поэтому его запуски полагаются на --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'

Кэширование испытаний в составном action отключено по умолчанию, потому что кэш может содержать промпты, определения инструментов и ответы провайдера. Установите cache: 'true' только когда этот материал не является чувствительным и приемлемо постоянное хранение на GitHub.

Action блокирует измеряемый вызов с более чем 6 инструментами по умолчанию; max-tools может поднять лимит только до 1000. Его бюджет max-trials применяется к каждому измеряемому вызову. Сравнительный рабочий процесс, который измеряет и головную, и базовую ревизии, может использовать бюджет испытаний один раз для каждого запуска; с настройкой по умолчанию это максимум 50 испытаний для головы и 50 для базы.

Опустите provider, чтобы запустить только бесплатный статический проход: inspect, плюс tasks lint, если присутствует набор задач. Полный рабочий процесс (включая сравнение с базовой веткой, записываемое в сводку задания) находится в examples/github-action.

Как MCP-сервер:

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

MCP-сервер намеренно ограничен по возможностям своими аргументами запуска. Он не автообнаруживает и не выполняет конфигурацию JavaScript/TypeScript: передайте проверенный JSON-файл явно с помощью --config. Вызовы инструментов используют настроенную цель и не могут заменить её произвольным путём, URL или подпроцессом. Выбранные агентом входные файлы задач/отчётов должны оставаться в рабочем каталоге.

Предполагаемый рабочий процесс агента начинается с артефактов оценки, которые вы уже подготовили и проверили: inspect_surface, validate_task_file, run_evaluation, затем diff_saved_results на сохранённых запусках. MCP-поверхность не генерирует и не изменяет наборы задач. Она предоставляет тот же одношаговый бенчмарк маршрутизации; это не оценщик или исполнитель для полного рабочего процесса агента. run_evaluation всегда может создать план сухого прогона, но не может связаться с провайдером, если оператор не запустит сервер с --allow-paid-runs. Принадлежащий оператору бюджет реального запуска составляет 50 общих испытаний по умолчанию; только флаг запуска --max-trials или trials.maxTrials в проверенной конфигурации может поднять его, вплоть до абсолютного максимума 1000. Агент не может переопределить этот бюджет. То же правило, принадлежащее оператору, применяется к значению по умолчанию 6 инструментов через запуск --max-tools или trials.maxTools, с абсолютным максимумом 1000. repeat и параллелизм также имеют ограничения. Полный запуск возвращает компактную сводку. Добавьте --result-file ./latest-run.json, чтобы сохранить полный отчёт вне контекста модели. --allow-dynamic-targets существует для изолированных сред разработки и должен рассматриваться как небезопасный opt-in. Переопределения провайдера/модели также только через конфигурацию, если оператор не добавит --allow-provider-overrides. Постоянное кэширование испытаний отключено в режиме MCP; оператор должен явно добавить --cache после решения, что промпты, вызовы и ответы могут быть записаны на диск.

Примеры

Пример

Что показывает

quickstart

Полный цикл на поверхности, которую можно запустить локально.

ambiguous-server

Намеренно нечитаемая поверхность.

ollama-qwen3

Локальный запуск модели, который расходится со статическим линтом.

github-action

Настройка 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, но рассматривайте его значение токенов подсказки как нижнюю границу, а не как оценку цены. Ollama и другие локальные конечные точки остаются на вашей машине.

  • Инструменты на тестируемом сервере никогда не вызываются. stdio действительно запускает команду, которую вы передаёте, с вашими привилегиями — относитесь к этой команде как к коду.

  • Автономные бинарные файлы пока не распространяются. Публикация остаётся отключённой, пока уведомления третьих сторон встроенной среды выполнения не будут проверены и не смогут поставляться рядом с каждым бинарным файлом.

  • Не является сканером безопасности. Поверхность может пройти inspect и всё равно быть опасной. Подробности: SECURITY.md.

Лицензия

MIT — LICENSE.md.

Related MCP Connectors

Related MCP Servers