ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);"> ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">在 MCP 生态飞速发展的过程中,MCP的调用也呈现出一定问题,比如直接调用工具会让每一次定义和结果都占用上下文空间。 ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">11月4日,Anthropic发布了一篇文章,探讨通过编写代码来调用MCP工具,智能体能更好地扩展规模。 ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">Model Context Protocol(MCP)是一个开放标准,用于连接 AI 智能体与外部系统。过去,想让智能体与外部工具或数据交互,往往需要针对每种组合定制集成方式,这造成了碎片化和重复工作,也让大规模连接系统变得困难。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">MCP 通过通用协议解决了这个问题:开发者只需在智能体中实现一次 MCP,就能接入整个生态系统的工具与数据。ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> ingFang SC", system-ui, -apple-system, "system-ui", "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.544px;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">自 2024 年 11 月推出以来,MCP 发展迅速:MCP星球(官网:MCPmarket.cn)作为全网最大的MCP平台,拥有近4万个MCP Server,热门MCP提供一键直连API,并支持一键安装到Cursor等客户端。开发者常常会构建能访问上百乃至上千工具的智能体。然而,随着连接的工具越来越多,加载所有工具定义和在上下文中传递中间结果会显著降低性能、增加成本。
这篇文章将探讨如何通过代码执行(Code Execution)让智能体更高效地与 MCP 服务器交互,在处理更多工具的同时,使用更少的 tokens。
1. 工具调用引发的 Token 消耗问题MCP 使用扩大后,主要有两种常见模式导致智能体成本上升、响应变慢: 1)工具定义(Tool Definitions)塞满上下文窗口; 2) 中间结果(Intermediate Results)反复占用上下文空间。
1)工具定义占满上下文大多数 MCP 客户端会在启动时把所有工具定义一次性加载进上下文,例如: gdrive.getDocumentDescription:RetrievesadocumentfromGoogleDriveParameters:documentId(required,string):TheIDofthedocumenttoretrievefields(optional,string):SpecificfieldstoreturnReturns ocumentobjectwithtitle,bodycontent,metadata,permissions,etc. salesforce.updateRecordDescription:UpdatesarecordinSalesforceParameters bjectType(required,string):TypeofSalesforceobject(Lead,Contact,Account,etc.)recordId(required,string):TheIDoftherecordtoupdatedata(required,object):FieldstoupdatewiththeirnewvaluesReturns:Updatedrecordobjectwithconfirmation 工具描述会大量占用上下文窗口的 token 空间,从而增加响应时间和使用成本。当智能体连接几千个工具时,可能在理解请求之前就得处理几十万 token。
2) 中间结果消耗额外Token大多数MCP客户端允许模型直接调用MCP工具。例如,你让智能体执行任务:“从 Google Drive 下载会议记录,并附加到 Salesforce 销售线索上。”
模型会执行两次工具调用: 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 needstowrite entire transcript into context again)
每一个中间结果都必须经过模型传递。在上面的例子中,整份会议记录内容在流程中被传递了两次。
如果这是一次持续 2 小时的销售会议,记录文本可能就会额外占用5 万个 token。
而对于更大的文档,这种数据传递甚至可能超出模型的上下文窗口限制,导致整个工作流中断。
此外,当文档体量大或数据结构复杂时,模型在不同工具调用之间复制这些数据时,也更容易出现错误,比如遗漏内容、格式混乱或数据不匹配等问题。 MCP 客户端会将工具定义加载到模型的上下文窗口中,并在模型与工具之间协调一套消息循环机制(message loop)。在这个循环中,每一次工具调用及其返回结果,都需要经过模型本身来传递和处理, 这就导致上下文在多次交互中不断被占用和膨胀。 2. 使用 MCP 的代码执行方式随着代码执行环境在智能体中越来越普及,一种更高效的解决方案是: 👉将 MCP 服务器以代码 API 的形式呈现,而不是直接调用工具。
这样,智能体就可以直接编写代码来与 MCP 服务器交互。这种方法能同时解决前面提到的两大问题:
实现方式有多种,其中一种做法是:从已连接的 MCP 服务器生成一个包含所有可用工具的文件树结构(file tree)。
下面是一个使用TypeScript的示例: servers├──google-drive│├──getDocument.ts│├──...(othertools)│└──index.ts├──salesforce│├──updateRecord.ts│├──...(othertools)│└──index.ts└──...(otherservers) 每个工具对应一个文件,例如: // ./servers/google-drive/getDocument.tsimport{ callMCPTool }from"../../../client.js";
interfaceGetDocumentInput{documentId:string;}
interfaceGetDocumentResponse{content:string;}
/* Read a document from Google Drive */exportasyncfunctiongetDocument(input:GetDocumentInput) romise<GetDocumentResponse> {returncallMCPTool<GetDocumentResponse>('google_drive__get_document', input);}
上文的 Google Drive 到 Salesforce 的示例可以写成如下代码: // Read transcript from Google Docs and add to Salesforce prospectimport *asgdrivefrom'./servers/google-drive';import *assalesforcefrom'./servers/salesforce';
consttranscript= (await gdrive.getDocument({documentId:'abc123'})).content;await salesforce.updateRecord({objectType:'SalesMeeting',recordId:'00Q5f000001abcXYZ',data: {Notes: transcript }});
智能体通过遍历文件系统来发现可用工具: 1. 先列出./servers/目录,找到已连接的服务器(例如google-drive、salesforce); 2. 再读取其中具体的工具文件(如getDocument.ts、updateRecord.ts),以了解每个工具的接口定义。
这样,智能体只需加载当前任务所需的工具定义即可,无需一次性载入全部工具。
这种方式能将 token 使用量从15 万减少到2000个,实现98.7% 的时间与成本节省。
Cloudflare 也发表了类似的研究成果,他们将这种基于 MCP 的代码执行方式称为「Code Mode」。
其核心思想是一致的:大语言模型擅长编写代码,开发者应充分利用这一优势,让智能体以更高效、更可扩展的方式与 MCP 服务器进行交互。 3. 使用MCP进行代码执行的优势通过 MCP 实现的代码执行,让智能体能够更高效地利用上下文。
它可以按需加载工具、在数据进入模型前先进行过滤和处理,并能在一次执行中完成复杂逻辑。此外,这种方式在安全性和状态管理方面也带来了额外的好处。
1) 渐进式加载(Progressive Disclosure)
模型非常擅长浏览文件系统。当工具以代码文件的形式呈现在文件系统中时,模型就可以按需读取工具定义,而不是一开始就加载所有内容。
例如,在前文提到的 Salesforce 服务器场景中,可以为服务器添加一个search_tools工具,用于搜索相关的工具定义。
当智能体搜索 “salesforce” 时,它只会加载当前任务所需的那几个工具。
此外,还可以为search_tools工具添加一个细节级别参数(detail level),让智能体自行选择加载的定义程度:
这种机制能让智能体节省上下文空间,并更高效地发现合适的工具。
2) 上下文高效的结果处理(Context Efficient Tool Result)
当处理大规模数据集时,智能体可以在执行环境中先过滤、转换结果,再将精简后的数据返回模型。
例如,假设要获取一个包含 10,000 行数据的电子表格: // Without code execution - all rows flow through contextTOOLCALL: gdrive.getSheet(sheetId:'abc123') → returns10,000rowsincontext to filter manually
// With code execution - filter in the execution environmentconstallRows =awaitgdrive.getSheet({sheetId:'abc123'});constpendingOrders = 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
智能体最终只会看到前5 行数据,而不是完整的1 万行表格。
这种模式同样适用于聚合计算(aggregations)、跨多个数据源的关联(joins),或提取特定字段(field extraction)等场景,整个过程都不会让上下文窗口“爆炸”。
3) 更强大且更节省上下文的控制逻辑(More Powerful and Context-Efficient Control Flow)
通过代码执行,循环、条件判断、错误处理等逻辑都可以用常见的编程结构来实现,而不需要在每次工具调用之间反复让模型判断和响应。
例如,如果你需要在Slack中接受部署完成的通知,智能体可以这样写: letfound=false;while(!found){constmessages=awaitslack.getChannelHistory({channel:'C123456'});found=messages.some(m=>m.text.includes('deploymentcomplete'));if(!found)awaitnewPromise(r=>setTimeout(r,5000));}console.log('Deploymentnotificationreceived');这种方式比在智能体循环中反复切换MCP 工具调用与sleep 命令要高效得多。
此外,能够直接编写并执行条件分支(conditional tree)还能显著减少「首个 Token 延迟」(time to first token latency)。
也就是说,模型无需等待自身去判断if语句的结果,执行环境会直接处理这些逻辑,从而更快地进入下一步。
4) 隐私保护型操作(Privacy-Preserving Operations)
当智能体通过 MCP 执行代码时,中间结果默认保留在执行环境内,模型只会看到那些被明确记录(log)或返回(return)的内容。
这意味着,你不希望模型接触的数据,可以在整个流程中安全流转,而不会进入模型的上下文。
对于更加敏感的任务,智能体运行框架(Agent harness)还能自动对敏感数据进行脱敏与标记化(tokenization)。
例如,当你需要从电子表格中导入客户联系信息到 Salesforce 时,智能体可以这样编写代码: constsheet=awaitgdrive.getSheet({sheetId:'abc123'});for(constrowofsheet.rows){awaitsalesforce.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,Personally Identifiable Information)进行标记化处理(tokenization)。 //Whattheagentwouldsee,ifitloggedthesheet.rows:[{salesforceId:'00Q...',email:'[EMAIL_1]',phone:'[PHONE_1]',name:'[NAME_1]'},{salesforceId:'00Q...',email:'[EMAIL_2]',phone:'[PHONE_2]',name:'[NAME_2]'},...]随后,当这些数据在后续的 MCP 工具调用中被使用时,MCP 客户端会通过查找(lookup)机制自动进行反标记(untokenize),将占位符还原为真实的邮箱地址、电话号码和姓名。
因此,真实数据会在Google Sheets 与 Salesforce之间安全传递,但整个过程中,模型从未直接接触这些敏感信息。
这种机制能有效防止智能体无意间记录或处理隐私数据,
同时,开发者还可以基于此定义确定性的安全规则(deterministic security rules),明确规定哪些数据可以在哪些系统之间流动,实现更严格、更可控的数据安全策略。
5) 状态持久化与技能(State Persistence and Skills)
通过具备文件系统访问能力的代码执行环境,智能体可以在多次运行之间保持状态(persist state)。它能够将中间结果写入文件,以便后续任务继续使用或追踪进度。
例如: constleads =awaitsalesforce.query({query:'SELECT Id, Email FROM Lead LIMIT 1000'});constcsvData = leads.map(l=>`${l.Id},${l.Email}`).join('\n');awaitfs.writeFile('./workspace/leads.csv', csvData);
// Later execution picks up where it left offconstsaved =awaitfs.readFile('./workspace/leads.csv','utf-8');
智能体还可以将自己编写的代码保存为可复用的函数。当智能体为某个任务成功生成并验证了可用的代码后,它可以将这段实现保存下来,作为未来任务的现成工具重复使用。 // In ./skills/save-sheet-as-csv.tsimport*asgdrivefrom'./servers/google-drive';exportasyncfunctionsaveSheetAsCsv(sheetId: string) {constdata =awaitgdrive.getSheet({ sheetId });constcsv = data.map(row=>row.join(',')).join('\n');awaitfs.writeFile(`./workspace/sheet-${sheetId}.csv`, csv);return`./workspace/sheet-${sheetId}.csv`;}
// Later, in any agent execution:import{ saveSheetAsCsv }from'./skills/save-sheet-as-csv';constcsvPath =awaitsaveSheetAsCsv('abc123');
这与“技能(Skills)”的概念密切相关。技能是由一组可复用的指令、脚本和资源组成的目录,用于帮助模型在特定任务上获得更好的表现。
当智能体将这些可复用的函数保存下来,并在其中添加一个SKILL.md文件(用于说明该技能的用途、输入输出等),就能形成一个结构化的技能单元(structured skill)。
模型随后可以直接引用并调用这些技能,从而逐渐构建出一个包含高层能力的工具箱。
随着时间推移,智能体会在不断的任务中积累出一整套成熟的“脚手架”(scaffolding),让它在未来的工作中运行得更稳定、更高效。
不过,代码执行本身也引入了一定复杂性。运行由智能体生成的代码,需要一个安全的执行环境,包括沙盒隔离(sandboxing)、资源限制(resource limits)和运行监控(monitoring)等机制。
这些基础设施要求会带来额外的运维成本和安全考量,而这正是直接调用工具(direct tool calls)所不需要的。
因此,采用代码执行模式的好处,需要在收益与实现复杂度之间做出权衡。例如降低 token 成本、减少延迟、提高工具组合灵活性, 4. 总结MCP 为智能体提供了一个连接多种工具与系统的基础协议。但当连接的服务器过多时,工具定义与结果数据会迅速消耗上下文空间,降低运行效率。
虽然这些问题(上下文管理、工具组合、状态持久化等)看起来很新,但在传统软件工程中早已有成熟的解决方案。
代码执行(Code Execution)将这些经典模式引入智能体架构,让模型能够通过熟悉的编程逻辑更高效地与 MCP 服务器交互。 |