第 02 节:三种积木:tool、resource、prompt
本节 objectives:
- 能区分 tool、resource、prompt 三种 server primitive。
- 能把一个含糊需求拆成动作、数据、交互模板。
- 能避免把只读资料和提示模板都塞进 tool。
"给 agent 一个函数"只是三分之一
很多 MCP 入门教程一上来就写 tool。这没错,但容易造成错觉:好像 MCP server 就是函数调用目录。
官方 SDK 和 spec 都把 server 能力拆成几类 primitive:tools、resources、prompts。SDK 页面也明确说各语言 SDK 都支持创建暴露 tools、resources、prompts 的 server。1 这三个东西的使用权不一样:tool 是可执行动作,resource 是可读取上下文,prompt 是可复用交互模板。
讲解
先用一句话分开:
- Tool: server 能做的动作。模型可能根据任务选择调用它。
- Resource: server 能提供的数据。host/client 可以把它作为上下文读取。
- Prompt: server 提供的可复用消息模板。用户或 host 可以显式选择它来启动一种工作流。
MCP tools 的 spec 把 tool 看成 model-controlled 能力:host 暴露工具列表后,模型可以请求调用某个 tool,client 再按权限和实现去执行。2 所以 tool 的描述和输入 schema 很重要,它们会影响模型是否正确选择工具。
Resource 的气质相反。它不是"执行一个动作",而是"这里有一份可以读的上下文"。官方 TypeScript SDK 文档把 resource 描述成只读数据,例如文件、数据库 schema、配置。host 决定如何获取和呈现它。3
Prompt 也不是 tool。Prompt 是模板,用来把一个常见交互包装成可复用入口。比如"用团队 code review 标准审这段 diff"适合 prompt;"真的运行测试"适合 tool。
跟我做一遍(worked example)
需求:你想让 agent 帮你维护一个本地学习日志。
先拆:
一个合理 server 可能这样设计:
这里的关键是:不要为了省事把 read_today_log、append_entry、weekly_review_prompt 都做成 tool。它们的控制方式和安全边界不同。
换你补全(faded example)
需求:你给项目写了一个 MCP server,希望 agent 能读取 docs/adr/、运行测试、并按团队模板写 PR 描述。
请给每个能力选 primitive:
参考答案:
常见错误:把"生成 PR 描述草稿"写成 tool。它没有必要执行外部动作,本质是把上下文组织成一段固定格式的请求。
小结 + 通向下一节
MCP server 的最小设计动作是分类:动作进 tool,上下文进 resource,交互模板进 prompt。分类正确,后面的 schema、权限、调试都会更顺。
下一节开始写一个最小 TypeScript server。我们先只暴露一个 tool,把协议跑通。
Footnotes
-
MCP SDKs — https://modelcontextprotocol.io/docs/sdk ↩
-
MCP Tools Specification — https://modelcontextprotocol.io/specification/2025-11-25/server/tools ↩
-
MCP TypeScript SDK — https://github.com/modelcontextprotocol/typescript-sdk ↩
练习
Level 1: 找一个你自己的项目目录,列出 5 个 agent 可能需要的能力。给每个能力标 tool/resource/prompt,并写一句理由。
提示 1
先写最笨但准确的名字。
提示 2
再删掉多余词。
提示 3
不要为了让模型更愿意调用而淡化风险。
看参考答案
如果你发现全是 tool,通常说明你还没把"数据"和"交互模板"拆出来。 Level 2: 重新命名你的 3 个 tool。 要求:
- 名字用动词短语,例如
append_learning_entry。 - 名字不要假装无害,例如把删除叫
clean_item。 - 描述里写清楚副作用。