MCP Server 的代码 review 会上,小王把老李写的 Server 代码投影到大屏幕上。老李的代码很“实在”——他把所有功能都做成了 Tool。导出报表是 Tool,格式化日期是 Tool,连“生成周报邮件草稿”都是一个参数多达 12 个的巨型 Tool。
“老李,你这个 Server 现在有多少个 Tools?”小王问。
“52 个。”老李底气十足,“我把公司所有能用 API 干的事全做成 Tool 了,Agent 想干什么都找得到。”
“那你最近没发现什么问题吗?”
老李沉默了几秒。他想起上周 Agent 帮行政部导出员工考勤表时,连续三次选了错误的 Tool——先调了“生成报表”,又调了“导出 CSV”,最后调了“发送邮件”。三件套全是错的。Agent 面对 52 个 Tools 的选择困难,就像一个刚学做饭的人站在一面挂满厨具的墙前,不知道该拿哪一把刀。
“我觉得我家厨房有 50 把刀,但菜还是做不好。”老李终于承认。
小王走到白板前,画了一把菜刀和一本菜谱。“老李你想啊,你在家做饭,需要两样东西——工具和方法。刀是工具,负责切。菜谱是方法,告诉你什么时候切、切多大、先炒哪个后放哪个。你给了 Agent 52 把刀,但一本菜谱都没给。它当然乱切一气。”
菜刀 vs 菜谱:Tool 和 Prompt 的本质区别
“Tool 和 Prompt 的关系,就是菜刀和菜谱的关系。”小王在白板上写下定义。
Tool——执行具体动作。 查数据库、发邮件、调 API、写文件。Tool 是有副作用的,它会改变世界。你调用它,它干一件事,返回结果。
Prompt——引导思考和流程。 告诉 AI 什么时候该用哪个 Tool,用之前要注意什么,用完之后怎么解读结果、怎么组织回复。Prompt 是纯粹的知识和模板,不改变世界。
“导出报表这个功能,”小王指着老李那个 12 个参数的巨型 Tool,“你把它做成了一个 Tool——export_report,接受 12 个参数。但实际上,导出报表是一个流程,不是单一动作。你需要先查数据库拿到原始数据,再格式化,再生成文件,再通知用户。这应该是多个 Tool 配合一个 Prompt 来完成的。”
老李若有所思:“所以 Tool 应该拆细,Prompt 来编排?”
“对!Tool 遵循单一职责——一个 Tool 只做一件事。Prompt 负责教 AI‘在什么场景下该用哪个 Tool,用完之后怎么处理结果’。两者配合,AI 就不是随机选刀,而是照着菜谱一步步来。”
图:Tool 不是越多越好——配合 Prompt 的引导,准确率才能上去
实战:拆分巨型 Tool,搭配 Prompt 引导
“拿你的 export_report 来说,”小王打开代码编辑器,“我们把它拆成三个细粒度 Tool,然后配一个 Prompt 来教 AI 怎么用它们。”
他先把老李那个 12 个参数的函数拆成了三个独立的 Tool:
// 拆成三个细粒度 Tool,每个只做一件事
server.setRequestHandler("tools/list", async () => ({
tools: [
{
name: "query_report_data",
description: "从数据库查询报表所需的原始数据。返回 JSON 数组。",
inputSchema: {
type: "object",
properties: {
report_type: { type: "string", description: "报表类型:attendance/sales/inventory" },
date_from: { type: "string", description: "开始日期 YYYY-MM-DD" },
date_to: { type: "string", description: "结束日期 YYYY-MM-DD" }
},
required: ["report_type"]
}
},
{
name: "format_to_csv",
description: "将 JSON 数组格式化为 CSV 字符串。不会写入文件,只返回字符串。",
inputSchema: {
type: "object",
properties: {
data: { type: "array", description: "从 query_report_data 返回的原始数据" }
},
required: ["data"]
}
},
{
name: "send_email",
description: "发送一封邮件给指定收件人。需要先确认用户要发送的内容。",
inputSchema: {
type: "object",
properties: {
to: { type: "string" },
subject: { type: "string" },
body: { type: "string" }
},
required: ["to", "subject", "body"]
}
}
]
}));“原来的一个巨型 Tool 变成了三个独立的。每个都简单、清晰、可复用。接下来是 Prompt——教 AI 怎么在‘导出报表’这个场景下串联使用它们。”
小王又加了一个 Prompt 模板:
// 教 AI 如何组合使用 Tools 的"菜谱"
server.setRequestHandler("prompts/list", async () => ({
prompts: [
{
name: "export_report_workflow",
description: "当用户要求导出报表时,使用此工作流模板。引导 AI 按正确顺序调用 Tools。",
arguments: [
{ name: "report_type", description: "报表类型", required: true }
]
}
]
}));
server.setRequestHandler("prompts/get", async (request) => {
if (request.params.name === "export_report_workflow") {
const reportType = request.params.arguments?.report_type || "attendance";
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `用户需要导出${reportType}报表。请按以下步骤操作:
1. 先向用户确认日期范围(默认本月)
2. 调用 query_report_data 获取数据
3. 调用 format_to_csv 格式化
4. 将 CSV 内容展示给用户预览,确认无误后
5. 询问用户邮件地址,调用 send_email 发送
注意:每一步执行前都要向用户说明正在做什么。`
}
}
]
};
}
throw new Error("Prompt not found");
});“看到区别了吗?”小王敲了敲屏幕,“Tool 只定义‘能做什么’。Prompt 定义‘什么时候做、按什么顺序做、做完之后怎么跟用户交代’。AI 拿到这个 Prompt,就像厨师拿到了一张带步骤图的菜谱,不会再乱切一气了。”
老李看着代码,眼神渐渐从戒备变成了若有所思。“那原来的 52 个 Tool,是不是很多都可以转成 Prompt?”
什么时候做成 Tool,什么时候做成 Prompt?
“问得好。”小王在白板上画了一个决策流程图。
“做 Tool 的信号:这个操作会改变外部状态——写数据库、发邮件、调 API、生成文件。或者需要精确的参数校验——金额、日期、枚举值。或者外部系统只认特定的调用格式。”
“做 Prompt 的信号:你在教 AI 一种工作方法——先干什么后干什么、遇到错误怎么处理、回答用什么语气。或者你有一大段上下文想预先注入——比如‘你是一个客服专家,请用礼貌但坚定的语气拒绝退款’。或者你需要带参数的模板——‘生成{产品}的周报,包含{数据维度}’。”
老李追问:“那像‘生成周报’这种功能,拆成 Tool + Prompt 之后,Agent 的表现会好多少?”
“上个月我做过对比测试。”小王调出一张数据表,“同一批导出周报的请求,用你的 52 Tool 方案,Agent 一次性走对流程的概率是 58%。改成 10 个细粒度 Tool + 5 个 Prompt 模板后,一次成功率到了 93%。而且因为 Tool 的参数少、职责单一,Token 消耗反而降低了——AI 不需要在巨大的 inputSchema 里找自己该填哪个参数。”
老李沉默了。他低头看着自己那 52 个 Tool 的代码清单,又抬头看了看小王那套 Tool + Prompt 的组合架构。
图:Prompt 负责路由和流程编排,Tool 负责具体执行
“嗯……”老李靠在椅背上,拧开保温杯喝了一口。枸杞已经沉底了,但水还温着。
“那我把那 52 个 Tool 拆了。该合并的合并,该转 Prompt 的转 Prompt。下周再 review 一次。”
他站起来,走到白板前,盯着那幅菜刀和菜谱的简笔画看了几秒,忽然转过身:“那什么,你刚才说的 Prompt 可以带参数——那如果用户同时要求导出考勤表和销售表,Prompt 怎么引导 AI 并行处理两个工作流?AI 会不会把两个流程的参数搞混?给我看看你那部分的设计。”
小王咧嘴一笑,把 prompts/get 的完整实现调了出来。窗外日光正亮,白板上的菜刀和菜谱并排挂着,像一对终于和解的搭档,在老李的 MCP Server 里找到了各自的位置。

