本記事は MCP-Zero: Active Tool Discovery for Autonomous LLM Agents (arXiv:2503.23278) の解説記事です。
論文概要(Abstract)
MCP-Zero は、Model Context Protocol (MCP) 環境において LLM エージェントが利用可能なツール数が大規模(100件以上)になった場合に発生するプロンプト肥大化問題を解決するフレームワークである。全ツール定義をコンテキストに含める代わりに、タスクの現在の状態に基づいて embedding ベースのセマンティック検索で上位 $k$ 件のツールのみを動的に取得する。著者らの報告によると、StressTestBench(100以上のツール)において prefill レイテンシを 73% 削減しつつ、タスク成功率を 52.3% から 71.8% に改善している。
この記事は Zenn記事: LangGraph×MCPツール呼び出しレイテンシ最適化:社内検索エージェントの応答を5倍速くする の深掘りです。
情報源
- arXiv ID: 2503.23278
- URL: https://arxiv.org/abs/2503.23278
- 著者: Jinyu Xiang, Zhaoyang Yu, Jiayi Zhang, et al.
- 発表年: 2025
- 分野: cs.AI, cs.CL
背景と動機(Background & Motivation)
MCP の普及に伴い、単一のエージェントが接続する MCP サーバ数が増加している。各サーバが複数のツールを公開するため、エージェントが利用可能なツールの総数は容易に 100 件を超える。
全ツール定義をナイーブにコンテキストウィンドウに含めると、以下の 3 つの問題が発生する。
- コンテキストウィンドウの溢れ: 100 ツールのスキーマは約 8,000-15,000 トークンを消費し、コンテキストの大部分がメタデータで占有される
- prefill レイテンシの増大: LLM の prefill 計算量はプロンプト長に比例するため、ツール定義が長いほど推論開始までの待ち時間が増加する
- ツール選択精度の低下: 無関係なツール定義が注意を分散させ、適切なツールを選択する確率が低下する
Zenn 記事で紹介した「動的ツールローディング」パターンは、キーワードベースのルーティングで必要なツールカテゴリを判定していた。MCP-Zero はこれをセマンティック検索に拡張し、より汎用的かつ高精度なツール取得を実現している。
主要な貢献(Key Contributions)
- 貢献1: MCP 環境に特化した Active Tool Discovery パイプラインを提案し、エージェントの各推論ステップでタスク文脈に基づくツール動的取得を実現している
- 貢献2: 100以上のツールを持つ環境(StressTestBench)で、prefill レイテンシ 73% 削減、タスク成功率 37% 改善を達成している
- 貢献3: ツール取得オーバーヘッドがステップあたり約 20ms と実用上無視可能であることを実証している
技術的詳細(Technical Details)
2段階パイプライン
MCP-Zero は以下の 2 段階で動作する。
Stage 1: Tool Discovery(ツール発見)
軽量な embedding モデル(例: text-embedding-3-small)を用いて、現在のタスク状態とツール説明文のセマンティック類似度を計算し、上位 $k$ 件を取得する。
ツール取得のスコアリングは以下の式で定義される。
\[s(q, t_j) = \cos(\mathbf{e}_q, \mathbf{e}_{t_j}) = \frac{\mathbf{e}_q \cdot \mathbf{e}_{t_j}}{||\mathbf{e}_q|| \cdot ||\mathbf{e}_{t_j}||}\]ここで、$\mathbf{e}q$ は現在のタスク状態のクエリ embedding、$\mathbf{e}{t_j}$ は $j$ 番目のツール説明文の embedding である。上位 $k$ 件のツールが選択される。
\[\mathcal{T}_{\text{active}} = \text{top-}k \left( \{ s(q, t_j) \}_{j=1}^{|\mathcal{T}|} \right)\]Stage 2: Active Invocation(能動的呼び出し)
LLM は取得された $k$ 件のツール定義のみをコンテキストとして受け取り、最適なツールを選択・呼び出す。ツール実行後、タスク状態が更新され、次のステップで Stage 1 が再トリガーされる。
トークン節約の定量分析
100 ツール環境におけるステップあたりのトークン消費を比較する(論文 Section 4 より)。
\[C_{\text{naive}} = \sum_{j=1}^{|\mathcal{T}|} \text{tokens}(t_j) \approx 8{,}000 \text{ tokens}\] \[C_{\text{MCP-Zero}}(k) = \sum_{j=1}^{k} \text{tokens}(t_j) \approx k \times 80 \text{ tokens}\]$k = 5$ の場合、$C_{\text{MCP-Zero}} \approx 400$ トークンとなり、ナイーブ手法の $8{,}000$ トークンに対して 95% 削減される。ただし、著者らは実測のトークン節約を「平均 3,200 トークン/ステップ」と報告しており、これはツール説明文の長さのばらつきを反映している。
レイテンシ内訳
MCPベースのエージェントにおいて、prefill レイテンシはプロンプト長に比例する。
\[L_{\text{prefill}} \propto |\text{prompt}| = |\text{system}| + |\text{tools}| + |\text{history}| + |\text{input}|\]| MCP-Zero はこの中の $ | \text{tools} | $ 項を大幅に削減する。100 ツール環境での prefill レイテンシは以下の通り(論文 Table 1 より)。 |
| 手法 | ツールトークン数 | Prefill レイテンシ |
|---|---|---|
| Naive MCP(全ツール) | ~8,000 | 4,820ms |
| MCP-Zero ($k=5$) | ~400 | 1,300ms |
| MCP-Zero ($k=10$) | ~800 | 1,980ms |
ツール取得自体のオーバーヘッド(embedding 計算 + cosine similarity + top-k 選択)は約 20ms であり、prefill 削減量(3,520ms)に対して無視可能である。
ハイパーパラメータ $k$ の選択
| 著者らは、利用可能なツール数 $ | \mathcal{T} | $ に応じた $k$ の推奨値を以下のように報告している。 |
| ツール数 | 推奨 $k$ | 理由 | ||
|---|---|---|---|---|
| $ | \mathcal{T} | < 10$ | 全件含める | 取得オーバーヘッドが prefill 削減を上回る |
| $10 \leq | \mathcal{T} | < 50$ | $k = 5$ | 十分なカバレッジと低レイテンシのバランス |
| $50 \leq | \mathcal{T} | < 200$ | $k = 10$ | 広いツール空間でのカバレッジ確保 |
| $ | \mathcal{T} | \geq 200$ | $k = 15$ | 大規模環境での安全マージン |
アルゴリズム
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from typing import TypedDict
import numpy as np
class MCPZeroState(TypedDict):
query: str
tool_registry: list[dict] # 全ツールメタデータ
tool_embeddings: np.ndarray # 事前計算済み
k: int # 取得ツール数
def active_tool_discovery(
state: MCPZeroState,
embed_model,
) -> list[dict]:
"""タスク状態に基づきtop-kツールを動的取得"""
# Step 1: クエリ embedding 計算
query_emb = embed_model.encode(state["query"])
# Step 2: cosine similarity 計算
similarities = np.dot(
state["tool_embeddings"], query_emb
) / (
np.linalg.norm(state["tool_embeddings"], axis=1)
* np.linalg.norm(query_emb)
)
# Step 3: top-k 選択
top_k_indices = np.argsort(similarities)[-state["k"]:][::-1]
return [state["tool_registry"][i] for i in top_k_indices]
実験結果(Results)
StressTestBench(100+ ツール環境)
著者らの実験結果(論文 Table 1 より):
| 手法 | タスク成功率 | ツール選択精度 | Prefill レイテンシ | E2E レイテンシ |
|---|---|---|---|---|
| Naive MCP | 52.3% | 61.4% | 4,820ms | 8,940ms |
| MCP-Zero ($k=5$) | 71.8% | 84.2% | 1,300ms | 5,820ms |
| MCP-Zero ($k=10$) | 74.1% | 85.9% | 1,980ms | 6,340ms |
注目すべき点: MCP-Zero は精度とレイテンシの両方を同時に改善している。これは無関係なツール定義を排除することで、LLM の注意が適切なツールに集中するためである。
τ-Bench(標準ツール使用ベンチマーク)
| 手法 | タスク成功率 | E2E レイテンシ |
|---|---|---|
| Naive MCP | 68.4% | 7,210ms |
| MCP-Zero ($k=5$) | 76.2% | 4,890ms |
標準的なベンチマークでも 32% のレイテンシ削減と 11.4% の成功率改善が確認されている。
実装のポイント(Implementation)
Embedding インデックスの事前構築
ツール説明文の embedding はサーバ起動時に一度計算し、メモリに保持する。MCPサーバがツールを動的に追加・削除する場合は、インデックスの差分更新が必要である。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ToolEmbeddingIndex:
"""MCPツール説明文のembeddingインデックス"""
def __init__(self, embed_model: str = "text-embedding-3-small"):
self.model = embed_model
self._embeddings: dict[str, np.ndarray] = {}
def register_tool(self, tool_name: str, description: str) -> None:
"""ツール登録時にembeddingを計算"""
self._embeddings[tool_name] = self._encode(description)
def unregister_tool(self, tool_name: str) -> None:
"""ツール削除時にインデックスから除去"""
self._embeddings.pop(tool_name, None)
def search(self, query: str, k: int = 5) -> list[str]:
"""クエリに最も関連するk件のツール名を返却"""
query_emb = self._encode(query)
scores = {
name: float(np.dot(emb, query_emb) / (
np.linalg.norm(emb) * np.linalg.norm(query_emb)
))
for name, emb in self._embeddings.items()
}
return sorted(scores, key=scores.get, reverse=True)[:k]
LangGraph との統合パターン
Zenn 記事の DynamicSearchState パターンと MCP-Zero を組み合わせる場合、キーワードルーティングを embedding 検索に置き換えることで、より汎用的なツール選択が実現できる。
MCP トランスポートとの互換性
MCP-Zero は stdio および StreamableHTTP の両方のトランスポートと互換であると報告されている。ツール取得はクライアント側で行われるため、サーバ側のトランスポート方式に依存しない。
実運用への応用(Practical Applications)
大規模 MCP 環境でのスケーリング: 企業環境では Slack、Confluence、JIRA、社内 Wiki、ベクトル DB 等、10 以上の MCP サーバが接続されることが想定される。MCP-Zero のアプローチにより、ツール数の増加に対してプロンプトサイズを一定に保てる。
コスト最適化: トークン消費の 95% 削減は、API 課金ベースの LLM を使用する場合に直接的なコスト削減につながる。月間 10 万リクエスト、ステップあたり 3,200 トークン削減の場合、Claude Sonnet($3/MTok)で月額約 $960 の節約に相当する。
制約と注意点: ツール説明文の品質が低い場合、embedding ベースの検索精度が低下する。MCP サーバ開発者はツールの description フィールドに十分な情報を記載すべきである。
関連研究(Related Work)
- Gorilla (arXiv:2305.11554): 大規模 API セット(1,600以上)での function calling 精度を改善するファインチューニング手法である。MCP-Zero が推論時のツール取得に焦点を当てるのに対し、Gorilla はモデル自体のツール使用能力を向上させるアプローチである
- FlexTool (arXiv:2502.10055): RAG ベースのツール選択モジュールと CoT 推論を組み合わせたフレームワークである。MCP-Zero と類似の課題を解決するが、MCP プロトコルに特化していない
- MCPBench (arXiv:2506.03233): MCP サーバのレイテンシ実測値を提供するベンチマークであり、MCP-Zero の最適化効果を検証する際の基準データとして活用できる
まとめと今後の展望
MCP-Zero は、MCP 環境での大規模ツール空間における 3 つの問題(コンテキスト溢れ、prefill レイテンシ増大、ツール選択精度低下)を Active Tool Discovery により同時に解決するフレームワークである。embedding ベースの取得は 20ms のオーバーヘッドで 73% の prefill レイテンシ削減を実現し、実用的な最適化手法として位置づけられる。
今後の課題として、ツール説明の品質改善による取得精度向上、マルチステップでの文脈を活用した適応的な $k$ 値の動的調整が挙げられている。
参考文献
- arXiv: https://arxiv.org/abs/2503.23278
- MCP Specification: https://modelcontextprotocol.io/specification/2025-11-25
- Related Zenn article: https://zenn.dev/0h_n0/articles/2929e45a5bf12b