筆者は、この記事で使う採点ツール Forecall の開発者です。採点はすべて無料で、登録なしで試せます。
AI エージェントはツールの何を読んでいるか
MCP サーバーのツールを AI エージェントが選ぶとき、手がかりは tools/list の結果だけです。具体的には、ツールの 名前、説明文(description)、入力スキーマ(inputSchema)の 3 つです。
{
"tools": [
{
"name": "API-get-block-children",
"description": "Notion | Retrieve block children\nError Responses:\n400: Bad request",
"inputSchema": {
"type": "object",
"properties": {
"block_id": { "type": "string", "description": "Identifier for a [block](ref:block)" }
},
"required": ["block_id"]
}
}
]
}
実装がどれだけ良くても、説明文が曖昧なら、エージェントは違うツールを選んだり、引数を間違えたり、そもそも呼ばなかったりします。
そこで、公開されている MCP サーバー 8 つの tools/list(合計 126 ツール)を、同じ規則で採点してみました。
採点の結果
1 ツールを 100 点満点で採点し、サーバーごとに平均を出しました。採点規則は Forecall の v1 です。
| サーバー | ツール数 | 平均点 | 取り違えやすい組 |
|---|---|---|---|
| Notion API | 24 | 33.0 | 57 |
| Playwright | 25 | 41.9 | 0 |
| debugbase-mcp | 11 | 42.9 | 0 |
| memory-server | 9 | 43.8 | 1 |
| secure-filesystem-server | 14 | 51.2 | 1 |
| firecrawl-fastmcp | 29 | 61.3 | 0 |
| Context7 | 2 | 69.5 | 0 |
| bhived-mcp | 12 | 70.3 | 0 |
よく見つかった欠けは次の 3 つです。
| 欠け | 該当したツール |
|---|---|
| いつ使うか(使わないか)が書かれていない | 87 / 126 |
| 何を返すかが書かれていない | 61 / 126 |
| 説明のない引数がある | 54 / 126 |
7 割のツールが「いつ使うか」を書いていませんでした。似たツールが並んだとき、エージェントがいちばん必要とするのがこの一文です。
説明文に書くべき 6 項目
Forecall は、説明文とスキーマを次の 6 項目で採点します。配点の合計が 100 点です。
| 項目 | 配点 | 見ているもの |
|---|---|---|
| 目的 | 20 | 動詞で始まるか、十分な長さがあるか、名前を言い換えただけになっていないか |
| いつ使うか | 20 | 「Use this when …」「Do not use …」「… instead」のような使い分けの記述 |
| 引数 | 25 | 引数ごとの説明、文字列への enum format pattern などの制約、required
|
| 戻り値 | 15 |
outputSchema、または「Returns …」のような戻り値の説明 |
| 制約と副作用 | 10 |
annotations(readOnlyHint destructiveHint など)、上限やページ送り、認証の記述 |
| 例 | 10 | 説明文や引数の説明に具体的な値の例があるか |
直す前と後
表の先頭にある Notion のツールを、実際に書き直して採点し直しました。スキーマは記事用に $defs を省いています。
{
"name": "API-get-block-children",
- "description": "Notion | Retrieve block children\nError Responses:\n400: Bad request",
+ "description": "Lists the blocks inside a page or block (its children), one page of results at a time. Use this to read the contents of a page. For the block itself, use API-retrieve-a-block instead. Returns a list of block objects and next_cursor; pass next_cursor as start_cursor to get the next page. Read-only. Returns up to 100 blocks per call.",
"annotations": { "title": "Get Block Children", "readOnlyHint": true },
"inputSchema": {
"type": "object",
"properties": {
- "block_id": { "type": "string", "description": "Identifier for a [block](ref:block)" },
+ "block_id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "ID of the page or block whose children to list, e.g. \"9bc30ad4-9373-46a5-84ab-0a7845ee52e6\"."
+ },
"start_cursor": { "type": "string", "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results." },
"page_size": { "type": "integer", "format": "int32", "default": 100, "description": "The number of items from the full list desired in the response. Maximum: 100" }
},
"required": ["block_id"]
}
}
点数は 35 点から 74 点になりました。
| 項目 | 直す前 | 直した後 |
|---|---|---|
| 目的 | 10 | 17 |
| いつ使うか | 0 | 15 |
| 引数 | 18 | 20 |
| 戻り値 | 0 | 7 |
| 制約と副作用 | 7 | 10 |
| 例 | 0 | 5 |
| 合計 | 35 | 74 |
変えたのは次の点です。
- 何をするかを動詞で始める。 「Lists the blocks inside …」
- いつ使うか、隣のツールとの違いを書く。 「Use this to read the contents of a page. For the block itself, use API-retrieve-a-block instead.」
- 何を返すか、次のページの取り方を書く。 「Returns a list of block objects and next_cursor …」
- 制約を書く。 「Read-only.」「up to 100 blocks per call」
-
引数に形式と例を付ける。
format: "uuid"と、ID の例
取り違えやすいツールの組
Notion の公式サーバーには、エージェントが取り違えやすい組が 57 ありました。いちばん似ていたのは次の 2 つです。
| ツール | 説明文 |
|---|---|
API-get-block-children |
Notion | Retrieve block children |
API-retrieve-a-block |
Notion | Retrieve a block |
Forecall は、ツールの説明文と名前がどれだけ似ているかを測り、似すぎている組を報告します。この 2 つの説明文の類似度は 0.88 でした。
直し方は、それぞれに「どちらを使うか」の一文を足すことです。
-
API-get-block-children: 「For the block itself, use API-retrieve-a-block instead.」 -
API-retrieve-a-block: 「To list the blocks inside it, use API-get-block-children instead.」
ツールが多すぎる場合
Forecall は、1 サーバーのツールが 25 を超えると軽い指摘、40 を超えると重い指摘を出します。ツールが増えるほど似た組も増えるので、説明文を直す前に、ツールをまとめられないかを検討するのも有効です。
自分のサーバーを採点する
Web 版は、tools/list の JSON を貼るだけで採点できます。
手元では CLI が使えます。lint は通信しないので、未公開のサーバーでも試せます。
# サーバーから tools/list を取り出す(stdio のサーバーは -- の後にコマンドを書く)
npx forecall dump -o tools.json -- node dist/server.js
# 採点する
npx forecall lint tools.json
CI に入れる
--fail-under を付けると、平均点がその値を下回ったときに終了コード 1 で終わります。採点規則が変わると CLI のマイナーバージョンが上がるので、バージョンは固定するのがおすすめです。
name: MCP tool descriptions
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 22
- run: npm ci && npm run build
- run: npx forecall@0.2 dump -o tools.json -- node dist/server.js
- run: npx forecall@0.2 lint tools.json --fail-under 60
静的な採点なので、文の意味までは読めません。名前だけで十分に伝わる短いツールが低く出ることもあります。どこで CI を止めるかは、自分のサーバーの点数を見てから決めてください。
まとめ
- エージェントが読むのは、ツールの名前、説明文、入力スキーマだけ
- 公開 8 サーバーでは、7 割のツールが「いつ使うか」を書いていなかった
- 「Use this when …」「… instead」の一文と、戻り値と引数の説明を足すだけで、点数は大きく変わる
次は、実際のモデルにツールを選ばせて、選び間違いと引数の誤りを測る評価を作っています。進み具合は @forecalldev で発信しています。

