Skip to main content
Glama

whichtool

모델이 실제로 MCP 서버에서 올바른 도구를 선택할까요?

Italiano

[!WARNING] 게시가 일시적으로 중지되었습니다. 자동 릴리스가 비활성화되었으며, 공개 GitHub 저장소가 온라인 상태인 동안 npm 패키지를 사용할 수 없을 수 있습니다. 아래의 레지스트리 및 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를 읽고 모델이 호출했을 것을 기록한 뒤 멈춥니다.

이는 의도적으로 단일 턴 라우팅 벤치마크입니다. 준비된 의도 집합에 대한 모델의 도구 선택 결정을 측정합니다. 다단계 에이전트 실행, 얕은 스키마 검사를 넘어선 의미론적 인자 정확성, 도구 결과, 복구, 최종 답변 품질은 평가하지 않습니다.

그 턴에서 제안된 모든 호출은 JSON 보고서의 trials[].calls에 유지됩니다. 첫 호출 필드는 호환성 관점으로 남아 있으며, 추가 호출을 버릴 이유가 아닙니다.

두 가지 작업을 수행합니다:

  • inspect — 토큰 예산, 모순된 주석, 거의 동일한 설명, 잘못된 x-mcp-header 값. 모델 호출이나 모델 공급자 키가 필요 없습니다. 라이브 대상은 여전히 자체 인증이 필요할 수 있습니다.

  • run — 트라이얼, 순열화된 도구 순서, 혼동 행렬, Wilson 95% 구간의 비율.

inspect는 표면이 6개 이상의 도구를 노출할 때 경고합니다. 실제 CLI, MCP, GitHub Action 실행은 그 기본값을 초과할 경우 모델을 호출하기 전에 중지합니다. 표면을 검토한 후 운영자는 --max-tools N, trials.maxTools, MCP 시작 플래그 또는 Action의 max-tools 입력으로 제한을 올릴 수 있습니다. 1,000이 절대 상한입니다. 6은 보수적인 기본값이지 보편적인 규칙이 아닙니다. 도구가 많을수록 모호성과 프롬프트 크기가 커질 수 있지만, 적절한 숫자는 모델, 스키마, 설명, 작업에 따라 달라집니다. 또한 --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은 절대적이고 재정의할 수 없는 최대값입니다.

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는 다른 모델, 엔드포인트, 비밀 아닌 공급자 요청 지문, temperature, seed, 반복 횟수, 순열 설정 또는 작업 집합을 사용한 실행과의 비교를 거부합니다. 결과를 작업 및 트라이얼 인덱스로 매칭한 다음, 정확한 양측 대응 부호 검정(p <= 0.05)을 사용하여 이동이 구별 가능한지 결정합니다. 예상치 못한 다중 호출 동작의 구별 가능한 증가는 첫 선택이 움직이지 않았더라도 회귀입니다.

명령

Command

설명

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, 그리고 openai-compatible 엔드포인트의 경우 WHICHTOOL_PROVIDER_API_KEY에서 가져옵니다. 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 Completions를 사용하려면 openai-chat를 명시적으로 선택하세요. 다른 OpenAI 호환 프리셋은 계속해서 chat-completions 엔드포인트를 사용합니다.

anthropic은 chat-completions 방식 대신 Messages API를 사용합니다. 이 공급자는 temperature나 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'

복합 작업에서 트라이얼 캐싱은 기본적으로 비활성화되어 있습니다. 캐시에 프롬프트, 도구 정의, 공급자 응답이 포함될 수 있기 때문입니다. 해당 자료가 민감하지 않고 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 구성을 자동 발견하거나 실행하지 않습니다. 검토된 JSON 파일을 --config로 명시적으로 전달하세요. 도구 호출은 구성된 대상을 사용하며 임의의 경로, URL 또는 하위 프로세스로 대체할 수 없습니다. 에이전트가 선택한 작업/보고서 입력은 작업 디렉터리 내에 있어야 합니다.

의도된 에이전트 워크플로는 이미 준비하고 검토한 평가 산출물에서 시작합니다: inspect_surface, validate_task_file, run_evaluation, 그리고 저장된 실행에 대한 diff_saved_results. MCP 표면은 작업 집합을 생성하거나 변경하지 않습니다. 동일한 단일 턴 라우팅 벤치마크를 노출합니다. 완전한 에이전트 워크플로를 위한 평가자 또는 실행자가 아닙니다. run_evaluation은 항상 dry-run 계획을 생성할 수 있지만, 운영자가 --allow-paid-runs로 서버를 시작하지 않는 한 공급자에 연락할 수 없습니다. 운영자 소유의 실제 실행 예산은 기본적으로 총 50회 트라이얼입니다. 시작 --max-trials 플래그 또는 검토된 구성의 trials.maxTrials만이 이 예산을 절대 최대값인 1,000까지 올릴 수 있습니다. 에이전트는 이 예산을 재정의할 수 없습니다. 동일한 운영자 소유 규칙이 시작 --max-tools 또는 trials.maxTools를 통한 6개 도구 기본값에도 적용되며, 절대 최대값은 1,000입니다. repeat와 동시성에도 상한이 있습니다. 전체 실행은 간결한 요약을 반환합니다. --result-file ./latest-run.json을 추가하여 전체 보고서를 모델 컨텍스트 밖에 유지하세요. --allow-dynamic-targets는 격리된 개발 설정을 위해 존재하며 안전하지 않은 옵트인으로 취급해야 합니다. 공급자/모델 재정의도 운영자가 --allow-provider-overrides를 추가하지 않는 한 구성 전용입니다. MCP 모드에서는 영구 트라이얼 캐싱이 꺼져 있습니다. 운영자는 프롬프트, 호출 및 응답을 디스크에 써도 된다고 결정한 후 --cache를 명시적으로 추가해야 합니다.

예제

Example

설명

quickstart

로컬에서 실행할 수 있는 표면의 전체 루프.

ambiguous-server

의도적으로 읽기 어려운 표면.

ollama-qwen3

정적 린트와 일치하지 않는 로컬 모델 실행.

github-action

base 브랜치 diff가 있는 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