MCPでのコード実行:より効率的なエージェントの構築
公開日: 2025年11月4日
著者: Adam Jones、Conor Kelly
原文: Code Execution with MCP: Building More Efficient Agents
私の環境(Claude Code)で使えるか?
| アプローチ | 適用可否 | 備考 |
|---|---|---|
| コード実行によるツールオーケストレーション | ❌ | Claude APIのベータ機能(code_execution)が必要 |
| MCPサーバーのファイルシステム構成 | ❌ | Claude Codeでは直接サポートされていない |
| PII自動トークン化 | ❌ | カスタムMCPクライアント実装が必要 |
| カスタムMCPサーバー作成 | ✅ | 自作MCPサーバーをClaude Codeに接続可能 |
結論
この記事で紹介されているコード実行アプローチの大部分は、Claude Codeでは直接利用できません。
理由:
- Programmatic Tool Calling(
code_executionツール)はClaude APIのベータ機能 - Claude Codeは従来の直接ツール呼び出し方式のみサポート
- MCPサーバーをファイルシステムとして公開する機能はない
唯一できること
カスタムMCPサーバーの作成は可能です。例えば:
- 複数のツールをまとめた高レベルMCPサーバーを自作
- データフィルタリングをサーバー側で行い、結果のみ返す
- これにより間接的にトークン削減は実現可能
ただし、記事で説明されている「エージェントがコードを書いてツールをオーケストレーション」というパターンは使えません。
概要
この記事では、エージェントが直接ツール呼び出しではなくコード実行を通じてMCPサーバーとより効率的に連携する方法を探ります。
課題
エージェントが多数のMCPサーバーに接続する際に2つの主要な課題が生じます:
1. ツール定義のオーバーロード
すべてのツール定義を事前に読み込むと、コンテキストウィンドウの大部分を消費します。
「ツールの説明がコンテキストウィンドウをより多く占有し、応答時間とコストが増加する」
2. 中間結果の重複
エージェントがツールを順次呼び出すと、結果はモデルを複数回通過する必要があります。
たとえばGoogle Driveから会議の議事録を取得してSalesforceに添付する場合、議事録全体がコンテキストを2回通過し、長いドキュメントでは50,000トークン以上が追加される可能性があります。
解決策:コード実行アプローチ
ツールを直接関数呼び出しとして公開する代わりに、MCPサーバーをコードAPIとして提示します。エージェントはコードを書いてツールと対話し、オンデマンドのツール読み込みと環境内でのデータ処理によって両方の課題に対処します。
ファイルシステムアーキテクチャ
MCPツールをファイルシステムとして構成:
servers
├── google-drive
│ ├── getDocument.ts
│ ├── ... (他のツール)
│ └── index.ts
├── salesforce
│ ├── updateRecord.ts
│ ├── ... (他のツール)
│ └── index.ts
└── ... (他のサーバー)
実装例:ツールラッパー
// ./servers/google-drive/getDocument.ts
import { callMCPTool } from "../../../client.js";
interface GetDocumentInput {
documentId: string;
}
interface GetDocumentResponse {
content: string;
}
export async function getDocument(input: GetDocumentInput):
Promise<GetDocumentResponse> {
return callMCPTool<GetDocumentResponse>
('google_drive__get_document', input);
}
実践的な使用パターン
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%の時間とコストの削減となる」
主要な利点
1. 段階的開示(Progressive Disclosure)
モデルはファイルシステムを自然にナビゲートし、すべてを事前に読み込むのではなく、オンデマンドでツール定義を読み取ります。
代替アプローチとして、エージェントが詳細レベル(最小限 vs 完全なスキーマ)を指定できるsearch_tools関数を実装することもできます。
2. コンテキスト効率的な結果
エージェントは実行環境内で大規模なデータセットをフィルタリングしてから、モデルに結果を返すことができます。
const allRows = await gdrive.getSheet
({ sheetId: 'abc123' });
const pendingOrders = allRows.filter(row =>
row["Status"] === 'pending'
);
console.log(pendingOrders.slice(0, 5));
10,000行のスプレッドシートを処理する場合、モデルに返すのはフィルタリングされた5行だけになります。
3. 制御フロー
ループ、条件分岐、エラー処理がモデルの繰り返し呼び出しを必要とせず、コード内で実行されます。
let found = false;
while (!found) {
const messages = await slack.getChannelHistory
({ channel: 'C123456' });
found = messages.some(m =>
m.text.includes('deployment complete'));
if (!found) await new Promise
(r => setTimeout(r, 5000));
}
条件ロジックは反復的なモデル呼び出しを必要とせず、環境内で実行されます。
4. プライバシー保護
中間結果はデフォルトで実行環境内に留まります。システムは個人識別情報(PII)を自動的にトークン化し、データをモデルに公開することなくサービス間で流すことができます。
const sheet = await gdrive.getSheet
({ sheetId: 'abc123' });
for (const row of sheet.rows) {
await salesforce.updateRecord({
objectType: 'Lead',
recordId: row.salesforceId,
data: {
Email: row.email,
Phone: row.phone,
Name: row.name
}
});
}
MCPクライアントはPIIをインターセプトし、モデルが見る前に[EMAIL_1]、[PHONE_1]のようなトークンに変換します。実際の値はモデルに公開されることなく、サービス間で直接流れます。
5. 状態の永続化
エージェントは中間結果をファイルに書き込むことができ、進捗追跡と再開可能なワークフローを可能にします。
const leads = await salesforce.query({
query: 'SELECT Id, Email FROM Lead LIMIT 1000'
});
const csvData = leads.map(l =>
`${l.Id},${l.Email}`).join('\n');
await fs.writeFile('./workspace/leads.csv', csvData);
// 後で読み込み
const saved = await fs.readFile
('./workspace/leads.csv', 'utf-8');
6. スキル開発
エージェントは動作するコード実装を再利用可能な関数として保存し、より高レベルな機能のツールボックスを徐々に構築できます。
// ./skills/save-sheet-as-csv.ts
import * as gdrive from './servers/google-drive';
export async function saveSheetAsCsv(sheetId: string) {
const data = await gdrive.getSheet({ sheetId });
const csv = data.map(row =>
row.join(',')).join('\n');
await fs.writeFile
(`./workspace/sheet-${sheetId}.csv`, csv);
return `./workspace/sheet-${sheetId}.csv`;
}
// 使用例
import { saveSheetAsCsv } from
'./skills/save-sheet-as-csv';
const csvPath = await saveSheetAsCsv('abc123');
実装上の考慮事項
このアプローチには、適切なサンドボックス化、リソース制限、監視を備えた安全なコード実行インフラストラクチャが必要です。
「エージェントが生成したコードを実行するには、適切なサンドボックス化、リソース制限、監視を備えた安全な実行環境が必要です」
これらの運用要件は、効率性の向上と比較検討する必要があります。
関連情報
記事ではCloudflareの並行した取り組みに言及し、LLMコード生成の利点に関する類似の洞察を指摘しています。MCPコミュニティとの実装共有も推奨しています。
結論
コード実行は複雑さを導入しますが、確立されたソフトウェアエンジニアリングパターンをエージェント開発に適用し、馴染みのあるプログラミング構造を通じてより効率的なMCPサーバー連携を実現します。