MCPサーバーを「使う側」から「作る側」の視点へ反転させる章。AIが正しいツールを選べるかは説明文の書き方で決まり、エラーから回復できるかはエラーの返し方で決まる——という設計思想のドメイン。この章は「導入レッスン(20行のMCPサーバーを作って心臓部を理解する)」→「タスクステートメント2.1〜2.5」→「演習」→「章末ミニクイズ」の順で、この1ページだけでDomain 2の学習が完結する。
第1章の土台レッスン(ツールカタログを手書きしてエージェントループを回す)が前提。まだなら第1章から。docstring・デコレータなどの基礎用語は準備章のことば図鑑にある。
MCPサーバーの正体は「ツールのカタログと実装をまとめて、標準の通信規約(Model Context Protocol)で公開する小さなプログラム」。Python なら公式SDKで20行で書ける。
# 最小のMCPサーバー(天気ツール1個)
# pip install "mcp[cli]"
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather") # サーバー名
@mcp.tool()
def get_weather(city: str) -> str:
"""指定した都市の現在の天気を返す。
都市名は日本語・英語どちらでも可(例: 東京, Osaka)。
現在の天気・気温の質問に使う。過去の天気には get_weather_history を使う。
"""
# ↑ この docstring がそのまま「ツールの説明文」としてAIに渡る(2.1の主戦場)
return f"{city}: 晴れ、28度"
if __name__ == "__main__":
mcp.run() # 標準入出力で通信(Claude Code から接続できる)
上のdocstringに詰めた4要素:何をするか/入力の形式と例/エッジケース/境界(いつ使い・いつ使わないか)。「過去の天気には get_weather_history を」の1行が誤ルーティングを防ぐ肝。
@mcp.tool()
def get_weather(city: str) -> dict:
"""(説明文は同じ)"""
if not weather_api.is_alive():
return { # 一時的な障害 → リトライする価値あり
"error": True,
"errorCategory": "transient",
"isRetryable": True,
"message": "天気サービスが応答しません。少し待って再試行してください。",
}
result = weather_api.lookup(city)
if result is None:
return { # 入力の問題 → リトライしても無駄
"error": True,
"errorCategory": "validation",
"isRetryable": False,
"message": f"都市 '{city}' が見つかりません。表記を確認してください。",
}
return {"city": city, "weather": result} # 成功
# 重要な区別: 「検索は成功したが該当0件」はエラーではなく正常な結果として返す
1体のエージェントに渡すツールは役割に必要な4〜5個まで。18個渡すと選択の信頼性が落ちる。高頻度の単純ニーズには機能を絞った専用ツール(例:統合係に verify_fact だけ渡す)、複雑ケースはコーディネーター経由——「85/15の分離」が模範解答の型。
// .mcp.json(プロジェクト直下・チーム共有・git管理)
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["servers/weather.py"],
"env": { "WEATHER_API_KEY": "${WEATHER_API_KEY}" } // ← 直書き禁止。環境変数展開
}
}
}
// 個人の実験用サーバーは ~/.claude.json 側に書く(チームに配らない)
ここまでが「作る側」の全体像。ここから先は、その設計判断を試験が問う形(タスクステートメント)で1つずつ整理していく。
analyze_content と analyze_document)は誤ルーティングの温床analyze_content → extract_web_results)→ 汎用ツールを目的別に分割(例:analyze_document を「データ点抽出」「要約」「出典照合」の3つへ)agents/skills の frontmatter description がまさにこれ。config-optimizer エージェントが「description品質」を監査項目にしているのは、この試験思想の運用版。skills の description に「〜のときに起動 / 〜は別スキルへ」と境界を書き込む流儀(例: seo-schema「サイトマップはseo-sitemapを使う」)は満点回答のパターン。
isError フラグ:ツールの失敗をエージェントに伝える標準の仕組みerrorCategory(transient/validation/permission)+ isRetryable(真偽値)+ 人間が読める説明文(→導入レッスン2のコードがこの形)retriable: false + 顧客向けに説明できる文言を付ける(AIが適切に謝れる)failed経験の宝庫。integration-discovery ルールの「2>/dev/null でstderrを捨てて空判定するな」は「一般エラーと正当な0件の混同」事故そのもの(Metabase初見化事件)。x-posting-worker のIPガチャ(Geminiの間欠エラー→5分後リトライで自己回復)は transient / isRetryable=true の実例。n8n診断の「生エラーログから読む」も同じ思想。
tool_choice で強制する。後半の tool_choice は、APIに渡す「ツールをどれくらい強制的に使わせるか」のダイヤルで、3段階ある。普段のエージェントは一番ゆるい "auto":ツールを使うかどうかも含めてモデルが判断するので、「こんにちは」と話しかけられたら普通にテキストで返事をする。これがデフォルト。
問題はパイプラインの部品としてAIを使うとき。たとえばメール分類システムで、モデルが気を利かせて「このメールは請求に関するもののようですね」と会話文で返してしまったら、ツール呼び出しを前提に組んだ後続のプログラムは壊れる。そこで "any":「テキストだけの返答は禁止。必ずどれかのツールを呼べ」という縛り。さらに一歩進んで「どれか」ですらなく特定の1つを名指しで呼ばせるのが {"type": "tool", "name": "..."}。文書処理の最初に必ず extract_metadata を走らせる、のような固定手順に使う。
| モード | 挙動 | テキストだけの返答 | 典型的な使い所 |
|---|---|---|---|
"auto"(デフォルト) | ツールを使うかどうかもモデルが判断 | あり得る | 普通の会話エージェント・Claude Codeの通常ターン |
"any" | どれかのツールを必ず呼ぶ | 禁止 | 会話文が混ざると壊れるパイプライン(必ず構造化された呼び出しが欲しい) |
{"type":"tool","name":"..."} | 名指しした特定ツールを必ず呼ぶ | 禁止 | 固定手順の強制(最初に必ず extract_metadata)・スキーマ通りのJSON抽出 |
3つ目の「特定ツール強制」は、第3章(D4)で学んだ構造化出力の強制とつながっている:欲しい出力のスキーマを input_schema に持つ抽出ツールを1個だけ定義し、それを名指しで強制すると、返答が必ずそのスキーマ通りのJSONになる。「tool_choice強制でJSONを取る」は、この3モードの一番強い段を抽出に応用した技、という関係。
試験が問うことverify_fact(単純な事実確認専用)を渡し、複雑な検証は従来どおりコーディネーター経由——85%の単純ケースの往復を削減しつつ関心の分離を守るfetch_url → 文書URLだけ通す load_document)tool_choice の3モード:"auto"(ツールを使うかもモデル判断=テキスト返答もあり得る)/"any"(必ずどれかのツールを呼ぶ)/{"type":"tool","name":"..."}(特定ツールを強制)extract_metadata を走らせたい→強制指定、会話文でなく必ず構造化出力が欲しい→ "any"agents/*.md の tools 制限そのもの。verification-agent は読み取り専用(Read/Grep/Glob/Bash)、planner は Read/Grep/Glob のみ、audit系はWrite封印——「役割外のツールは渡さない」の実装。52体のエージェントにフルツールを渡していないのは、まさにこの試験原則。
tool_choice という決定論的な仕組みがある(第1章1.4の「プロンプトは確率的、仕組みは決定論的」と同じ軸).mcp.json(プロジェクト直下・git管理)、個人の実験なら ~/.claude.json(ユーザー領域)。秘密鍵は環境変数参照で書き、ファイルに直書きしない。.mcp.json(チーム共通ツール)vs user-level ~/.claude.json(個人・実験用).mcp.json 内の環境変数展開(例:${GITHUB_TOKEN})で、シークレットをコミットせずに認証情報を管理(→導入レッスン3のコードがこの形)16本のMCPサーバー運用と registry/integrations.yaml(接続情報のSSOT)。「シークレットは環境変数参照」は、うちでは op:// 参照+opx で徹底している(試験の${VAR}方式と同じ思想の上位互換)。「コミュニティサーバー優先・自作は固有ニーズのみ」は resilience-first の判定表と同じ考え方。
Claude Codeが最初から持っている基本道具(組み込みツール)は、図書館にたとえると分かりやすい。Glob は書棚の背表紙を眺める道具:「ファイル名のパターン」で探す(**/*.test.tsx =「名前が .test.tsx で終わる本を全部の棚から」)。Grep は全巻の本文検索:「ファイルの中身」をパターンで探す(関数名・エラーメッセージ・import文がどの本の何ページにあるか)。Read は1冊を開いて読む、Write は丸ごと書き直す、Edit は特定の一文だけを差し替える朱入れ。探す2つ(中身=Grep/名前=Glob)と、書く2つ(全体=Write/ピンポイント=Edit)の対比で覚える。
具体例で流れをつかむ。「ログイン画面の『パスワードが違います』という文言を直したい」なら:①その文言がどのファイルにあるかは中身の検索だから Grepで文字列を検索 → ②見つかったファイルを Readで開いて 前後の文脈を確認 → ③直したい一文だけを Editで差し替える。逆に「テストファイルが全部でいくつあるか知りたい」なら中身は関係ないので Globでファイル名パターン を引く。「ファイル名で探したいのにGrep」「中身で探したいのにGlob」という用途の取り違えが、試験で狙われる第一のポイント。
第二のポイントが Edit失敗時のフォールバック。Editは「この文字列をこれに置き換えて」という指定で動くが、同じ文字列がファイル内に複数あると「どれのことか一意に決められない」と失敗する。このときの正解は、同じEditをやみくもに再試行することではなく、Readでファイル全体を読み、修正した全文をWriteで書き戻すこと。ピンポイントの朱入れが効かないなら、ページごと書き直す——道具を一段強いものに持ち替える判断。
第三のポイントが段階的探索。初めてのコードベースを理解するとき、「まず全ファイルをReadで読み込む」のは膨大なコンテキストを浪費するだけで誤答。Grepで入口(目的の関数や文字列)を見つける → そのファイルをReadで読む → import文を辿って関連ファイルへ広げる、と必要な分だけ段階的に読む。ラッパー(別名の窓口関数)越しに使われている関数を追うときも同じで、まずexportされている全名称を特定してから、各名称を横断検索する。
試験が問うこと**/*.test.tsx)毎日使っている道具そのもの。運用知見の蓄積(feedback-edit-before-read「Edit/Write前に同一会話でRead」、ensoレッスン「Globにはpathを付けて範囲を絞る」)は試験知識の実戦版。Claude Codeの画面でツール名を見るたびに「なぜ今GrepでなくGlobなのか」を一言説明する癖をつけると、このタスクステートメントは日常が教材になる。
Anthropic 公式の無料学習サイト Claude Academy(2026-08-20 公開、/ja/ で日本語版)のうち、第4章(ドメイン2: ツール設計と MCP)に対応するレッスン。「作る側」は Model Context Protocol入門 が本丸。ツール説明文・tool_choice は API コースのツール使用セクション、組み込みツールは Claude Platform 101 が対応する。使い方は「この章を読み終えてから、同じテーマを公式がどう説明しているかを確かめる」の一方向。先に公式を読む必要はない。レッスン本文の閲覧には無料アカウントでのサインインが必要。
この章で使うコース: Model Context Protocol入門 / Claude APIを使った構築 / Claude Platform 101 / Claude Code 101 / MCP: 高度なトピック
対応付けはレッスン題名とコース説明文から行った(2026-08-25 時点)。レッスン本文までは精査していないので、読んでみて「この章の項目とずれている」と感じたら、その節は公式を優先せずこの章の記述で答える(試験ガイドのタスクステートメントに合わせて書いてあるため)。
この試験にコードを書く場面はない。必要なのは「コードを見て意味が分かる目」だけなので、写経(見ながら書き写して動かす)で十分——やり方は第1章の「写経の作法」(1行写すごとに何をする行か声に出す🥈方式)を参照。Claudeに「c4演習やる」と言えば環境準備から伴走してもらえる。
実は第1章の演習2(紛らわしいツールの説明文を書き分ける)と演習3(構造化エラーを返す)は、手書きカタログ側でのD2.1・D2.2の体験だった。今回はそれと同じことをMCPサーバー側でやる——「あのとき手書きしたものが docstring と返り値の設計に化ける」のを確かめるのがこの演習の狙い。
get_weather_history(過去の天気)を足し、境界を書き分けた説明文で「昨日の東京の天気」「今の東京の天気」が正しく振り分けられるかを、.mcp.json に登録して Claude Code に接続してテストする(→2.1と2.4の体験)FastMCP=PythonでMCPサーバーを最小の手間で書くための公式SDKの部品。関数に @mcp.tool() を付けると、関数定義と docstring(関数直下の説明文)からツールカタログを自動生成する。docstringがそのまま「AIに渡る説明文」になるため、説明文の品質=ツール選択の精度に直結する(→ことば図鑑にも項目あり)。
MCPツールの結果が「失敗である」ことをエージェントに伝える標準フラグ。これに errorCategory / isRetryable などのメタ情報を添えるのが構造化エラー応答。
エラーの種類(transient=一時的 / validation=入力不正 / permission=権限)と、リトライで直る見込みがあるかの真偽値。これが無いとAIは「もう一回試す価値があるか」を判断できない。
ツール使用の強制度を決めるAPI設定。"auto"=使うかはモデル次第/"any"=必ずどれかのツールを呼ぶ/{"type":"tool","name":"..."}=指名したツールを必ず呼ぶ。特定ツール強制+スキーマ付き抽出ツールの組み合わせが、第3章(D4)の「JSONを確実に取る」技の正体。
役割の壁を越える高頻度ニーズにだけ、機能を絞った専用ツールを渡す設計。「85%の単純ケースは直接、15%の複雑ケースはコーディネーター経由」のような最小権限の落とし所。
MCPサーバー設定の置き場所。前者=プロジェクト直下・git共有(チーム用)、後者=ユーザー個人(実験用)。シークレットは ${ENV_VAR} 参照で書く。
「実行するもの(ツール)」ではなく「参照するもの(コンテンツカタログ)」をMCPサーバーが公開する仕組み。issue一覧・DBスキーマなどを渡しておくと、エージェントの探り打ちツールコールが減る。
「検索は成功したが該当なし」と「検索自体ができなかった」は別物。混同すると、無いだけのものを延々リトライしたり、障害を「該当なし」と誤報したりする。
組み込みツール=Claude Codeが最初から持つ基本道具(Read / Write / Edit / Bash / Grep / Glob)。フォールバック=第一候補の道具が効かないとき一段強い道具に持ち替えること。代表例が「Editの一致が一意でない→Read+Writeで全文書き戻し」。
本番形式の4択。この章で学んだことの思い出す練習。総合模試とは別シナリオで、2.5(組み込みツール)と tool_choice を重点的に出す。3問目は第3章(D4)の復習を混ぜてある——章をまたいで思い出す方が記憶に残る。
timeout: 30 を timeout: 60 に Edit で修正しようとしたら「一致箇所が一意でない」と失敗した(同じ記述が複数ある)。正しい次の一手は?extract_metadata ツールを実行する」ことを保証したい。正しい設定は?