关于 mcp-code-execution
mcp-code-execution 是一项指导如何通过生成代码与 MCP 服务交互的技能,适用于需要处理大量工具或大型结果的 Agent。内容涵盖按需发现工具、沙盒执行、结果筛选、敏感数据处理和状态复用。
主要功能
- 01渐进式工具发现
- 02TypeScript/Python 类型化封装
- 03沙盒代码执行
- 04在结果进入上下文前筛选
- 05PII 标记化与状态持久化
- 06跨运行复用技能
适用场景
- 01协调多个 MCP 服务及大量工具
- 02处理大型中间结果,避免载入上下文
- 03在工具调用间运行循环、重试和条件逻辑
- 04在系统间传递 PII,同时避免其进入模型上下文
MCP 相关
介绍一种通过类型化封装和客户端发现并调用 MCP 服务工具的 Agent 架构。代码在沙盒中运行,筛选后的结果再返回给 Agent。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill mcp-code-execution安装后在 Claude Code 中输入/mcp-code-execution确认已加载。
详细介绍
MCP 代码执行模式
用于设计 Agent 系统的专业知识:这类系统生成并执行代码来与 MCP 服务交互,而不是直接调用工具。
何时使用此技能
| 在以下情况下使用此技能…… | 在以下情况下改用 mcp-management…… |
|---|---|
| 设计需要跨 10+ 个 MCP 服务或 50+ 个工具进行扇出的 Agent | 在 .mcp.json 中安装或配置单个 MCP 服务 |
| 中间工具结果很大(>10K 个令牌),会撑爆上下文 | 操作一两个服务,且每个结果都足够小,可以内联 |
| 工作流需要在工具调用之间使用循环、重试或条件判断 | 执行一次性连接检查或线性的 2–3 次调用 |
| 必须确保 PII 不进入模型上下文 | 工具响应不包含敏感数据 |
何时使用此模式
| 在以下情况下使用代码执行…… | 在以下情况下直接调用工具…… |
|---|---|
| 连接到 10+ 个 MCP 服务或 50+ 个工具 | 服务很少,工具也只有几个 |
| 中间结果很大(>10K 个令牌) | 结果很小,且模型需要所有结果 |
| 工作流需要循环、重试或条件判断 | 线性的 2-3 次工具调用 |
| 必须确保 PII 不进入模型上下文 | 工具响应中没有敏感数据 |
| 任务受益于跨运行的状态持久化 | 无状态的一次性操作 |
| 希望 Agent 积累可复用技能 | 固定的预定义工作流 |
核心架构
工作原理
Agent 不会预先将所有 MCP 工具定义加载到模型上下文中,而是会:
- 发现:通过浏览类型化文件树来发现可用工具
- 生成:生成导入并调用类型化封装函数的 TypeScript/Python 代码
- 执行:在沙盒环境中执行代码
- 返回:仅向模型返回经过筛选/汇总的结果
这样可将令牌用量从 O(所有工具定义) 降低到 O(仅相关导入项)。
文件树结构
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
类型化封装模式
每个 MCP 工具都有一个类型化封装函数,供 Agent 导入:
// 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);
}
然后,Agent 会编写代码,自然地使用这些封装函数:
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 },
});
关键模式
1. 渐进式工具发现
Agent 按需浏览文件系统以查找相关工具,而不是预先加载所有定义。
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
令牌影响:令牌数从 150,000(所有定义)降至约 2,000(单个定义),减少 98.7%。
2. 高效利用上下文的数据筛选
在执行环境中筛选大型数据集,再将结果交给模型:
// 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
3. 原生控制流
使用代码原生循环和条件判断取代串联的工具调用:
// 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");
4. PII 令牌化
MCP 客户端会拦截响应,并在敏感数据到达模型之前将其令牌化:
// 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`);
模型在执行输出中看到的内容:
[
{ 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. 状态持久化
将中间结果保存到工作区,以便在不同执行之间保持连续性:
// 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");
6. 技能积累
Agent 会将可复用函数持久化为技能,供后续执行使用:
// 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;
}
后续执行可直接导入该技能:
import { saveSheetAsCsv } from "./skills/save-sheet-as-csv";
const csvPath = await saveSheetAsCsv("abc123");
搭建新项目
步骤 1:确定 MCP 服务
列出 Agent 需要交互的 MCP 服务。检查 .mcp.json 或项目的 MCP 配置:
cat .mcp.json 2>/dev/null || echo "No MCP config found"
步骤 2:生成服务目录
为每个 MCP 服务创建一个包含类型化封装函数的目录。每个工具都使用自己的文件,并包含:
- 输入接口
- 输出接口
- 描述工具的 JSDoc 注释
- 封装
callMCPTool的异步函数
步骤 3:创建 MCP 客户端
客户端会将 callMCPTool 调用路由到相应的 MCP 服务:
// 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;
}
第 4 步:配置沙箱
执行环境需要满足以下要求:
| 关注事项 | 要求 |
|---|---|
| 隔离 | 进程级或容器级沙箱 |
| 资源限制 | CPU 时间、内存上限、磁盘配额 |
| 网络 | 仅允许连接 MCP 服务 |
| 超时 | 每次运行均设定硬性执行时间限制 |
| 文件系统 | 限定在 workspace/ 和 servers/ 目录内 |
| 监控 | 记录所有执行和 MCP 调用 |
第 5 步:接入 Agent 循环
Agent 循环变为:
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?
安全检查清单
| 项目 | 状态 |
|---|---|
| 沙箱执行环境 | 必需 |
| 资源限制(CPU、内存、磁盘) | 必需 |
| 网络隔离(仅允许 MCP 服务) | 必需 |
| 执行超时 | 必需 |
| 在 MCP 客户端中对 PII 进行令牌化 | 建议用于敏感数据 |
| 记录所有执行的审计日志 | 建议 |
对 servers/ 进行只读访问 | 建议 |
仅对 workspace/ 开放受限写入权限 | 建议 |
Agentic 优化
| 场景 | 方法 |
|---|---|
| 工具较多(50+) | 通过文件树逐步发现 |
| 中间数据较大 | 在沙箱中筛选并返回摘要 |
| 多步骤工作流 | 生成包含控制流的单个代码块 |
| 敏感数据管道 | 在 MCP 客户端中启用 PII 令牌化 |
| 长时间运行的任务 | 使用 workspace/ 持久化状态 |
| 重复操作 | 提取到 skills/ 中以供复用 |
快速参考
令牌影响
| 方法 | 工具定义 | 中间数据 | 总体 |
|---|---|---|---|
| 直接调用工具 | 全部预先加载 | 经过上下文 | 高 |
| 代码执行 | 按需发现 | 保留在沙箱中 | 低 |
不适用此模式的情况
- 仅与 1-3 个 MCP 服务进行简单集成
- 所有工具响应都很小,且模型都需要这些响应
- 工具响应中不包含敏感数据
- 基础设施复杂度不合理(沙箱设置、监控)
- 原型或概念验证阶段
参考资料
- Anthropic Engineering:使用 MCP 执行代码
- Cloudflare“Code Mode” — 对同一模式的独立验证