mcp-code-execution

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

MCP 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+ toolsFew 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 conditionalsLinear sequences of 2-3 tool calls
PII must not reach the model contextNo sensitive data in tool responses
Tasks benefit from state persistence across runsStateless, one-shot operations
You want agents to accumulate reusable skillsFixed, 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:
  1. Discovers available tools by navigating a typed file tree
  2. Generates TypeScript/Python code that imports and calls typed wrapper functions
  3. Executes the code in a sandboxed environment
  4. Returns only filtered/summarized results to the model
This reduces token usage from O(all_tool_definitions) to O(only_relevant_imports).
无需提前将所有MCP工具定义加载到模型上下文中,Agent会按以下步骤执行:
  1. 发现:通过遍历结构化文件树查找可用工具
  2. 生成:编写TypeScript/Python代码,导入并调用带类型定义的封装函数
  3. 执行:在沙箱环境中运行代码
  4. 返回:仅将过滤/摘要后的结果返回给模型
该模式将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 configuration
project/
├── 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 getDocument
Token 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 leads
The 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
.mcp.json
or the project's MCP configuration:
bash
cat .mcp.json 2>/dev/null || echo "No MCP config found"
列出Agent需要交互的MCP服务器列表,查看
.mcp.json
或项目的MCP配置:
bash
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
callMCPTool
calls to the appropriate MCP server:
typescript
// 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;
}
客户端负责将
callMCPTool
调用路由到对应的MCP服务器:
typescript
// 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:
ConcernRequirement
IsolationProcess-level or container-level sandboxing
Resource limitsCPU time, memory caps, disk quotas
NetworkRestrict to MCP server connections only
TimeoutHard execution time limit per run
FilesystemScoped to
workspace/
and
servers/
directories
MonitoringLog all executions and MCP calls
执行环境需要满足以下要求:
关注点要求
隔离性进程级或容器级沙箱隔离
资源限制CPU时间、内存上限、磁盘配额限制
网络仅允许连接MCP服务器的网络访问
超时控制单次执行的硬超时限制
文件系统仅允许访问
workspace/
servers/
目录
监控记录所有执行和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

安全检查清单

ItemStatus
Sandboxed execution environmentRequired
Resource limits (CPU, memory, disk)Required
Network isolation (MCP servers only)Required
Execution timeoutRequired
PII tokenization in MCP clientRecommended for sensitive data
Audit logging of all executionsRecommended
Read-only access to
servers/
Recommended
Scoped write access to
workspace/
only
Recommended
检查项要求
沙箱化执行环境必须
资源限制(CPU、内存、磁盘)必须
网络隔离(仅允许访问MCP服务器)必须
执行超时控制必须
MCP客户端PII脱敏敏感数据场景推荐开启
所有执行操作审计日志推荐
servers/
目录只读权限
推荐
仅允许向
workspace/
目录有写权限
推荐

Agentic Optimizations

Agent优化方案

ContextApproach
Many tools (50+)Use progressive discovery via file tree
Large intermediate dataFilter in sandbox, return summaries
Multi-step workflowsGenerate single code block with control flow
Sensitive data pipelinesEnable PII tokenization in MCP client
Long-running tasksUse workspace/ for state persistence
Repeated operationsExtract to skills/ for reuse
场景优化方案
工具数量多(50+)使用基于文件树的渐进式发现
中间数据量大在沙箱中过滤,仅返回摘要
多步骤工作流生成包含控制流的单个代码块
敏感数据流水线在MCP客户端开启PII脱敏
长时间运行任务使用workspace/持久化状态
重复操作提取到skills/目录复用

Quick Reference

快速参考

Token Impact

Token消耗对比

ApproachTool definitionsIntermediate dataTotal
Direct tool callsAll loaded upfrontPasses through contextHigh
Code executionOn-demand discoveryStays in sandboxLow
方案工具定义加载方式中间数据处理总消耗
直接工具调用提前加载所有定义全部经过上下文传递
代码执行模式按需发现保留在沙箱中

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

参考资料