摘要
代码模式让 AI 智能体运行一段调用多个 MCP 工具的简短程序,而不是通过模型逐个调用这些工具。本文介绍为什么这样可以节省 token 和往返次数、何时有用、何时没用,以及 AnythingMCP 如何在隔离的运行器中提供三种形式:已保存的代码工具、内联代码和智能体提案。
TL;DR: 使用普通 MCP 时,AI 智能体先调用一个工具,读取完整结果,做出判断,再调用下一个工具,如此往复。每一步都要经过一次模型往返,每个中间结果都会占用模型的上下文窗口。代码模式让智能体(或管理员提前)编写一段简短的 JavaScript 程序,由它发起这些调用、过滤并关联结果,只返回最终答案。在 AnythingMCP 中,程序运行在一个隔离的运行器里,它只能访问调用者本来就有权使用的 MCP 工具。代码模式从 v0.52.0 起在自托管 AnythingMCP 中可用,AnythingMCP Cloud 即将支持;默认处于关闭状态,需要你手动开启。
问题:工具调用都要经过模型
假设销售负责人向一个已连接 CRM 和 ERP 的助手提问:
"我们哪些未结报价单属于仍有逾期发票的客户?"
如果每一步都是一次工具调用,智能体会这样做:
- 调用 CRM 列出未结报价单(比如 40 条),并把这 40 条全部读入上下文;
- 针对每位客户调用一次 ERP 查询未结发票:再调用 40 次,上下文中又多了 40 个结果;
- 在"脑中"做比对,然后写出答案。
每次调用都是一个回合:模型写出调用,客户端执行,结果送回模型,模型阅读后再写下一个调用。完整的结果会一直留在上下文中,而答案可能只需要五行。这会带来 token 成本(模型读取的所有内容都会计费,并占用上下文窗口)、时间成本(几十个回合),以及准确性问题(靠阅读来比对 40 份列表,正是模型容易出错的地方)。
思路:让模型改写一段程序
语言模型很擅长编写简短的程序。因此,智能体不再亲自逐个发起调用,而是写一段程序:
const quotes = await amcp.run('crm_list_open_quotes', {});
const overdue = [];
for (const q of quotes) {
const invoices = await amcp.run('erp_open_invoices', { customer: q.customerId });
const late = invoices.filter((i) => i.dueDate < new Date().toISOString().slice(0, 10));
if (late.length) overdue.push({ quote: q.number, customer: q.customerName, overdueInvoices: late.length });
}
return overdue;
工具名称仅为示例;实际使用的是你的连接器所提供的工具。
程序运行在工具旁边。40 条报价记录和 40 份发票列表都不会进入模型的上下文,只有返回的列表会进入。四十一个回合变成了一个回合。这一思路在 2025 年以"code mode"和"code execution with MCP"等名称流行起来;AnythingMCP 将其实现为网关中一项受管控的功能。
| 每步一次工具调用 | 代码模式 | |
|---|---|---|
| 经过模型的回合数 | 每次调用一个回合(示例中为 41) | 一个 |
| 进入上下文的内容 | 每一个中间结果 | 程序及其返回值 |
| 循环、过滤、关联 | 由模型通过阅读完成 | 由代码精确完成 |
| 最适合 | 单次查询、需要判断的步骤 | 重复性、机械化的多步骤工作 |
AnythingMCP 中的三种形式
已保存的代码工具。 管理员编写一次程序,并将其保存为工具,例如 customer_overview(customer),它会读取 ERP 和 CRM 并返回一份汇总。对 AI 客户端来说,它就是一个普通的 MCP 工具:会被列出、按角色授权、可审计。智能体只需调用它即可。构建你的第一个代码工具。
内联代码(code_execute)。 在启用该功能的服务器上,智能体可以当场编写并运行程序,作用范围是用户有权使用的工具。始终只读,始终使用调用者自己的权限。
提案(code_propose_tool)。 当智能体发现某个值得保留的多步骤模式时,可以把它作为已保存的代码工具提出提案。提案不会运行任何东西,也不会创建任何东西;由管理员审阅程序后点击 Create tool。提案如何获得批准。
如何保证安全
模型编写的代码从本质上就是不可信的:被提示注入的工具结果可能左右模型写出的内容。因此 AnythingMCP 绝不会在自己的进程中运行它。每次运行都会交给独立的 code-runner 服务,每次运行对应一个被严格锁定的子进程,没有网络、没有文件系统、没有环境变量,也没有任何密钥。唯一的出口是 amcp.run,网关会以调用者的角色来响应它,读写规则与直接调用工具时相同。每次运行以及其中的每个工具调用都会记录在审计日志中。完整模型见:AI 智能体的安全代码执行。
代码模式何时有用,何时没用
适合的情况:工作是机械且重复的,例如对 100 篇文章做同样的查询、跨两个系统求和、将发票与订单匹配,或者总是需要相同五次调用的报表。参见三个示例方案。
不适合的情况:只需要一次调用(围绕单次调用写程序只会多出一步),或者每一步都需要模型根据刚读到的内容做判断(例如"阅读这份合同,然后决定下一步检查什么")。写操作受到刻意限制:内联代码永远不会执行写操作;已保存的代码工具只有在管理员允许时才能调用写入类工具,且仅限 Enterprise 版。
可用性与限制
| 自托管(v0.52.0+) | AnythingMCP Cloud | |
|---|---|---|
| 代码模式 | 可用,默认关闭 | 即将推出 |
| 要求 | 需要 code-runner 服务,并在每个 MCP 服务器上单独开启代码模式 | – |
各版本的情况(随 v0.52 发布):
| Community | Starter | Team | Enterprise | |
|---|---|---|---|---|
| 已保存的代码工具 | 3 | 5 | 20 | 无限制 |
| 内联代码与智能体提案 | – | – | ✓ | ✓ |
| 可执行写操作的代码工具("以定义者身份运行") | – | – | – | ✓ |
单次运行限制为 10 秒、500 次工具调用(同时最多 16 个)以及 1 MB 的返回数据。代码工具仅在工作区自己的 MCP 服务器上提供,绝不会出现在目录类 AI 客户端使用的共享 /mcp 端点上。比较各套餐。
FAQ
代码模式是 MCP 的替代品吗? 不是。它只是使用 MCP 工具的一种方式。程序调用的是智能体本来也可以直接调用的同一批工具,经过同样的网关和权限。
哪些 AI 客户端支持它?
全部支持。已保存的代码工具是普通的 MCP 工具,code_execute 则是一个以程序作为参数的普通工具。Claude、ChatGPT、Copilot、Gemini 和 Cursor 都可以调用这两者。
使用哪种语言?
JavaScript,作为异步函数的函数体。不能使用 import,也没有任何软件包:程序只有 amcp 和语言本身。
能节省多少? 完全取决于任务。单次查询不会节省任何东西。而一个原本需要把几十个中间结果读入上下文的任务,则可以节省其中大部分 token 和回合数,因为只有返回值会回到模型。
相关阅读
- 一步一步构建你的第一个代码工具:一次调用获取 ERP 订单和 CRM 客户账户
- AI 智能体的安全代码执行:隔离运行器的工作原理
- 代码模式示例方案:月度收入、发票对账、100 次价格查询
- 智能体提出代码工具提案,管理员批准
- 什么是 MCP?
- MCP 治理、用户角色与权限
这份指南对你有帮助吗?