Anthropic公式のMCPサーバー設計術!98.7%のトークン削減を実現
こんにちは、とまだです。
「MCPサーバーを作ってみたけど、ツールが増えるとトークン消費が増え続ける...」と悩んでいませんか?
Anthropicが公式エンジニアリングブログで、トークン消費を98.7%削減する「コード実行パターン」を公開しました。
この記事では、その内容を初心者にも分かりやすく噛み砕いて解説します。
なお、この記事は、Anthropicの公式エンジニアリングブログを初心者向けに噛み砕いたものです。
より詳しい技術的背景は、原文も合わせてご参照ください。
著者について
とまだ
- Claude Code・Cursor・Codex などAI駆動開発の実践者
- 本業はフリーランスエンジニア、ならびに法人向けAI駆動開発の導入コンサルタント
- AI駆動開発を学ぶ方が集まる Vibe Coding Studio コミュニティを運営
- UdemyでAI駆動開発を学べる複数のベストセラー講座を展開
- 東京AI祭プレイベントに登壇
SNS
忙しい人のために要約
この記事のポイントを5つにまとめました。
- 全ツール定義を前段で読み込む設計では、約150,000トークン規模に膨らむ例がある
- 「コード実行」方式では約2,000トークンに圧縮できた例(約98.7%削減)が報告されている
- ツールをファイルシステムのように階層化し、エージェントが必要な定義だけを動的にロードする
- Google Drive→Salesforceの事例などで効果が示されている
- 小規模プロジェクトからでも応用可能で、スケーラビリティが大幅に向上する
では、順番に見ていきましょう。
MCPのトークン消費問題とは?
まず、MCPとは「Model Context Protocol」の略です。
これは、Claudeと外部ツールを接続するためのプロトコルです。
図書館の司書のようなものだと考えてください。Claudeが代わりに必要な情報を取りに行ってくれる仕組みです。
しかし、ここに大きな問題があります。ツールが増えれば増えるほど、トークン消費が急速に増えてしまうのです。
これは、スーパーで買い物をする時に、毎回全商品のカタログを持ち歩くようなものです。必要なのは牛乳とパンだけなのに、何千ページもあるカタログを毎回読み込むのは非効率ですよね。
元記事の例では、ツール定義を大量に前段読み込みする実装だと、1リクエストあたりの文脈に約150,000トークン相当が載ってしまうケースがあると指摘されています。
そのため、コストとレスポンス速度の両面で深刻な問題を引き起こします。
なぜツール定義が膨大になるのか
MCPでは、各ツールに対して「引数の型」「説明文」「使い方の例」などの定義が必要です。
そのため、ツールが10個、20個と増えていくと、それぞれの定義が積み重なります。その結果、膨大なトークン数になってしまいます。
加えて、多くのクライアント実装では、モデルに露出するために全ツール定義を前段で読み込ませる傾向があります。
その結果、1回の会話で何度もリクエストが発生すると、同様の定義が繰り返し流れやすく、トークンの無駄遣いにつながります。
トークン消費が引き起こす3つの問題
この問題が引き起こす課題は、主に以下の3つです。
まず、コスト増加です。APIの料金はトークン数に比例するため、150,000トークンを毎回消費すると費用が跳ね上がります。
次に、レスポンス遅延です。大量のトークンを処理するには時間がかかるため、ユーザー体験が悪化します。
そして、スケーラビリティの限界です。ツールを追加するたびにトークン消費が増え、いずれは限界に達してしまいます。
Anthropicの解決策「コード実行パターン」
Anthropicが提案したのは、「ツールを直接呼び出す」のではなく、「ツールをコードとして呼び出す」という発想の転換です。
たとえば、レストランで完成品を注文するのではなく、レシピ本を見ながら自分で料理を作るイメージです。
完成品(ツールの実行結果)を毎回用意するのではなく、材料と手順(コードとAPI)を提供することで、必要な時に必要なものだけを作れるようになります。
この「コード実行パターン」の核心は、次の2つのアイデアにあります。
ファイルシステムベースのツール管理
まず、ツールをファイルシステムのように階層化して整理します。
以下のような構造です。
servers
├── google-drive
│ ├── getDocument.ts
│ ├── ... (other tools)
│ └── index.ts
├── salesforce
│ ├── updateRecord.ts
│ ├── ... (other tools)
│ └── index.ts
└── ... (other servers)
このように整理することで、Claudeは「どんなツールがあるのか?」をリスト形式で取得できます。
そして、必要なツールだけを選んで、その定義を読み込めます。
図書館で例えるなら、まず本棚の目次を見て、必要な本だけを取り出すイメージです。全ての本を一度に持ってくる必要はありません。
動的ツールロード
次に、エージェントが必要なツール定義だけをその場で読み込む「動的ツールロード」を実現します。
たとえば、レストランで全メニューを暗記するのではなく、注文する時にメニューを見るようなものです。このように、必要な情報だけを、必要な時に取得することで、トークンの無駄を大幅に削減できます。
では、どのようにツール定義を絞り込むのでしょうか?
具体的には、以下のようなフローになります。
- エージェントが「Google Driveからファイルを取得したい」と判断する
- ファイルシステム(例:
./servers/google-drive)を探索、またはsearch_toolsのような検索ツールで候補を絞り込む - 必要なツール(例:
getSheet.ts)の定義だけを読み込む - そのツールを使ってコードを実行
このように、150,000トークンの定義を全部読み込むのではなく、必要な部分だけを読み込みます。
元記事の例では、約2,000トークンまで圧縮できたと報告されています。具体的な実装例で見ていきましょう。
98.7%削減の実装例を見てみよう
では、実際にどのように実装するのか、Google DriveからSalesforceへのデータ移行を例に見ていきましょう。
難しそうに感じるかもしれませんが、順を追って説明します。一つ一つ理解していけば、必ず仕組みが見えてきますので、一緒に見ていきましょう。
このタスクでは、Google Driveのスプレッドシートを読み込み、特定条件でフィルタリングします。
そして、個人情報を匿名化してからSalesforceに登録します。
手順1: ツール定義の階層化
まず、必要なツールをファイルシステムのように整理します。
これは、ファイルやフォルダを整理するのと同じ感覚なので、プログラミング初心者の方でもイメージしやすいはずです。
// ./servers/google-drive/getDocument.ts
import { callMCPTool } from "../../../client.js";
interface GetDocumentInput {
documentId: string;
}
interface GetDocumentResponse {
content: string;
}
/* Google Drive からドキュメントを読み込む */
export async function getDocument(input: GetDocumentInput): Promise<GetDocumentResponse> {
return callMCPTool<GetDocumentResponse>('google_drive__get_document', input);
}
これらのツールを、エージェントが必要に応じて読み込めるようにします。
手順2: エージェントが動的に探索
次に、エージェントは、まずファイルシステムを探索するか、search_tools のような検索ツールを呼んで必要な候補だけを取得します。
ここが少し技術的に見えるかもしれませんが、やっていることは「どんなツールがあるのか確認する」だけです。図書館で本棚の目録を見る感覚ですね。
ここでは具体的なコード例は示していませんが、原文では「ファイルシステムの列挙」や search_tools のような検索機能を使って、必要な定義のみをオンデマンドで読み込む方針が説明されています。
このように、全てのツール定義を読み込むのではなく、必要なものだけを選びます。
コード例を見て「複雑そう」と感じた方もいるかもしれませんが、実際にやっていることはシンプルです。「必要なツールだけを選ぶ」という、本質は変わりません。その結果、トークン消費を大幅に削減できます。
手順3: コード実行で処理
そして、最後に、読み込んだツールを使って、実際の処理コードを実行します。
// Read transcript from Google Docs and add to Salesforce prospect
import * as gdrive from './servers/google-drive';
import * as salesforce from './servers/salesforce';
const transcript = (await gdrive.getDocument({ documentId: 'abc123' })).content;
await salesforce.updateRecord({
objectType: 'SalesMeeting',
recordId: '00Q5f000001abcXYZ',
data: { Notes: transcript }
});
注目すべきポイントは、エージェントが「ツールを直接呼び出す」のではなく、「ツールを使ったコードを書いて実行する」ことです。これによって、柔軟性と効率性を両立できます。
ツール定義を全部読み込むのではなく、必要な時に必要な分だけ読み込みます。
元記事の例では、約150,000トークン相当から約2,000トークンへ圧縮(約98.7%削減)できたと報告されています。実際の効果はツール構成やワークロードに依存します。
一見複雑に感じるかもしれませんが、基本的な考え方は「図書館の目次を見て、必要な本だけを取り出す」というシンプルなものです。
まとめ
この記事では、約98.7%削減が報告された「コード実行パターン」を紹介しました。
従来の「ツール直接呼び出し」では、ツールが増えるたびにトークン消費が増えていく問題がありました。しかし、「コードとして呼び出す」方式に切り替えることで、必要な定義だけを動的に読み込み、大幅な効率化を実現できます。
この手法は、小規模なプロジェクトでも応用可能です。ぜひ、ご自身の開発にも取り入れてみてください。
— 出典: Anthropic Engineering「Code execution with MCP: Building more efficient agents」(公開日: 2025-11-04、著者: Adam Jones, Conor Kelly) 原文
この記事が役に立ったら「いいね」で応援いただきつつ、Xもフォローしていただけると嬉しいです。
AI駆動開発を学ぶ同士が集まるDiscordコミュニティを運営しています
Discord無料コミュニティ「Vibe Coding Studio」では、AI駆動開発を学ぶ同士が集まり、最新情報を共有しています。
また、実装例も公開していたり、参加者によるナレッジシェアも活発ですので、興味がある方はぜひご参加ください!
今回の記事の内容について、ご質問や相談があれば、お気軽にDiscordでお声がけください!
Discussion