本模块回答三个架构问题:MCP 的三方架构如何划分职责?三大原语各归谁控制?以及最常被考到的——什么时候用 MCP,什么时候直接调 API(direct API integration)。
📘 重要英语词汇:模块 06 词汇表
🎯 学习重点:先掌握「三方角色、三大原语、两种传输、一个选型框架」,再展开版本与安全细节。
学完本模块你应能:
配套可运行示例(均在本模块 examples/,先跑后读,本文多处引用它们):
| 脚本 | 演示内容 | 是否需要 key |
|---|---|---|
01_server_primitives_demo.py | 一个进程内同时扮演 host/client/server,走完三大原语的发现与调用 | ❌ 不需要 |
02_tool_error_handling.py | ToolError → is_error=True 的错误语义与修复式重试 | ❌ 不需要 |
03_context_cost_simulator.py | 全量注入工具定义 vs progressive discovery 的上下文成本模拟 | ❌ 不需要 |
04_mcp_connector_api.py | Anthropic MCP connector(Messages API 内置 MCP client)用法 | 🔑 需要(静态校验) |
🎯 学习重点:必考 MCP 解决 M×N 集成问题,以及 Modern 2026-07-28 无状态、无 initialize 握手的版本分界。
模型上下文协议 (Model Context Protocol, MCP) 是一个把 AI 应用连接到外部系统(数据源、工具、工作流)的开放标准。官方的类比是:MCP 之于 AI 应用,就像 USB-C 之于电子设备——一个标准化接口,接上谁都能用。 来源: https://modelcontextprotocol.io/docs/2026-07-28/getting-started/intro(访问于 2026-08-30;该页同时是 platform.claude.com 文档中 MCP 概念页的落点)
没有 MCP 的话,每个 AI 应用要为每个外部系统写一份专用集成(M×N 问题);有了 MCP,外部系统方实现一次 MCP server,所有支持 MCP 的 host(Claude、ChatGPT、VS Code、Cursor 等)都能接入(M+N 问题)。
协议底座(截至 2026-08-30,规范最新版本为 2026-07-28):
来源: https://modelcontextprotocol.io/specification/2026-07-28(访问于 2026-08-30)
⚠️ 版本剧变提醒(截至 2026-08-30):2026-07-28 版把 MCP 从「连接级会话」改成了「每请求携带元数据」的无状态模型。规范自己用两个词划分时代:Modern(2026-07-28 及以后:无握手、每请求_meta携带版本与能力、server/discover可选发现)与 Legacy(2025-11-25 及以前:initialize握手建立会话、server 可主动发 JSON-RPC 请求如 sampling)。双时代实现(dual-era)需按版本页的兼容矩阵回退。旧教程里的initialize流程不是错误,但属于 Legacy 时代。 来源: https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning(访问于 2026-08-30)
🔪 犀利细节|标准化不等于零成本:M×N → M+N 消除的是适配器重复建设,不会消除 server 开发、版本兼容、授权和运行运维。反模式是为了单应用的 1 个稳定 API 引入完整 MCP 平台;正解是先确认是否存在多 host 复用或动态发现需求,再决定是否支付协议层成本。
🎯 学习重点:高频易错点是 host 负责全局编排与同意、client 与 server 严格 1:1、server 看不到完整对话和其他 server。
(结构对照官方 Architecture 页的示意图重绘;来源: https://modelcontextprotocol.io/specification/2026-07-28/architecture(访问于 2026-08-30))
| 角色 | 职责 | 关键约束 |
|---|---|---|
| 宿主 (Host) | LLM 应用本体:创建并管理多个 client 实例;控制连接权限与生命周期;执行安全策略与用户同意 (consent);协调 LLM 集成;跨 client 聚合上下文 | 完整对话历史留在 host;由它决定哪些内容发给哪个 server |
| 客户端 (Client) | host 内的连接器:只与一个 server 通信(1:1);双向路由协议消息;管理订阅与通知 | 维持 server 之间的隔离边界 |
| 服务器 (Server) | 通过 MCP 原语暴露资源/工具/提示;独立运行、职责单一;本地进程或远程服务均可 | 不能读取整个对话,也看不见其他 server;只能拿到 host 判定必要的信息 |
四条官方设计原则(架构师面试可直接引用):
来源: https://modelcontextprotocol.io/specification/2026-07-28/architecture(访问于 2026-08-30)
能力协商 (Capability Negotiation) 是「双方声明自己会什么」的机制。Modern 版规范里:客户端把能力放进每个请求的 _meta.io.modelcontextprotocol/clientCapabilities;server 在 server/discover 的响应里宣告 tools/resources/prompts 等能力;扩展(如 Tasks、MCP Apps)也在 capabilities 的 extensions 字段里协商。双方必须尊重声明的能力。 来源: https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning 与 /architecture(访问于 2026-08-30)
对应到 examples/01_server_primitives_demo.py:Client(mcp) 进入 async with 时 SDK 自动完成探测与协商,之后 client.server_capabilities、client.protocol_version(实测输出 2026-07-28)、client.instructions 直接可读——这就是 host 侧「连接事实」的数据来源。
🔪 犀利细节|1:1 client 是隔离单元:不要让一个 client 对象在多个 server 间复用身份、订阅或错误状态。反模式是把 client 当全局连接池;正解是每个 server 独立 client,由 host 做跨 server 聚合,并只转发完成当前调用所需的最小上下文。
🎯 学习重点:必须能无提示写出 tools=模型控制、resources=应用驱动、prompts=用户控制,并解释控制权为何影响审批与注入面。
三大原语的根本区别不是数据格式,而是控制权 (control) 归属:
| 原语 | 控制方 | 官方定性 | 典型形态 | 对应示例 |
|---|---|---|---|---|
| Tools | 模型控制 (model-controlled) | 模型依据上下文自主决定发现与调用 | 查数据库、调 API、执行计算 | 01 中 search_books |
| Resources | 应用驱动 (application-driven) | host 应用决定如何取用上下文 | 文件、数据库 schema、URI 标识的数据 | 01 中 catalog://{section} 模板 |
| Prompts | 用户控制 (user-controlled) | 用户显式选择启用(常做成斜杠命令) | 「/code-review 代码评审」模板 | 01 中 recommend |
注意:Prompts 的「user-controlled」指由用户决定何时使用,内容仍由 server 定义——这是个容易出错的考点。 来源: https://modelcontextprotocol.io/specification/2026-07-28/server/tools、/server/resources、/server/prompts(均访问于 2026-08-30)
tools 能力的 server 必须响应 tools/list(支持分页与缓存)与 tools/callname、title、description、JSON Schema 形式的 inputSchematools/call 的结果带 isError 标志:业务错误是结果的一部分,不是协议崩溃(详见 §7 与示例 02)来源: https://modelcontextprotocol.io/specification/2026-07-28/server/tools(访问于 2026-08-30)
file:///project/src/main.rs),可带 mimeTyperesources/list / resources/read;server 可在一次 read 里返回多个内容(如目录资源)catalog://{section})listChanged(列表变更通知)与 subscribe(单个资源的更新订阅)https:// scheme 的资源允许 client 直接从 web 拉取,不必经 server 中转来源: https://modelcontextprotocol.io/specification/2026-07-28/server/resources(访问于 2026-08-30)
prompts/list 发现,prompts/get + 参数渲染成消息/code-review 选中来源: https://modelcontextprotocol.io/specification/2026-07-28/server/prompts(访问于 2026-08-30)
InputRequiredResult(多轮请求 MRTR 模式)来源: https://modelcontextprotocol.io/specification/2026-07-28(Specification 首页)、/basic/transports、/server/tools 的 InputRequiredResult 小节(均访问于 2026-08-30)
🔪 犀利细节|按控制权选原语:只读参考数据若包装成 tool,会平白增加一次模型决策和潜在审批;有副作用的动作若伪装成 resource,则绕开工具调用治理。正解是让 resource 承载应用选取的上下文,让 tool 承载可审计行动,让 prompt 成为用户显式触发的模板入口。
🎯 学习重点:考试先按部署边界选 stdio 或 Streamable HTTP,再分别检查本机权限与 OAuth/Origin 风险。
传输层 (Transport) 只是一个「绑定 (binding)」:定义消息如何封装与投递,协议语义在所有传输上完全一致。2026-07-28 版定义两种标准传输(+ 自定义传输通道):
| stdio | Streamable HTTP | |
|---|---|---|
| 形态 | host 以子进程拉起 server,stdin/stdout 上的换行分隔 JSON-RPC | 独立 server 进程,单一 MCP endpoint 接受 POST |
| 每条消息 | 进程标准流里一行 | 一个 HTTP POST;响应是单个 JSON 或请求作用域的 SSE 流 |
| 取消 | 发 notifications/cancelled 通知 | 直接关闭该请求的 SSE 响应流 |
| 认证 | 从环境取凭证,不应走 OAuth 流程 | OAuth 2.1 子集(Protected Resource Metadata 等) |
| 典型场景 | 本地开发工具(编辑器、Claude Code 接本地 server) | 远程/多客户端共享的 server、企业集中部署 |
| 安全要点 | 子进程拥有本机权限,供应链风险直接落地 | 必须校验 Origin 头防 DNS rebinding;本地运行应只绑 127.0.0.1 |
来源: https://modelcontextprotocol.io/specification/2026-07-28/basic/transports、/basic/transports/streamable-http、/basic/authorization(均访问于 2026-08-30)
三个易混的历史节点(均出自 Streamable HTTP 页 Info 框,访问于 2026-08-30):
所以「MCP 走 HTTP 要不要建 session」这种问题,答案取决于版本年代——截至 2026-08-30 的 Modern 规范:不要。
认证补充:HTTP 传输上 MCP server 是 OAuth 2.1 的 resource server,client 是 OAuth client;授权服务器发现走 RFC 9728 Protected Resource Metadata。stdio 传输则明确 SHOULD NOT 走这套,凭证来自环境。 来源: https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization(访问于 2026-08-30)
Python SDK 视角(示例 01 用的 Client):传 MCPServer 实例 = 进程内传输(测试/教学);传 URL 字符串 = Streamable HTTP(生产路径);传 StdioServerParameters = 拉起子进程走 stdio。三种方式上层的协议动词完全一致。 来源: https://py.sdk.modelcontextprotocol.io/client/(访问于 2026-08-30;本机实测 mcp SDK 2.1.1)
🔪 犀利细节|stdio 的 stdout 是协议线:server 把调试日志写到 stdout 会污染逐行 JSON-RPC,表现成随机解析失败;日志必须走 stderr。Streamable HTTP 的对应反模式是把本地服务绑定到所有网卡且不校验Origin;正解是本地只绑127.0.0.1并保留 Origin 防护。
🎯 学习重点:能画出 host 汇总工具定义、转发 tools/call、回喂 tool_result 的完整 agent 回路,并说清 connector 的能力缺口。
把 MCP 放进一个真实 agent 系统(对应模块 08 的 agent loop):
架构要点:
mcp-client-2025-11-20):请求里放 mcp_servers(URL 型 server 定义 + 可选 authorization_token)和 tools: [{type: "mcp_toolset", ...}],Claude 侧直接调远程 server 的工具,你的应用不用自建 MCP client 编排层。限制:只支持远程 HTTP server(Streamable HTTP 与 SSE)、只支持工具调用,不支持 resources/prompts、本地 stdio server 不能直连;ZDR 不适用。示例 04 演示的就是这条路。来源: https://platform.claude.com/docs/en/agents-and-tools/mcp-connector(访问于 2026-08-30)
🔪 犀利细节|connector 是托管捷径,不是完整替代:它省掉自建 client 编排,却只覆盖远程 HTTP 的 tools,resources、prompts 与本地 stdio 都不在能力面内,且 ZDR 不适用。反模式是先选 connector 再发现合规或原语缺口;正解是先列能力/数据保留矩阵,再在托管便利与自建控制之间选型。
03 的主题)🎯 学习重点:记住 30–50 个工具后的选择退化、1%–5% 上下文阈值,以及 catalog → inspect → execute 三层发现。
MCP 工具与普通 REST SDK 有一个本质区别:工具定义会被注入模型上下文,REST SDK 不会。官方 Client Best Practices 给出的数据点:上百工具时全量定义可占 ~150,000 tokens,而渐进式发现只需 ~2,000 tokens;工具选择准确率在可用工具超过 30–50 个后明显下降(后一点来自 Anthropic tool search tool 文档的典型多 server 场景:~55k tokens 定义、降幅 >85%)。 来源: https://modelcontextprotocol.io/docs/2026-07-28/develop/clients/client-best-practices、https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool(均访问于 2026-08-30)
两级解法:
search_tools 元工具,返回名字 + 一行描述tool_search_tool_regex_20251119 / tool_search_tool_bm25_20251119,所有工具定义照常放 tools 数组但标 defer_loading: true,由 Claude 服务端按需检索加载再往上还有动态 server 管理:host 维护 server 注册表,模型需要时才连接某 server,不用就断开释放上下文。
examples/03_context_cost_simulator.py 用确定性 token 估算复现了这套对比:12 个工具时全量注入只占 1% 窗口(不值得做任何优化);210 个工具时占 18% 窗口,渐进式只剩 ~0.3%——先量化再优化,小规模不要过度工程。
🔪 犀利细节|先算定义税,再建搜索层:示例中 210 个工具由 18% 降到约 0.3%,但 12 个工具仅占 1% 时引入检索层反而增加实现、检索和观测复杂度。反模式是按工具总数机械切换;正解是同时看定义 token 占比、候选混淆度和调用准确率。
🎯 学习重点:场景题按集成数量、消费方数量、动态发现、延迟控制与信任边界五轴选 MCP 或 direct API。
这是本模块最重要的架构判断。 MCP 不是「更高级的 API 调用方式」,它解决的是工具的标准化发现、描述与注入问题。决策表:
| 判断维度 | 倾向 直接 API 集成 | 倾向 MCP |
|---|---|---|
| 集成数量 | 就 1–2 个系统,工具 <10 个 | 多系统、多 server,工具几十上百 |
| 谁消费工具 | 只有你一个应用,调用模式固定 | 多个 host/agent 都要消费(Claude Code、Desktop、自研 agent) |
| 复用生态 | 内部私有系统,无人复用 | 已有现成 MCP server(GitHub、Slack、DB…)或你希望别人接入 |
| 工具集稳定性 | 工具集固定,应用发版一起变 | 工具动态变化、运行时发现(tools/list) |
| 延迟/控制 | 毫秒级延迟敏感、需要精细重试/熔断/限流 | 可接受一层协议封装的开销,换取标准化 |
| 上下文成本 | 工具少,注入无压力 | 工具多,需要 progressive discovery / tool search 治理 |
| 信任边界 | 凭证留在你的服务里,全链路可控 | 接第三方 server 需要额外信任评估与授权治理 |
| 团队/组织 | 单团队端到端 | 平台团队出 server、业务团队做 host 的分工 |
经验法则:
(判断维度综合自 MCP 架构与 Client Best Practices 官方文档及本模块示例 03 的量化结论;两来源 URL 见上文,均访问于 2026-08-30。场景级演练见 questions/exam-style.md 的 S1–S3 三道决策题。)
🎯 学习重点:能把上下文爆炸、信任错位、token passthrough、错误语义错位分别映射到具体修复措施。
❌ 事故点 1(上下文爆炸):
host 启动即连接 15 个 server,把 210 个工具定义全部注入每轮请求
→ 18% 上下文窗口没了,工具选择准确率还下降
❌ 事故点 2(信任错位):
把第三方 server 的工具描述/注解当可信信息,直接按描述放行调用
→ 规范明确:描述与注解应视为不可信(除非来自可信 server)
❌ 事故点 3(认证反模式):
MCP proxy server 拿 client 传来的上游 token 原样转发给下游 API
(token passthrough——授权规范明文禁止的反模式,会绕过下游的
限流/审计等基于 audience 的控制)
❌ 事故点 4(错误处理错位):
工具业务错误直接当异常抛出、或 host 不检查 is_error 就消费
structured content → 模型失去自我修正的机会 / 下游解析崩溃
✅ 1. 先量化再决定:工具定义超过窗口 1%–5% 才切 progressive discovery;
更省事的首选是 Anthropic 原生 tool search tool(defer_loading: true)
✅ 2. 信任分级:第三方 server 的工具默认不可信——人类在回路确认、
按工具粒度授权(connector 的 allowlist/denylist 就是这个用途)
✅ 3. 认证:HTTP server 实现 OAuth 2.1 resource server,校验 token
audience;proxy 型 server 必须做 per-client consent 防 confused deputy
✅ 4. 错误语义:业务错误用 ToolError → is_error=True + 可读修复线索,
让模型读到错误后自我修正(示例 02 的完整回路);host 先查 is_error
再信任结构化结果
(事故点 2/3 的依据:https://modelcontextprotocol.io/specification/2026-07-28(Specification 首页 Security 节)与 https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices(访问于 2026-08-30);事故点 4 见示例 02 实测输出)
🎯 学习重点:安全必考 confused deputy、token passthrough、SSRF、工具描述注入,以及 human-in-the-loop 的责任归属。
官方 Security Best Practices 文档逐条列出的攻击面(架构师至少要能点名):
| 攻击 | 一句话机制 | 核心缓解 |
|---|---|---|
| Confused Deputy(混淆代理人) | MCP proxy server 用静态 client ID + 动态客户端注册 + 第三方授权服务器的 consent cookie,让恶意方跳过用户同意拿到授权码 | proxy 必须 per-client consent;静态 client ID 场景重点审计 |
| Token Passthrough(令牌透传) | server 把 client 的上游 token 原样转发下游——被授权规范明文禁止 | server 校验 token 是发给自己的;对下游换发自己的 token |
| SSRF(服务端请求伪造) | server 会按请求去拉 URL(资源、授权服务器元数据)时被指向内网 | 出网白名单、禁内网地址、校验授权 URL |
| State Handle Hijacking(状态句柄劫持) | 状态句柄可猜测/重放时被劫持会话状态 | 句柄不可预测、绑定会话、短时效 |
| Local MCP Server Compromise(本地 server 失守) | 恶意/被攻破的本地 server 拥有用户本机权限,可窃取配置与凭证 | 只装可信 server、最小权限、隔离运行 |
| OAuth 授权 URL 校验 / localhost 重定向伪装 / Mix-Up 攻击 | 授权 URL 或重定向 URI 被偷换、多个授权服务器响应混淆 | 严格校验 issuer 与 redirect URI、state/nonce |
| Scope 最小化失效 | 请求超出手头 token 的 scope 而未拒绝 | server 按 scope 拒绝,客户端只申请所需 scope |
三大原则(Specification 首页 Security 节):用户同意与控制(数据访问与操作需显式同意、保留控制权)、数据隐私(未经同意不得把用户数据传给 server 或再外传)、工具安全(工具=任意代码执行路径;工具描述/注解视为不可信;调用前应有人类在回路)。
MCP 特有的注入风险要单独记住两条:
stdio 特有:本地 server 是你机器上的进程,等价于你安装的软件——供应链信任问题,不是协议能解决的。
🔪 犀利细节|描述、参数、结果都是不可信数据:只审核 tool 名称不够;恶意指令可以藏在 description,也可以经网页/工单结果回流模型。正解是在 host 同时执行 server 信任分级、参数审批、最小 scope、结果隔离与下一步动作再授权,形成跨调用的纵深防御。
来源: https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices、https://modelcontextprotocol.io/specification/2026-07-28(Specification 首页)(均访问于 2026-08-30)
🎯 学习重点:任何 MCP 收益都伴随协议、延迟、上下文和信任成本,答题必须写出「得到什么、付出什么」。
| 选择 | 得到 | 失去/付出 |
|---|---|---|
| MCP vs 直接 API | 标准化发现、多 host 复用、生态现成 server、动态工具集 | 协议层复杂度、每跳延迟、多一层信任边界与安全治理 |
| stdio vs Streamable HTTP | 本地零网络开销、易调试 / 远程共享、集中管控、OAuth | 子进程本机权限暴露 / 需公网暴露 + Origin 校验 + 授权基建 |
| 全量注入 vs progressive discovery | 实现零成本、工具全知 / 上下文节省、准确率保持 | 小规模下前者够用;后者的检索层本身要建设(或用原生 tool search) |
| 自建 MCP client 编排 vs MCP connector | 完全控制(stdio/resources/prompts 都能用)/ 零编排代码、托管鉴权 | connector 只支持远程 HTTP server 且仅工具调用、beta 依赖 |
| tools vs resources vs prompts | 模型自主行动 / 应用控制上下文 / 用户显式触发 | 用错控制方:把只读数据做成 tool 会白白让模型决策;把行动做成 resource 则模型不会调 |
🎯 学习重点:重点排雷旧版 session 思维、全量工具注入、业务错误当协议错误、connector 能力误判与 Origin 漏检。
tools/call 的业务错误走 isError=true,让模型读到并修复;协议级错误才是 JSON-RPC errorinitialize 握手、HTTP+SSE、GET 流、session id 都是 Legacy 概念;Modern(2026-07-28+)无握手、无协议级会话Origin 就可能被 DNS rebinding 打穿🎯 学习重点:术语题要精确区分 host/client/server、transport、capability negotiation 与 progressive discovery。
| 术语 | 一句话定义 |
|---|---|
| Model Context Protocol (MCP) | 连接 AI 应用与外部系统的开放协议(本模块主角) |
| Host | 宿主 AI 应用:管理 client、执行权限与同意、聚合上下文 |
| Client | host 内与恰好一个 server 通信的连接器 |
| Server | 通过 MCP 原语暴露能力的服务(本地进程或远程服务) |
| Tools / Resources / Prompts | 三大 server 原语:模型控制 / 应用驱动 / 用户控制 |
| Resource Template | 用 URI 模板(RFC 6570)参数化的资源 |
| Transport | 消息封装与投递的绑定层;语义与传输无关 |
| stdio / Streamable HTTP | 两种标准传输:子进程标准流 / 单端点 POST + 请求级 SSE |
| Capability Negotiation | 双方声明能力、按声明行事的协商机制 |
| Elicitation | server 向用户征询额外信息(Modern 版经 InputRequiredResult/MRTR) |
| Progressive Discovery | 按需注入工具定义的规模化模式(catalog → inspect → execute) |
| Tool Search Tool | Anthropic 原生的工具按需检索加载(defer_loading: true) |
| MCP Connector | Messages API 内置的 server-side MCP client(beta) |
| Confused Deputy / Token Passthrough | MCP 两大经典 OAuth 攻击/反模式 |
| JSON-RPC 2.0 | MCP 的消息编码格式 |
更多术语见 ../glossary/glossary-core.md 的「模块 06」小节。
🎯 学习重点:认证高频是控制权、版本年代与 MCP/direct API 选型,题干中的规模和延迟约束通常是决胜信息。
questions/exam-style.md S1–S3 专练);规模化时选 progressive discovery / tool search 的时机(1%–5% 阈值);安全题考 token passthrough 为何被禁、工具描述为何不可信🎯 学习重点:至少亲跑三份无 key 示例,观察能力发现、is_error 修复与工具定义 token 占比。
| 文件 | 说明 |
|---|---|
examples/01_server_primitives_demo.py | 三方角色 + 三大原语最小演示(无 key,已实跑通过) |
examples/02_tool_error_handling.py | ToolError / is_error / 修复式重试(无 key,已实跑通过) |
examples/03_context_cost_simulator.py | 工具定义上下文成本模拟(无 key,已实跑通过) |
examples/04_mcp_connector_api.py | MCP connector 用法(需 key,静态校验;遗留一处语法缺陷,见 coordination 汇报) |
labs/lab.md | 动手实验 A–E |
questions/architect-questions.md | 架构师问答题(含 2 道场景决策题) |
questions/exam-style.md | 考试题型(12 选择 + 3 道场景决策,答案与解析在文末) |
../flashcards/flashcards-06.csv | 22 张记忆卡 |
../glossary/glossary-core.md | 模块 06 术语追加 |
../sources/sources-core.csv | C08–C23 来源追加 |