mcp-code-execution
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMCP Code Execution Pattern
MCP 代码执行模式
Expert knowledge for designing agent systems that generate and execute code to interact with MCP servers, instead of calling tools directly.
用于设计Agent系统的专业知识,这类Agent系统会生成并执行代码与MCP服务器交互,而非直接调用工具。
When to Use This Pattern
适用场景
| Use code execution when... | Use direct tool calls when... |
|---|---|
| Connecting to 10+ MCP servers or 50+ tools | Few servers with handful of tools |
| Intermediate results are large (>10K tokens) | Results are small and all needed by the model |
| Workflows need loops, retries, or conditionals | Linear sequences of 2-3 tool calls |
| PII must not reach the model context | No sensitive data in tool responses |
| Tasks benefit from state persistence across runs | Stateless, one-shot operations |
| You want agents to accumulate reusable skills | Fixed, predefined workflows |
| 适合使用代码执行模式的场景 | 适合直接调用工具的场景 |
|---|---|
| 需要连接10个以上MCP服务器或50个以上工具 | 仅需对接少量服务器和少数几个工具 |
| 中间结果体积大(超过1万tokens) | 结果体积小,且模型需要完整结果 |
| 工作流需要循环、重试或条件判断逻辑 | 仅需2-3次工具调用的线性流程 |
| PII不得传入模型上下文 | 工具响应中不含敏感数据 |
| 任务需要跨运行保留状态 | 无状态的一次性操作 |
| 需要Agent积累可复用的技能 | 固定的预定义工作流 |
Core Architecture
核心架构
How It Works
运行逻辑
Instead of loading all MCP tool definitions into the model context upfront, the agent:
- Discovers available tools by navigating a typed file tree
- Generates TypeScript/Python code that imports and calls typed wrapper functions
- Executes the code in a sandboxed environment
- Returns only filtered/summarized results to the model
This reduces token usage from O(all_tool_definitions) to O(only_relevant_imports).
无需提前将所有MCP工具定义加载到模型上下文中,Agent会按以下步骤执行:
- 发现:通过遍历结构化文件树查找可用工具
- 生成:编写TypeScript/Python代码,导入并调用带类型定义的封装函数
- 执行:在沙箱环境中运行代码
- 返回:仅将过滤/摘要后的结果返回给模型
该模式将token消耗量从O(所有工具定义)降低到O(仅相关导入内容)。
File Tree Structure
文件树结构
project/
├── servers/
│ ├── google-drive/
│ │ ├── getDocument.ts
│ │ ├── getSheet.ts
│ │ ├── listFiles.ts
│ │ └── index.ts # Re-exports all tools
│ ├── salesforce/
│ │ ├── query.ts
│ │ ├── updateRecord.ts
│ │ └── index.ts
│ └── slack/
│ ├── sendMessage.ts
│ ├── getChannelHistory.ts
│ └── index.ts
├── skills/ # Agent-accumulated reusable functions
│ └── save-sheet-as-csv.ts
├── workspace/ # Persistent state between executions
├── client.ts # MCP client that routes calls to servers
└── sandbox.config.ts # Execution environment configurationproject/
├── servers/
│ ├── google-drive/
│ │ ├── getDocument.ts
│ │ ├── getSheet.ts
│ │ ├── listFiles.ts
│ │ └── index.ts # 重新导出所有工具
│ ├── salesforce/
│ │ ├── query.ts
│ │ ├── updateRecord.ts
│ │ └── index.ts
│ └── slack/
│ ├── sendMessage.ts
│ ├── getChannelHistory.ts
│ └── index.ts
├── skills/ # Agent积累的可复用函数
│ └── save-sheet-as-csv.ts
├── workspace/ # 跨执行的持久化状态存储
├── client.ts # 负责将调用路由到对应服务器的MCP客户端
└── sandbox.config.ts # 执行环境配置Typed Wrapper Pattern
类型封装模式
Each MCP tool gets a typed wrapper function that the agent imports:
typescript
// 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);
}The agent then writes code that uses these wrappers naturally:
typescript
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 },
});每个MCP工具都对应一个带类型定义的封装函数,供Agent导入使用:
typescript
// servers/google-drive/getDocument.ts
import { callMCPTool } from "../../client.js";
interface GetDocumentInput {
documentId: string;
}
interface GetDocumentResponse {
content: string;
}
/** 从Google Drive读取文档 */
export async function getDocument(
input: GetDocumentInput
): Promise<GetDocumentResponse> {
return callMCPTool<GetDocumentResponse>("google_drive__get_document", input);
}Agent可以直接编写代码调用这些封装函数:
typescript
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 },
});Key Patterns
核心模式
1. Progressive Tool Discovery
1. 渐进式工具发现
The agent navigates the filesystem to find relevant tools on demand, instead of loading all definitions upfront.
Agent: "I need to read from Google Drive"
→ ls servers/
→ ls servers/google-drive/
→ cat servers/google-drive/getDocument.ts (reads signature + JSDoc)
→ generates code importing only getDocumentToken impact: 150,000 tokens (all definitions) reduced to ~2,000 tokens (one definition). 98.7% reduction.
Agent按需遍历文件系统查找相关工具,无需提前加载所有工具定义。
Agent: "我需要从Google Drive读取数据"
→ ls servers/
→ ls servers/google-drive/
→ cat servers/google-drive/getDocument.ts (读取函数签名 + JSDoc注释)
→ 生成仅导入getDocument的代码Token消耗影响:150000 tokens(全量定义)降低到约2000 tokens(单个工具定义),减少了98.7%。
2. Context-Efficient Data Filtering
2. 上下文高效数据过滤
Filter large datasets in the execution environment before results reach the model:
typescript
// Filter in the sandbox — only summary reaches the model
const allRows = await gdrive.getSheet({ sheetId: "abc123" });
const pending = allRows.filter((row) => row["Status"] === "pending");
console.log(`Found ${pending.length} pending orders`);
console.log(pending.slice(0, 5)); // Only first 5 for model review在执行环境中先过滤大数据集,再将结果返回给模型:
typescript
// 在沙箱中完成过滤 —— 仅摘要会传入模型
const allRows = await gdrive.getSheet({ sheetId: "abc123" });
const pending = allRows.filter((row) => row["Status"] === "pending");
console.log(`Found ${pending.length} pending orders`);
console.log(pending.slice(0, 5)); // 仅返回前5条供模型审核3. Native Control Flow
3. 原生控制流
Replace chained tool calls with code-native loops and conditionals:
typescript
// Polling loop — runs entirely in sandbox
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");用代码原生的循环和条件判断替代链式工具调用:
typescript
// 轮询循环 —— 完全在沙箱中运行
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");4. PII Tokenization
4. PII脱敏
The MCP client intercepts responses and tokenizes sensitive data before it reaches the model:
typescript
// Agent writes this code
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`);What the model sees in the execution output:
[
{ salesforceId: "00Q...", email: "[EMAIL_1]", phone: "[PHONE_1]", name: "[NAME_1]" },
{ salesforceId: "00Q...", email: "[EMAIL_2]", phone: "[PHONE_2]", name: "[NAME_2]" }
]
Updated 247 leadsThe actual PII flows between external systems without entering model context.
MCP客户端会拦截响应,在结果传入模型前对敏感数据进行脱敏替换:
typescript
// Agent编写的代码
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");模型在执行输出中看到的内容:
[
{ salesforceId: "00Q...", email: "[EMAIL_1]", phone: "[PHONE_1]", name: "[NAME_1]" },
{ salesforceId: "00Q...", email: "[EMAIL_2]", phone: "[PHONE_2]", name: "[NAME_2]" }
]
Updated 247 leads实际的PII仅在外部系统之间流转,不会进入模型上下文。
5. State Persistence
5. 状态持久化
Save intermediate results to the workspace for cross-execution continuity:
typescript
// Execution 1: fetch and save
const leads = await salesforce.query({
query: "SELECT Id, Email FROM Lead LIMIT 1000",
});
await fs.writeFile("./workspace/leads.csv", leads.map((l) => `${l.Id},${l.Email}`).join("\n"));
// Execution 2: resume from saved state
const saved = await fs.readFile("./workspace/leads.csv", "utf-8");将中间结果保存到工作区,实现跨执行的状态延续:
typescript
// 第一次执行:拉取并保存数据
const leads = await salesforce.query({
query: "SELECT Id, Email FROM Lead LIMIT 1000",
});
await fs.writeFile("./workspace/leads.csv", leads.map((l) => `${l.Id},${l.Email}`).join("\
"));
// 第二次执行:从保存的状态恢复工作
const saved = await fs.readFile("./workspace/leads.csv", "utf-8");6. Skill Accumulation
6. 技能积累
Agents persist reusable functions as skills for future executions:
typescript
// skills/save-sheet-as-csv.ts
import * as gdrive from "../servers/google-drive";
import * as fs from "fs/promises";
export async function saveSheetAsCsv(sheetId: string): Promise<string> {
const data = await gdrive.getSheet({ sheetId });
const csv = data.map((row) => row.join(",")).join("\n");
const path = `./workspace/sheet-${sheetId}.csv`;
await fs.writeFile(path, csv);
return path;
}Later executions import the skill directly:
typescript
import { saveSheetAsCsv } from "./skills/save-sheet-as-csv";
const csvPath = await saveSheetAsCsv("abc123");Agent将可复用的函数作为技能持久化,供后续执行使用:
typescript
// skills/save-sheet-as-csv.ts
import * as gdrive from "../servers/google-drive";
import * as fs from "fs/promises";
export async function saveSheetAsCsv(sheetId: string): Promise<string> {
const data = await gdrive.getSheet({ sheetId });
const csv = data.map((row) => row.join(",")).join("\
");
const path = `./workspace/sheet-${sheetId}.csv`;
await fs.writeFile(path, csv);
return path;
}后续执行可以直接导入该技能:
typescript
import { saveSheetAsCsv } from "./skills/save-sheet-as-csv";
const csvPath = await saveSheetAsCsv("abc123");Scaffolding a New Project
新项目脚手架搭建
Step 1: Identify MCP Servers
步骤1:确定MCP服务器
List the MCP servers the agent needs to interact with. Check or the project's MCP configuration:
.mcp.jsonbash
cat .mcp.json 2>/dev/null || echo "No MCP config found"列出Agent需要交互的MCP服务器列表,查看或项目的MCP配置:
.mcp.jsonbash
cat .mcp.json 2>/dev/null || echo "No MCP config found"Step 2: Generate Server Directory
步骤2:生成服务器目录
For each MCP server, create a directory with typed wrappers. Each tool gets its own file with:
- Input interface
- Output interface
- JSDoc comment describing the tool
- Async function wrapping
callMCPTool
为每个MCP服务器创建目录并生成带类型的封装函数。每个工具对应单独的文件,包含:
- 入参接口定义
- 出参接口定义
- 描述工具功能的JSDoc注释
- 封装的异步函数
callMCPTool
Step 3: Create the MCP Client
步骤3:创建MCP客户端
The client routes calls to the appropriate MCP server:
callMCPTooltypescript
// client.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
const clients = new Map<string, Client>();
export async function callMCPTool<T>(
toolName: string,
input: Record<string, unknown>
): Promise<T> {
const serverName = toolName.split("__")[0];
const client = clients.get(serverName);
if (!client) throw new Error(`No MCP client for server: ${serverName}`);
const result = await client.callTool({ name: toolName, arguments: input });
return result.content as T;
}客户端负责将调用路由到对应的MCP服务器:
callMCPTooltypescript
// client.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
const clients = new Map<string, Client>();
export async function callMCPTool<T>(
toolName: string,
input: Record<string, unknown>
): Promise<T> {
const serverName = toolName.split("__")[0];
const client = clients.get(serverName);
if (!client) throw new Error(`No MCP client for server: ${serverName}`);
const result = await client.callTool({ name: toolName, arguments: input });
return result.content as T;
}Step 4: Configure the Sandbox
步骤4:配置沙箱环境
The execution environment needs:
| Concern | Requirement |
|---|---|
| Isolation | Process-level or container-level sandboxing |
| Resource limits | CPU time, memory caps, disk quotas |
| Network | Restrict to MCP server connections only |
| Timeout | Hard execution time limit per run |
| Filesystem | Scoped to |
| Monitoring | Log all executions and MCP calls |
执行环境需要满足以下要求:
| 关注点 | 要求 |
|---|---|
| 隔离性 | 进程级或容器级沙箱隔离 |
| 资源限制 | CPU时间、内存上限、磁盘配额限制 |
| 网络 | 仅允许连接MCP服务器的网络访问 |
| 超时控制 | 单次执行的硬超时限制 |
| 文件系统 | 仅允许访问 |
| 监控 | 记录所有执行和MCP调用日志 |
Step 5: Wire Up the Agent Loop
步骤5:对接Agent执行循环
The agent loop becomes:
1. Receive user request
2. Agent explores servers/ tree to find relevant tools
3. Agent generates TypeScript code using typed wrappers
4. Code executes in sandbox
5. Filtered output returns to agent
6. Agent decides: done, or generate more code?Agent执行流程变为:
1. 接收用户请求
2. Agent遍历servers/目录查找相关工具
3. Agent基于类型封装函数生成TypeScript代码
4. 代码在沙箱中执行
5. 过滤后的输出返回给Agent
6. Agent判断:任务完成,或继续生成更多代码?Security Checklist
安全检查清单
| Item | Status |
|---|---|
| Sandboxed execution environment | Required |
| Resource limits (CPU, memory, disk) | Required |
| Network isolation (MCP servers only) | Required |
| Execution timeout | Required |
| PII tokenization in MCP client | Recommended for sensitive data |
| Audit logging of all executions | Recommended |
Read-only access to | Recommended |
Scoped write access to | Recommended |
| 检查项 | 要求 |
|---|---|
| 沙箱化执行环境 | 必须 |
| 资源限制(CPU、内存、磁盘) | 必须 |
| 网络隔离(仅允许访问MCP服务器) | 必须 |
| 执行超时控制 | 必须 |
| MCP客户端PII脱敏 | 敏感数据场景推荐开启 |
| 所有执行操作审计日志 | 推荐 |
| 推荐 |
仅允许向 | 推荐 |
Agentic Optimizations
Agent优化方案
| Context | Approach |
|---|---|
| Many tools (50+) | Use progressive discovery via file tree |
| Large intermediate data | Filter in sandbox, return summaries |
| Multi-step workflows | Generate single code block with control flow |
| Sensitive data pipelines | Enable PII tokenization in MCP client |
| Long-running tasks | Use workspace/ for state persistence |
| Repeated operations | Extract to skills/ for reuse |
| 场景 | 优化方案 |
|---|---|
| 工具数量多(50+) | 使用基于文件树的渐进式发现 |
| 中间数据量大 | 在沙箱中过滤,仅返回摘要 |
| 多步骤工作流 | 生成包含控制流的单个代码块 |
| 敏感数据流水线 | 在MCP客户端开启PII脱敏 |
| 长时间运行任务 | 使用workspace/持久化状态 |
| 重复操作 | 提取到skills/目录复用 |
Quick Reference
快速参考
Token Impact
Token消耗对比
| Approach | Tool definitions | Intermediate data | Total |
|---|---|---|---|
| Direct tool calls | All loaded upfront | Passes through context | High |
| Code execution | On-demand discovery | Stays in sandbox | Low |
| 方案 | 工具定义加载方式 | 中间数据处理 | 总消耗 |
|---|---|---|---|
| 直接工具调用 | 提前加载所有定义 | 全部经过上下文传递 | 高 |
| 代码执行模式 | 按需发现 | 保留在沙箱中 | 低 |
When NOT to Use This Pattern
不适用本模式的场景
- Simple integrations with 1-3 MCP servers
- All tool responses are small and needed by the model
- No sensitive data in tool responses
- Infrastructure complexity isn't justified (sandbox setup, monitoring)
- Prototype or proof-of-concept stage
- 仅需对接1-3个MCP服务器的简单集成
- 所有工具响应体积小,且模型需要完整结果
- 工具响应中无敏感数据
- 基础设施复杂度无法支撑(沙箱搭建、监控)
- 处于原型或概念验证阶段
Reference
参考资料
- Anthropic Engineering: Code Execution with MCP
- Cloudflare "Code Mode" — independent validation of the same pattern
- Anthropic Engineering: Code Execution with MCP
- Cloudflare "Code Mode" — 同一模式的独立验证案例",