MCP 学习路线:按角色、按规范版本选路径

MCP 学习路线:按角色、按规范版本选路径

走完 MCP 最短的路线不是一份固定的章节清单。它取决于两件一分钟就能定下来的事:你扮演什么角色,以及你的对端说哪一代协议。下面把这两个决定做成表格,并在每个阶段的末尾放一个可以运行的检查,它要么通过,要么不通过。

建议按这个顺序读:先选角色(第一节),再选你要面向的协议代际(第二节),如果手上已有旧修订版的实现就做迁移(第三节),然后按阶段推进(第四节),出了问题回到第五节。

一、选你的角色

角色你想要按这个顺序读先运行做到这样才算完成
评估 MCP判断 MCP 是否适合,以及它覆盖什么简介、架构、服务器概念暂时不用你能说出每个用例需要工具、资源、提示中的哪一种(提示详解第一节)
服务器开发者做一个别人的客户端能调用的服务器构建服务器、工具、资源、提示、最佳实践“构建服务器”里的 SDK 示例,再对它运行 lint_tools.pylint_tools.py(以及你提供的资源与提示对应的检查脚本)退出码为 0
客户端或宿主开发者让你的应用连接不是你写的服务器构建客户端、客户端最佳实践、版本与兼容在 _meta 里带协议版本发请求,或先发 server/discover收到 UnsupportedProtocolVersionError 时,你的客户端会用 supported 里的版本重试,遇到旧代服务器会报告而不是卡住
集成者把现成的服务器接进 IDE 或聊天应用这类宿主连接本地服务器、连接远程服务器、Inspector 指南在宿主看到服务器之前,先对它运行 inspector_smoke.pyInspector 列出你预期的工具,冒烟脚本退出码为 0
安全或平台负责人把服务器放到认证、网关或防火墙后面授权、安全最佳实践、最佳实践对预发布端点运行 probe_http.pyprobe_http.py 退出码为 0,并且你清楚每条 WARN 为什么可以接受
发布者登记一个服务器,让别人能找到并安装发布、使用对你的 server.json 运行 preflight.py运行 mcp-publisher publish 之前,preflight.py 退出码为 0

二、选协议代际

MCP 一共有五个修订版。下表列出每个修订版新增的、会出现在你代码里的东西;最后一行是你今天该起步的地方。

修订版新增的、你会注意到的东西官方变更日志
2024-11-05站内记录的第一个修订版;下一份变更日志就是相对它写的2025-03-26 变更日志
2025-03-26基于 OAuth 2.1 的授权框架、Streamable HTTP 取代 HTTP+SSE、JSON-RPC 批处理、工具注解、音频内容、completions 能力主要变更
2025-06-18批处理又被移除、结构化工具输出、服务器作为 OAuth 资源服务器并提供受保护资源元数据、资源指示符(RFC 8707)、征询(elicitation)、工具结果里的资源链接、MCP-Protocol-Version 头、title 字段主要变更
2025-11-25OpenID Connect 发现、图标、增量范围授权、URL 模式征询、采样里的工具调用、客户端 ID 元数据文档、实验性任务、JSON Schema 2020-12 成为默认方言主要变更
2026-07-28没有会话,也没有 initialize 握手:每个请求都带版本和能力。server/discover、subscriptions/listen、多轮往返请求、必填的 resultType、缓存提示、Mcp-Method 与 Mcp-Name 头主要变更

2026-07-28 修订版把直到 2025-11-25 的版本称为旧代(legacy,先用 initialize 握手建立会话),把 2026-07-28 及之后的版本称为新代(modern,版本、身份和能力随每个请求发送)。两代都支持的实现叫双代(dual-era)。两者相遇时会怎样,由规范的兼容矩阵定义:

客户端服务器结果怎么做
新代新代可用server/discover 是可选的。收到 UnsupportedProtocolVersionError 时,用 supported 里的版本重试
新代旧代失败在 stdio 上先发 server/discover,让失败是确定的,并给用户一条可操作的错误
双代新代可用客户端保持新代
双代旧代可用探测以非新代错误失败(或超时),客户端回退到 initialize
旧代新代失败只支持新代的服务器应当在对 initialize 的错误里写明它支持的版本:这条消息可能是旧代客户端唯一能展示的信息
旧代双代可用服务器回答 initialize,并按协商出的旧代修订版为客户端服务

旧代对旧代按旧代修订版运作,不在 2026-07-28 文本的范围内。该做哪一代,由这张表推出:

  • 客户端由你掌控的新服务器:只做新代。实现更小,客户端也由你来升级。
  • 有你无法掌控的客户端的服务器,例如仍在发送 initialize 的宿主:做双代。服务器可以同时实现两种行为,并在同一个端点上同时服务两代。
  • 面向你无法掌控的服务器的客户端:做双代,因为新代客户端对旧代服务器会失败。在 stdio 上用 server/discover 探测,遇到任何不是已识别新代错误的错误就回退;在 Streamable HTTP 上先发新代请求,读 400 的响应体后再决定是否回退。按服务器进程或来源缓存这个判断。
  • 面向你掌控的服务器的客户端:只做新代。

三、从 2025-11-25 迁到 2026-07-28

每一行是官方 2026-07-28 变更日志里的一项变更,加上你该怎么办,以及站内在哪里讲它。

变了什么你该做什么阅读
移除协议层会话与 Mcp-Session-Id 头;列表端点不再因连接而异不再用会话来存状态或区分列表;状态放你自己的存储,或放进 requestState最佳实践第二节
移除 initialize 握手;每个请求在 _meta 里带协议版本与客户端能力每个请求都带 _meta 字段;不再等待初始化结果版本与兼容
新增 server/discover,服务器必须实现实现它;只在想预先知道支持的版本时才先调用它Discover
subscriptions/listen 取代 GET 端点与 resources/subscribe用你要的通知类型打开一条流;变更后重新列出资源详解第四节
多轮往返请求取代 roots/list、sampling/createMessage、elicitation/create 这类服务器发起的请求回答 input_required 结果,并带 inputResponses 与 requestState 重试多轮往返请求
每个结果都带必填的 resultType普通结果发 "complete";客户端先读它再读别的提示详解第五节
列表结果与 resources/read 必须带 ttlMs 和 cacheScope拿不准就发 ttlMs: 0 与 "private";只有对所有用户都相同的列表才用 "public"工具详解、提示详解第四节
Streamable HTTP 的 POST 请求必须带 Mcp-Method 与 Mcp-Name两个都发;非 ASCII 的 Mcp-Name 用 Base64 编码;让你的网关原样转发提示详解第六节
资源不存在的错误码从 -32002 改为 -32602返回 -32602;客户端对旧服务器仍应接受 -32002资源详解第七节
移除 ping、logging/setLevel 与 notifications/roots/list_changed日志级别改为在 _meta 里逐请求设置;不再发送被移除的消息变更日志
实验性任务移出核心协议,成为官方扩展把任务当作通过 extensions 协商的扩展扩展
移除 SSE 流的可恢复性与 Last-Event-ID 头响应流断开就丢了这个请求:客户端重新发起变更日志

四、分阶段的路径

每个阶段都以你能拿出来的东西收尾。下面提到的脚本,都是嵌在各自所属页面里的那一份。每个脚本在没有检查 FAIL 时退出码为 0,至少有一项 FAIL 时退出码为 1。

阶段做什么检查点页面
1. 理解读架构与服务器、客户端概念。弄清每种原语由谁控制:用户(提示)、应用(资源)、模型(工具)你能说出自己设计里每种原语的控制方架构、提示详解第一节
2. 构建并运行按你所用语言的指南,用官方 SDK 做一个服务器Inspector 能连接、协商版本并列出你的工具:inspector_smoke.py 退出码为 0构建服务器、Inspector 指南
3. 原语按各页面的说明定义工具、资源与提示,包括失败的情形lint_tools.py、lint_resources.py、lint_prompts.py 对你的端点各自退出码为 0工具、资源、提示
4. 远程与安全通过 Streamable HTTP 提供服务,加上授权,检查 Origin、令牌受众与请求头probe_http.py 对预发布环境退出码为 0最佳实践、授权
5. 发布用 server.json 描述服务器,证明所有权,发布preflight.py 退出码为 0发布
6. 保持兼容定下代际(第二节),测试兼容表中适用于你的行每个适用的行都以表里写的结果收尾,而不是卡住版本与兼容

五、不工作时看这里

现象最可能的原因去哪里
2026-07-28 的客户端拒绝你的列表结果结果缺 resultType、ttlMs 或 cacheScope(2025-11-25 的形态)三个检查脚本的 list-envelope 检查;提示详解第九节
每个请求都是 HTTP 400 和 -32020Mcp-Method 或 Mcp-Name 缺失、与正文不一致,或非 ASCII 的值没有做 Base64 编码提示详解第六节
-32022 Unsupported protocol version服务器没有实现你发送的版本用 data.supported 里的版本重试;版本与兼容
旧代客户端连不上你的新服务器只支持新代的服务器会拒绝 initialize第二节的“旧代对新代”一行;做双代,或升级客户端
resources/subscribe 回复 404 与 -32601该方法在 2026-07-28 里已不存在改用 subscriptions/listen;资源详解第四节
资源不存在时回复 -32002服务器在 2025-11-25 或更早的版本客户端两种码都接受;资源详解第七节
模型总是调错工具,或发来无效参数定义没有让模型能够恢复工具详解、最佳实践第四节
服务器在本地能用,放到网关后面就失败网关丢掉或改写了 Mcp-Method、Mcp-Name 或 MCP-Protocol-Versionprobe_http.py;最佳实践第五节

版本与验证说明

以上都以 2026-07-28 修订版及之前四个修订版为准;事实来自规范的官方变更日志与版本页,固定在同一个提交。

来源