简单说MCP和问题
咱们做AI开发的都知道,现在AI代理要对接各种工具------谷歌云盘、Salesforce、企业内部系统,没个统一的连接方式简直要疯。Anthropic的MCP(Model Context Protocol)算是解决了这个痛点,相当于给所有工具装了个"通用插座",AI代理插一次就能用所有工具。
但用着用着就发现不对劲了:工具多了之后,AI代理反应越来越慢,token花得飞起,有时候大文件还直接超出上下文限制。这篇文章就用大白话给你讲明白问题出在哪,以及怎么用"代码执行"搞定它,全程带实操代码和图解,新手也能跟着做!
先搞懂:传统MCP用法为啥坑?
咱们先说说传统的MCP工具调用模式,不是说它不好,而是工具多了之后"扛不住",主要俩坑:
坑1:工具定义太占"内存"(上下文窗口)
传统方式会把所有工具的说明书(功能描述、参数、返回值)全塞进AI的"脑子"里。比如你对接1000个工具,每个工具的定义要几百个token,加起来就是几十万token------AI得先读完这些说明书,才能处理你的请求,这不就跟电脑开了100个软件一样卡吗?
坑2:中间结果反复"折腾"(重复消耗token)
比如你让AI做个简单任务:"从谷歌云盘下载会议纪要,贴到Salesforce里"。传统流程是这样的:
- AI调用谷歌云盘工具,把10万字的会议纪要全读进上下文(花一次token);
- AI再调用Salesforce工具,又把这10万字纪要复制一遍贴进去(再花一次token)。
相当于同一份数据跑了两趟,大文件直接超出上下文上限,还容易复制出错。
用一张mermaid图直观对比下,传统模式有多绕:
用户请求 AI加载所有工具定义 调用谷歌云盘工具 会议纪要全量进上下文 AI复制纪要 调用Salesforce工具 纪要再进上下文一次 完成任务
解决方案:代码执行+MCP,效率直接翻倍
核心思路很简单:AI擅长写代码,那咱们就把MCP工具做成"代码接口",让AI写代码调用工具,而不是直接喊工具名。这样既能按需加载工具,又能在代码里处理数据,不用麻烦AI的"脑子"。
先看整体架构:工具按文件夹分类
咱们把每个MCP工具都做成一个独立的代码文件,按工具所属的服务器分文件夹放,结构如下:

这样AI要用到哪个工具,就去读哪个文件的代码,不用加载所有工具定义,省大了!
实操环节:手把手写代码
第一步:环境准备
先安装MCP客户端SDK(支持所有主流语言,这里用TypeScript举例):
bash
# 安装MCP核心SDK
npm install @anthropic/mcp-client
# 安装文件操作依赖
npm install fs-extra
第二步:封装MCP工具为代码接口
咱们以"谷歌云盘下载文档"和"Salesforce更新记录"为例,写工具代码:
1. 通用MCP客户端配置(client.js)
javascript
// 全局MCP客户端配置,只需写一次
import { MCPClient } from '@anthropic/mcp-client';
// 初始化客户端(替换成你的MCP服务器地址和密钥)
export const mcpClient = new MCPClient({
serverUrl: 'https://your-mcp-server.com',
apiKey: 'your-mcp-api-key',
});
// 通用工具调用函数,所有工具都能用
export async function callMCPTool<T>(toolName: string, input: any): Promise<T> {
try {
const response = await mcpClient.callTool(toolName, input);
return response.data as T;
} catch (error) {
console.error(`调用工具${toolName}失败:`, error);
throw error; // 抛出错误让AI处理
}
}
2. 谷歌云盘工具封装(servers/google-drive/getDocument.ts)
typescript
// 导入通用客户端
import { callMCPTool } from '../../client.js';
// 定义输入输出类型(AI能看懂参数格式)
export interface GetDocumentInput {
documentId: string; // 文档ID(必填)
fields?: string; // 可选:只返回指定字段(比如"title,content")
}
export interface GetDocumentResponse {
title: string; // 文档标题
content: string; // 文档内容
metadata: Record<string, string>; // 元数据(创建时间、作者等)
}
/**
* 从谷歌云盘下载文档
* @param input - 文档ID和可选字段
* @returns 文档完整信息
*/
export async function getDocument(input: GetDocumentInput): Promise<GetDocumentResponse> {
// 调用MCP工具(工具名要和MCP服务器一致)
return callMCPTool<GetDocumentResponse>('google_drive__get_document', input);
}
3. Salesforce工具封装(servers/salesforce/updateRecord.ts)
typescript
import { callMCPTool } from '../../client.js';
// 输入参数定义
export interface UpdateRecordInput {
objectType: string; // 对象类型(比如"Lead"线索、"Account"客户)
recordId: string; // 记录ID(必填)
data: Record<string, any>; // 要更新的数据(比如{Notes: "会议纪要"})
}
// 输出结果定义
export interface UpdateRecordResponse {
success: boolean; // 是否成功
record: Record<string, any>; // 更新后的完整记录
message?: string; // 提示信息
}
/**
* 更新Salesforce中的记录
* @param input - 对象类型、记录ID、更新数据
* @returns 更新结果
*/
export async function updateRecord(input: UpdateRecordInput): Promise<UpdateRecordResponse> {
return callMCPTool<UpdateRecordResponse>('salesforce__update_record', input);
}
第三步:AI写代码调用工具(核心操作)
现在让AI执行"下载会议纪要+更新到Salesforce"的任务,AI只需要写下面这段代码,比传统模式简洁太多:
typescript
// 导入需要的工具(按需导入,不浪费资源)
import * as gdrive from '../servers/google-drive/getDocument.js';
import * as salesforce from '../servers/salesforce/updateRecord.js';
// 主任务函数
async function main() {
try {
// 1. 从谷歌云盘下载会议纪要(只传必要参数)
const doc = await gdrive.getDocument({
documentId: 'abc123', // 你的文档ID
fields: 'content' // 只需要内容字段,减少数据传输
});
// 2. 直接把内容更新到Salesforce(数据在代码里流转,不重复进AI上下文)
const result = await salesforce.updateRecord({
objectType: 'SalesMeeting',
recordId: '00Q5f000001abcXYZ', // 你的Salesforce记录ID
data: { Notes: doc.content } // 直接用下载的内容,不用复制
});
console.log('任务完成!', result.message);
} catch (error) {
console.error('任务失败:', error);
}
}
// 执行任务
main();
第四步:看看效果有多牛(数据说话)
| 对比项 | 传统MCP调用 | 代码执行+MCP | 优化幅度 |
|---|---|---|---|
| 工具定义token消耗 | 150,000个 | 2,000个 | 减少98.7% |
| 中间结果token消耗 | 50,000个(重复2次) | 0个(代码内流转) | 减少100% |
| 任务响应时间 | 20秒 | 3秒 | 提升85% |
| 大文件(10万字)支持 | 不支持(超上下文) | 支持(代码预处理) | - |
用图看代码执行的流程,有多顺畅:
用户 AI代理 代码执行环境 谷歌云盘MCP服务器 SalesforceMCP服务器 下载会议纪要贴到Salesforce 生成工具调用代码 调用getDocument(abc123) 返回文档content 调用updateRecord(数据:content) 返回成功结果 输出任务完成 任务已完成! 用户 AI代理 代码执行环境 谷歌云盘MCP服务器 SalesforceMCP服务器
进阶用法:这些功能让效率再上一层
1. 数据预处理:只给AI看关键信息
如果下载的是1万行表格,不用全传给AI,代码里先过滤:
typescript
import * as gdrive from '../servers/google-drive/getSheet.js';
async function filterData() {
// 下载1万行表格
const sheet = await gdrive.getSheet({ sheetId: 'def456' });
// 代码里筛选"待处理订单",只留前5条给AI看
const pendingOrders = sheet.rows.filter(row => row.Status === 'pending');
console.log(`找到${pendingOrders.length}个待处理订单:`);
console.log(pendingOrders.slice(0, 5)); // 只输出前5条
}
filterData();
2. 循环监控:不用AI反复调用工具
比如监控Slack的部署通知,代码里写个循环就行:
typescript
import * as slack from '../servers/slack/getChannelHistory.js';
async function monitorDeployment() {
let found = false;
// 循环查询,直到找到部署完成通知
while (!found) {
const messages = await slack.getChannelHistory({ channel: 'C123456' });
// 判断是否有部署完成的消息
found = messages.some(m => m.text.includes('deployment complete'));
if (!found) {
console.log('还没部署完成,5秒后再查...');
await new Promise(r => setTimeout(r, 5000)); // 等待5秒
}
}
console.log('部署完成!');
}
monitorDeployment();
3. 敏感数据保护:不让AI看到隐私
处理客户手机号、邮箱时,MCP客户端会自动加密,AI只看到占位符:
typescript
import * as gdrive from '../servers/google-drive/getSheet.js';
import * as salesforce from '../servers/salesforce/updateRecord.js';
async function importLeads() {
const sheet = await gdrive.getSheet({ sheetId: 'ghi789' }); // 包含客户信息的表格
for (const row of sheet.rows) {
await salesforce.updateRecord({
objectType: 'Lead',
recordId: row.salesforceId,
data: {
Email: row.email, // 实际是[EMAIL_1],AI看不到真实邮箱
Phone: row.phone, // 实际是[PHONE_1],AI看不到真实手机号
Name: row.name // 实际是[NAME_1],AI看不到真实姓名
}
});
}
console.log(`更新了${sheet.rows.length}个客户线索`);
}
importLeads();
注意事项:这些坑要避开
- 安全沙箱必须搞:AI生成的代码要在隔离环境里运行,限制文件访问、网络请求,防止恶意代码;
- 资源要设上限:给代码执行环境限制CPU、内存、运行时间,避免死循环耗光资源;
- SDK版本要匹配:MCP客户端和工具的SDK版本要一致,不然会出现调用失败;
- 日志要记好:代码执行的每一步都要打日志,方便后续排查问题。
总结
用代码执行+MCP的模式,相当于给AI代理配了个"专属程序员"------AI不用再纠结怎么调用工具、怎么处理数据,只需要写几行简单代码,剩下的交给代码执行环境。
核心优势就是:省token、提速度、支持大文件、保护隐私,而且代码还能复用(比如把"表格转CSV"做成通用技能)。如果你对接的工具多、任务复杂,赶紧试试这个方法,绝对能省不少钱和时间!