スタンフォード大学の講義 CS146S(The Modern Software Developer)の資料を読みながら、AIと壁打ちして MCP を理解した。その過程で自分が何を勘違いしていたかを残しておく。
最初に引っかかったこと
LLM が持つ世界知識は、学習した時点で止まっている。完全に自律して動くシステムを作るなら、新しいデータをリアルタイムに渡す仕組みがいる。MCP(Model Context Protocol)は、そのための共通の作法だ。すごく雑に言うと、LLM にツールを見せるときの標準フォーマットである。
MCP がなければ、AI アプリごと、ツールごとにコネクタを書くことになる。アプリが M 個、ツールが N 個なら M×N 通りだ。MCP を挟むと、ツール側が Server を1つ、アプリ側が Client を1つ用意すれば済み、M+N に減る。認証、エラー処理、レート制限を毎回作り直さなくていいのも大きい。
登場人物は3つ
Host(ホスト)は Cursor や Claude Desktop のような、ユーザーが触るアプリ。Client はその中に組み込まれた通信用のライブラリで、MCP Server は個々のツールの前に置かれる薄いラッパーにあたる。
自分は最初、Agent と MCP Client を同じものとして考えていた。Agent 全体の中で、Server と話す部分を担当するのが Client、と分けて捉えたほうが後の話が追いやすい。
MCPのやり取りの流れ
「Jack から来たメールを要約して」と頼む場面で追ってみる。
- Client が MCP Server に「どんなツールがある?」と聞く。Server は、ツール名、用途、引数を JSON Schema(データ構造の定義)で書いた説明書を返す。これは通常、セッションの初期化時に済んでいる。
- ユーザーが Host に質問する。
- Client は、質問とツールの説明書をまとめて LLM に渡す。LLM は説明書を読み、
search_emails(from="Jack")を呼ぶと決めて、Tool Call(ツール呼び出し)を構造化データで出力する。 - Client がその Tool Call を受け取り、MCP Server に実行を依頼する。Server は裏で Gmail API を叩き、結果を返す。
- Client が結果を LLM に渡し、LLM が人間向けの文章に整えて回答する。
ここで押さえておきたいのは、LLM は「何をどんな引数で呼ぶか」を決めるだけで、自分ではネットワークに出ていかないという点だ。実際に手を動かすのは Client になる。LLM が頭脳、Client が手足と考えるとイメージしやすい。
ハマった3つの勘違い
実際に自分が間違えたところを3つ挙げる。
1つ目は、MCP Server がユーザーの依頼を見て、使うべき API を自分で探すと思っていたこと。Server は受け身のツール置き場で、判断はしない。どのツールを選び、どんな引数を渡すかを決めるのは LLM だ。
2つ目は、 tools/list を「ユーザーが入れている MCP の一覧を取る操作」だと思っていたこと。これは特定の Server に「あなたはどんなツールを持っている?」と聞く操作で、どの Server をつなぐかは Host の設定が決める。
3つ目は、ユーザーが質問する前に、Client が LLM へ Tool Call を投げているのだと思っていたこと。Tool Call を出せるのは LLM だけで、質問前に Client がやっているのは、ツール一覧を取って Prompt の材料を用意するところまでだ。
MCPとAPIは何が違うのか
| API | MCP | |
|---|---|---|
| 使う側 | 開発者、従来のプログラム | LLM、Agent |
| やり取りする中身 | データそのもの(HTTP のリクエストとレスポンス) | ツールの意味づけと、呼び出し方の標準形式 |
| 呼ぶタイミングを決めるのは | コードを書いた人 | LLM が文脈から判断する |
| 位置づけ | 一番下のサービス接続口 | LLM と下位サービスの間の中間層 |
MCP Server は多くの場合、裏で API を呼ぶ。だから MCP は「API を LLM 向けに包んだもの」と見ておけばだいたい合っている。ただ「多くの場合」であって、ローカルのファイルやデータベースを直接触る Server もあるので、必ず API が裏にあるとは言えない。
ツールが増えたときの設計
講義では、MCP Server の設計について2つの方向性が出ていた。
1. 操作ではなく結果でツールを作る
REST API をそのままツールに分解しない。たとえば送金なら、 get_users → list_account → send_payment と3つに分けて Agent に組み立てさせるより、 send_payment(user_email) を1つ用意したほうが Agent は迷わない。引数にネストした辞書を使わないこと、docstring やエラーメッセージを LLM が読む前提で書くこと、ツール名にサービス名の接頭辞をつけること、も挙がっていた。
2. 検索と実行を分ける
Server が大量に増えると、全ツールの説明書を最初から Prompt に入れるのは重すぎる。そこで LLM に見せるツールを search と execute の2つだけにする。LLM はまず search で必要なツールを探し、それから execute で実行する。講義では、これで Token が90%以上減り、Server の数にも依存しなくなると説明されていた。
違いは説明書を見せるタイミングにある。全部を最初に見せるか、薄い目次だけ見せて必要なときに中身を引くか。後者が「必要になってから読み込む」考え方だ。
SkillsはMCPの上に何を足すのか
資料では Agent Skills を、特定の領域向けに、コードと Prompt をセットにして、必要なときに読み込む標準的な能力のまとまり、と説明していた。使いどころは文書作成、PowerPoint 作成、データ分析など。
Figma で考えると分かりやすい。Figma の MCP だけあっても、Agent は create_frame のようなツールがあることを知っているだけで、Web ページ設計の作法までは知らない。位置のずれた四角形が並ぶだけの画面になりかねない。そこに figma-web-design という Skill を足す。1440px のルートフレームを作り、色や文字のルールを決め、Header、Hero、Feature Grid、Footer の順に組み、Auto Layout を有効にする、といった手順を書いておく。
自分の理解はこうなった。MCP は「そのツールを使えるか」を決め、Skills は「そのツールをうまく使えるか」を決める。
ただし、Skill が MCP に必ず依存するわけではない。Skill は自分でスクリプトを持てるので、Figma の REST API を直接呼ぶ作りもありえる。MCP は標準化されたツールの通り道、Skill は進め方の知識を担当し、組み合わせたときに一番よく働く、くらいの言い方が正確だ。
最後に、3つを並べておく。
| 何か | 誰が使うか | 主な用途 | |
|---|---|---|---|
| API | アプリが外に公開する HTTP、REST、GraphQL の接続口 | 開発者、SDK | 認証、リトライ、ページング、入力検証を開発者が自分で制御する |
| MCP | サーバー側が公開するツール定義。LLM が標準的な形式で呼ぶ | モデル、Agent の実行環境(Tool Call として) | Agent が外部のデータやサービスとやり取りする |
| Skills | 動的に読み込む再利用可能なタスクのまとまり(コードと Prompt) | Agent、Agent のフレームワーク | 文書作成、PPT 作成、データ分析などの作業手順の抽象化 |
参考
CS146S The Modern Software Developer https://themodernsoftware.dev/