Lv4 MCP(Model Context Protocol)
🔮 ウォームアップ — 読む前に予想する
まだ解けなくて正常です(採点されません)。先に予想を立てると本文の読み方が変わり、学習効果が上がります(事前テスト効果 → 設計根拠)。頭の中で答えてから開いてください。同じ概念は本編の自己チェックで再登場します。
同僚が「MCPはtool useのラッパーで、直接APIを呼ぶのと変わらない」と言った。技術的に正確な応答は?
半分正しい——実行される中身(外部API呼び出し)は同じで、MCPは能力を増やさない。変わるのは「誰がschemaと関数を書き、テストし、保守するか」で、MCPはその責任をserver実装者へ移す通信レイヤ。tool useとは同一でなく補完関係。なおツールを実行するのはclientではなくserver(clientは転送役)——ここを誤解すると4.6/4.7が理解できない。自作ツール1個で済む閉じた用途ならMCP化の利点は小さいこともある。
本編で学ぶ → 自己チェック
公開MCP serverに要約機能を入れる。serverから直接Claude APIを呼ぶ設計の問題点を2つ以上挙げ、samplingがどう解決するか。
問題点: ①serverがAPIキーを保持(漏えいリスク・管理負担)。②見知らぬ利用者のトークン費用をserver運営者が全額負担。③呼び出し・応答抽出コードでserverが複雑化。samplingは生成の実行をclient側へ移す——serverはプロンプトを組み create_message で依頼するだけ。clientは既にClaude接続を持つので負担増は小さく、serverはキー不要・費用は利用者側になる。
本編で学ぶ → 自己チェック
安全4(rootsの強制力・S.5 の補足): 「rootsを設定したのでこのserverは安全」というレビューコメントへの正しい指摘は?
rootsは許可範囲の伝達であり強制ではない。SDKは自動ブロックしないので、パス検査(root内か・../ やsymlinkで抜けられないか)の実装をコードで確認しない限り「安全」とは言えない(4.6参照)。
前提: L3A(level-3-tools-rag-features.md)修了。tool schema・tool useループを自分で書けることが必須(L4はその「自作部分」をプロトコルへ委譲する話だから)。 CCAドメイン: ② / 力量マップ: C. ツール設計・MCP統合 ゲート共通運用は README.md、安全性の横断必修は safety-security.md。
学習目標
- MCPが何の負担を誰に移す仕組みかを、tool use(L3A)との対比で説明できる。
- 3プリミティブ(tools / resources / prompts)を実装し、MCP Inspectorで検証できる。
- 制御主体(model / app / user controlled)から、新機能をどのプリミティブで作るか判断できる。
- Sampling・Log/Progress Notifications・Roots の目的と実装責任の所在を説明できる。
- STDIO / StreamableHTTP の違いと、
stateless_http/json_responseが何を壊すかを、メッセージ方向(server→client)の観点から説明できる。
教材: 4.1〜4.5は introduction-to-mcp 全文日本語ガイド、4.6〜4.7は mcp-advanced-topics 全文日本語ガイド。副参照: building-with-the-claude-api 全文ガイド の「Introducing MCP」〜「MCP review」(圧縮版・復習用)。着手前に動画で全体像を掴むとよい(4.1に埋め込み)。公式: modelcontextprotocol.io・仕様リポジトリ(schema.ts)。
演習の共通ルール(DESIGN.md): ①ベースライン→②設計・実装→③敵対テスト→④測定→⑤言語化 の5段階。提出物4点 = 実装 / テスト・evalデータ / 実行結果 / 設計判断メモ。L4は中盤なので足場は「要件のみ」が基本(4.7のみ障害シナリオ型)。
モジュール 4.1 — MCPの動機と全体像
学ぶこと
MCPが解決する問題 = サービス連携ごとのツールschema・関数の自作・テスト・保守の負担を、アプリ開発者からMCP server実装者(多くはサービス提供者自身)へ移すこと。host(自分のアプリ)/ MCP client(仲介役・ツールは実行しない)/ MCP server(ツールを実装・実行)の関係と、list tools / call tool の request/result メッセージ対。
次の図で、host / MCP client / MCP server の位置関係と、「統合コードを書く責任がアプリ開発者からserver実装者へ移る」構図を先に掴む。
✏️ 再現チェック: モジュールを読み終えたら、この図を見ずに白紙へ描き直す(矢印のラベルまで)。描けなかった部分が復習ポイント。
読む
- 生徒先生、GitHubもSlackも操れるエージェントを作りたいんだけど、サービスが増えるたびにツールのスキーマとか関数とか全部自分で書くの、正直しんどい…
- 先生そこがMCPの出発点。想像してみて。M個のサービス×N個のツール分、みんなが同じような統合コードを別々に書いてる。その負担を、アプリ開発者から「MCP server」という別の役割へ丸ごと移すのがMCP。
- 生徒移すって言われても、自分のアプリ側には何も残らないの?
- 先生残るよ。host——つまり君のアプリ——の中に「MCP client」って仲介役が住んでる。ただしこのclient、ツールは自分では実行しないんだ。
- 生徒実行しないなら、何のために存在するの?
- 先生通信の橋渡し専門。「どんなツールある?」って聞いて(list tools request)一覧をもらい(list tools result)、「これ実行して」と頼んで(call tool request)結果を受け取る(call tool result)。実際にツールを実装して動かすのはMCP serverの方だよ。
- 生徒つまりGitHub用のツールコードは、GitHubのMCP serverの中の誰かがもう書いてくれてるってこと?
- 先生その通り。しかも多くはサービス提供者自身が公式実装を出してる。だから僕らは繋ぐだけで済む。
- 生徒なら「MCPって結局API直叩きと同じでしょ」って言われたらどう返す?
- 先生半分正解、って答える。実行される中身は同じAPI呼び出し。変わるのは「誰がスキーマと関数を書き、テストし、保守するか」——それをserver実装者へ移す通信の型がMCPなんだ。
- 生徒今までの話、いつもclientがserverに「お願いします」って頼む側だったよね。逆方向ってないの?
- 先生いいところに気づいたね。実はMCPには「serverからclientへ」向かうメッセージもある。代表格が3つ——sampling・通知・roots。
- 生徒samplingって、名前だけ聞くと統計みたいで身構える…
- 先生それ、生成時のtemperature/top-pの「サンプリング」とは全くの別概念だから混同しなくていいよ。MCPのSamplingは「serverがLLM呼び出しをclientに依頼するプロトコル機能」の名前として使われてる。実体はシンプルで、serverがclientに頼んで、client側が接続しているLLM(必ずしもClaudeとは限らない)にテキストを生成してもらう仕組み。serverはAPIキーを持たなくていいし、生成コストも呼び出す側であるclientが負担する。公開serverほど重要になる。
- 生徒じゃあ「通知」は?
- 先生ツール実行中に「今こんな状況です」とserverからclientへ流す進捗・ログのメッセージ。時間のかかる処理が「動いてるのか固まったのか」分からない、というUXの穴を埋める役目。
- 生徒rootsは正直、名前からは何も想像つかない…
- 先生rootsは、ユーザーが事前に許可したファイル・フォルダの集合。serverに「ここまでは触っていいよ」と伝える仕組みだけど、実際にその範囲を守るかどうかをSDKが自動で強制してはくれない。守る責任はserver開発者側にある。
- 生徒3つとも方向は同じなのに、中身は結構バラバラだね
- 先生そう、共通してるのは「clientが頼まれるだけじゃなく、serverから話しかけられる側にもなる」という点。詳しい実装は4.6で、この向きの通信がHTTPだとなぜ壊れやすいかは4.7で見ていくよ。
introduction-to-mcp §0〜2。GitHubチャットボットの例、「よくある3つの疑問」、13ステップのメッセージフローを重点的に。
やる(演習 4.1: 責任の移動を自分のコードで確認する)※要件のみ
- ベースライン: L3Aの自作tool use実装で「schema定義」「tool関数」「実行ループ」の3箇所に印を付ける。
- 設計: MCP導入で書かなくてよくなる部分とアプリに残る部分を表に分ける(答え合わせは§1〜2)。
- 敵対テスト(思考実験): 「社内専用ツール1個だけ」のケースでMCP化する価値を賛否両論で書く。
- 測定: ツール1個あたりの実装行数を数え、「N個のサービス×M個のツール」に外挿する。
- 言語化: ユーザー質問→最終応答の流れを host / client / server / 外部サービス / Claude の5者で図解し60秒で説明する。
自己チェック
同僚が「MCPはtool useのラッパーで、直接APIを呼ぶのと変わらない」と言った。技術的に正確な応答は?
半分正しい——実行される中身(外部API呼び出し)は同じで、MCPは能力を増やさない。変わるのは「誰がschemaと関数を書き、テストし、保守するか」で、MCPはその責任をserver実装者へ移す通信レイヤ。tool useとは同一でなく補完関係。なおツールを実行するのはclientではなくserver(clientは転送役)——ここを誤解すると4.6/4.7が理解できない。自作ツール1個で済む閉じた用途ならMCP化の利点は小さいこともある。
モジュール 4.2 — toolsの定義とテスト(MCP Inspector)
学ぶこと
Python SDK(mcp パッケージ)でのserver構築。@mcp.tool + pydantic.Field の引数説明からJSON schemaが自動生成される。存在しないID要求には ValueError 送出(モデルが回復できるエラー)。mcp dev <server.py> で起動する MCP Inspector で、アプリに配線せず単体検証(Connect → Tools → List Tools → 個別実行)。client側は session.list_tools() / session.call_tool() の薄いラッパー(sessionはクリーンアップ込みのクラスでラップする慣習)。
読む
introduction-to-mcp §3〜6。Inspectorはポート・UIが頻繁に変わる(講義内でも6277/6274の両言及)ので画面でなく機能で覚える。
やる(演習 4.2: 自分のserverをInspectorで叩く)※要件のみ
- ベースライン: コース同等の最小server(ドキュメント辞書+read/edit)を動かし、Inspectorで両ツールの成功を確認。
- 設計・実装: 自分の題材で2〜3ツールのserverを書く(例: メモディレクトリへの
list_notes/read_note/append_note)。全引数にField(description=...)、L3Aのschema設計基準を適用。 - 敵対テスト: 存在しないID・空文字列・極端に長い入力・型違いを投入し、エラーが回復可能なメッセージか記録。
- 測定:
list_tools出力(=Claudeに渡るschema)を保存し、descriptionのトークン数を概算(毎リクエストに乗るコスト)。 - 言語化: 手書きschema(L3A)とSDK自動生成の違い、生成schemaのどこを目視レビューすべきかをメモに書く。
自己チェック
read_document が存在しないIDを受けたとき (a) 空文字列を返す (b) ValueError を送出 (c) {"error": ...} を返す。コースは(b)。なぜ(a)が最悪か。
(a)は呼び出しが成功したように見えるsilent failureで、Claudeは「ドキュメントは空」という誤前提で回答を続ける。(b)はエラーがtool resultとして伝わり、IDを直して再試行する回復ループに乗る。(c)も動くが正常系と同じ型に異常を混ぜ、一貫したエラー処理に乗りにくい。基準は「モデルが失敗に気づき自力で回復できるか」。
モジュール 4.3 — resources(direct / templated、MIME type、@メンション連携)
学ぶこと
resources = serverがclientへデータを公開する仕組み(読み取り操作ごとに1 resourceが目安)。direct(静的URI、例 docs://documents)と templated(例 docs://documents/{doc_id}、URIパラメータが関数のキーワード引数になる)。MIME type(application/json / text/plain)は「clientがどうパースすべきか」のヒントで、デシリアライズはclient側の仕事。応用: @メンション=ユーザーが先回りして内容をプロンプトへ注入し、ツール往復を不要にする。
読む
introduction-to-mcp §7〜8。client側 read_resource がMIMEで json.loads するか生テキストで返すか分岐する実装まで。
やる(演習 4.3: @メンションを組み立てる)※要件のみ
- ベースライン: 4.2のserverに一覧用direct・内容用templatedの2 resourceを追加し、InspectorでResourcesとResource templatesが別枠表示されることを確認。
- 設計・実装: client側
read_resource(MIME分岐込み)を実装し、@メンション相当(指定資料の内容をプロンプトへ事前挿入)をつなぐ。 - 敵対テスト: 存在しないIDのtemplated URIと、
application/json宣言なのにJSONでない文字列を返すバグで、client側がどこでどう壊れるか観察。 - 測定: 同じ資料参照を「@メンション(事前挿入)」と「read系ツールを呼ばせる」で実行し、往復回数・レイテンシ・トークンを比較。
- 言語化: toolでなくresourceにした理由、返すデータ構造(内容のみ vs id・著者含むレコード)の判断をメモに書く。
自己チェック
「@ で候補一覧を出し、選ばれたら内容をプロンプトに挿入」に必要なresourceはいくつで、それぞれdirect/templatedのどちらか。挿入後にClaudeがツールを呼ばなくなるのは異常か?
2つ。候補一覧は引数不要のdirect(application/json)、個別内容はIDで変わるtemplated(内容そのものなら text/plain)。「読み取り操作ごとに1 resource」の原則どおり一覧と個別取得は分ける。ツールを呼ばないのは正常で狙いそのもの——内容が既にプロンプト内にあるためread系ツールが不要になり、往復1回分のレイテンシ・トークンが浮く(4.3④の測定で確認)。
モジュール 4.4 — prompts(user controlled、スラッシュコマンド連携)
学ぶこと
prompts = 「ユーザーが手打ちでも実現できる操作」を、server作者がテスト・評価済みの高品質プロンプトとして配布する仕組み(コード削減でなく品質保証が本質)。@mcp.prompt で定義し、base.UserMessage のメッセージ列を返す。引数はプロンプト文へ補間される。UIの典型はスラッシュコマンド(例 /format)。client側は list_prompts / get_prompt。
読む
introduction-to-mcp §9〜10。「実は開発しなくても動く」の節を最重点で。
やる(演習 4.4: 評価済みプロンプトを配布する)※要件のみ・L2接続
- ベースライン: 素朴な手打ち指示(例「この資料を要約して」)で3件処理し、品質のばらつきを記録。
- 設計・実装: 同タスク用の作り込んだプロンプトを書き、L2のevalハーネスで採点してから
@mcp.promptに載せる。InspectorのGet Promptで引数補間済みメッセージ列を確認。 - 敵対テスト: 引数に存在しないIDや、指示を上書きしようとする文字列(インジェクション)を渡し、補間結果を確認。
- 測定: 手打ち版とprompt版をevalで比較し品質差を数値で示す。
- 言語化: clientアプリ直書きでなくMCP promptsとして公開する利点と欠点をメモに書く。
自己チェック
/format(Markdown整形)はユーザーが「Markdownにして」と打っても動く。ではpromptsの価値は?
品質の底上げと再利用。手打ちでもまずまず動くが、server作者はドメインを熟知し、テスト・評価済みプロンプトを用意できる。ユーザーは開発コストゼロでその品質を得て、どのclientアプリからも同じプロンプトを使える。なお実行を開始するのはユーザー(user controlled)であり、モデルが自律判断で使うのはtools——この整理は4.5で。
モジュール 4.5 — 3プリミティブの制御主体(model / app / user controlled)
学ぶこと
tools = model-controlled(いつ使うかはClaudeが決める)/ resources = app-controlled(アプリのコードが取得・利用を決める)/ prompts = user-controlled(ユーザーが起動を決める)。Claude.aiの実例: チャット開始ボタン群=prompts、Google Driveのドキュメント追加=resources、コード実行=tools。この区分が「新機能をどのプリミティブで作るか」の設計指針。
次の図で、3プリミティブを『誰が実行を決めるか』という1つの軸で見分けられるようにする。
読む
introduction-to-mcp §11+まとめ。
やる(演習 4.5: 分類ドリル)※要件のみ
- ベースライン: Claude.aiの3実例を根拠つきで自分の言葉で分類し直す。
- 設計: 自分のプロダクト(またはキャップストーン)から機能候補を6個挙げ、「誰が実行を決めるか」を根拠に分類。
- 敵対テスト: 境界例を2つ以上含める(例: ユーザーがボタンで起動し、実行中はモデルがツールを連鎖させる機能)。
- 測定: 分類表を第三者(またはClaude)にレビューさせ不一致箇所を特定。
- 言語化: 不一致項目について採用案と棄却案の両論拠を書く。
自己チェック
①「サイドバーに接続先の最新レポート一覧を常時表示」②「/review と打つとClaudeが規約チェック→修正案→要約の順に作業」。それぞれの制御主体は?
①はresources——一覧を取得しUIに出すと決めるのはアプリのコード(app-controlled)。tools棄却: モデルの判断は不要で毎回のツール往復は無駄。prompts棄却: 指示テンプレートでなくデータ供給(Claude.aiの「Add from Google Drive」と同型)。②は起動がuser controlled(prompts)、実行中のツール選択がmodel controlled(tools)——1機能の中で複数プリミティブが役割分担する。「機能ごとに1プリミティブ」と考えるのが誤り。
モジュール 4.6 — advanced: Sampling・通知・Roots
学ぶこと
- Sampling: serverがclient経由でLLM生成を依頼し、LLMを呼ぶ責任(APIキー・トークン費用)をclientへ移す(モデル非依存のプロトコル機能で、呼び出し先はclientの実装次第。必ずしもClaudeとは限らない)。公開serverで特に重要。server側は
create_message、client側はsamplingコールバック(LLMを呼びcreate_message_resultを返す責任は開発者)。なお同名の「サンプリング」(Claude APIのtemperature/top_p等の生成制御パラメータ)とは別概念。 - Log/Progress Notifications: ツール関数に Context型で型注釈した引数(位置は自由、Contextアノテーションがあれば自動注入される)を追加し、その
info()/report_progress()で発行し、client側の2つのコールバック(ログ用はclient sessionへ、進捗用はcall_toolへ)で受ける。UX向上のためのオプション。 - Roots: ユーザーが事前に許可したファイル/フォルダ集合。①アクセス許可の体系的伝達、②LLM(サーバー経由で動くエージェント。必ずしもClaudeとは限らない)の探索範囲の絞り込み、の2目的。SDKは自動強制しない「緩い」仕組みで、
is_path_allowedのような検査はserver開発者の責任。 - (参考)Elicitation: MCP公式のもう1つのプリミティブ(
elicitation/create)。serverが処理の途中でユーザーに追加情報を尋ね、accept/decline/cancelで応答を受け取る仕組み。本モジュールの実技・自己チェックでは扱わないが、実装や他のMCPサーバーで遭遇したときに独自拡張と誤解しないよう名前だけ把握しておく。
読む
mcp-advanced-topics §1〜3。Samplingの「2つの選択肢」比較、Rootsの3ツールデモ(Convert Video / Read Directory / List Roots)と「実装は緩い」の注意を重点的に。
やる(演習 4.6: server→client方向の機能を体験する)※要件のみ・低コスト版あり
- ベースライン: 時間のかかるツール(
sleep入り擬似リサーチで可)を通知なしで実行し「失敗か停止か区別できない」体験を記録。 - 設計・実装: (a)
context.info()/report_progress()を追加しclient側コールバックで表示。(b) 要約ツールをsamplingで実装——低コスト版: samplingコールバックを固定文字列を返すスタブにして費用ゼロで往復を検証し、最後に1回だけ実Claude呼び出しへ差し替え。(c) ファイルを扱うツールにroots検査(is_path_allowed相当)を実装。 - 敵対テスト: roots外の絶対パス・
../入り相対パス・シンボリックリンクを投入し、検査を抜ける入力がないか確認(抜けたらそれが提出物の発見事項)。 - 測定: sampling版と「serverが直接Claudeを呼ぶ」版で、増えるコード行数・server側に必要な秘密情報(APIキー)の有無を比較表に。
- 言語化: 公開serverでsamplingを使う理由を、複雑さの移動先・APIキー・費用負担の3点で説明。
自己チェック
公開MCP serverに要約機能を入れる。serverから直接Claude APIを呼ぶ設計の問題点を2つ以上挙げ、samplingがどう解決するか。
問題点: ①serverがAPIキーを保持(漏えいリスク・管理負担)。②見知らぬ利用者のトークン費用をserver運営者が全額負担。③呼び出し・応答抽出コードでserverが複雑化。samplingは生成の実行をclient側へ移す——serverはプロンプトを組み create_message で依頼するだけ。clientは既にClaude接続を持つので負担増は小さく、serverはキー不要・費用は利用者側になる。
モジュール 4.7 — advanced: transport(STDIO / StreamableHTTP / stateless化)
学ぶこと
- JSONメッセージ型: 仕様リポジトリの
schema.ts(SDKとは別物・実行されない型定義)にある Request/Result ペアと応答不要の Notification。核心はServerRequest/ServerNotification——server→client方向のメッセージが存在すること。 - STDIO: clientがserverを別プロセスとして起動し stdin/stdout で通信。同一マシン限定だがどちら側からでも通信を開始できる完全な双方向性。初期化は initialize request → initialize result → initialized notification の3メッセージ。
- StreamableHTTP: リモートホスティング可能だが、HTTPではserver→clientのリクエスト開始が難しい。回避策 = 初期化時にヘッダーで MCP session ID を発行し、①長寿命の GET SSE接続(server起点メッセージ用)と、②call tool requestごとに開き result 送信で自動クローズする短命SSE接続を使い分ける。多くのSDK実装で progress notification は①側で送られる癖がある。
- 2つのフラグ:
stateless_http=true→ session ID不発行 → 長寿命GET SSE経路が張れず、教材のSDK実装では sampling・progress/log通知・リソース購読が使えなくなる(代わりに水平スケーリングが容易・初期化往復も省略)。ただしこの帰結はSDK実装依存——プロトコル仕様上は POST への SSE 応答でも server→client メッセージを流せるため、「stateless なら必ず不可能」ではない(使う SDK がどの経路で何を送るかを確認する)。json_response=true→ POST応答がストリーミングされず最終結果のみのプレーンJSONになる。
読む
mcp-advanced-topics §4〜8。§4の server messages / client messages の区分、§8の水平スケーリング(ロードバランサー配下でGET SSEとPOSTが別インスタンスに割れる問題)を重点的に。
やる(演習 4.7: 「本番だけ壊れる」を再現して直す)※障害シナリオ型・足場なし
- ベースライン: STDIOのserverに initialize request → initialized notification → call tool request のJSONをターミナルから手で貼り付けて通す(§5の再現)。通知(応答なし)とrequest/resultの挙動差を体感。
- 障害シナリオ: 「ローカル(STDIO)では進捗バーもsamplingも動いたのに、本番(StreamableHTTP+
stateless_http=true)では進捗が出ず生成も失敗する」。原因を仕様レベル(どのメッセージがどの経路を通れなくなったか)で特定し、対策3案(フラグを戻す/sticky session等インフラ調整/sampling・通知に依存しない設計へ変更)を比較して1つ選ぶ。 - 敵対テスト:
json_responseも加えた4通りのフラグ組み合わせで同じツール呼び出しを実行し、「届く/届かないメッセージ」のマトリクスを作る。 - 測定: stateless化で省ける初期化往復と、失う機能の対応表を作る。
- 言語化: 「開発時から本番と同じtransport・フラグ構成を使うべき理由」をこの障害シナリオを根拠に説明。
自己チェック
①StreamableHTTPでclientがツール呼び出しのPOSTとは別に長寿命GETを送るのはなぜか。②水平スケーリング目的で stateless_http=true にするトレードオフは?
①HTTPではserverからclientへリクエストを開始できない(serverはclientのアドレスを知らない)。しかしMCPにはsampling(create message request)や通知などserver起点のメッセージがある。そこでclientが先にGETを送りSSE応答として開きっぱなしの経路を確保し、serverはいつでもそこへメッセージを流せる——これが回避策の核心(call tool用の短命SSEとは役割が別)。②ロードバランサー配下ではGET SSEを張ったインスタンスとPOSTを受けるインスタンスが別マシンになりえて、samplingにインスタンス間中継が必要になる。stateless化はsession IDをやめてこの問題ごと消す。得るもの: どのインスタンスでも同等処理・初期化往復の省略。失うもの: 長寿命GET SSEのserver→client経路(教材のSDK実装では sampling・progress/log通知・リソース購読が不可になる)。ただし「statelessなら必ず不可能」と断定しないこと——SDK実装依存で、仕様上は POST の SSE 応答でも server→client メッセージを流せる(採点観点: 実装依存である点まで言及できれば満点、断定止まりは減点1)。判断基準は「失う機能に依存しないserverか」。
キャップストーン増分 — ドキュメント調査アシスタント【第5形態】
ここまでに育てたアシスタント(構造化出力CLI → evalハーネス → tool呼び出し。L3B 修了済みなら RAG+caching も)をMCPサーバー化し、汎用clientから使えるようにする。L4 の必須前提は L3A のみなので、実技は2段構成: 基本(L3A 成果物のみで完結)と L3B 修了済みの場合の追加。足場なし・5段階と提出物4点は共通ルールどおり。
- tools: 基本: L3A のツール群(一覧・読み取り。例:
list_docs、read_doc、summarize_doc)を@mcp.toolで公開。L3B 修了済みの場合: RAG 検索 tool(search_docs)も MCP 化して加える(未修了なら省略し、後から L3B を修了した時点で追加すればよい——ゲート再受験は不要)。descriptionはL3Aの設計基準で書き直す。 - resources: 収録ドキュメント一覧(direct・
application/json)と個別内容(templated・text/plain)。 - prompts: L2のevalで採点済みの調査プロンプト(例
/deep-research <トピック>)を1本以上。 - 検証: Inspectorで3プリミティブすべてを手動検証した記録(スクリーンショットまたはログ)。
- 接続: STDIOで Claude Code(
claude mcp addで登録)または Claude Desktop(設定ファイルにserver追加)へ接続し、実際の調査タスクを1件完遂(登録手順は変わりやすいので公式ドキュメントで最新を確認)。 - 敵対テスト: 4.2の異常入力+(ファイルアクセスがあるなら)4.6のパス検査テストを自serverに実施。
- 設計判断メモ: (a) 各機能のプリミティブ選定理由(4.5のマトリクス)、(b) transport選定(STDIOで足りる理由と、リモート公開時に何を変えるか——session・フラグ・sampling依存)、(c) 秘密情報の所在(Claude APIキーをclient/serverどちらに置いたか、なぜか)。
低コスト版: Claude API呼び出しを伴うツールは記録済みレスポンスのfixtureで代替可。Inspector検証は費用ゼロで全項目可能。
修了ゲート(L4)
共通運用(README.md)どおり: 知識確認20% / 実技60% / 設計判断の説明20%、総合80%以上。実技はルーブリック5観点(機能/堅牢性/安全性/評価/説明)×0〜3点。知識確認は類題2〜3種。修了1〜2週間後に遅延チェック。
- 知識確認: 各モジュール自己チェックの類題(「どれを選ぶか・なぜ棄却するか・何が壊れるか」形式)。例: 「本番デプロイ後にsamplingだけ失敗する」ログから原因のフラグ設定を特定させる。
- 実技: キャップストーン第5形態で採点。3プリミティブ+Inspector検証+実clientからの接続実績、敵対テストの記録(発見ゼロでも「何を試したか」が残っていること)。
- 説明: プリミティブ選定を棄却案込みで、transport・フラグ選定をserver→clientメッセージの観点で、それぞれ口頭説明できること。
実技ルーブリック(5観点 × 0〜3点)
| 観点 | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 機能 | serverが起動しない | tools のみ | 3プリミティブすべて実装 | 左+実client(Claude Code / Desktop)から調査タスク完遂 |
| 堅牢性 | 異常入力でクラッシュ | 正常系のみ | 回復可能なエラーメッセージを返す | 左+敵対テスト(異常入力・パス検査)の記録 |
| 安全性 | 秘密情報をコードに直書き | 資格情報の所在の説明なし | 資格情報の所在と最小権限を設計 | 左+信頼境界(tool poisoning 等)への対策まで説明 |
| 評価 | 検証なし | 一部ツールの手動確認のみ | Inspector で3プリミティブを検証した記録 | 左+schema のトークンコスト等の測定 |
| 説明 | メモなし | 実装の羅列 | プリミティブ選定理由を記述 | 左+transport・フラグ選定を棄却案込みで記述 |
安全必須問題(配点と独立に全問正解。詳細は safety-security.md)
安全1(MCP serverの信頼境界): 社外製の便利そうなMCP serverを見つけた。自分の環境(ファイル・認証情報・社内データに届くclient)に接続してよいか判断する基準を挙げよ。
MCP serverは信頼境界の内側に招き入れるコード。基準の例: ①提供元(サービス公式か無名の第三者か)とソースの監査可能性。②要求するツール・アクセス範囲が目的に対し最小か(読み取り用途に書き込み系ツールが混ざっていないか)。③tool result・resource経由で指示文が流入する経路(prompt injection)になるため、serverの返すデータを信頼しない前提でclient側権限を絞れるか。④接続後もツール定義は変わりうるので更新の監視・バージョン固定ができるか。「便利そう」は基準にならず、最悪ケース(serverが悪意を持ったら何ができるか)で評価する。
安全2(token passthrough / tool poisoning): MCP の代表的な攻撃・アンチパターンである token passthrough と tool poisoning をそれぞれ説明し、どの設計原則で防ぐか述べよ。
Token passthrough = serverが「自分宛てに発行されたのではないトークン」を検証せず下流APIへそのまま転送するアンチパターン。下流側の認可・監査・レート制御を素通りさせるため、serverは自分宛てのトークンだけを受け入れ、下流アクセスは自分の資格情報(最小スコープ)で行う。Tool poisoning = toolのdescriptionはモデルに読まれるため、そこに指示文(インジェクション)を仕込めば接続先の会話・行動を操作しうる攻撃。接続時にtool定義をレビューし、バージョン固定と定義変化の検知(rug pull対策)を併用する(safety-security.md S.5)。
安全3(資格情報の最小権限): あなたのserverは外部サービスのAPIトークンを使う。権限設計と置き場所の原則を述べよ。
①最小権限: ツールが実際に行う操作に必要なスコープだけのトークンを発行(read系ツールしかないserverにwrite権限を渡さない)。②所在の分離: LLMのAPIキーはsamplingでclient側に置けばserverには不要(4.6)。外部トークンは環境変数・シークレット管理に置き、コード・リポジトリ・description・ログに載せない。③露出面の想定: tool resultやログ通知に混入するとモデルのコンテキスト(=会話ログ)へ漏れる。エラーメッセージに秘密が含まれないことを敵対テストで確認。④漏えい時に失効・ローテーションできる形で発行する。
安全4(rootsの強制力・S.5 の補足): 「rootsを設定したのでこのserverは安全」というレビューコメントへの正しい指摘は?
rootsは許可範囲の伝達であり強制ではない。SDKは自動ブロックしないので、パス検査(root内か・../ やsymlinkで抜けられないか)の実装をコードで確認しない限り「安全」とは言えない(4.6参照)。
部分合格方式: 不合格項目のみ補習して再受験する(合格済み項目は保持。共通運用は README.md 参照)。
力量マップ・CCA接続
- 力量マップ: C. ツール設計・MCP統合 の3項目(server/client実装・高度トピック・ツールスキーマ設計)。数値更新は証拠リンク必須——段階2 = 演習4.2〜4.4の提出物、段階3 = キャップストーン第5形態を要件のみで自走した成果物、段階4 = 修了ゲートの設計判断説明(transport選定・棄却案比較)+他者への解説記録。
- CCA副線(ドメイン②): cca-prep.md のドメイン②設問(2-1〜2-3)を修了後に再受験し、学習前診断との差分をログへ記録。CCAの形式・重みは暫定情報のため修了基準には使わない(DESIGN.md)。
- 次へ: L5(Claude Code) でMCP連携を利用者側から運用する。L6設計パートはL4修了を推奨前提とする。
最終確認日: 2026-07-11 — 変わりやすい項目: Inspector のUI・ポート、Python SDK のAPI表面(デコレータ・フラグ名)、Claude Code / Claude Desktop へのserver登録手順、StreamableHTTP仕様。原理(3プリミティブと制御主体・メッセージ方向とtransport制約・信頼境界)は安定しているため、鮮度切れ時は事実部分のみ公式ドキュメントで更新する。