Anthropic「Code Execution × MCP」を具体例で理解する ―― 抽象な元記事を噛み砕いてみた
はじめに:正直、元記事が分からなかった
Anthropic社の「Code Execution with MCP」が示す未来を読んだんですが、正直かなり抽象的で理解するのに苦労しました。
「ツールコール時代の終焉」とか「エージェントはコードを書く」とか言われても、具体的に何がどう変わるのかがイマイチ掴めなかったんですよね😓
そこで自分なりに具体例を作って理解を深めてみたので、この記事ではその内容をまとめてます!
まだ実際に試してないので、「こんな感じで動くはず」というイメージベースですが、抽象的な説明よりは分かりやすいんじゃないかなと思ってます🧐
問題の本質:MCPは便利だけど、スケールすると死ぬ
MCPって何?(超ざっくり)
MCPは一言で言うと、AIに外部ツールを使わせるための標準化プロトコルです。
例えば、
- スプレッドシートにデータを書き込む
- タスク管理ツールからタスクを取得する
- 燃料使用量のデータを取得する
こういう外部操作を、ChatGPTでもClaudeでもGeminiでも同じ方式で扱えるようにする、みたいな感じです。
でも、素直に実装すると破綻する
元記事で衝撃的だったのがこの数字👇
「質問に答える前に15万トークン使っていた」という実例が報告されている
具体的に何が起きてるかというと...
ありがちな実装(= 地獄への道)
- MCPツールを10個以上用意
- すべてのツール定義をコンテキストに詰め込む
- AIに「どのツールを使うか」を判断させる
- ツール実行結果を全部AIに戻す
- AIが次のツールを選ぶ
- また実行結果を全部AIに戻す
- これを繰り返す…
→ トークン消費が爆発する
具体例で見てみる
「燃料使用量を機械ごとに集計してスプレッドシートに出力する」というタスクで考えてみます。
旧方式(ツールコール中心)
ユーザー: 「今月の燃料使用量を集計してシートに出力して」
┌─────────────────┐
│ AI (Claude) │
└────────┬────────┘
│ 1. どのツール使う?
▼
┌─────────────────┐
│ get_fuel_usage │ ← ツール実行
└────────┬────────┘
│ 2. 全データ(10,000トークン)をAIに返す
▼
┌─────────────────┐
│ AI (Claude) │ ← 中間データを読んで判断
└────────┬────────┘
│ 3. 次のツール呼ぶ
▼
┌─────────────────┐
│ filter_by_month │ ← ツール実行
└────────┬────────┘
│ 4. またAIに返す(8,000トークン)
▼
┌─────────────────┐
│ AI (Claude) │
└────────┬────────┘
│ 5. さらに次のツール
▼
┌─────────────────┐
│ group_by_machine│
└────────┬────────┘
│ 6. またAIに返す(5,000トークン)
▼
┌─────────────────┐
│ AI (Claude) │
└────────┬────────┘
│ 7. 最後のツール
▼
┌─────────────────┐
│ write_to_sheet │
└────────┬────────┘
│ 8. 完了
問題点:
- AIとの往復が5回以上
- 中間データ(フィルタ済み、集計済みなど)を毎回AIに送る
- 合計トークン消費:15,000〜20,000トークン
- 処理時間:15秒以上
新方式(Code Execution × MCP)
ユーザー: 「今月の燃料使用量を集計してシートに出力して」
┌─────────────────┐
│ AI (Claude) │
└────────┬────────┘
│ 1. 必要なツールファイルだけ確認
│ (write_to_sheetのみ読む)
│
│ 2. コードを生成
▼
┌─────────────────────────────────┐
│ 生成されたPythonコード │
│ │
│ from mcp_tools import get_fuel_usage│
│ from mcp_tools import write_to_sheet│
│ │
│ # データ取得 │
│ data = get_fuel_usage() │
│ │
│ # フィルタ(コード内で完結) │
│ this_month = [ │
│ row for row in data │
│ if row['month'] == '2025-11' │
│ ] │
│ │
│ # 集計(コード内で完結) │
│ by_machine = {} │
│ for row in this_month: │
│ machine = row['machine_id'] │
│ if machine not in by_machine: │
│ by_machine[machine] = 0 │
│ by_machine[machine] += row['amount']│
│ │
│ # 出力 │
│ write_to_sheet(by_machine) │
└────────┬────────────────────────────┘
│ 3. コード実行(1回で完結)
▼
┌─────────────────┐
│ 完了! │
└─────────────────┘
改善点:
- AIとの往復が1回だけ
- 中間データ(フィルタ、集計)はコード内で処理
- AIに戻すのは最終結果のみ
- 合計トークン消費:1,600トークン(削減率89%)
- 処理時間:3秒
Code Execution × MCP の仕組み
Anthropicが提示した解決策は、こういう流れです。
ステップ1:ファイル構造を見る
mcp-workspace/
├── fuel-server/
│ └── src/
│ └── get_fuel_usage.ts
├── sheet-server/
│ └── src/
│ └── write_to_sheet.ts
└── progress-server/
└── src/
└── list_tasks.ts
AIはまず、どんなツールファイルがあるかだけを確認します。
重要なのは、この時点ではファイルの中身は読まないこと。ファイル名だけで「あ、燃料データ取得できそうだな」「シート書き込みできそうだな」と判断します。
ステップ2:必要な時だけファイルを読む
// AIが read_file で読み込むのはこれだけ
// fuel-server/src/get_fuel_usage.ts
export function get_fuel_usage(options?: {
start_date?: string;
end_date?: string;
}) {
// 燃料使用量データを取得
return fetch('/api/fuel-usage', {
method: 'POST',
body: JSON.stringify(options)
});
}
全ツール定義を最初から詰め込むのではなく、必要なファイルだけその場で読む。
これで初期トークン消費が激減します。
ステップ3:コードを生成する
AIが実際に生成するコードはこんな感じ:
from mcp_tools.fuel_server import get_fuel_usage
from mcp_tools.sheet_server import write_to_sheet
from datetime import datetime
# 今月のデータを取得
current_month = datetime.now().strftime('%Y-%m')
data = get_fuel_usage(
start_date=f"{current_month}-01",
end_date=f"{current_month}-30"
)
# 機械ごとに集計(コード内で完結)
result = {}
for row in data:
machine_id = row['machine_id']
amount = row['amount']
if machine_id not in result:
result[machine_id] = {
'total_amount': 0,
'total_cost': 0
}
result[machine_id]['total_amount'] += amount
result[machine_id]['total_cost'] += amount * row['unit_price']
# シートに書き込み
write_to_sheet('FuelReport', result)
print("集計完了!")
ポイント:
- データ取得、フィルタ、集計、出力が1つのコードで完結
- 中間データはコード内の変数で管理
- AIに戻すのは最終的な
printだけ
ステップ4:コードを実行
生成されたコードをそのまま実行します。
中間処理はすべてコード側で完結するので、AIは意思決定(どんなコードを書くか)だけに集中できます。
実装例(まだ試してないイメージ)
実際にどう実装するのか、TypeScriptとPythonで考えてみました。
TypeScript(Next.js での活用)
// app/api/fuel-analysis/route.ts
import { get_fuel_usage } from '@/mcp-tools/fuel-server';
import { write_to_sheet } from '@/mcp-tools/sheet-server';
export async function POST(req: Request) {
const { startDate, endDate } = await req.json();
// 1. データ取得
const data = await get_fuel_usage({ startDate, endDate });
// 2. 集計(コード内で完結)
const byMachine = data.reduce((acc, item) => {
const { machineId, amount, cost } = item;
if (!acc[machineId]) {
acc[machineId] = { totalAmount: 0, totalCost: 0 };
}
acc[machineId].totalAmount += amount;
acc[machineId].totalCost += cost;
return acc;
}, {} as Record<string, { totalAmount: number; totalCost: number }>);
// 3. シートに出力
await write_to_sheet('FuelAnalysis', byMachine);
return Response.json({ success: true, data: byMachine });
}
Claude Code に「燃料コスト分析APIを実装して」と指示すれば、こういうコードを1回で生成してくれるはずです。
Python(GASでの活用)
# Google Apps Script でも同じ考え方
from mcp_tools import get_fuel_usage, get_spreadsheet
def analyze_fuel_cost(start_date, end_date):
# 1. データ取得
data = get_fuel_usage(start_date, end_date)
# 2. 集計(Python内で完結)
by_machine = {}
for row in data:
machine_id = row['machine_id']
if machine_id not in by_machine:
by_machine[machine_id] = {
'amount': 0,
'cost': 0
}
by_machine[machine_id]['amount'] += row['amount']
by_machine[machine_id]['cost'] += row['cost']
# 3. スプレッドシートに書き込み
sheet = get_spreadsheet('燃料コスト分析')
sheet.clear()
# ヘッダー
sheet.append_row(['機械ID', '使用量', 'コスト'])
# データ
for machine_id, data in by_machine.items():
sheet.append_row([
machine_id,
data['amount'],
data['cost']
])
return by_machine
# 実行
result = analyze_fuel_cost('2025-11-01', '2025-11-30')
print(f"集計完了: {len(result)}台分")
なぜこれが「次の標準」になるのか?
元記事では3つの理由が挙げられていました。
理由1:エージェントが肥大化する未来に耐えられる
今後、AIエージェントが扱う情報は際限なく増えていきます。
- ツール定義
- 内部検索結果
- 制約条件
- 過去の履歴
これらを全部コンテキストに詰め込む方式では、すぐに破綻します。
Code Execution × MCP の方式なら、必要なファイルだけその場で読むので、スケールに強いです。
理由2:マルチモデル時代に相性が良い
ChatGPT、Claude、Gemini…どれが主流になるか分かりません。
でもコードファイルという形式は、どのモデルでも読めます。
「ツール定義をモデル固有の形式で書く」よりも、「TypeScript/Pythonで書く」方が汎用性が高いです。
理由3:役割分担が綺麗になる
- LLM = 意思決定(どんなコードを書くか)
- MCP = 接続の標準化(ツールの呼び出し方を統一)
- コード = 状態管理、処理、制御
この三層構造は、大規模なエージェントシステムを作る上で非常に相性が良いです。
まとめ:今後MCPを触るなら
元記事の結論を引用すると:
最初から "コード実行前提" で設計したほうがいい。
ツール定義をコンテキストに全部詰める旧式MCPサーバは
1〜2年以内に確実に陳腐化する。
具体的には:
-
ツールは
src/*.tsのコードファイルにする- ツール定義をJSON等で管理しない
- TypeScriptやPythonの関数として書く
-
エージェントは必要時に
read_fileで読む- 全ツール定義を最初から詰めない
- 必要なファイルだけその場で読む
-
処理はコードで完結させる
- フィルタ、集計、ループなどの中間処理
- これらをツールコールで実現しようとしない
-
AIには意思決定だけやらせる
- 「どんなコードを書くか」を判断させる
- 実行はコード側に任せる
最後に
正直、元記事の抽象的な説明だけでは理解しきれなかったので、自分なりに具体例を作って整理してみました。
まだ実際に試してないので「こんな感じで動くはず」というイメージですが、「ツールコール中心 → コード実行中心」への転換という大きな流れは理解できたんじゃないかなと思ってます。
これからMCPに触る人の参考になれば嬉しいです。
参考
- 元記事:Anthropic社の「Code Execution with MCP」が示す未来
- Anthropic公式ドキュメント:https://docs.anthropic.com/
Discussion
大元の Anthropic の記事読んだ方がいいですよ
Code execution with MCP: building more efficient AI agents \ Anthropic
「コード実行は、これらの確立されたパターンをエージェントに適用することで、使い慣れたプログラミング構造を用いてMCPサーバーとより効率的にやり取りできるようにします。」
MCP サーバーが提供するツールごとに呼び出しスクリプトを生成させて、そのスクリプト経由でMCPサーバーのツールを実行すると効率良くできます、って内容ですね。MCP サーバーはツールの仕様を提供してくれるので、ツール呼び出しスクリプト自体も Claude Code に生成させることができます
記事中のコードで
callMCPToolというのを使っていることがMCPサーバー自体は今までのものを使う想定であることを示していますツールスクリプトが生成済みであることを Claude Code に教えれば、MCP 設定されていない Claude Code にタスク依頼しても、それらツールスクリプトを使った使い捨てスクリプトを作ってそのまま実行することが Claude Code にはできます。 ツールスクリプトを通して間接的に MCP を呼ぶ形ですね
なので Next.js などでラップする必要もないです