Skip to content

MCPの基礎と実装

Model Context Protocol(MCP)は、LLMアプリケーションが外部のデータや機能へ安全に接続するための、共通の通信仕様である。MCPにより、個別API連携のたびに接続方式や権限管理を作り直す負担を減らし、同じ枠組みで多様なツール・データ源を扱えるようになる。

参考ドキュメント

1. MCPが解決する問題

LLMを実務や研究で使うとき、学習済み知識だけでは不足し、実データ(社内文書、実験ログ、計算結果、DB)や実行機能(検索、計算、ファイル操作、ジョブ投入など)に接続したくなる。ところが従来は、接続先ごとにAPI仕様が違い、認証方式も異なり、データ形式やエラー表現もばらばらで、統合のコストが高くなりがちである。

この状況は、モデル側の数を N、接続先の数を M とすると、組合せ的に統合点が増える問題として捉えられる。単純化すると、個別実装の総量が

CN×M

に近い形で増え、保守やセキュリティレビューも同様に膨らむ。MCPは、LLMアプリケーションと外部接続の間に共通のやりとりを定義し、少なくとも「接続の形」を揃えることで、この増え方を抑える方向へ寄せる仕様である。

また、LLM連携では「データを読ませる」だけでなく、「何を読ませ、何を実行させるか」をユーザーが理解し、同意し、制御できることが重要になる。MCPは、機能公開(Toolsなど)と権限制御(Authorizationなど)を、通信仕様として分離して扱いやすくすることに焦点がある。

2. 用語

2.1 LLM

LLM(Large Language Model)は、テキストや構造化情報を入力として、次トークン確率 p(xtx<t) をもとに出力を生成するモデルである。会話では生成結果だけが見えるが、内部的には

x^1:T=argmaxx1:Tt=1Tp(xtx<t)

のような逐次生成に基づく。

MCPはLLMそのものの学習法ではなく、LLMアプリケーションが外部と接続するときの通信と機能の表現を扱う仕様である。したがって、同じLLMでも、接続するアプリケーションがMCPを実装していれば、外部連携の形を揃えられる。

2.2 Host

HostはLLMを内包するアプリケーションであり、ユーザー体験(UI/UX)と、安全な実行の最終責任を持つ側である。具体的には、IDE、チャットアプリ、実験ノート統合ツールなどがHostになりうる。

Hostは、外部のMCP Serverに対して接続を開始し、ユーザーの同意や権限を管理し、必要ならばサーバからの依頼(SamplingやElicitation)をユーザーへ提示する。MCPでは、Hostがすべての操作を自動化する前提ではなく、同意と制御を設計に含めることが求められる。

2.3 Client

ClientはHostの内部で、MCPの通信を担当する接続子である。Hostが複数のServerへ接続する場合、ServerごとにClient相当の部品が存在することがある。

Clientは、通信路(stdioやHTTP)を確立し、能力交渉を行い、Serverが公開するTools/Resources/Promptsを列挙・呼び出しする。さらにClient側の機能として、Sampling、Roots、Elicitationなどを提供する場合がある。

2.4 Server

Serverは、外部のデータや機能をMCPの形で公開する側である。たとえば、材料DB、装置ログ、計算機クラスタのジョブ管理、ファイルリポジトリなどがServerとして実装されうる。

Serverの責務は、公開する機能を定義し、入力を検証し、結果を返すことである。とくに、外部へ副作用のある操作(削除、送信、課金など)を含む場合、Host側の同意や権限付与と整合する形で設計される必要がある。

3. MCPの機能

MCPの仕様は大きく、Serverが提供する機能と、Clientが提供する機能に分かれる。ここでは、実装で混乱しやすい差を、情報の流れとして整理する。

3.1 Tools

Toolsは、LLMが呼び出せる関数としてServerが提供する機能である。入力はスキーマにより制約され、出力も一定の形で返されることが想定される。

Tool呼び出しは、抽象的には写像

f:XY

として捉えられるが、現実には副作用を持ちうるため、状態 s を含めた

f:X×SY×S

として設計する方が安全である。副作用がある場合は、Hostがユーザーに理解可能な説明を提示できるよう、Toolの説明や権限スコープを丁寧に設計することが重要になる。

3.2 Resources

Resourcesは、Serverが保有するデータを、参照可能な形で公開する仕組みである。ファイル、DBスキーマ、計測データ、ドキュメントなどを、URIで識別して提供することが多い。

Resourceアクセスは、関数というより「読み出し」に近く、概念的には

r:URIContent

である。Resourcesを設計するときは、URI設計、アクセス範囲、ページング、キャッシュ方針が重要になる。特に大きなデータを一度に返すと、LLMへ渡せるコンテキスト長の制約にぶつかりやすく、分割や要約をどこで行うかの設計が必要である。

3.3 Prompts

Promptsは、会話や作業を進めるためのテンプレートとしてServerが提供する仕組みである。ユーザーに対して定型の入力を促す形式や、作業手順に沿ったメッセージ列を用意する形で活用される。

Promptは「LLMに与える入力を整える」機能であり、Toolのように外部へ作用するとは限らない。ただし、PromptがTool呼び出しを促す構造を含むと、結果として副作用へつながるため、Host側で提示の仕方を慎重に扱う必要がある。

3.4 Sampling

Samplingは、ServerがClientを介してLLMに推論を依頼する仕組みである。Serverが自前でLLM APIキーを持たずとも、Hostが持つLLM実行環境を利用できる設計になる。

このとき重要なのは、ServerがLLMへ投げる入力を完全に自由にできると危険である点である。仕様では、ユーザーがSamplingを承認し、送信内容や可視範囲を制御できることが重視される。抽象的には、Serverが要求する推論を q、Hostが許可する推論を q とすると、

q=Π(q)

のように、Host側の射影 Π により制限されたものだけが実行されるべきである。

3.5 Roots

Rootsは、ClientがServerに対して「アクセス可能な境界」を提示する仕組みである。ファイルシステムやURI空間において、Serverが操作できる範囲を明示し、越境を防ぐための枠になる。

境界を集合 R とし、Serverが要求する対象を u とすると、許可条件は

uR

の形で表される。実際には、パス正規化やシンボリックリンク、相対参照などで条件が崩れやすいため、Host側で正規化後の判定を行う設計が重要になる。

3.6 Elicitation

Elicitationは、Serverが追加情報をユーザーから得るために、Clientを介して入力収集を依頼する仕組みである。フォーム入力のような形だけでなく、仕様の更新でURLを使う形も扱われるようになっている。

Elicitationは、ユーザーごとの状態をServerが保持する必要が生じやすい。ユーザー集合を U、サーバ状態を S とすると、状態更新は

δ:S×U×InputS

の形で表せる。複数ユーザーを扱う環境では、状態の取り違えが直ちに情報漏えいに直結するため、識別子の扱いとセッション管理が重要になる。

4. 通信とセッション

4.1 メッセージモデル

MCPは、JSON-RPC 2.0の枠組みでメッセージをやりとりする仕様である。実装の理解では、個々のメッセージを「呼び出し名」と「引数」と「相関ID」を持つ要素として捉えるとよい。

抽象化すると、要求メッセージは

mreq=(id,method,params)

応答メッセージは

mres=(id,result)または(id,error)

である。ここで id は要求と応答の対応付けに使われ、並行処理や再送の扱いに関わる。

4.2 状態を持つ接続

MCPは接続が状態を持つことを前提にし、初期化時に能力交渉を行う。能力交渉は、Clientが提供できる機能集合 C とServerが提供できる機能集合 S の共通部分を取り、

F=CS

として、実際に使う機能を決める操作とみなせる。

能力交渉を明示する利点は、相互運用性が上がる点である。片方が未対応の機能を無理に呼び出さずに済み、段階的な導入がしやすくなる。

4.3 エラーと回復

外部連携では失敗が前提であり、エラーを「仕様レベルの不整合」と「入力が不適切」と「外部が落ちている」に分けて扱うと実装が整理される。特に、入力検証エラーを適切に返すことは、LLMが自己修正する上で重要である。

形式的には、入力 x に対して検証関数 v(x){0,1} を定義し、v(x)=0 の場合に説明可能なエラーを返す設計が望ましい。LLMは確率的に誤った入力を作るため、検証が薄いほど危険な呼び出しが起きやすい。

5. Transports

MCPは複数の通信路を定義し、環境に応じて選べるようにしている。実装では、同じ論理メッセージをどのように運ぶかだけが違う、と整理すると理解しやすい。

5.1 stdio

stdioは、標準入力・標準出力を用いてメッセージを送受信する方式である。ローカルプロセスとしてServerを起動し、Hostがそのプロセスと通信する形になりやすい。

この方式はネットワーク露出が小さく、ローカル統合に向く。一方で、プロセス起動、環境変数による資格情報の受け渡し、ログ出力の扱いなど、OS境界の設計が重要になる。

5.2 Streamable HTTP

Streamable HTTPは、HTTP上で双方向に近い通信を実現するための方式である。クライアントからサーバへはHTTPリクエストで送信し、サーバからクライアントへはストリーム(SSEを含む)を用いて通知する形が採られる。

ストリーミングが必要になる理由は、結果が逐次届く、進捗を伝える、長時間処理を中断する、といった要求があるためである。時間 t に対して部分結果 y(t) が増分的に得られるとき、最終結果を待つ方式は遅延が

ΔwaitTfinish

に近づくが、逐次通知では、ユーザーが意味ある情報を得るまでの遅延が

ΔstreamTfirst_chunk

まで下がりうる。体感品質の差はこの Tfirst_chunk に強く依存する。

Streamable HTTPは認可仕様と結びつくため、Origin検証、トークン管理、スコープの設計が実装上の中心課題になる。

6. Authorization

HTTP系のTransportでは、MCPはOAuth 2.1に基づく認可の枠組みを持つ。ここで重要なのは、認証(誰か)と認可(何をしてよいか)が分離される点である。

6.1 認可の抽象モデル

ユーザーを u、クライアントを c、サーバを s、資源を r、操作を a とし、認可判定を

Allow(u,c,s,r,a){0,1}

で表す。実装では、この判定がアクセストークンとスコープにより代替される。

スコープ集合を Σ とし、要求が必要とするスコープを σneedΣ、付与されたスコープを σgrantΣ とすれば、必要条件は

σneedσgrant

である。副作用の大きいToolや機微データResourceでは、σneed を細かく分割し、最小権限に寄せる設計が重要になる。

6.2 PKCE

PKCEは、認可コードの横取りに対する防御として用いられる。抽象的には、クライアントが秘密 v を持ち、そこからチャレンジ c を導出し、後で v を提示して整合性を証明する。

ハッシュ関数 H を用いて

c=H(v)

としておき、トークン交換時に v を提示することで、サーバ側が H(v)=c を確認できる。これにより、途中で認可コードが漏れても、v を知らない第三者はトークン交換が困難になる。

6.3 同意と段階的スコープ

認可は一度決めたら終わりではなく、必要に応じてスコープを追加する場面がある。スコープ同意を段階化するとき、ユーザー負担を減らしつつ、権限の過大付与を避けられる。

段階化は、時刻 t における付与スコープ σgrant(t) を単調増加として扱い、

σgrant(t1)σgrant(t2)(t1<t2)

の形で拡張する設計に対応する。拡張のたびにユーザー同意が必要であり、Host側UI設計と一体で考える必要がある。

7. Security Best Practicesを理解する

MCPでは、Tool実行やResource参照が強力であるため、攻撃面が広がる。特に、外部データ中に混入した指示がLLMの判断を乗っ取る形や、権限境界を越えたアクセスの誘発が問題になりやすい。

7.1 信頼境界

Host、Client、Server、ユーザーの間には、それぞれ信頼できる範囲とできない範囲がある。Serverが返す説明文やメタデータが安全とは限らず、Hostはそれを無条件に信用しない設計が求められる。

この点は、形式的には「入力を信頼しない」原則に近い。Serverから来るすべての文字列やパラメータを z とし、Hostが内部的に利用する前に正規化・検証写像 Φ を通すとすると、

z=Φ(z)

を徹底することが、安全性の基本になる。

7.2 ユーザー同意

仕様上、ユーザーがデータ共有とTool実行を把握し、止められる設計が重視される。自動化を強くすると便利になる一方で、誤実行の影響が増えるため、同意粒度をどこに置くかが重要になる。

同意を、操作 a ごとに与える方式は安全側であるが煩雑になりうる。逆に、広い権限を一度に与える方式は簡便だが危険側に寄る。実装では、操作の危険度を d(a) とし、同意を要求する閾値 θ を置き、

d(a)θ同意が必要

のように層を作る考え方が有効である。

7.3 入力検証と最小権限

Tool入力に対し、型、範囲、列挙値、長さ制限を設け、意味的に不正な要求を拒否する必要がある。LLMは自然言語から入力を生成するため、機械的な境界条件を破りやすい。

また、ResourcesとToolsを分けて考え、読み取り専用の操作と、状態変更操作を分離するのがよい。状態変更操作は、監査ログ、レート制限、段階同意、再確認など、追加の保護と合わせて設計されるべきである。

8. Utilities

MCPには、Tools/Resources/Prompts以外にも、通信を現実的にするための補助機能がある。実装では、これらが揃って初めて「長い処理」「止めたい処理」「進捗を見たい処理」を扱える。

8.1 Logging

ログは、障害解析と監査に必要である。stdioではstderrを利用でき、HTTPでは別のログ基盤と統合されることが多い。

ログの設計では、個人情報や秘密情報を含めないこと、識別子で追跡可能にすること、粒度を調整できることが重要である。たとえば、呼び出し相関IDを id とし、ログ行を (t,id,,msg) として残すと、並行処理でも追跡しやすい。

8.2 Progress

進捗通知は、長時間処理でUIを固めないために重要である。進捗を p[0,1] として数値化できる処理では、時間 t の関数 p(t) として扱える。

ただし、p(t) を過度に信用すると、見かけの進捗だけが増える実装になりやすい。進捗は、処理の段階(フェーズ)と併記し、段階集合 K を用いて (k,p) を返す設計が理解しやすい。

8.3 Cancellation

キャンセルは、ユーザーが誤った操作をしたときや、不要になったときに、計算資源とリスクを抑えるために必要である。キャンセル可能性は、処理を中断できる点に依存し、状態 s と入力 x の処理が可逆でない場合は注意が必要である。

形式的には、処理を st+1=δ(st,x) とする逐次更新として、キャンセルはある時刻 tc 以降の更新を停止する操作である。停止だけで副作用が残る場合は、ロールバック設計が別途必要になる。

8.4 Tasks

Tasksは、長時間処理や非同期処理を追跡するための仕組みである。仕様上は耐久的な状態機械として扱われ、要求側がポーリングしたり、後で結果を取得できるようにする。

タスクを状態機械として

T=(S,s0,δ,F)

とみなし、s0 が初期状態、δ が遷移、F が終端状態集合である。タスクIDは、要求と状態の対応付けに使われ、結果取得や進捗取得のキーになる。

Tasksが重要になるのは、HTTP接続が途中で切れることを前提にできる点である。処理自体は続き、要求側は後からタスクIDで追跡できるため、ネットワークに弱い環境でも扱いやすくなる。

9. 実装

ここでは、特定言語のコードを示さずに、実装で必要な設計判断を、作業の粒度で説明する。

9.1 Server側の設計

最初に決めるべきは、何をToolsとして公開し、何をResourcesとして公開し、何をPromptsとして用意するかである。Toolsは副作用を持ちうるため、実装だけでなく権限と同意の設計が不可欠になる。

ResourcesはURI空間を設計し、一覧取得、詳細取得、ページング、フィルタリングの方針を整える必要がある。材料分野では、試料ID、測定条件、計算条件などで検索が多様化しやすく、URIだけで表現しきれない場合はToolsとして検索APIを用意する設計が自然である。

Promptsは、ユーザー入力のブレを抑えたい箇所に向く。たとえば、測定依頼、解析条件の確認、レポート生成などで、必要項目を埋める形式を作ると安定する。

9.2 Toolスキーマの設計

Tool入力は、型と範囲を厳密にし、許容しない入力を早期に拒否する方が安全である。入力空間 X を広く取りすぎると、LLMが想定外の値を生成し、外部系へ危険な作用を及ぼす可能性が上がる。

逆に、厳しすぎるとLLMが呼び出せず、価値が出ない。したがって、実装では、必要最小のパラメータ集合 P を定め、デフォルト値 p0 を用意し、入力が部分的でも動く設計が有効である。形式的には

x={pi}iI(IP)

の部分入力を許容し、欠落分を補う関数 Γ により

x~=Γ(x)

としてから実行する。

9.3 ClientとHost側の設計

Hostは、どのServerへ接続するかをユーザーが把握できるUIを持つべきである。Serverが増えるほど、データがどこへ流れ、どのToolが呼ばれたかが不明確になりやすい。

SamplingやElicitationを有効にする場合、ユーザーの確認画面が重要になる。送信されるプロンプトの一部が秘密情報を含む可能性があるため、送信内容の編集や、Serverへ返す情報の制限をHost側で提供できる設計が望ましい。

Rootsを用いる場合、ユーザーが境界を設定でき、後から変更できることが重要になる。境界の誤設定は情報漏えいに直結するため、境界が何を意味するかをUIで明確に示す必要がある。

9.4 認可の実装方針

HTTP Transportで認可を扱う場合、OAuth 2.1とPKCEを中心に設計する。認可の実装は、ユーザー体験とセキュリティの両方を左右するため、スコープ設計と同意の粒度が重要である。

また、Serverが扱うデータの所有者が誰かを明確にし、ユーザー単位でのアクセス境界を設計する必要がある。ユーザー u ごとに分離された資源集合 Ru を定めると、越境防止条件は

rRu

として表現できる。実装では、識別子の扱いとセッションの結び付けがこの条件の実体になる。

10. テストとデバッグ

MCPは複数の機能が絡むため、段階的に確認するのが重要である。まず、Tools/Resources/Promptsの列挙と単発呼び出しが成立するかを確認し、その後にStreaming、Cancellation、Tasks、Authorizationへ進めると原因切り分けが容易になる。

公式のMCP Inspectorは、Serverの動作確認とデバッグに用いられる。Inspectorにより、メソッド呼び出し、応答、ログ、スキーマの見え方を対話的に確認でき、Host実装に依存しない切り分けができる。

さらに、認可を含む場合は、トークン失効、スコープ不足、Origin不正などの失敗系を必ず確認する。成功系だけでは運用時の問題が再現できず、障害対応が難しくなる。

11. 材料科学での利用像

材料科学では、データ源が多様であり、計算(DFT、MD、FEM)、計測(XRD、XAFS、磁気計測)、文献、試料管理が分断されやすい。MCP Serverを各データ源の前段に置けば、Hostから統一的にTools/Resourcesへアクセスでき、作業の分断を減らしやすい。

たとえば、計算ジョブ投入、結果収集、解析、レポート生成を、ToolとResourceに分割して設計できる。ジョブ投入は副作用を持つためToolsとして扱い、出力ファイルや解析結果はResourcesとして参照させると、権限設計と監査が整理しやすい。

また、同じ試料に対して、別手法で得られた観測(スペクトル、顕微鏡画像、磁化曲線)を統合する場合、Resourcesにメタデータを付け、検索・集約をToolで提供する形が取りやすい。LLMは自然言語で探索し、必要なResourceを読み、Toolで処理を進めるという役割分担が成立する。

12. バージョンと仕様の変化

MCPは仕様改訂が続いており、実装では「どの版に準拠するか」を明示する必要がある。2025-03-26ではTransport周辺の整理が進み、Streamable HTTPが定義され、過去の方式から置換されている。

2025-06-18では、Client側機能(Roots、Sampling、Elicitation)やサーバ機能の整理が進み、相互運用性が高められている。2025-11-25では、認可サーバ発見や段階的同意、Elicitationの拡張、Tasksの試験的導入などが加わっている。

実装では、能力交渉により未対応機能を避けられるが、TransportやAuthorizationのように根本が変わる点は互換性に影響する。したがって、Server公開時に仕様版を固定し、Host側が複数版に対応するか、更新時に移行手順を用意する設計が必要になる。

まとめと展望

MCPは、LLMアプリケーションと外部データ・外部機能の接続を共通化し、Tools/Resources/Promptsと、Sampling/Roots/Elicitationを明確に分けて設計できる仕様である。実装では、TransportとAuthorizationの選定、入力検証、最小権限、ユーザー同意を軸に、強力な連携を安全に扱うことが要点である。

今後は、Tasksのような長時間処理の扱い、認可の拡張、運用に耐える水平スケールの議論が進むことで、より大規模な統合へ広がっていくと考えられる。材料科学のようにデータと計算が分散しやすい分野では、MCPにより統合の再利用性が上がり、研究開発の反復速度を押し上げる余地が大きい。