CCDV-F 备考手册 · Claude Certified Developer – Foundations
Chapter 12 · Domain 8(本章 skill 权重合计 6.5%)

工具实现与 MCP 服务器开发
一次工具往返的确切形状,与「什么时候值得建一个 server」

TS 8.1 考「怎么把一个工具做对」——定义字段、description 写作、错误处理、工具使用模式;TS 8.2 考「什么时候该把它做成一个 MCP server」——三种原语、通信模式、client 与 server 的分界。官方样题 Q3 就出在本章,它的三条排除理由几乎是这一整章的提纲,所以最后一节专门精讲它。本章是配置速查与概念推演的混合体:字段与配置进速查栏,取舍进推演。

本章的事实纪律 — 工具与 MCP 是最容易「凭印象写字段名」的地方,所以本章每个字段名、每个取值、每条 transport 都挂了 vb:。速查栏里标「真实」的都有登记支撑,标「不存在」的是本书按 D1 工艺自制的干扰项,无官方出处,捏造只发生在名字这一层。MCP 的原句我全部取自 Anthropic 自家页面,没有引 modelcontextprotocol.io(它不在本书的来源白名单内)。

一、tool definition:三个字段,与那个「最重要的因素」

客户端工具定义放在请求顶层的 tools 参数里,一个用户自定义工具由三个必需字段构成。

字段官方描述
name工具名,须匹配正则 ^[a-zA-Z0-9_-]{1,128}$
description一段详细的纯文本描述,说明工具做什么、何时该用、如何表现
input_schema一个 JSON Schema 对象,定义该工具预期的参数
input_examples(可选)一组示例输入对象,帮助 Claude 理解怎么用这个工具

description 不是文档,是这个工具的运行时行为规格。官方把话说得非常重:写极其详细的 description 是工具表现里最重要的因素。它应当解释:工具做什么;何时该用以及何时不该用;每个参数的含义与它如何影响行为;以及重要的注意事项与限制——官方专门点了一类容易被忘的内容:这个工具不返回什么信息。篇幅上给了硬指标:每个工具的 description 至少 3–4 句,复杂工具更多。

为什么这条能撑起一整类题 — 「模型没在该调工具的时候调工具」「模型调错了工具」「模型漏填参数」,这三类现象在题目里长得很不一样,但官方给的第一处方是同一个:把 description 写得更详细。看到「加一条 system prompt 告诉它该用哪个工具」这类选项,先想想 description 里是不是压根没写「何时不该用」。

二、tool set 构建:三条官方最佳实践

单个工具写好之后,还有一层是「这一套工具放在一起好不好用」。官方给了三条:

第三条把工具设计和 ch01 P9 接上了:工具的返回值是你唯一能完全控制的那部分上下文。一个返回整行数据库记录的工具,和一个返回三个字段的工具,在十轮之后的上下文账单上差出一个量级。

速查栏 1 · tool definition 字段

tools[].name                     ✔ 真实 · 须匹配 ^[a-zA-Z0-9_-]{1,128}$
tools[].description              ✔ 真实 · 至少 3–4 句
tools[].input_schema             ✔ 真实 · JSON Schema 对象
tools[].input_examples           ✔ 真实 · 可选,示例输入对象数组
tools[].strict                   ✔ 真实 · 保证入参严格符合 schema
tools[].output_schema            ✘ 不存在 · 自制干扰项
tools[].required                 ✘ 不存在 · 自制干扰项
tools[].timeout_ms               ✘ 不存在 · 自制干扰项
tools[].retry_policy             ✘ 不存在 · 自制干扰项

三、一次工具往返的确切形状

先记住一条结构性差异:Claude API 与那些把 tool use 分开、或使用 tool / function 这类特殊 role 的 API 不同——它把工具直接集成进 user 与 assistant 的消息结构里。消息装的是 text / image / tool_use / tool_result block 的数组:user 消息装 client 内容与 tool_result,assistant 消息装 AI 生成的内容与 tool_use。从别家 SDK 迁过来的人最容易在这里找一个不存在的 tool role。

往返的三拍:

  1. 模型侧。响应的 stop_reason 是 tool_use,带一个或多个 tool_use block,字段是 id(这一次工具使用的唯一标识,用来在稍后把结果对应回来)、name、input(符合该工具 input_schema 的输入对象)。
  2. 你的代码。客户端工具由你的应用执行,服务端工具由 Anthropic 执行。
  3. 回传。发一条 role 为 user 的新消息,content block 类型 tool_result,字段:tool_use_id(对应哪一次请求)、content(可选,字符串或嵌套 content block 列表)、is_error(可选,工具执行出错时设 true)。

两条格式硬要求,违反直接 400。其一,tool_result block 必须紧跟在对应的 tool_use block 之后——assistant 的 tool use 消息与 user 的 tool result 消息之间不能夹任何消息。其二,在含 tool result 的那条 user 消息里,tool_result block 必须排在 content 数组的最前面,任何 text 都要排在所有 tool result 之后。「我先写一句 Here are the results 再放结果」正是这条的经典违反。

tool_result 是不可信内容的正确容器 — 官方在这一页专门加了警告:tool result 经常携带你控制范围之外的内容(网页、来信、用户上传、第三方 API),要当作不可信的——能影响它的攻击者可能嵌入试图重定向 Claude 的指令(indirect prompt injection)。给出的做法很具体:把不可信内容放在 tool_result block 里,而不是放进 system prompt 或普通的 user text block。这是 ch01 P2 在工具层的官方落点;防护的完整层次见 ch14。

速查栏 2 · content block 与回传字段

tool_use.id                      ✔ 真实 · 用来匹配结果
tool_use.name / tool_use.input   ✔ 真实
tool_result.tool_use_id          ✔ 真实 · 对应哪一次 tool_use
tool_result.content              ✔ 真实 · 可选
tool_result.is_error             ✔ 真实 · 可选,出错时设 true
tool_result.status               ✘ 不存在 · 自制干扰项
tool_result.error_code           ✘ 不存在 · 自制干扰项
role: "tool"                     ✘ 不存在 · 自制干扰项
role: "function"                 ✘ 不存在 · 自制干扰项

四、错误处理:三类错误,三种处置

错误类型官方处置
工具执行出错(网络错误等)把错误消息放进 content 并带 "is_error": true;Claude 会把这个错误纳入它给用户的回应
调用无效(缺必填参数等)开发期最好的办法是把 description 写得更详细再试;也可以回一个标注错误的 tool_result,Claude 会带着补上的信息再试
server tool 出错Claude 透明地处理,尝试给出替代回应;你不需要为 server tool 处理 is_error

错误消息本身是一个 prompt。官方给了一条很实用的写作要求:写有指导性的错误消息——不要用 "failed" 这种泛化错误,而要说明出了什么问题、Claude 接下来该试什么,例如 "Rate limit exceeded. Retry after 60 seconds."。理由是这样 Claude 才有恢复或调整所需的上下文,不用瞎猜。把 str(exception) 直接塞回去往往就是那个泛化错误。

还有一个数字要记:请求无效或缺参数时,Claude 会带修正重试 2–3 次,然后向用户致歉。这解释了一个常见现象——日志里同一个工具连着三条参数错误,然后模型放弃:那不是你的重试逻辑在跑,是模型自己在试。

五、什么时候调工具:tool_choice、client / server、approval

TS 8.1 把工具使用模式点成三项:agentic harness dispatch、client-side vs. server-side tools、approval patterns。三项各对一个真实机制。

tool_choice:四个取值

auto——让 Claude 自行决定要不要调工具,提供 tools 时的默认值;any——必须用所提供工具中的一个,但不指定哪个;tool——强制总是使用某个特定工具;none——禁止使用任何工具,没有提供 tools 时的默认值。

两条副作用容易被忽略。其一,设为 any 或 tool 时,API 会 prefill assistant 消息来强制用工具,因此模型不会在 tool_use block 之前输出自然语言回应或解释,即使你明确要求它这么做。想要「既解释又必须调某个工具」,官方给的办法是保持 auto 并在 user 消息里明确要求。其二,改动 tool_choice 会让已缓存的 message block 失效——tool 定义与 system prompt 仍然缓存,但 message 内容必须重新处理。第三条约束在 ch06 讲过:manual extended thinking 下只支持 auto 与 none。

第四条是型号约束,而且越来越常见。Claude Opus 5.5、Sonnet 5.5、Fable 5.1 与 Mythos 5.1 无论 thinking 怎么设,收到 any 或 tool 都直接返回 400;在这些型号上要「保证调到工具且输入合 schema」,官方给的替代是 auto 加 strict tool use,要固定 JSON 形状时用 structured outputs。在仍接受强制调用的型号上(官方点名 Claude Opus 5 与 Claude Haiku 5.5),强制调用还有一个代价:它会跳过 thinking,响应直接以 tool_use 开头、没有 thinking block。所以看到 tool_choice 先查型号:同一份请求在一个型号上「只是没了开场白」,换到另一个型号就是 400。

client-side vs. server-side tools

判据只有一句:模型返回结构化调用后,client tool 由你的应用执行,server tool 由 Anthropic 执行。由此派生出两条工程后果:client tool 能触达你的内网与私有数据(因为代码跑在你这边),而 server tool 不需要你实现执行层、错误也由 Claude 透明处理。

agentic harness dispatch 与 approval patterns

「谁来跑这个循环」是 ch08 的题目:Client SDK 下 tool loop 自己写或交给 beta tool runner;Agent SDK 是在你运营的进程里跑 Claude Code 的库;Managed Agents 由 Anthropic 托管 agent harness,沙箱可以是 Anthropic 的云沙箱或自托管。approval patterns 落在同一个层级上——Agent SDK 的 permissions 控制哪些工具自动跑、哪些需要审批;Managed Agents 则用 toolset 的 configs 为单项工具设置 approval policy。本章只需记住一件事:审批发生在 harness 层,不在 tool 定义里——所以速查栏 1 里没有、也不该有一个 requires_approval 字段。

六、MCP:三种原语与它的通信模式

TS 8.2 点名了 MCP resources / tools / prompts 与通信模式 stdio、sockets。原语这一侧官方文档对得很整齐,通信模式那一侧需要一点措辞对照。

定位:MCP 是连接 AI 与外部工具、数据源的开源标准,MCP server 让 Claude Code 访问你的 tools、databases 与 APIs;它为一个外部系统提供专门打造的工具,而连接与认证由 server 处理——最后半句是它与「自己写一个 client tool」最实际的差别。

三种原语

原语它在 Claude 应用里长什么样
toolsserver 暴露的可调用能力,与其他工具一起进入模型的工具面
resources用 @ mention 引用,就像引用文件;输入 @ 会在自动补全里与文件一起出现,格式 @server:protocol://resource/path
prompts成为命令;输入 / 可见,菜单里列为 /servername:promptname (MCP),键入 /mcp__servername__promptname 也能运行

三者在协议层各有自己的发现端点:连接成功后跑的能力发现请求是 tools/list、prompts/list、resources/list;而且 server 可以在连接期间改它的 tools、prompts 或 resources 并发 list_changed 通知:交互式终端会话里 Claude Code 会重新拉取该 server 的列表,不需要断开重连;-p 非交互模式与 Agent SDK 里则只刷新 tool 列表。

通信模式:blueprint 说 stdio 与 sockets,官方文档怎么说

这一小节要如实对照,不能反过来编。blueprint 的原文清单是「stdio、sockets」。其中 stdio 与官方用词完全一致;而 sockets 这个词不是官方 transport 的名字——Anthropic 文档里列的远程 transport 是 http(MCP 规范里叫 streamable-http)、sse 与 ws(WebSocket)。下表按官方用词列,并注明它与 blueprint 措辞的关系:

官方 transport官方描述与 blueprint 措辞的关系
stdio作为本地进程在你的机器上运行,适合需要直接系统访问或自定义脚本的工具与 blueprint 的 stdio 逐字对应
http连接远程 MCP server 的推荐选项,云端服务最广泛支持的 transport;type 接受 streamable-http 作为别名,因为MCP 规范用的就是这个名字blueprint 未点名
sse已 deprecated,能用 HTTP 就改用 HTTP;仍只暴露 SSE 端点的服务,现在也用 claude mcp add --transport http 添加,Claude Code 先试 HTTP、server 不接受时自动切到 SSE(v2.1.265 起)blueprint 未点名
wsWebSocket,保持一条持久的双向连接,适合会主动向 Claude 推送事件的远程 server;只响应请求就该用 HTTP,因为 HTTP 支持 OAuth 与 --transport 标志而 WebSocket 两者都不支持「socket」这一族里语义最接近的官方项,但官方从不用 sockets 这个词
怎么答这类题 — blueprint 的名词清单是考点范围,不是官方 API 用词表。考场上出现「stdio 与 sockets」时,抓的是「本地进程 vs. 远程连接」这条轴;但如果选项里出现具体配置写法,以官方用词为准:type 的合法值是 http(别名 streamable-http)、sse、ws,以及「没有 type 就被读成 stdio」。本书不把 sockets 写成一个配置值,因为它不是。

配置与部署:三个 scope

local 是默认:只在你添加它的那个项目里加载、仅对你可见,存在 ~/.claude.json 该项目路径下。project:配置存在项目根目录的 .mcp.json 里——把 .mcp.json 提交进版本控制,团队每个人就拿到同一套 MCP 工具与服务。user:存在 ~/.claude.json,跨项目可用但仍是你个人私有。「要让团队都有」= project scope + 提交 .mcp.json,这是本节最可能被直接考的一句。

速查栏 3 · MCP 配置

.mcp.json                        ✔ 真实 · 项目根目录,project scope,应提交
~/.claude.json                   ✔ 真实 · local 与 user scope 的存放处
"type": "stdio"                  ✔ 真实 · 本地进程(缺 type 即按此读)
"type": "http"                   ✔ 真实 · 远程首选
"type": "streamable-http"        ✔ 真实 · http 的别名,MCP 规范用词
"type": "sse"                    ✔ 真实 · 已 deprecated
"type": "ws"                     ✔ 真实 · WebSocket,只能写在 JSON 配置里
"type": "sockets"                ✘ 不存在 · 自制干扰项
"type": "grpc"                   ✘ 不存在 · 自制干扰项
.claude/mcp-servers.json         ✘ 不存在 · 自制干扰项

七、样题 Q3 精讲:什么时候值得建一个 MCP server

官方样题只有三道,其中一道正好落在本章。题干形状:一个内部 REST 库存服务,要跨多个 Claude 应用复用,且要独立维护。正确项是建一个 MCP server 把库存操作暴露为 tools,官方理由两条:多个 Claude 应用可以共享("multiple Claude applications can share"),以及可以独立维护("maintained independently")。

三条排除理由比正确项更值得背,因为它们各自代表一整类干扰项:

排除项官方理由本书归类
把库存逻辑写进各应用的 system prompt"is neither reusable nor maintainable"D5 错层承载 / 违反 P4
每次请求把数据贴进 context"gives no live access and wastes context"D5(失守点在上下文开销时标 P9)
指望 built-in tools 触达内部 API"do not automatically reach arbitrary internal APIs"D1 凭空捏造 / 违反 P5

把它反过来用,就得到本章的选型判据:三个问题里有一个答「要」,就不该住在某个应用的 prompt 里——要不要跨应用复用?要不要独立于任何单个应用维护?数据要不要是活的?这正是 ch01 P4「能力放对载体」的原文出处。而 MCP 相对于「自己写一个 client tool」的额外好处,官方也点了:连接与认证由 server 处理。

反向边界 — 复用诉求不存在时,为一个只有一处调用的能力去建 MCP server 就轮到 P10 了。built-in tools / custom tools / Skills / MCP 的完整四方取舍是 TS 8.3 的地界,见 ch13;本章只回答「做成工具之后,怎么把它做对」与「什么时候值得升格成一个 server」。
本章刻意没写的:MCP 的 OAuth 发现链路与 authServerMetadataUrl、server 的 health check 与 discovery cache、list_changed 失败时的降级细节、以及 Anthropic 提供的各个 server tool(web search、code execution 等)的逐项参数。前三类是运维粒度,最后一类属工具目录而非 blueprint 点名的能力。另外,MCP 协议本身的规范文本在 modelcontextprotocol.io,那不在本书的来源白名单内,所以本章所有 MCP 原句都取自 Anthropic 自家页面——这也意味着本章讲的是「Claude 应用怎么用 MCP」,不是「MCP 规范全文」。

本章题组

QUESTION 01 · TS 8.1 · WHY THE TOOL IS NOT CALLED
An agent has a tool lookup_order whose full description reads Looks up an order. In production, Claude answers order-status questions from conversation history instead of calling it about 30% of the time, and when it does call it, it sometimes passes a customer email where an order ID is expected. The input_schema is correct and the tool works when called. What is the first change?
正确 C官方把这条写得毫不含糊:写极其详细的 description 是工具表现里最重要的因素,要覆盖工具做什么、何时该用与何时不该用、每个参数的含义与它如何影响行为、以及重要的限制(含不返回什么);每个工具至少 3–4 句。而针对「参数传错」这一症状,官方给的第一处方同样是把 description 写得更详细。Looks up an order. 正是文档里那个 poor description 的形状。
D7 过度工程违反 P10A:为绕开一行没写好的 description 而自建一个意图分类器,还引入两个副作用——any 或 tool 会让模型不再输出任何自然语言前言,并且改动 tool_choice 会让已缓存的 message block 失效。而且它一个字也没修「传错参数」。
D5 错层承载违反 P4B:把「这个工具是干什么的、参数是什么」写进 system prompt,是把工具规格搬离了它该住的地方。description 的官方职责就是说明工具做什么、何时使用、如何表现;写在 system prompt 里的版本不会随工具一起被复用,也不会随工具一起被维护。
D4 换模型当解法违反 P1D:官方确实建议复杂工具与含糊查询用最新的 Opus 模型,这半句不假。但题干指认的变量是工具规格缺失——description 只有五个词,连「不该在什么时候用」都没写。给一个拿不到规格的模型升档,它只会更自信地猜。
QUESTION 02 · TS 8.1 · THE 400 ON THE WAY BACK
A developer ports a tool loop from another vendor's SDK. After Claude returns stop_reason: "tool_use", their code sends back a message with "role": "tool" containing the result string. That fails, so they change it to a user message shaped as [{"type":"text","text":"Here are the results:"}, {"type":"tool_result", ...}]. That fails too, with an error mentioning tool_use ids without tool_result blocks immediately after. What is wrong?
正确 A两个症状对应两条官方规则。第一个:Claude API 把工具直接集成进 user 与 assistant 的消息结构,不像那些使用 tool 或 function 特殊 role 的 API——user 消息装 tool_result。第二个正是报错原文对应的规则:在含 tool result 的 user 消息里,tool_result block 必须排在 content 数组最前面,任何 text 都要排在所有 tool result 之后。
D1 凭空捏造违反 P5B:方向完全反了。官方明确要求「发一条 role 为 user 的新消息」来回传 tool_result;assistant 消息装的是 tool_use 而不是结果。
D1 凭空捏造违反 P5C:tool_result 没有 name 字段。配对靠的是 tool_use_id——它对应 tool_use block 的 id,官方对 id 的说明就是「用来在稍后把结果对应回来」。
D6 半对半错违反 P5D:「不能混合 block 类型」是编出来的限制。官方给的正确示例恰恰是同一条 user 消息里 tool_result 在前、text 在后。而且拆成两条会踩另一条硬规则——tool result 必须紧跟在 tool use 之后,中间不能夹任何消息。
QUESTION 03 · TS 8.1 · WHAT TO PUT IN AN ERROR
An agent calls query_warehouse, which occasionally hits a 60-second per-tenant rate limit. The current handler catches the exception and returns {"type":"tool_result","tool_use_id":"...","content":"failed","is_error":true}. Traces show Claude then either gives up and apologizes, or immediately retries the identical call and fails again. The rate limit response includes a Retry-After: 60 header the handler discards. What should change?
正确 D官方给的写作要求几乎是逐字命中题干:写有指导性的错误消息——不要用 "failed" 这种泛化错误,而要说明出了什么问题、Claude 接下来该试什么,例句正是 "Rate limit exceeded. Retry after 60 seconds.";理由是这样 Claude 才有恢复或调整所需的上下文、不用瞎猜。题干里被丢掉的那个 Retry-After 头,正是这条消息该携带的信息。
D6 半对半错违反 P7A:它确实能让模型不再重试,但代价是把一次失败伪装成一个事实——Claude 会据此告诉用户仓库里没有数据。官方给 is_error 的语义就是「工具执行出错时设为 true」,抹掉它是在向下游撒谎,比报错危险得多。
D6 半对半错违反 P1B:工具内部做退避重试本身是合理工程,但 60 秒的租户级限流意味着这次调用要阻塞一分钟,而题干指认的变量是模型收到错误后不知道该怎么办。它把一个「信息传递」问题当成「重试策略」问题修,而且没有解决限流仍会最终暴露给模型的那一次。
D1 凭空捏造违反 P5C:tool_result.error_code 与 tool_result.retry_after 都不存在。官方给的 tool_result 字段只有 tool_use_id、content、is_error——结构化恢复信息的正确载体就是 content 里那句话。本书自制的干扰项,无官方出处。
QUESTION 04 · TS 8.1 · FORCING A TOOL HAS SIDE EFFECTS
A support agent on claude-haiku-5-5 keeps a 50k-token cached prefix (tools plus knowledge base) and must always log a ticket via create_ticket before replying. An engineer sets tool_choice: {"type": "any"} on every request. Two regressions follow: the assistant's friendly opening line disappears from every reply, and cache_read_input_tokens drops on turns where the setting is toggled. What explains both?
正确 B官方在同一页给了这两条。其一:tool_choice 为 any 或 tool 时,API 会 prefill assistant 消息来强制用工具,因此模型不会在 tool_use block 之前输出自然语言回应或解释,即使你明确要求。其二:改动 tool_choice 会让已缓存的 message block 失效,tool 定义与 system prompt 仍缓存,但 message 内容必须重新处理。题干钉的是仍接受强制调用的 claude-haiku-5-5;同一份请求发给 Opus 5.5 或 Sonnet 5.5 不会出现这两个症状,而是直接 400。
D6 半对半错违反 P5A:前半句的现象描述接近,但结论反了——any 与 tool 同属「强制用工具」这一类,两者都会 prefill、都会压掉前言。换成 tool 不会恢复任何东西。
D1 凭空捏造违反 P5C:把失效范围说反了。官方明说 tool 定义与 system prompt 仍然保持缓存,失效的是 message block。「固定 tools 数组顺序恢复缓存」也是编的,而且它与开场白毫无因果关系。
D2 无关杠杆违反 P6D:把两个同源症状拆成两件事,然后给其中一个安上 TTL 解释。缓存默认 5-minute lifetime 且每次被用到都免费刷新,而题干说的是「切换该设置的那些轮」掉——这是配置改动而不是时间流逝。
QUESTION 05 · TS 8.2 · MCP TRANSPORT CONFIG
A platform team writes a .mcp.json entry for a remote inventory server: {"inventory": {"url": "https://mcp.acme.internal/mcp"}}. Claude Code refuses to start it and reports that the entry has a url but no type. A teammate suggests "type": "sockets" because the exam blueprint lists "stdio, sockets" as the MCP communication modes. What is correct?
正确 D三条依据。报错来源:有 url 却没有 type 是配置错误,因为 Claude Code 会把没有 type 的条目读成 stdio server。该填什么:HTTP server 是连接远程 MCP server 的推荐选项,type 接受 streamable-http 作为别名,因为 MCP 规范用的就是这个名字。而 sockets 是 blueprint 的措辞,不是官方配置值——官方的远程 transport 是 http / sse / ws。
D1 凭空捏造违反 P5A:"type": "sockets" 不存在。它之所以像真的,是因为 blueprint 里确实有 sockets 这个词——但那是考纲对通信模式的概括措辞,不是 JSON 里的合法取值。本书自制的干扰项,无官方出处。把考纲名词当配置值填,是本章最典型的一类错误。
D6 半对半错违反 P5B:「无 type 被读成 stdio」这半句是官方原话,但后半句是编的——stdio server 是在你机器上运行的本地进程,它不是「触达内网主机的唯一 transport」。题干那个 server 在内网 HTTPS 端点上,正是 HTTP transport 的场景。
D6 半对半错违反 P5C:sse 确实是一个真实取值,但定性反了两处:官方说 SSE transport 已经 deprecated,能用 HTTP 就改用 HTTP;而 http 恰恰是远程 server 的推荐选项,不是本地开发专用。
QUESTION 06 · TS 8.2 · WHICH MCP PRIMITIVE
An internal MCP server must expose three things to Claude Code users: (1) the ability to open and close incidents, (2) the current on-call roster document, which people want to pull into a prompt by reference, and (3) a standard "post-incident review" workflow that engineers invoke by name and fill in. Which primitives map to which?
正确 A三条逐一对上官方描述。tools:MCP server 给 Claude Code 访问 tools、databases 与 APIs 的能力。resources:server 可以暴露 resources,你用 @ mention 引用它们、就像引用文件,格式 @server:protocol://resource/path——「想按引用拉进 prompt」正是这个形状。prompts:server 暴露的 prompts 成为可用命令,/ 菜单里列为 /servername:promptname (MCP),键入 /mcp__servername__promptname 也能运行——「按名字调用并填写」正是这个形状。
D6 半对半错违反 P5B:把 (2) 与 (3) 对调了。判据不是「静态还是会变」,而是怎么被调起:按引用拉进 prompt 的是 resource(@),按名字调起并填写的是 prompt(/)。
D6 半对半错违反 P4C:「tools 是唯一可调用的原语」把三种原语压成一种。三者在协议层各有自己的发现端点——tools/list、prompts/list、resources/list,而且 resources 与 prompts 在 Claude Code 里各有各的调起方式(@ 与 /)。全做成 tool 会让 roster 每次都占一次工具调用,也拿不到 @ 补全。
D1 凭空捏造违反 P5D:「prompts 只能通过 plugin 系统露出」是编的。官方明说 MCP server 可以暴露 prompts,它们在 Claude Code 里成为可用命令。plugin 确实能打包 MCP server,但那是分发方式,不是 prompts 露出的前提。
QUESTION 07 · TS 8.2 · SHARE IT WITH THE TEAM
An engineer adds an MCP server for the team's deployment API and it works on their machine. Two weeks later nobody else has it, and a new hire's clone does not pick it up either. They added it with claude mcp add --transport http deploy https://mcp.acme.internal/mcp and no other flags. What is the fix?
正确 C官方对三个 scope 的划分正好对上题干:local 是默认——只在你添加它的那个项目里加载、仅对你可见,所以两周后没人有它;而 project scope 把配置存进项目根目录的 .mcp.json,官方明说把 .mcp.json 提交进版本控制,团队每个人就拿到同一套 MCP 工具与服务。
D6 半对半错违反 P4A:user scope 的定性没写错——它跨项目可用。但它仍然是你个人私有的,存在 ~/.claude.json 里;「让每个同事各跑一遍同样的命令」是把版本控制该做的事改成口头约定,新人 clone 仓库依旧什么都拿不到。
D5 错层承载违反 P4B:把个人配置文件的片段搬进仓库,绕开了官方为此设计的 project scope。~/.claude.json 是 local 与 user scope 的存放处,它混着这台机器上所有项目的配置与凭据;提交它既分享不了、也是一次真实的泄密风险。
D7 过度工程违反 P10D:plugin 确实能打包 MCP server 并通过 marketplace 分发,在跨仓库复用时是对的选择。但这里只需要一个 flag 加一次 commit,而这一项要建 marketplace、发插件、全员安装;理由那半句「不能通过仓库分享」还与官方原话直接相反。
QUESTION 08 · TS 8.2 · SAMPLE Q3, ONE STEP FURTHER
A team maintains an internal REST inventory service. Three separate Claude applications need to read and adjust stock, the inventory team wants to own and version that integration independently, and stock levels change by the minute. A proposal circulates with four options. Which one matches the requirement, and what disqualifies the rest?
正确 B这是官方样题 Q3 的正确项,理由是多个 Claude 应用可以共享、且可以独立维护。题干的三个条件——跨三个应用复用、由库存团队独立拥有与版本化、数据分钟级变化——正好对应 ch01 P4 的三问。另外 MCP 还顺带解决了认证:连接与认证由 server 处理。
D5 错层承载违反 P9A:官方对这一型的排除理由是「gives no live access and wastes context」。题干把「分钟级变化」写在明处,隔夜快照连第一个条件都过不去;而且每次请求贴数据的开销会随应用数与轮数一起放大。
D1 凭空捏造违反 P5C:官方对它的排除理由是 built-in tools「do not automatically reach arbitrary internal APIs」。这是全书标准的 D1 子型——机制真实存在、名字也对,只是被安上了它没有的能力。「在 prompt 里点一下服务名它就会路由过去」更是把措辞当成了配置。
D5 错层承载违反 P4D:官方原话是「is neither reusable nor maintainable」。写进三个应用的 system prompt 意味着同一份集成规格有三个副本、三条更新路径,而库存团队一条都拥有不了。