Claude Certified知识点复习:MCP 工具接口设计指南:给架构师的三个 primitive 选型清单

如果你读过 Model Context Protocol(MCP)spec,你知道 MCP server 可以暴露三种 primitive:tool、resource、prompt。你大概也发现了一件事:公开示例里 80% 都在用 tool,另外两种几乎没人用。
这是个问题。Tool 并不总是对的答案,反射式地把所有东西都做成 tool,是干净的集成慢慢变成无法维护的屎山的主要原因。这篇是一份偏实战的决策指南:当你准备把一个新能力暴露给 Claude 时,它应该做成哪种 primitive、为什么。
面向对象:读过 MCP spec 但还没形成强 design sense 的 solution architect。所有内容都基于公开的 MCP 规范和 Anthropic 官方 MCP 文档。
三种 primitive,一句话各自讲完
- Tool:模型可以主动选择去做的一个动作。允许 side effect。由模型发起。
- Resource:客户端可以去拉取并塞进上下文的一份数据。只读。由客户端(或用户)发起。
- Prompt:用户可以显式调用的一个参数化 prompt 模板。由用户发起。
实战里最重要的区别是谁发起。Tool 是模型发起的:Claude 在推理过程中决定去调。Resource 是客户端发起的:宿主应用(或用户)决定把它加载到上下文里。Prompt 是用户发起的:用户显式从一个菜单里挑一个。
这一点搞错,你要么会逼模型去做一件"用户点一下就行"的事,要么反过来。
选型,归结成一个问题
当你要暴露一个新能力,问自己:
谁来决定这玩意儿什么时候跑 —— 模型、客户端、还是用户?
- 模型决定 → Tool。
- 客户端或用户决定,而且是只读的 → Resource。
- 用户显式从模板菜单里挑 → Prompt。
就这个。剩下的全是细节推导。
什么时候用 Tool
Tool 是模型可以在推理中间主动选择去调用的动作。模型读每个工具的 description,中间决定某一个相关,带参数调用,结果作为 tool_result 折回上下文。
合适的场景:
create_ticket(title, body)—— 写操作,模型决定什么时候需要开单search_codebase(query)—— 读操作,但 query 是只有模型能根据上下文组织出来的run_sql(query, database)—— 读 / 写,query 由模型写send_message(channel, content)—— 有 side effect 的动作,时机和内容都需要模型判断
不合适的场景(常见错误):
- "查询用户 profile" —— 如果客户端每次对话都该带着这个信息,直接塞到 system prompt / 上下文里就行,别让模型调工具。
- "取今天日期" —— 这顶多是个 resource,更合理的是客户端直接注入 system prompt。永远不要为此付一次 round trip。
- "列出可用项目" —— 如果反正是用户选一个,这就是客户端 UI 的事,不是模型的事。
什么时候用 Resource
Resource 是客户端可以把它加进对话上下文的只读数据。客户端(或用户通过客户端)决定加载哪个,模型被动消费。
Resource 是 MCP 生态里被严重低估的 primitive —— 它在比大家想象得更多的场景里才是对的答案。它适合:
- 数据是结构化且可寻址的(文件、wiki 页面、issue、记录)
- 宿主应用能把"把这个附到对话上"做成有意义的用户操作
- 模型不应该去主动"决定要不要看" —— 当它出现在对话里的时候,用户已经替它决定了
例子:公司内部 wiki。你可以暴露 search_wiki(query) 当 tool —— 但这等于让 Claude 去猜该搜什么,这是一个绕了一圈才能解决"用户就是想讨论这一页"的设计。正确的设计是把每个 wiki 页面暴露成 resource。宿主应用给用户一个"附加 wiki 页面"的 UI,选中的页面进入上下文,Claude 直接读,不需要猜。
一条经验:如果用户已经知道自己想要哪份数据、只需要把它弄进对话,那就是 resource,不是 tool。
什么时候用 Prompt
Prompt 是用户显式调用的参数化模板 —— 通常在客户端表现为 slash command 或者菜单。它是三种里用得最少的,但合适的时候非常合适。
合适的场景:
- 团队高频使用、值得标准化的分析模板:
/review-pr {number}、/summarize-incident {id} - 需要跨成员统一措辞的工作流
- 串多个工具的"配方",用户想按名字调用
不合适的场景:
- 模型自己应该搞明白的事。如果用户既要挑 prompt 又要写一段描述,你白做了一层 UI。
- 一次性调查。Prompt 是给重复模式用的。
一个判断标准:同一个请求,团队里两个人会用两种不同的方式描述 —— 这大概就值得做成一个 prompt 模板,把措辞固化下来。
三个具体的例子
例 1:集成 Jira
错:一个 mega-tool,jira(action, args),action 取 {create, search, update, comment, ...}。模型得从上下文里猜对的 action,Jira 的所有知识都被压缩在一个自由文本 schema 里。
对:按"谁决定"拆开。
- Resources:单个 issue 按 key 暴露(
jira://PROJ-1234)。用户附上自己想讨论的那条。 - Tools:
create_issue、comment_on_issue(key, body)、transition_issue(key, to_status)。模型发起的动作,每个 schema 干净。 - Prompt(可选):
/triage-issue {key}作为规范化的 triage 流程,把上面这些串起来。
例 2:集成 SQL 数据库
错:把数据库 schema 按表暴露成工具,一张表一个(query_users、query_orders、query_products)。
对:
- Resources:把 schema 本身暴露成 resource(
db://schema),模型可以读到表定义而不烧 tool-call round trip。 - Tools:一个
run_sql(query, database_name)。模型基于 schema resource 写 query。 - Prompt:
/analyze-metric {name},用于分析团队已经标准化的常见指标 query。
例 3:集成内部文档
错:search_docs(query) 作为主交互。模型得猜 query。
对:
- Resources:每篇文档按 URL 暴露,用户附上想讨论的那篇。
- Tools:
search_docs(query)只作为"用户不知道要附什么"时的兜底。 - Prompt:如果存在一个常见的"查 feature X 然后解释给我"模式,
/explain-feature {name}。
三个例子的共同主题:Resource 处理用户 / 客户端能直接寻址的东西,Tool 处理动作和真正开放式的搜索,Prompt 处理标准化的团队 workflow。
Transport:stdio 还是 HTTP?
一个小插曲,因为这个选型问题出现频率太高。MCP spec 支持多种 transport:
- stdio:MCP server 作为客户端的子进程跑,通过 stdin/stdout 通信。最低延迟、零 auth 开销、一个客户端一个 server 实例。
- HTTP(streamable):MCP server 作为网络服务跑。多客户端、网络 auth、更高的运维复杂度。
选 stdio 的情形:
- Server 包一个本地命令行工具或文件
- 客户端就是单个用户的 IDE / CLI
- 你想零运维
选 HTTP 的情形:
- Server 代理访问一个共享的后端(公司 wiki、生产数据库、内部服务)
- 多个客户端要跟同一个 server 实例通信
- 你需要集中的 auth 和审计
大多数企业级集成最后都是 HTTP。大多数个人集成从 stdio 起步,其中一部分会迁到 HTTP。
跟考试相关的地方
如果你在备考 Claude Certified Architect —— MCP 相关的题在 Domain 2(Tool Design & MCP Integration),占 18%。真正拉分的题不是"这个 primitive 是干嘛的",而是"给定这个集成,哪个 primitive 最合适、为什么"。Domain 2 的相关知识点在 claudecertified.io/zh/knowledge/domain2 上有社区整理好的版本 —— 那是一个社区搭的免费备考站,按 Domain 分题,中英双语。
如果你不是为了考试 —— 上面的判断框架照样适用。下次你要把一个能力做成 tool,先问一句:谁来决定它什么时候跑? 如果答案不是"模型,在推理中间,根据对话上下文",那它很可能就不该是 tool。
Claude Certified 是一个独立的社区备考平台,与 Anthropic 无官方关联。

浙公网安备 33010602011771号