摘要

1) 一句话总结

通过将模型上下文协议 (MCP) 与代码执行相结合,智能体能够以编写代码的方式按需调用工具并处理中间数据,从而显著降低 token 消耗、提升运行效率并增强数据隐私。

2) 关键要点

  • 传统模式的瓶颈:随着 MCP 连接工具数量的增加,预加载所有工具定义以及通过模型传递中间结果会使上下文窗口超载,导致延迟增加和 token 成本高昂。
  • 代码执行解决方案:将 MCP 服务器作为代码 API(例如呈现为文件树)暴露给智能体,让智能体通过编写代码来与服务器交互,而非直接进行工具调用。
  • 渐进式披露(按需加载):智能体可以通过导航文件系统或使用 search_tools 功能,仅加载当前任务所需的工具定义。案例显示,此方法可将 token 使用量从 150,000 降至 2,000,节省 98.7% 的时间和成本。
  • 提升上下文效率:智能体可以在代码环境中对大型数据集进行过滤、聚合和转换(例如只提取 10,000 行表格中的 5 行),避免海量中间数据使上下文膨胀。
  • 优化复杂逻辑处理:循环、条件判断和错误处理可直接在代码中执行,无需模型反复参与,从而节省了“首个 token 延迟 (time to first token)”。
  • 保护隐私的操作:中间结果默认保留在执行环境中。配合 MCP 客户端的自动标记化 (tokenization) 拦截机制,敏感数据(PII)可以在不同工具间流转,而永远不会进入模型的上下文。
  • 状态持久化与技能构建:智能体可以将中间结果写入文件以保持跨操作的状态,或将成功的代码实现保存为带有 SKILL.md 的可重用“技能 (Skills)”,逐步构建高级工具箱。

3) 风险与不足

  • 安全与基础设施要求:运行智能体生成的代码需要构建安全的执行环境,必须配备适当的沙箱机制、资源限制和监控。
  • 运营开销增加:相比于直接的工具调用,代码执行引入了额外的基础设施复杂性,增加了运营开销和安全考量,开发者需要在效率收益与实现成本之间进行权衡。

正文

模型上下文协议 (MCP) 是一个用于将 AI 智能体连接到外部系统的开放标准。传统上,将智能体连接到工具和数据需要为每个配对进行自定义集成,这会导致碎片化和重复劳动,使得真正互联的系统难以扩展。MCP 提供了一个通用协议——开发者只需在其智能体中实现一次 MCP,即可解锁整个集成生态系统。

自 2024 年 11 月推出 MCP 以来,其普及速度非常快:社区已经构建了数千个 MCP 服务器,所有主流编程语言都有可用的 SDK,并且业界已将 MCP 视为连接智能体与工具和数据的事实标准。

如今,开发者经常构建能够访问数十个 MCP 服务器上成百上千种工具的智能体。然而,随着连接工具数量的增加,预先加载所有工具定义并通过上下文窗口传递中间结果,会拖慢智能体的速度并增加成本。

在本博客中,我们将探讨代码执行如何使智能体更高效地与 MCP 服务器交互,在处理更多工具的同时消耗更少的 token。

工具消耗过多 token 会降低智能体的效率

随着 MCP 使用规模的扩大,有两种常见模式会增加智能体的成本和延迟:

  • 工具定义使上下文窗口超载;

  • 中间工具结果消耗额外的 token。

1. 工具定义使上下文窗口超载

大多数 MCP 客户端会预先将所有工具定义直接加载到上下文中,使用直接的工具调用语法将它们暴露给模型。这些工具定义可能如下所示:

工具描述占据了更多的上下文窗口空间,增加了响应时间和成本。在智能体连接到数千个工具的情况下,它们在读取请求之前就需要处理数十万个 token。

2. 中间工具结果消耗额外的 token

大多数 MCP 客户端允许模型直接调用 MCP 工具。例如,您可能会要求您的智能体:“从 Google Drive 下载我的会议记录,并将其附加到 Salesforce 的潜在客户中。”

模型将进行如下调用:

每个中间结果都必须经过模型。在这个例子中,完整的通话记录流转了两次。对于一个 2 小时的销售会议,这可能意味着需要额外处理 50,000 个 token。更大的文档甚至可能超出上下文窗口的限制,从而中断工作流。

在处理大型文档或复杂数据结构时,模型在工具调用之间复制数据时可能更容易出错。

结合 MCP 的代码执行提高了上下文效率

随着代码执行环境在智能体中变得越来越普遍,一种解决方案是将 MCP 服务器呈现为代码 API,而不是直接的工具调用。然后,智能体可以编写代码来与 MCP 服务器交互。这种方法解决了上述两个挑战:智能体可以仅加载它们需要的工具,并在将结果传回模型之前在执行环境中处理数据。

实现这一点有多种方法。一种方法是从连接的 MCP 服务器生成所有可用工具的文件树。以下是使用 TypeScript 的实现示例:

然后每个工具对应一个文件,大致如下:

我们上面 Google Drive 到 Salesforce 的例子就变成了如下代码:

智能体通过探索文件系统来发现工具:列出 ./servers/ 目录以查找可用的服务器(如 google-drivesalesforce),然后读取它需要的特定工具文件(如 getDocument.tsupdateRecord.ts)以了解每个工具的接口。这使得智能体能够仅加载当前任务所需的定义。这将 token 使用量从 150,000 个 token 减少到 2,000 个 token——节省了 98.7% 的时间和成本。

Cloudflare 发表了类似的发现,将结合 MCP 的代码执行称为“代码模式 (Code Mode)”。其核心见解是一致的:LLM 擅长编写代码,开发者应该利用这一优势来构建能够更高效地与 MCP 服务器交互的智能体。

结合 MCP 的代码执行的优势

结合 MCP 的代码执行使智能体能够通过按需加载工具、在数据到达模型之前对其进行过滤以及在单个步骤中执行复杂逻辑,从而更高效地使用上下文。使用这种方法在安全性和状态管理方面也有好处。

渐进式披露

模型非常擅长导航文件系统。将工具作为文件系统上的代码呈现,允许模型按需读取工具定义,而不是预先读取所有定义。

或者,可以在服务器中添加一个 search_tools 工具来查找相关的定义。例如,在使用上述假设的 Salesforce 服务器时,智能体搜索“salesforce”并仅加载当前任务所需的那些工具。在 search_tools 工具中包含一个详细级别参数,允许智能体选择所需的详细程度(例如仅名称、名称和描述,或带有模式的完整定义),这也有助于智能体节省上下文并高效地查找工具。

上下文高效的工具结果

在处理大型数据集时,智能体可以在返回结果之前在代码中对其进行过滤和转换。考虑获取一个包含 10,000 行的电子表格:

智能体看到的是 5 行而不是 10,000 行。类似的模式也适用于聚合、跨多个数据源的连接或提取特定字段——所有这些都不会使上下文窗口膨胀。

循环、条件判断和错误处理可以使用熟悉的代码模式来完成,而不是将单个工具调用链接起来。例如,如果您需要在 Slack 中发送部署通知,智能体可以编写:

这种方法比在智能体循环中交替使用 MCP 工具调用和 sleep 命令更高效。

此外,能够写出并执行条件树还可以节省“首个 token 延迟 (time to first token)”:智能体可以让代码执行环境来评估 if 语句,而无需等待模型来执行此操作。

保护隐私的操作

当智能体结合 MCP 使用代码执行时,中间结果默认保留在执行环境中。这样,智能体只能看到您明确记录 (log) 或返回的内容,这意味着您不希望与模型共享的数据可以在您的工作流中流转,而永远不会进入模型的上下文。

对于更敏感的工作负载,智能体框架 (agent harness) 可以自动对敏感数据进行标记化 (tokenize) 处理。例如,假设您需要将客户联系方式从电子表格导入 Salesforce。智能体编写:

MCP 客户端会拦截数据,并在 PII(个人身份信息)到达模型之前对其进行标记化:

然后,当数据在另一个 MCP 工具调用中共享时,MCP 客户端会通过查找将其还原 (untokenize)。真实的电子邮件地址、电话号码和姓名从 Google Sheets 流向 Salesforce,但绝不会经过模型。这可以防止智能体意外记录或处理敏感数据。您还可以使用此功能来定义确定性的安全规则,选择数据的流向和来源。

状态持久化与技能

具有文件系统访问权限的代码执行允许智能体在跨操作时保持状态。智能体可以将中间结果写入文件,从而使其能够恢复工作并跟踪进度:

智能体还可以将其自己的代码持久化为可重用的函数。一旦智能体为某项任务开发了可用的代码,它就可以保存该实现以供将来使用:

这与技能 (Skills) 的概念密切相关,即包含可重用指令、脚本和资源的文件夹,用于提高模型在特定任务上的性能。向这些保存的函数添加一个 SKILL.md 文件,可以创建一个结构化的技能,供模型参考和使用。随着时间的推移,这允许您的智能体构建一个包含更高级别功能的工具箱,从而进化出其最高效工作所需的脚手架。

请注意,代码执行会引入其自身的复杂性。运行智能体生成的代码需要一个安全的执行环境,并配备适当的沙箱机制、资源限制和监控。这些基础设施要求增加了直接工具调用所能避免的运营开销和安全考量。在享受代码执行带来的好处(降低 token 成本、降低延迟和改进工具组合)时,应权衡这些实现成本。

总结

MCP 为智能体连接众多工具和系统提供了一个基础协议。然而,一旦连接了过多的服务器,工具定义和结果可能会消耗过多的 token,从而降低智能体的效率。

尽管这里的许多问题感觉很新颖——上下文管理、工具组合、状态持久化——但它们在软件工程中都有已知的解决方案。代码执行将这些成熟的模式应用于智能体,让它们能够使用熟悉的编程结构更高效地与 MCP 服务器交互。如果您实现了这种方法,我们鼓励您与 MCP 社区分享您的发现。

致谢

本文由 Adam Jones 和 Conor Kelly 撰写。感谢 Jeremy Fox、Jerome Swannack、Stuart Ritchie、Molly Vorwerck、Matt Samuels 和 Maggie Vo 对本文初稿提供的反馈。

关联主题