三类原语
Tools、Resources、Prompts 分别由谁触发、解决什么问题。
一句话理解:Tools 由模型决定何时调用,用来“做事”;Resources 由应用决定何时读取,用来“提供资料”;Prompts 由用户主动选择,用来“一键启动某种工作方式”。
很多人以为 MCP 就是“远程函数调用”。确实,大多数 MCP Server 只暴露了工具。但 MCP 规范为 Server 定义了三类原语,它们最大的区别不是数据格式,而是 由谁来决定使用。搞清楚这一点,你才能把一个业务能力放进正确的原语里,而不是全部做成工具。
三类原语一览
| 原语 | 谁来触发 | 解决什么问题 | 典型交互 | 订单场景的例子 |
|---|---|---|---|---|
| Tools 工具 | 模型 根据上下文自动决定 | 执行动作、查询动态数据 | 模型在推理中调用 | get_order、get_payment、create_refund |
| Resources 资源 | 应用 决定纳入哪些上下文 | 提供可读取的资料和数据,以 URI 标识 | 用户在资源选择器里挑选,或应用按规则自动附加 | orders://sop/aftersale-codes(售后原因代码手册)、orders://policy/{category_id}/refund-rule |
| Prompts 提示模板 | 用户 主动选择 | 提供预设的任务模板与工作流入口 | 斜杠命令、菜单项 | /diagnose-order(订单诊断)、/weekly-aftersale-report |
规范对这三种交互模型的措辞分别是 model-controlled、application-driven、user-controlled。规范也说明,协议本身不强制具体的界面形态,Host 可以按自己的方式呈现。
把三类原语和各自的触发方画在一起:
Tools:让模型去做事
工具是最常用的原语,前一个模块已经讲透了设计方法。MCP 里的工具定义与 Function Calling 几乎一一对应:
{
"name": "get_payment",
"title": "查询支付与退款",
"description": "按订单号查询支付与退款状态,包括支付时间、支付方式、已退金额与退款失败原因。适用于用户询问“这单付款成功了吗”“为什么还没退款”。不返回商品明细与发货记录。",
"inputSchema": {
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^ORD[0-9]{10}$", "description": "订单号,如 ORD2026090142" }
},
"required": ["order_id"],
"additionalProperties": false
},
"annotations": { "readOnlyHint": true }
}
MCP 在此基础上多了几样东西:
title:给人看的显示名称,name仍然是机器标识。outputSchema与structuredContent:可以声明结构化输出的 Schema,并在结果中返回结构化数据。规范建议同时在content里放一份序列化的文本,兼容只读文本的客户端。annotations:如readOnlyHint、destructiveHint、idempotentHint,Host 可以据此决定是否自动执行。但规范要求,来自不可信 Server 的标注必须视为不可信。- 两类错误:协议错误(未知工具、请求格式错误)走 JSON-RPC error;业务执行错误(参数不合法、下游 API 失败)放在结果里并设置
isError: true,让模型能读到并自我修正。
Resources:让应用提供资料
资源是 只读的上下文数据,每个资源由一个 URI 唯一标识,比如 file:///project/README.md 或自定义的 orders://sop/aftersale-codes。客户端通过 resources/list 列出资源,通过 resources/read 读取内容;带参数的资源可以用 URI 模板表达(如 orders://policy/{category_id}/refund-rule);支持订阅的 Server 还能在资源变化时通知客户端。
资源和“只读工具”有什么区别?关键在于 谁决定读:
举个例子:客服主管在处理一批售后单前,想让 Agent 先“读一遍最新版的售后处理 SOP”。把 SOP 做成资源,主管在 Host 的资源选择器里勾选即可,不需要指望模型自己想起来调用工具。
需要提醒的是,资源的支持程度因 Host 而异。比如 Claude API 的 MCP connector 目前只支持工具调用;使用前要确认目标 Host 是否以及如何呈现资源。
Prompts:让用户一键启动工作方式
提示模板是 Server 预先写好的 消息模板,带有可填写的参数。用户在 Host 里通过斜杠命令或菜单选择它,Host 调用 prompts/get 拿到填好参数的消息,再交给模型。
{
"name": "diagnose-order",
"title": "订单售后诊断",
"description": "按标准流程诊断一个有售后问题的订单,并给出处置建议",
"arguments": [
{ "name": "order_id", "description": "订单号", "required": true }
]
}
用户输入 /diagnose-order ORD2026090142 后,得到的消息可能是:“请按以下步骤诊断订单 ORD2026090142:1. 查询订单状态;2. 查询支付与退款流水;3. 查询该客户的历史售后工单;4. 输出结论与证据……”
提示模板的价值在于 把专家的工作方式产品化,让不会写 Prompt 的业务人员也能稳定地发起复杂任务。它和 Skills 有相似之处,都在封装“怎么做”;区别在于提示模板由用户显式触发、内容是一段消息,而 Skill 通常由 Agent 根据描述自动发现、可以包含脚本与参考资料,见 Skill 是什么。
客户端侧能力与扩展
除了 Server 提供的三类原语,规范还定义了由客户端提供给 Server 的能力。在 2026-07-28 版中:
- Elicitation(信息征集):Server 需要用户补充信息时,通过多轮往返请求让 Host 弹出表单,是当前推荐使用的客户端能力。
- Sampling(请 Host 调用模型)、Roots(告知 Server 可访问的目录) 以及 Logging(日志):在 2026-07-28 版中被标记为弃用,仍然可用,按弃用政策至少保留 12 个月。官方给出的迁移建议分别是:直接对接模型平台的 API;通过工具参数、资源 URI 或 Server 配置传递目录;stdio 下写
stderr,可观测性用 OpenTelemetry。
在核心协议之外,还有需要双方声明支持才启用的扩展,例如用于长时间运行任务的 Tasks、在对话中渲染交互界面的 MCP Apps。设计新 Server 时,优先使用核心原语,扩展按目标 Host 的支持情况再决定。
常见误区
- “所有东西都做成工具。” 用户明确想让 Agent 参考的资料、需要用户主动发起的标准流程,做成资源或提示模板往往体验更好,也更可控。
- “资源就是文件。” 资源可以是数据库记录、API 返回、渲染后的报表,只要能用 URI 标识、适合作为上下文读取即可。
- “Server 实现了三类原语,所有 Host 都能用。” 各 Host 支持的原语不同,上线前必须逐个确认。
设计要点
把一个业务能力放进 MCP Server 时,逐条判断:
- 这件事是“做动作 / 查动态数据”(工具),“提供参考资料”(资源),还是“启动一个标准流程”(提示模板)?
- 由谁决定使用它最合理:模型、应用,还是用户?
- 工具是否声明了读写属性标注?是否需要结构化输出?
- 资源的 URI 设计是否稳定、可读?是否需要订阅变化?
- 目标 Host 是否支持你选择的原语?不支持时有没有降级方案?
练习
为「订单售后诊断」设计一个 MCP Server 的原语清单(45 分钟):
- 列出 8–10 项候选能力,例如查订单、查支付、查发货记录、查历史售后工单、售后原因代码手册、退款时效规则、标准诊断流程、周报模板、建工单。
- 为每项能力选择原语类型,并写一句理由(重点说明由谁触发)。
- 为其中一个提示模板写出参数定义与展开后的消息内容。
延伸阅读
- MCP Tools 规范:工具定义、结构化输出、错误处理与安全注意事项。
- MCP Resources 规范:资源、URI 模板、订阅与注解。
- MCP Prompts 规范:提示模板的交互模型与消息格式。
- Deprecated Features:当前被弃用的功能与迁移路径。
下一步
原语决定 Server“提供什么”,传输方式决定它“跑在哪里”。下一课「本地与远程 MCP」讲 stdio 与 Streamable HTTP 的选择。