Forecall: MCP ツールの説明文を採点するリンターを作って分かったこと
目次
きっかけ
MCP サーバーをいくつか作って使ううちに、エージェントがツールを選び間違える、引数の形を間違える、という場面に何度も出会った。モデルが見ているのは tools/list が返す名前と description と inputSchema だけだ。つまりツール説明の書き方が、そのまま呼ばれ方になる。それなのに、説明文を lint する道具がなかった。

公開サーバーを採点してみた
まず、よく知られた MCP サーバー 8 つ、計 126 ツールを同じ物差しで採点した。平均点はサーバーごとに 33 から 70 の間に散った。Notion の公式サーバーだけで、説明がほぼ同じツールのペアが 57 組あった。

典型例は filesystem サーバーの list_directory と list_directory_with_sizes で、説明の類似度は 0.86。どちらも「何をするか」は書いてあるが、「どちらをいつ使うか」がどこにもない。エージェントから見ればコイントスになる。この 2 つについては、書き換え案を添えて modelcontextprotocol/servers#5071 として報告した。
リンターの採点
採点は 6 観点で 100 点満点にした。
| 観点 | 配点 | 見ているもの |
|---|---|---|
| 目的 | 20 | 名前の言い換えになっていないか、短すぎないか |
| 使いどころ | 20 | いつ使うか、いつ使わないか、代わりに何を使うか |
| 引数 | 25 | 各引数の説明、文字列の制約や例、required |
| 戻り値 | 15 | 何が返るか |
| 制約と副作用 | 10 | 認証、レート制限、副作用、annotations |
| 例 | 10 | 具体的な呼び出し例 |
ツール単位の指摘とは別に、サーバー全体の問題を出す。ツールが多すぎる、説明がほぼ同一、説明を共有している、の 3 つ。これを分けないと「近い説明がある」という指摘が全ツールに付いてノイズになる。
採点ルールはバージョン管理している(いま v2)。どれかの入力の点数や指摘を変えうる変更はバージョンを上げ、fixture の期待値を更新する。CI のゲートに使う人がいるので、点が黙って動くのがいちばん困る。
npx forecall dump -o tools.json -- node build/index.js # 自分のサーバーから tools/list を取る
npx forecall lint tools.json # 採点する。何も送信しない
@forecall/lint は依存ゼロでネットワークにも出ない。GitHub Action forecall/forecall-cli@v1 を置くと、PR ごとに採点してジョブサマリーに出し、min-tool-score や fail-on で落とせる。
リンターの先
静的な点数と、実際のモデルがそのツールを選ぶかどうかは別物だ。そこで 2 つ足した。
評価。 ツールごとに「いちばん大きいファイルを探して」のような依頼を用意し、Claude、GPT、Gemini に実際に選ばせて呼ばせ、正しいツールを正しい引数で呼べた割合を測る。干渉用に公開サーバーの tools/list を横に置く。
Failure KB。 MCP ツール呼び出しの既知の失敗と回避策を、エージェントが呼ぶ前後に引ける MCP サーバー。あるエージェントが報告した失敗は、別の 2 チームのエージェントが再現して初めて verified になる。Streamable HTTP のリモートサーバーなので、stdio でしかサーバーを起動できないクライアントには forecall-mcp という小さなリレーを用意した。
静的な点と実測が本当に相関しているかは、同じケース生成と呼び出しを使う較正ツールで測り続けている。点が高ければ選ばれる、とは限らない。
作り
全部 Cloudflare Workers に載せた。API は Hono、公開サイトとダッシュボードは React Router v8、評価は Workflows で 1 インスタンスが 1 スイートを回し、回数制限は Durable Object。DB は Neon の Postgres(pgvector)を Hyperdrive 経由で、各社の LLM は AI Gateway 経由で呼ぶ。リンターと CLI だけ公開リポジトリ forecall/forecall-cli に切り出し、本体は npm に出た版を固定して使っている。
学び
- 「ほぼ同一の説明」はツールの問題ではなくサーバーの問題。指摘の単位を間違えると直す気が失せる
- 採点ルールのバージョンは成果物の一部。変えたら言う
- 最初の採点規則は調査用の Python スクリプトだった。8 サーバーの採点結果を fixture に固定してから TypeScript に移植し、v2 からはそちらを正にした。移植の正しさは fixture が担保する
forecall.dev で JSON を貼れば、登録なしで採点結果のページが作れる。
RELATED
Flutter / AWS / 自宅サーバー。個人開発と OSS をいくつか。設計相談や協業の話は X の DM か About から。 About