MCPサーバーでコンテキスト消費が爆発する問題と、CLI/REST APIとの賢い使い分け
はじめに
Anthropicが発表したModel Context Protocol(MCP)は、AIモデルと外部のツールやデータソースを標準化された規格で接続するプロトコルとして、爆発的な注目を集めています。GitHub、Slack、PostgreSQL、ブラウザ自動化など、あらゆるサービスがMCPサーバーとして公開され、「エージェントにあらゆるツールを繋ぎ込む」ことが急速に容易になりました。
しかし、個人開発のPoC(概念実証)を終えて実務で本格的にMCPを運用し始めたエンジニアたちの間で、いま深刻な悲鳴が上がっています。
「MCPサーバーを5つ繋いだだけで、何も質問していないのに毎ターン数万トークンが消える」
「ブラウザツールやAPIの生レスポンスがコンテキストを一瞬で埋め尽くし、モデルが迷走する」
海外のHacker Newsでも「MCPは本当に必要なのか」「単なる過剰設計(fad)ではないか」という議論が巻き起こっています。その根本にあるのは、MCPの利便性と引き換えに発生する「コンテキスト消費の爆発」というアーキテクチャ上の課題です。
この記事では、なぜMCPサーバーを使うとコンテキストが急速に枯渇するのか、その構造的な原因を解き明かします。そのうえで、従来のUnix CLIやREST APIとの賢い使い分け、およびトークン消費を最大98%削減する最新の設計プラクティスを解説します。
MCPでコンテキストが爆発する2大要因
MCPサーバーを導入したシステムでトークン消費が跳ね上がる背景には、明確な2つの要因が存在します。
1. ツール定義(JSON Schema)自体の常時オーバーヘッド
MCPクライアント(Claude DesktopやCursor、Claude Code等)は、接続されているMCPサーバーから tools/list を呼び出して利用可能なツール一覧を取得します。
問題は、取得された全ツールの詳細な定義が、ユーザーとの対話の「毎ターン」にプロンプトのコンテキスト(Tool定義領域やシステムプロンプト)へ自動的に注入される点にあります。各ツールの名前だけでなく、説明文や全引数の型定義、バリデーションルールを含む長大なJSON Schemaが常時展開されます。
[プロンプト構造]
┌──────────────────────────────────────────────┐
│ システムプロンプト + 会話履歴 │
├──────────────────────────────────────────────┤
│ ツール定義(GitHub, Slack, DB, etc. の全Schema) │ ← 毎ターン1万〜3万トークン消費
├──────────────────────────────────────────────┤
│ ユーザー入力: 「今日のタスクを確認して」 │
└──────────────────────────────────────────────┘
便利なツールを次々と追加してツールの総数が20〜30個に達すると、ユーザーが一行質問しただけで、入力トークンは数万トークンに達します。
典型的な例が公式のGitHub MCPサーバーです。リポジトリ操作、Issue、プルリクエスト、コミット検索など多機能なツールが20個以上定義されており、このサーバーを1つ有効化するだけで、毎回約8,000〜12,000トークンがツール定義だけで消費されます。SlackやPostgreSQLなど複数のサーバーを併用すれば、質問する前からコンテキストの数割が埋まることになります。
「Prompt Caching(プロンプトキャッシュ)があるから費用は抑えられるのでは?」と考える方もいるかもしれません。しかし、キャッシュでAPI単価が割引されたとしても、「注意の散漫(Attention Dilution)」と「コンテキスト上限の圧迫」は一切解決しません。ツール定義が肥大化するほど、モデルが適切なツールを選び損ねたり、肝心の指示内容を見落としたりする確率は確実に上昇します。
2. 生データ(Raw Output)の無加工流し込み
もうひとつの致命的な原因が、ツール実行結果の肥大化です。
たとえばWebブラウザを操作するPlaywright系のMCPサーバーでページを取得した場合、未加工のDOMツリーやHTML全体(300KB以上)がそのままLLMのコンテキストに返却されるケースが多々あります。あるいは、APIの全JSONレスポンスや巨大なログファイルをそのまま返してしまう実装です。
一度のツール呼び出しで数十万トークンが消費され、コンテキスト長の上限に衝突したり、過去の重要な会話履歴が圧縮・忘却されたりする事故が頻発します。
なぜ従来の「CLI」が再評価されているのか
このコンテキスト爆発問題に対する反動として、英語圏の開発者コミュニティで急速に再評価されているのが、昔ながらの「Unix CLI(コマンドライン)」です。
エージェントに「Bash実行権限(ターミナル操作ツール)」をひとつだけ与え、CLI経由で外部サービスを叩かせるアプローチには、トークン効率の面で圧倒的な優位性があります。
【MCPのアプローチ】
・全APIエンドポイントを個別のToolとして事前登録
・ツールスキーマだけで毎ターン数万トークンを消費
【CLIのアプローチ】
・エージェントに渡すツールは「Bash実行」の1つだけ(数十トークン)
・必要に応じて「gh --help」を自律取得し、JIT(オンデマンド)で実行
CLIがもたらす「3つのトークン削減効果」
- 常時スキーマの極小化: エージェントが保持するツール定義は「シェルコマンドを実行して結果を返す」という1つのツールスキーマ(数十トークン)だけで済みます。
-
パイプライン処理による入力前圧縮: エージェントは
gh issue list --limit 5 --json number,titleやgrep、jq、headを使って、必要なデータだけを抽出した数行のテキストのみをコンテキストに返却できます。 -
オンデマンドな知識取得: コマンドの使い方がわからない場合のみ
--helpを叩いて参照するため、使わないコマンドの仕様でコンテキストを汚染しません。
忘れてはならない「セキュリティと認可」のトレードオフ
ただし、トークン効率が良いからといって、すべてをCLIに置き換えるのは極めて危険です。ここには重大なトレードオフが存在します。
エージェントにBash実行権限を渡すことは、潜在的なリモートコード実行(RCE)のリスクを抱えることを意味します。悪意あるWebページや外部データにPrompt Injectionが仕込まれていた場合、意図しないファイル削除や機密情報の外部送信(exfiltration)を実行されてしまう危険性があります。
これに対して、MCPの真の価値は**「最小権限の原則(Least Privilege)に基づく認可境界の強制」**にあります。MCPサーバーは、あらかじめ許可された特定のAPI操作(例: 「指定Issueの閲覧のみ」「特定Slackチャンネルへの投稿のみ」)だけをホワイトリストとして提供し、任意のシェルコマンド実行を遮断できます。
また、ローカルで常駐するstdio接続のMCPサーバーはプロセスが起動し続けるリソースオーバーヘッドがありますが、OAuth連携などをセキュアに仲介できる利便性があります。
MCPとCLI/REST APIの使い分け判断基準
実務においては、セキュリティとトークン効率のトレードオフを踏まえ、以下の基準で使い分けることが求められます。
| 観点 | MCPを採用すべきケース | CLI / REST APIを採用すべきケース |
|---|---|---|
| セキュリティ・認可 | 厳密な権限分離を行い、任意のコード実行を防ぎたい場合 | 隔離されたサンドボックスや開発者の安全なローカル端末 |
| 認証方式 | OAuth連携や安全なトークン保管を委託したい場合 | 端末側で既に gh や aws のCLI認証が完了している場合 |
| データの性質 | リアルタイム通知や双方向通信、厳密な型検証が必要な場合 | ログ解析やファイル操作など、パイプラインでの前処理が有効な場合 |
| 実行環境 | ターミナル操作が許可されていないWeb/デスクトップUI | 開発環境で動作するコーディングエージェント(Claude Code等) |
コンテキスト消費を抑える4つの設計プラクティス
MCPを採用する場合でも、コンテキストの爆発を防ぐための最新のアーキテクチャパターンが確立されつつあります。
プラクティス1:事前要約とエラーサニタイズ
ツールが取得した生データ(300KB以上のHTMLやJSON)を直接メインのLLMへ返してはなりません。
MCPサーバー内部、あるいは軽量なローカルモデル(Ollama等)のサンドボックスを中間に挟み、必要な情報だけを抽出・要約してメインLLMへ返却します。Hacker Newsで話題となった実装例では、Webブラウザの生出力をアクセシビリティツリーや構造化テキストへ事前圧縮することで、コンテキスト消費を98%削減(315KBから5.4KBへ縮小)することに成功しています。
[Webサイト / 外部API]
↓ (生データ 300KB)
[中間サンドボックス / 事前要約層]
↓ (構造化された要約 5KB)
[メインLLM(Claude等)]
また、見落とされがちなのが「エラー出力」のハンドリングです。API呼び出しの失敗時に長大なスタックトレースやHTMLエラー画面をそのまま返すと、エージェントがパニックを起こしトークンを連鎖的に浪費します。MCPサーバー側でエラーメッセージをサニタイズし、最大文字数を制限して簡潔なエラー要約を返す設計が必須です。
プラクティス2:MCPプリミティブの適正化(ToolsからResourcesへのオフロード)
MCPには「Tools(関数実行)」「Resources(データ参照)」「Prompts(テンプレート)」という3つの基本仕様が存在します。
最もコンテキストを食うのは、スキーマが常駐する「Tools」です。これに対し、「Resources」はURI(例: file:///path や postgres://table)として定義され、エージェントが必要とした瞬間にのみ読み込まれます。すべてのデータ取得をTool化するのではなく、静的なドキュメントや参照データはResourcesとして公開することで、毎ターンのツール定義オーバーヘッドを劇的に削減できます。
プラクティス3:動的ツール露出とサブエージェント化
すべてのMCPツールを常時クライアントに登録するのではなく、タスクの進行状況に応じて動的にツールをロードするか、専門のサブエージェントに隔離します。
例えば「データベース調査」が必要になった段階でのみDB用MCPツールをコンテキストにロードし、調査が完了したらアンロードします。または、DB操作専用のサブエージェントを起動して閉じられた空間で作業させ、メインエージェントには最終結果の要約のみを報告させる階層型エージェント構成をとります。
プラクティス4:検索によるJIT(Just-In-Time)参照
大量のドキュメントやAPIリファレンスをMCPのリソースとして常駐させるのではなく、SQLite FTS5やBM25等の古典的全文検索を組み合わせたハイブリッドRAGをMCPサーバーの背後に配置します。
エージェントが検索クエリを投げた際に関連する最小限のスニペットのみを返す設計にすることで、コンテキストの圧迫を最小限に食い止められます。
まとめ
MCPは、AIエージェントと外部世界を接続するための極めて強力な共通言語です。しかし、「何でもMCPサーバーにして繋げば良い」という無邪気なアプローチは、コンテキストの急激な枯渇とコストの跳ね上がりという手痛いしっぺ返しを招きます。
- 複雑なデータ加工やファイル操作は、トークン効率に優れた Unix CLI に委譲する
- 認証の分離や安全なGUI連携が必要なコア領域に MCP を絞り込む
- MCPツールの返却データは、メインLLMに届く前に 事前要約・フィルタリング を徹底する
「コンテキストウィンドウは有限の希少資源である」という原則に立ち戻り、ツールの接続形態を適切に設計することが、実用に耐えうる堅牢なAIエージェントを構築するための必須条件です。