MCPサーバーの肥大化を防ぎトークン消費と誤爆を抑える実務運用レシピ
目次
開閉
VS Code(Cline等のエージェント拡張機能)やAntigravity CLIなどのAIコーディング環境で、Anthropicが策定したオープン標準「Model Context Protocol (MCP)」への対応が急速に進んでいます。
ローカルのファイルシステムやGitHub、社内のPostgreSQLデータベースなどをMCPサーバーとして接続すれば、AIが自律的にコンテキストを取得し、コードの修正や調査を行えるようになります。
しかし、便利だからと手当たり次第にMCPサーバーを登録していくと、現場ではすぐに別の壁に直面します。
「何も質問していないのに、最初の1ターンだけで大量のトークンが消費される」
「単なるコードの相談なのに、AIが関係のない外部ツールを呼び出してエラーになる」
私自身、手元の開発環境(会社支給のMacBook Proと自宅のWindowsノートPC)で複数のMCPサーバーを常用する中で、この「ツールの肥大化による弊害」に悩まされました。
本記事では、MCPが裏側でツールを展開する仕組みとトークン消費の実測データ、現場でハマった通信の落とし穴、そしてトークン浪費と誤爆を抑えるための実践的な運用レシピをまとめます。
ツール肥大化が引き起こす「見えないコスト」の正体
MCPの利便性を享受する一方で、登録サーバーを増やしすぎると日常の開発効率を損なう原因になります。その背景には、MCPクライアントとLLMの間で行われるツール定義のやり取りがあります。
1. 毎ターン消費される大量のJSON Schema定義
MCPクライアント(VS Codeの拡張機能やAntigravity CLI、Claude Desktopなど)は、起動時に接続先のMCPサーバーへ tools/list リクエストを送信します。
サーバーから返ってきたツールの名前、説明文、引数の型情報(JSON Schema)は、ユーザーが入力したプロンプトと一緒に、毎ターンのシステムプロンプトとしてLLMへ送信されます。
手元環境で代表的なMCPサーバーのスキーマサイズとトークン消費量を計測した結果が以下です。
| MCPサーバー | 主な提供ツール | ツール数 | 推定トークン消費量 |
|---|---|---|---|
| Filesystem | ファイル読み書き、一覧取得、移動など | 約7個 | 約1,100 tokens |
| PostgreSQL | テーブルスキーマ取得、クエリ実行など | 約4個 | 約800 tokens |
| GitHub | PR作成、コミット取得、Issue検索など | 約26個 | 約3,800 tokens |
| Puppeteer / Fetch | Webページ取得、スクリーンショットなど | 約5個 | 約950 tokens |
| Slack / Linear | メッセージ送受信、チケット更新など | 約10個 | 約1,600 tokens |
これらをすべてグローバル設定(claude_desktop_config.json 等)に登録していると、合計で約8,200〜10,000トークンものスキーマ情報が、最初の挨拶を交わす前から毎往復のコンテキストに付加されます。
1回の往復で8,000トークン以上の入力が常に課金対象となるだけでなく、モデルが保持できる会話履歴(コンテキストウィンドウ)の上限を大きく圧迫してしまいます。
2. ツールの選択ミス(誤爆)と応答精度の低下
トークン消費以上に実務で厄介なのが、ツールの選択ミス(ハルシネーション)の増加です。
LLMに30個以上のツールを同時に提示すると、プロンプトの意図を解釈する際にツールの役割が競合しやすくなります。
たとえば「この関数のTypeScriptの型定義を修正して」と頼んだだけなのに、AIが余計なWeb検索ツールやGitHubのIssue検索ツールを呼び出そうとして処理が中断する現象が起きます。
AIに持たせるツールは多ければ良いわけではなく、「今取り組んでいるタスクに必要な道具だけを渡す」という絞り込みが欠かせません。
現場でハマった2大落とし穴と検証ログ
MCPサーバーの導入や自作を進める中で、実務上特に遭遇しやすい2つのトラブルがあります。
落とし穴1: stdio通信での console.log 混入によるJSON-RPC破壊
MCPの代表的な通信方式である stdio(標準入出力)では、クライアントとサーバーが改行区切りのJSON-RPC形式で通信します。
自作のMCPサーバーや一部のスクリプトで、接続確認やデバッグのために何気なく標準出力へログを出力してしまうと、通信が即座にクラッシュします。
実際にNode.jsで起動時に console.log を1行差し込んだミニサーバーを作成し、クライアントから初期化リクエスト(initialize)を送った際の検証ログが以下です。
[CLIENT CRITICAL ERROR] JSON-RPC parse failed! Raw message was: "[DEBUG] MCP server starting up and initializing connection pool..."
[CLIENT ERROR DETAILS]: Unexpected token 'D', "[DEBUG] MCP"... is not valid JSON
クライアントは標準出力から流れてくる文字列をすべてJSONとして解釈しようとするため、デバッグ用のテキストが混ざるとパースに失敗し、サーバーとの接続を切断してしまいます。
MCPサーバー内でデバッグログを出力する場合は、必ず**標準エラー出力(STDERR)**へ流す必要があります。Node.jsであれば console.error、Pythonであれば sys.stderr.write や logging モジュールを用います。
落とし穴2: ホームディレクトリ指定による過剰な権限付与
ファイルシステムを操作する @modelcontextprotocol/server-filesystem では、引数としてアクセスを許可するディレクトリパスを渡します。
ここで設定が面倒だからと、ホームディレクトリ全体(~ や C:\Users\username)を渡してしまうケースを見かけます。
この設定を行うと、AIが .ssh/ 配下の秘密鍵や、別プロジェクトの .env ファイル、OSの個人設定ファイルまで自由に探索できる状態になります。プロンプトインジェクションやツールの誤作動が発生した際のリスクが非常に高くなります。
アクセス許可パスは、必ず「作業対象のリポジトリ配下」や「共有ドキュメントフォルダ」に限定して指定します。
トークン浪費と誤爆を防ぐ3つの効率化レシピ
こうした課題を踏まえ、日々の開発環境を快適に保つために実践している3つの運用レシピを紹介します。
レシピ1: グローバル設定をやめ、プロジェクトやプラグイン別にスコープを分離する
すべてのMCPサーバーを単一のグローバル設定ファイルに集約せず、プロジェクトやタスク単位で設定を分離します。
たとえばAntigravity CLIであれば、マシン全体に適用される ~/.gemini/config/mcp_config.json にすべてのサーバーを書くのではなく、プロジェクト固有のプラグイン設定(plugins/<プラグイン名>/mcp_config.json)を活用することで、その機能が必要な時だけMCPツールをロードできます。
VS CodeのClineやRoo Code等の拡張機能でも、ワークスペース固有の設定やプロファイル機能を使い、プロジェクトごとに有効化するサーバーを切り替える運用が効果的です。
{
"mcpServers": {
"project-filesystem": {
"command": "node",
"args": [
"./scripts/mcp-filesystem.js",
"./src",
"./docs"
]
}
}
}
Webフロントエンドの開発中にはデータベースやクラウド連携のツールを読み込ませず、DBマイグレーションや管理作業を行うときだけ専用のプロファイルへ切り替える運用にすることで、コンテキストの消費を最小限に抑えられます。
レシピ2: npx -y の都度実行をやめ、ローカル固定または uvx で起動を速くする
MCPの設定例では npx -y @modelcontextprotocol/server-... という記述がよく使われます。
しかし、npx -y はエディタやクライアントが起動するたびにリモートリポジトリへの問い合わせやパッケージ解決を試みるため、起動に数秒のレイテンシが生じる場合があります。また、ネットワーク環境によっては起動エラーを引き起こします。
頻繁に利用するNode.js製サーバーは、ローカルに固定バージョンをインストールして直接起動するか、Python製サーバーであれば uvx を活用するのがおすすめです。
Astral社の高速パッケージマネージャー「uv」が提供する uvx コマンドは、強力なローカルキャッシュと仮想環境の高速生成により、コールドスタート時でも数百ミリ秒でサーバーを立ち上げられます。
{
"mcpServers": {
"git": {
"command": "uvx",
"args": ["mcp-server-git", "--repository", "."]
}
}
}レシピ3: 最小権限の原則に基づくパスのホワイトリスト化
ファイル操作ツールには、編集対象となる具体的なディレクトリのみを配列で渡します。
Windows環境とmacOS環境の併用では、パスの区切り文字やエスケープの違いに注意が必要です。JSONファイル内では、Windowsのバックスラッシュを \\ と二重にエスケープするか、スラッシュ / 表記に統一して記述します。
{
"mcpServers": {
"workspace-fs": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/username/projects/my-app/src",
"C:/Users/username/projects/my-app/public"
]
}
}
}設定ファイルの保存場所と管理のポイント
主要なMCPクライアントにおける設定ファイルの配置場所は以下のとおりです。
- Antigravity CLI / IDE:
- グローバル設定:
~/.gemini/config/mcp_config.json(Windows:%USERPROFILE%\.gemini\config\mcp_config.json) - プラグイン別スコープ:
plugins/<プラグイン名>/mcp_config.json
- グローバル設定:
- VS Code (Cline / Roo Code):
- 拡張機能の設定画面、またはストレージ設定(
cline_mcp_settings.json)
- 拡張機能の設定画面、またはストレージ設定(
- Claude Desktop:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
設定ファイル内にAPIキーなどのシークレット情報を記述する場合は、平文で直書きせず環境変数(env フィールド)を経由して注入します。
以前紹介したシークレット管理手法と組み合わせることで、リポジトリに設定ファイルをコミットしても機密情報が漏洩しない状態を維持できます。
シークレット管理の具体的なツール選定や使い分けについては、以下の記事で詳しく解説しています。
道具箱は、小さく保つくらいがちょうどいい
新しいプロトコルや便利な連携ツールが登場すると、つい「あれもこれも」と設定ファイルに詰め込みたくなります。私自身、最初は手持ちのMCPツールをすべて有効化しようとして、結果的に無駄なトークンを払い、AIの的外れなツール呼び出しに頭を抱えることになりました。
現実の開発現場でも、作業机の上にすべての工具を山積みにしていると、かえって目当てのレンチを探すのに手間取ります。AIへのツール提供も同じで、今から書くコードに必要なファイルやスキーマだけをそっと手渡すくらいの距離感が、一番テンポよく開発を進められます。
まずは作業対象のリポジトリに合わせて必要なMCPサーバーだけを最小限で立ち上げ、普段触るディレクトリだけをホワイトリストに指定してみる。そうした小さな環境づくりから、ノイズのない身軽なAIとの協業を試してみてください。
関連記事(開発環境)
「開発環境」の記事をもっと見るモダンなコマンドランナー「just」で整えるクロスプラットフォーム自動化レシピ
2026/10/18
GitでAPI定義を管理する「Bruno」のローカルファーストな実務運用
2026/10/04
Rustのビルド待ち時間を削る高速リンカとsccacheの実践レシピ
2026/10/01