Anthropic Engineering Blog 中文翻译

create: 2025-11-04
update: 2026-08-10
author: thinkycx
title: 【译】通过代码执行构建更高效的 MCP Agent
description: 随着 MCP 服务器数量增长,工具定义和中间结果会大量消耗上下文窗口 token,导致 Agent 效率下降。本文提出"代码执行"方案——让 Agent 编写代码调用 MCP 工具而非直接调用,从而实现按需发现工具、上下文高效利用、隐私保护和状态持久化,token 消耗可降低 98.7%。
category: translation
tags: anthropic, engineering, translation, mcp, code-execution

通过代码执行构建更高效的 MCP Agent

原文发布于 2025 年 11 月 4 日,作者 Adam Jones 和 Conor Kelly

引言

直接调用工具会让每个工具定义和结果都占用上下文,Agent 通过编写代码来调用工具可以更好地扩展。

MCP 是一个用于连接 AI Agent 与外部系统的开放标准。自 2024 年 11 月发布以来,社区已构建了数千个 MCP 服务器,各主流编程语言都有对应的 SDK

然而,随着连接的工具越来越多,一个核心问题浮现:预先加载所有工具定义,并将中间结果传递到上下文窗口中,会拖慢 Agent 并增加成本。


工具的过度 Token 消耗让 Agent 效率下降

工具定义和中间结果是两个主要的 token 消耗来源,严重制约 Agent 的扩展能力。

问题一:工具定义挤占上下文窗口

大多数 MCP 客户端会预先加载所有工具定义。以下是两个典型工具定义示例:

gdrive.getDocument
     Description: Retrieves a document from Google Drive
     Parameters:
                documentId (required, string): The ID of the document to retrieve
                fields (optional, string): Specific fields to return
     Returns: Document object with title, body content, metadata, permissions, etc.
salesforce.updateRecord
    Description: Updates a record in Salesforce
    Parameters:
               objectType (required, string): Type of Salesforce object (Lead, Contact, Account, etc.)
               recordId (required, string): The ID of the record to update
               data (required, object): Fields to update with their new values
     Returns: Updated record object with confirmation

当 Agent 连接数千个工具时,还没开始读取用户请求,就已经处理了数十万 token 的工具定义。

问题二:中间工具结果消耗额外 token

以"转移会议记录"为例,展示中间结果如何膨胀上下文:

TOOL CALL: gdrive.getDocument(documentId: "abc123")
         returns "Discussed Q4 goals...\n[full transcript text]"
           (loaded into model context)

TOOL CALL: salesforce.updateRecord(
            objectType: "SalesMeeting",
            recordId: "00Q5f000001abcXYZ",
            data: { "Notes": "Discussed Q4 goals...\n[full transcript text written out]" }
        )
        (model needs to write entire transcript into context again)

一场 2 小时的销售会议,仅这一个操作就可能额外处理 50,000 个 token。更大的文档甚至可能完全超出上下文窗口限制。

MCP 客户端架构示意

MCP 客户端将工具定义加载到模型的上下文窗口中,并编排消息循环。


代码执行方案:提升上下文效率

核心思路:将 MCP 服务器呈现为代码 API,让 Agent 编写代码来调用工具,而非直接进行工具调用。

一种实现方式是为所有可用工具生成文件树:

servers
├── google-drive
   ├── getDocument.ts
   ├── ... (other tools)
   └── index.ts
├── salesforce
   ├── updateRecord.ts
   ├── ... (other tools)
   └── index.ts
└── ... (other servers)

每个工具对应一个带类型定义的文件:

// ./servers/google-drive/getDocument.ts
import { callMCPTool } from "../../../client.js";

interface GetDocumentInput {
  documentId: string;
}

interface GetDocumentResponse {
  content: string;
}

/* Read a document from Google Drive */
export async function getDocument(input: GetDocumentInput): Promise<GetDocumentResponse> {
  return callMCPTool<GetDocumentResponse>('google_drive__get_document', input);
}

同样的"Google Drive 到 Salesforce"任务,用代码执行方式实现:

// 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 }
});

Agent 通过探索文件系统来发现可用工具。这将 token 消耗从 150,000 降低到 2,000——节省了 98.7% 的时间和成本。

Cloudflare 也发布了类似的发现,将这种方式称为"Code Mode"。


代码执行带来的五大优势

一、按需渐进式发现工具(Progressive Disclosure)

模型通过浏览文件系统按需读取工具定义,无需预先加载所有内容。

另一种替代实现是提供一个 search_tools 工具,可按不同详细程度查找相关定义:

详细程度 返回内容
仅名称 工具名称列表
名称 + 描述 工具名称及功能简介
完整定义 包含参数 schema 的完整定义

二、上下文高效的工具结果处理

Agent 在代码执行环境中过滤和转换结果,只将必要信息返回上下文。

// Without code execution - all rows flow through context
TOOL CALL: gdrive.getSheet(sheetId: 'abc123')
         returns 10,000 rows in context to filter manually

// With code execution - filter in the execution environment
const allRows = await gdrive.getSheet({ sheetId: 'abc123' });
const pendingOrders = allRows.filter(row => 
  row["Status"] === 'pending'
);
console.log(`Found ${pendingOrders.length} pending orders`);
console.log(pendingOrders.slice(0, 5)); // Only log first 5 for review

Agent 只看到 5 行数据,而不是 10,000 行。

三、更强大且上下文高效的控制流

循环、条件判断和错误处理使用熟悉的代码模式,无需每一步都等待模型推理。

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));
}
console.log('Deployment notification received');

这也降低了"首 token 延迟"(time to first token),因为代码执行环境在不等待模型评估的情况下处理条件判断。

四、隐私保护操作

中间结果默认留在执行环境中,敏感数据在系统间流转但不经过模型。

例如,批量导入客户信息时无需将 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
    }
  });
}
console.log(`Updated ${sheet.rows.length} leads`);

MCP 客户端还可以自动对 PII 进行脱敏处理(tokenization):

// What the agent would see, if it logged the sheet.rows:
[
  { salesforceId: '00Q...', email: '[EMAIL_1]', phone: '[PHONE_1]', name: '[NAME_1]' },
  { salesforceId: '00Q...', email: '[EMAIL_2]', phone: '[PHONE_2]', name: '[NAME_2]' },
  ...
]

真实数据在系统间流动,但绝不经过模型。开发者可以定义确定性的安全规则,决定数据可以从哪里流向哪里

五、状态持久化与技能复用(State Persistence and Skills)

Agent 可将中间结果写入文件,后续执行无缝衔接;还可沉淀可复用的技能函数。

状态持久化示例:

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);

// Later execution picks up where it left off
const saved = await fs.readFile('./workspace/leads.csv', 'utf-8');

技能复用示例:

// In ./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`;
}

// Later, in any agent execution:
import { saveSheetAsCsv } from './skills/save-sheet-as-csv';
const csvPath = await saveSheetAsCsv('abc123');

这与 Skills(技能)概念相呼应——可复用的指令、脚本和资源。添加 SKILL.md 文件可以创建结构化的技能供模型引用。


权衡取舍

代码执行带来了额外的工程复杂度,需要安全执行环境、资源限制和监控体系。

方面 直接工具调用 代码执行
实现复杂度 高(需要沙箱、资源限制、监控)
Token 效率 差(随工具数量线性增长) 好(按需发现,中间结果不入上下文)
隐私保护 弱(数据经过模型) 强(数据留在执行环境)
扩展性
状态管理 支持持久化和复用

应当权衡代码执行的收益与实现成本——并非所有场景都需要这种方案。


总结

MCP 提供了基础协议,但随着服务器规模增长,工具定义和结果会消耗过多 token。代码执行将软件工程中的成熟模式应用于 Agent,解决了上下文管理、工具组合和状态持久化问题。

核心问题都有软件工程领域的已知解决方案:

问题 代码执行的解决方式
上下文管理 按需发现工具,中间结果不入上下文
工具组合 代码中自由组合调用
状态持久化 文件系统存储中间状态

欢迎开发者将实践经验分享给 MCP 社区


致谢

感谢 Jeremy Fox、Jerome Swannack、Stuart Ritchie、Molly Vorwerck、Matt Samuels 和 Maggie Vo 对本文的反馈。

相关链接