本文收录于专栏AI Agent智能体系列—— 20 课从协议原理到生产部署的 MCP 中文实战课程,点击订阅可跟踪后续更新。
【摘要】
你写的 MCP Server 到底该把能力暴露成 Tool 还是 Resource?这课给你三种原语的决策表:Tools 模型自动调用、Resources 应用侧挂载、Prompts 人选触发,外加 2026-07-28 已弃用的 Sampling/Roots 该用什么替代。每个原语配最小 JSON 报文,你能照着设计自己的 Server 接口而不再混淆三者边界。
阶段 1 认识 MCP:概念与协议 | 来源:【原·01-CoreConcepts】 | 知识更新至 2026-10
关键字:MCP Tools、MCP Resources、MCP Prompts、MCP原语、tools/call、Sampling弃用、MCP Server开发、AI Agent工具接口
概念讲解
2.1 原语是什么:Server 能力的三种基本形态
MCP Server 对外提供的能力,归到底是三种原语(Primitive)。可以把它理解成 Server 的"接口类型"——就像 REST API 有 GET/POST/PUT/DELETE,MCP Server 有 Tools / Resources / Prompts。
| 原语 | 一句话定位 | 对应现实世界 |
|---|---|---|
| Tools(工具) | 模型可以调用的函数,能"做事" | 查订单、发消息、执行计算 |
| Resources(资源) | 模型可以读取的数据,能"看东西" | 文档库、数据库表、实时天气 |
| Prompts(提示模板) | 预定义的对话模板,能"教模型怎么做事" | 标准化的分析报告模板、客服话术 |
此外还有一个历史上存在、2026-07-28 起被弃用的原语Sampling(Server 反向请求模型生成内容),以及被弃用的Roots(文件系统位置提示)。本节最后专门讲弃用这件事。
2.2 Tools:动词
Tools 是 MCP 里最核心的原语——模型的"手"。
一个 Tool 的定义包含:
- name:唯一标识,如
search_orders - description:自然语言描述,模型靠它决定"什么时候用这个工具"——写描述就是写 prompt,这是 MCP 工程里最容易被低估的一点
- inputSchema:参数的 JSON Schema,2026-07-28 起升级为完整的 JSON Schema 2020-12(支持
oneOf/anyOf/allOf组合、$ref引用等) - annotations(注解):行为提示,帮助宿主做安全决策
注解里最重要的两个:
readOnlyHint: true:这个工具只读不写。宿主可以放心地自动执行,不用弹确认框destructiveHint: true:这个工具会改数据/删东西。负责任的宿主应该要求用户确认后才执行
一个"查订单"工具的完整定义长这样(TypeScript SDK 的写法,概念对各语言通用):
server.tool("search_orders",{keyword:z.string().describe("搜索关键词"),max_results:z.number().default(10).describe("最多返回多少条"),},async(params)=>{returnawaitorderService.search(params);});模型在对话中看到的就是这个定义的 JSON 形式(第 1 课案例的 D 报文里有完整的tools/list响应实例)。
2.3 Resources:名词
Resources 是 Server 暴露的可读数据。与 Tools 的区别:Tools 是"执行动作",Resources 是"读取内容"——读一份文档、看一张表、获取实时数据。
Resource 用 URI 标识,例如:
file://documents/product-manual.md database://shop/orders/schema api://weather/current对应的协议方法:
resources/list:列出 Server 有哪些资源resources/read:读取某个 URI 的内容
Resource 和 Tool 的边界有时会模糊——"查天气"既可以做成 Tool(get_weather(city))也可以做成 Resource(api://weather/current)。经验法则:需要参数计算/有副作用的用 Tool;静态或准静态的内容用 Resource。拿不准就用 Tool——Tool 更灵活,Resource 的优势主要是宿主可以做预取和缓存。
2.4 Prompts:预定义的工作流模板
Prompts 是 Server 提供的可复用提示模板。比如一个"订单分析"Server 可以提供这样的模板:
为 {{product}} 生成一份 {{report_type}} 报告,要求:{{requirements}}用户(或宿主)通过prompts/list发现模板,通过prompts/get带参数取出填好的提示词,然后发给模型。
Prompts 的价值在于把领域知识沉淀在 Server 端:订单系统的维护者最知道"分析退货数据该怎么问",他把模板写好,所有接入这个 Server 的 Agent 都受益——不用每个 Agent 开发者自己琢磨怎么写提示词。
2.5 Sampling 与 Roots:已弃用,了解即可
Sampling曾是 Server 反向调用模型能力的通道:Server 在处理请求的中途,可以反过来请求宿主的 LLM 生成内容(sampling/createMessage)。这让 Server 不用自己带 LLM SDK 就能获得 AI 能力。
Roots曾是 Client 告诉 Server "你可以关注哪些文件系统位置"的机制(file://URI 列表)。
2026-07-28 起,两者都被弃用(Deprecated),连同 Logging 和 Dynamic Client Registration 一起。弃用不等于立即删除——它们在当前规范里仍然可用以保证兼容性,但官方建议新实现不要再用,且它们最早可能在 2027-07-28 之后的首个规范修订版中被移除(原课 01-CoreConcepts/mcp-2026-07-28.md,2026-10-04 检索)。
替代方案:
| 弃用特性 | 官方推荐替代 |
|---|---|
| Sampling | Server 直接集成 LLM 提供方的 API(国产模型走 OpenAI 兼容接口即可) |
| Roots | 通过工具参数、Resource URI 或 Server 配置传递路径 |
| Logging | stdio 传输用stderr;结构化日志用 OpenTelemetry |
| Dynamic Client Registration | Client ID Metadata Documents |
弃用的原因值得理解:Sampling 让 Server 能白嫖宿主的模型配额,安全和计费边界模糊;Roots 把文件路径的授权语义搞得很暧昧("能看到路径"和"能访问文件"是两回事,但 Roots 容易被误解为授权)。2026-07-28 的整体方向是让显式的东西取代隐式的东西——状态用显式句柄传,授权用标准 OAuth2,上下文用显式参数。
2.6 2026-07-28 规范的其他关键变化
除了弃用清单,还有几个直接影响开发的点(原课 01-CoreConcepts/mcp-2026-07-28.md):
- Tools 的 Schema 升级为完整 JSON Schema 2020-12:输入 Schema 保持
type: "object"根约束,但允许组合和引用;输出 Schema 完全放开,structuredContent可以是任意 JSON 值(不再限定对象)。 - Extensions 成为一等公民:扩展用反向 DNS 命名(如
io.example/my-ext),在能力协商时通过extensions字段声明,独立版本化。本规范带两个官方扩展:MCP Apps(Server 可提供 HTML 界面,宿主在沙箱 iframe 里渲染)和Tasks(长任务管理)。 Mcp-Method和Mcp-Name成为 HTTP 必带头:负载均衡和网关不用拆 JSON body 就能路由。- 错误码
-32002→-32602:资源未找到改用 JSON-RPC 标准 Invalid Params。
案例实战
目标
设计一个"电商订单查询"Server 的三原语完整方案,并用 Python 生成它的tools/list、resources/list、prompts/list三种真实响应报文,验证结构合法性。
完整代码【已实测 2026-10,Python 3.10,纯标准库】
importjson# 三原语设计稿:一个电商订单 Server# - Tool: search_orders / get_order_detail(只读,标注 readOnlyHint)# - Tool: cancel_order(有副作用,标注 destructiveHint)# - Resource: 订单数据 schema(让模型知道表结构)# - Prompt: 退货分析报告模板tools_list={"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"search_orders","description":"按关键词/状态/时间范围搜索订单。用于'我的订单在哪''最近退货了哪些'类问题。","inputSchema":{"type":"object","properties":{"keyword":{"type":"string","description":"商品关键词"},"status":{"type":"string","enum":["待付款","已发货","已签收","已退货"]},"days":{"type":"number","default":30,"description":"最近 N 天"},},},"annotations":{"readOnlyHint":True},},{"name":"cancel_order","description":"取消一个待付款订单。此操作不可撤销。","inputSchema":{"type":"object","properties":{"order_id":{"type":"string","description":"订单号"}},"required":["order_id"],},"annotations":{"readOnlyHint":False,"destructiveHint":True},},],"ttlMs":300000,"cacheScope":"shared",},}resources_list={"jsonrpc":"2.0","id":2,"result":{"resources":[{"uri":"database://shop/orders/schema","name":"订单表结构","description":"orders 表的字段定义,供模型理解可查询的维度","mimeType":"application/json",},{"uri":"file://docs/return-policy.md","name":"退货政策文档","mimeType":"text/markdown",},],},}prompts_list={"jsonrpc":"2.0","id":3,"result":{"prompts":[{"name":"return_analysis","description":"生成指定时间段的退货原因分析报告","arguments":[{"name":"days","description":"分析最近 N 天","required":True},{"name":"category","description":"限定品类,如'数码'"},],}],},}forlabel,objin[("tools/list",tools_list),("resources/list",resources_list),("prompts/list",prompts_list)]:assertobj["jsonrpc"]=="2.0"assert"result"inobjprint(f"====={label}=====")print(json.dumps(obj,ensure_ascii=False,indent=2))print()# 关键设计检查asserttools_list["result"]["tools"][0]["annotations"]["readOnlyHint"]isTrueasserttools_list["result"]["tools"][1]["annotations"]["destructiveHint"]isTrueprint("[OK] 三种原语响应报文结构合法;readOnly/destructive 注解设计正确")预期输出(实测节选)
===== tools/list ===== { "jsonrpc": "2.0", "id": 1, "result": { "tools": [ { "name": "search_orders", "description": "按关键词/状态/时间范围搜索订单。用于'我的订单在哪''最近退货了哪些'类问题。", ... "annotations": { "readOnlyHint": true } }, { "name": "cancel_order", ... "annotations": { "readOnlyHint": false, "destructiveHint": true } } ], "ttlMs": 300000, "cacheScope": "shared" } } ... [OK] 三种原语响应报文结构合法;readOnly/destructive 注解设计正确设计要点复盘
search_orders的 description 写了"用于什么问题"——模型是靠描述来决定何时调工具的,写"按关键词搜索订单"不如写"用于’我的订单在哪’这类问题"。cancel_order标了destructiveHint: true——宿主看到这个标记,应该在执行前弹确认。这是安全原语,详见第 8 课。- Resource 给了 schema 而非数据本身——让模型先读
database://shop/orders/schema知道有什么字段,再用 Tool 去查,比直接暴露整表数据更省 token 也更安全。 - Prompt 模板带参数——
days必填、category选填,宿主渲染模板时会让用户填。
小结
- MCP Server 的三种原语:Tools(做事)/ Resources(看数据)/ Prompts(教怎么问)
- Tool 的 description 是写提示词的战场;annotations(readOnlyHint/destructiveHint)是宿主安全决策的依据
- 2026-07-28 弃用了 Sampling 和 Roots(还有 Logging、DCR),方向是让显式取代隐式
- 同规范升级:完整 JSON Schema 2020-12、Extensions 一等公民、
Mcp-Method/Mcp-Name必带头、错误码 -32002 → -32602 - 设计原则:能用 Tool 就不用 Resource;有副作用的工具必须标 destructiveHint
下一课讲这些报文怎么在网络上跑:stdio 与 Streamable HTTP 两种传输的选择——参见第 3 课《传输机制:stdio 与 HTTP Streaming》。
扩展阅读
- MCP for Beginners 原课 01-CoreConcepts:https://github.com/microsoft/mcp-for-beginners/tree/main/01-CoreConcepts
- 2026-07-28 规范变化详解:https://github.com/microsoft/mcp-for-beginners/blob/main/01-CoreConcepts/mcp-2026-07-28.md
- JSON Schema 2020-12 官方文档:https://json-schema.org/draft/2020-12
- MCP 官方规范(原语定义):https://modelcontextprotocol.io/specification/2026-07-28/
系列导航:本课程全集见专栏AI Agent智能体系列;上一课·第 1 课 MCP是什么与架构解剖;下一课·第 3 课 传输机制
我的专栏
| 蛋白 / 抗体 / 多肽 / 核酸 | 分子模拟 / 动力学 / 对接 | 药物 / 设计 / 案例 | AI / Agent / 大模型 |
|---|---|---|---|
| 开源蛋白结构预测 | 分子模拟基础 | 小分子药物设计案例 | AI Agent系列 |
| 开源蛋白生成方法实践 | 分子动力学模拟-Amber | 蛋白药物设计案例 | 化学大模型 |
| 开源多肽设计模型 | 分子动力学模拟-Gromacs | 多肽药物设计案例 | 《AI Agent原理与实战》 |
| 开源多肽性质预测 | 分子动力学模拟-OpenMM | 开源小分子生成设计 | CADD中的机器学习模型 |
| DNA/RNA药物设计 | 結合自由能 | 开源药代动力学软件 | 高效计算配置 |
| siRNA药物设计模型 | UCSF DOCK系列 | 我胡师兄说药 | |
| ASO药物设计模型 | rDock系列 LeDock系列 gnina系列 |