0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MCPサーバーのツール設計 — AIが迷わない「道具」の分割と説明の書き方

0
Last updated at Posted at 2026-09-14

MCPサーバーのツール設計 — AIが迷わない「道具」の分割と説明の書き方

はじめに

MCPサーバーの最小実装が動くようになると、次に必ずぶつかる壁があります。

  • ツールが増えてきたが、AIがどれを使うべきか選べていない気がする
  • 1つのツールに機能を詰め込んだら、引数の指定を間違え始めた
  • 動いたのはいいけれど、AIが意図しない書き込みを実行してヒヤッとした

これらはモデルの性能の問題ではなく、ほぼツール設計の問題です。MCPは「AIに道具を渡す」プロトコルなので、道具の作り方がそのままAIの精度になります。

この記事では FastMCP でサーバーを書く前提で、実装で効くツール設計の原則をコードと合わせて整理します。

前提: 動く最小サーバー

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("task-server")

@mcp.tool()
def ping() -> str:
    """疎通確認用。サーバーが応答するかだけを確認する。"""
    return "pong"

if __name__ == "__main__":
    mcp.run()

この土台にツールを足していくとき、設計を誤るとAIの成功率が落ちます。以降はよくある失敗と、その修正方法です。

原則1: ツールは「動詞単位」で分割する

最も多いアンチパターンが何でも屋ツールです。

# ❌ アンチパターン: 1つのツールに全部やらせる
@mcp.tool()
def manage_task(action: str, task_id: str = "", title: str = "", status: str = "") -> str:
    """タスクを管理する。action は create/update/delete/list のいずれか。"""
    ...

一見DRYで便利ですが、AIから見ると次の問題が起きます。

  1. action の値によって必要な引数が変わるため、スキーマだけでは正否が判断できないlist なのに title を渡す、など)
  2. 引数の取り違えに、ツール側で弾くまで気づけない
  3. 説明文が「全機能の説明」になり、どの場面で使うかが曖昧になる

正解は、動詞ごとにツールを分けることです。

# ✅ 良い設計: 1ツール1責務
@mcp.tool()
def create_task(title: str, due_date: str | None = None) -> dict:
    """新しいタスクを作成する。title は必須。due_date は YYYY-MM-DD 形式。"""
    ...

@mcp.tool()
def list_tasks(status: str = "open") -> list[dict]:
    """タスク一覧を取得する。status は open/done/all のいずれか。"""
    ...

@mcp.tool()
def complete_task(task_id: str) -> dict:
    """指定したタスクを完了にする。task_id は list_tasks で取得できる値を使う。"""
    ...

スキーマが引数の意味を語り、説明文が「いつ使うか」を語る。AIはこの2つだけを手がかりにツールを選ぶため、分割はそのまま精度に直結します

ツール名も動詞で始めると、AIが役割を推測しやすくなります(create_* / list_* / get_* / search_* / update_* / delete_*)。

原則2: description は「AIへのプロンプト」として書く

MCPのツール定義にある description は、人間向けのドキュメントではなくプロンプトです。AIはこれを読んで呼び出しを決めます。ここを削ると、実装が正しくても使われません。

# ❌ 情報量がゼロ
@mcp.tool()
def search(q: str) -> list[dict]:
    """検索する。"""

# ✅ 用途・入力形式・戻り値・次の一手まで書く
@mcp.tool()
def search_documents(q: str, limit: int = 5) -> list[dict]:
    """社内ドキュメントを全文検索する。

    キーワード検索のため、自然文の質問より語句を並べた方が精度が高い
    (例: "経費 締め日")。関連度の高い順に最大 limit 件を返す。
    各結果には doc_id / title / snippet が含まれる。本文全体が必要な場合は
    get_document(doc_id) を続けて呼ぶこと。
    """
    ...

書くべきポイントは4つです。

  • いつ使うか(全文検索であり、意味検索ではない)
  • 入力の書き方(自然文より語句を並べる)
  • 戻り値の構造doc_id / title / snippet
  • 次の一手(全文が要るなら get_document

特に「次の一手」を書いておくと、AIがツールを連鎖させてタスクを完遂できるようになります。1回の呼び出しで完結しないタスクほど、この一文が効きます。

原則3: 戻り値は「AIが読む前提」で削る

戻り値は人間が読むログではなく、コンテキストに載るトークンです。生のAPIレスポンスをそのまま返すと、AIはノイズに埋もれて判断を誤ります。

# ❌ 生データを丸ごと返す(不要なフィールドが大量に混ざる)
return requests.get(f"{API}/issues/{id}").json()

# ✅ AIの判断に必要な項目だけを構造化して返す
raw = requests.get(f"{API}/issues/{id}").json()
return {
    "id": raw["id"],
    "title": raw["title"],
    "state": raw["state"],
    "assignee": (raw.get("assignee") or {}).get("name"),
    "updated_at": raw["updated_at"],
    "body_excerpt": raw["body"][:500],  # 長文は切り詰める
}

判断に必要な情報を先頭に置き、長文は切り詰める。この一手間がAIの推論精度とコストの両方に効きます。特に一覧系ツールは、件数が増えるほど効いてきます。

原則4: 書き込み操作は「分離」と「確認」を設計に入れる

読み取りと書き込みは、別ツール・できれば別サーバーに分けるのが基本です。

  • 読み取りlist_* / get_* / search_*): 冪等で安全。積極的に公開してよい
  • 書き込みcreate_* / update_*): 影響範囲を説明文に明記し、可能なら dry-run を用意
  • 破壊的delete_* / deploy_*): 別サーバーに隔離し、人間の承認を挟む

さらに、いきなり実行しない設計も有効です。

@mcp.tool()
def update_document(doc_id: str, body: str, dry_run: bool = True) -> dict:
    """ドキュメント本文を上書き更新する。

    dry_run=True(既定)では変更差分のみを返し、実際には書き込まない。
    内容を確認したうえで dry_run=False を指定すると反映される。
    既存の本文は完全に置き換わるため、事前に get_document で確認すること。
    """
    ...

dry_run を既定にするだけでも、AIが誤って本番データを書き換える事故は大きく減ります。「AIは間違える前提で道具を作る」——これがMCP設計の基本姿勢です。

ツール設計チェックリスト

実装前に、次の7項目を確認してください。

  • 1ツール1責務になっているか(動詞単位で分割されているか)
  • description に「いつ使うか・入力形式・戻り値・次の一手」が書かれているか
  • 引数は型ヒント付きで、Optional と既定値が妥当か
  • 戻り値は必要項目に絞り、長文は切り詰めているか
  • 読み取りと書き込みが分離されているか
  • 破壊的操作に dry-run または承認ステップがあるか
  • エラー時に「AIが次に何をすべきか」が分かるメッセージを返しているか

最後の項目は見落とされがちです。エラー文字列をそのまま返すのではなく、「再試行すべきか、別のツールに切り替えるべきか」がAIに伝わる文言にします。

まとめ

  • MCPのツール設計は「AIに渡す道具の粒度」を決める作業であり、そのままAIの性能になる
  • 何でも屋ツールは禁止。動詞ごとに分割してスキーマに意味を持たせる
  • description はプロンプト。用途・入力形式・戻り値・次の一手を書く
  • 戻り値はAIが読むトークン。必要な項目だけを構造化して返す
  • 書き込み・破壊的操作は分離と dry-run で事故を防ぐ

ツールを1つ足すたびに「AIはこれを見て正しく使えるか」と自問する。この積み重ねが、実用的なエージェントを作ります。


MCPの基本概念からTools/Resources/Promptsの実装、Claude Desktop統合、複数サーバーの運用、実践プロジェクト集まで体系的にまとめた書籍を出版しています。

読者特典(無料)

本記事のような実装パターンを横断的にまとめたチートシートと、Obsidian・Notionのテンプレート集を無料配布しています。8冊の内容から「何をどのツールでやるか」の判断チャートも含みます。

🎁 読者特典を受け取る(無料・メール登録)

📗 『MCP実践入門』(Kindle・Kindle Unlimited読み放題対象)(Kindle)

ツール設計の章では、本記事の原則を実際のサーバー実装に落とし込む手順を、コード付きで解説しています。Kindle Unlimited会員は読み放題対象です。


著者: 葉山悠希 — 書籍シリーズは Zenn / Amazon で公開中

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?