当前位置: 首页 > news >正文

MCP(Model Context Protocol)模型上下文协议 番外篇 2025-03-26 更新

今年3月底。Anthropic对 MCP协议 进行了一次重大更新,具体改动参考:

Key Changes​spec.modelcontextprotocol.io/specification/2025-03-26/changelog/https://link.zhihu.com/?target=https%3A//spec.modelcontextprotocol.io/specification/2025-03-26/changelog/

主要代码改动https://link.zhihu.com/?target=https%3A//github.com/modelcontextprotocol/specification/compare/2024-11-05...2025-03-26

主要变更内容有:

1. 新增基于OAuth 2.1的完整授权框架

2. 使用更灵活的Streamable HTTP传输协议替代原有的HTTP+SSE传输方案

3. 新增JSON-RPC批处理支持

4. 引入完善的工具注解系统,可更清晰地描述工具行为(如只读/破坏性操作等)

由于原文说的很多,但是其实大部分都是引用的常见的OAuth和HTTP的基本知识,真正MCP相关内容并不多。下面我分章节简单分析下具体改动的重点和相关个人分析:

一、授权框架

在Roadmap里面躺了很久的授权功能总算有了。现在MCP总算可以在传输层提供授权能力了,允许MCP客户端代表资源所有者向受保护的MCP服务器发起请求。


1. 协议要求

  • 可选实现:MCP实现可选择是否支持授权功能
  • HTTP传输:若使用HTTP传输,应遵循本规范
  • STDIO传输:应从环境变量获取凭证,不适用本规范
  • 其他传输:必须遵循对应协议的安全最佳实践

可以看到,MCP开始把本地Stdio和HTTP传输彻底分开了,之后的第二部分HTTP stream传输也更加深化了这一点。待会儿可以细说。


2. OAuth 2.1基础授权


3. 服务器元数据发现

发现机制

  • 必须路径GET /.well-known/oauth-authorization-server
  • 版本协商:建议客户端在请求头添加MCP-Protocol-Version: <版本号>
  • 若发现失败,必须回退到预定义默认路径/authorize/token/register
  • 基础URL计算规则:从MCP服务器URL中剥离路径(如https://api.example.com/v1/mcp → 基础URL为https://api.example.com

基础URL规则(没有元数据时的fallback)

端点类型默认路径
授权端点/authorize
令牌端点/token
注册端点/register

4. 访问令牌使用规范

每次请求必须携带Authorization头

Authorization: Bearer <access-token>

安全要求

  • 禁止在URL查询参数传递令牌(也就是说GET的时候不用带)
  • 每次请求必须携带Authorization头(也就是说POST的时候需要带)
  • 无效令牌必须返回HTTP 401

5. 个人总结

原文真的写了一大堆,但很多都是开发人员本身就应该会的,我这里大致列了一张表:

特性MCP特有OAuth/HTTP标准
元数据发现失败回退路径❌(RFC8414无此规定)
基础URL剥离路径规则
动态注册的强推荐性❌(OAuth中为可选)
MCP-Protocol-Version头
PKCE流程✅(OAuth 2.1要求)
Bearer Token用法✅(RFC6750定义)

所以可以看到,MCP只是在服务发现、注册机制、版本管理上引入一些自定义规则,而授权流程本身严格遵循OAuth 2.1。其设计目标是通过标准化回退和自动化注册,确保在分布式模型交互场景中的可用性。


二、可流式HTTP传输协议规范(Streamable HTTP)

是的,你没看错,他前脚刚定义完,后脚又大改了。新的传输规范替代2024-11-05协议版本的HTTP+SSE传输方案。(所以我的实战篇压根就没弄SSE,当时就觉得这玩意定的像个半成品,绝对不是因为懒)


1. 协议概述

本传输方案中,服务端作为独立进程运行,支持多客户端连接。基于HTTP POST/GET请求实现,可选用服务器推送事件(SSE)实现多消息流式传输,既支持基础MCP服务,也可实现支持流式传输和服务器主动通知的高级功能。

服务端必须提供一个同时支持POST/GET方法的统一HTTP端点(称为MCP端点),例如:https://example.com/mcp


2. 客户端消息发送规范

请求方式

  • 所有客户端发往服务端的JSON-RPC消息必须通过独立HTTP POST请求发送至MCP端点
  • 请求头必须包含:Accept: application/json, text/event-stream

请求体格式

  • 单个JSON-RPC请求/通知/响应
  • 批量请求/通知数组
  • 批量响应数组

处理规则

  • 当请求体仅包含通知或响应时:
  • 拒绝时返回4xx状态码(如400),响应体可包含无ID的JSON-RPC错误对象
  • 服务端接受则返回202 Accepted(无响应体)

  • 当请求体包含任何请求时:
  • 服务端必须返回以下两种形式之一:
  • Content-Type: application/json(返回单JSON对象)
  • Content-Type: text/event-stream(启动SSE流)

SSE流管理

  • 服务端应在流中返回每个请求的响应(可批量)
  • 可在响应前发送关联的请求/通知(可批量)
  • 所有响应发送完成前不应主动关闭流(会话过期除外)
  • 连接中断不视为取消请求,显式取消应发送MCP CancelledNotification

(说实话,这一段我一开始没看懂,我都断了,还不能视为取消请求,还得显示发送Notification,这啥意思。后来结合上面的改动综述,我大概猜测有些工具的行为是改动或者破坏性操作,这样的操作确实不应该被连接中断打断,因为client发完请求就够了)


3. 服务端消息监听规范

连接初始化

  • 客户端可通过HTTP GET发起SSE流(无需预先POST数据)
  • 必须包含:Accept: text/event-stream
  • 服务端必须返回text/event-stream405 Method Not Allowed

流式传输规则

  • 服务端可发送非关联性请求/通知(可批量)
  • 禁止发送响应(恢复中断的流除外)
  • 任意一方可随时关闭流

4. 高级功能

多连接管理

  • 客户端可同时维护多个SSE流
  • 服务端禁止跨流广播相同消息

断线恢复

  • 服务端可为SSE事件添加全局唯一ID
  • 重连时客户端应携带Last-Event-ID
  • 服务端仅需恢复原流消息(非全量重发)

会话管理

  • 初始化阶段服务端可通过Mcp-Session-Id头建立会话
  • 会话ID要求:ASCII可见字符、全局唯一、加密安全
  • 后续请求必须携带该ID,缺失时返回400错误
  • 显式终止会话应发送DELETE请求

5. 个人总结

我觉得这一版的定义确实比之前成熟了很多:统一端点设计、动态传输模式、增强型SSE管理、有状态会话、可靠恢复机制等,在兼容性、灵活性和可靠性上显著超越之前的HTTP+SSE方案,尤其适合需要双向实时通信+强状态管理的复杂应用场景(如云IDE、协作编辑、IoT控制等)

但是问题来了,之前的版本咋办了,于是翻到末尾看到写的磕磕巴巴的一段:

向后兼容方案

服务端适配方案

  • 同时维护新旧协议端点
  • 或合并端点(需注意复杂度)

客户端适配方案

1. 尝试POST初始化请求到MCP端点:

  • 成功 → 使用新协议
  • 返回4xx错误 → 改用GET检测SSE端点

2. 收到SSE端点事件 → 切换至旧协议通信

(说实话,长期以后有谁会这么干啊,你还不如直接说SSE就凉了得了)


三、其他更新

其实重点就上面两个,剩下都是些边角料:

1. JSON-RPC批处理

JSON-RPC 的 批处理(Batch) 是一种允许客户端一次性发送多个请求对象的机制,旨在提高通信效率。以下是其核心特点和工作原理:

核心概念

1. 批量发送请求

    • 客户端可以将多个 请求对象(Request) 组合成一个 数组 一次性发送给服务器,例如:
--> [{"jsonrpc":"2.0", "method":"sum", "params":[1,2,4], "id":"1"},{"jsonrpc":"2.0", "method":"notify_hello", "params":[7]},  // 这是一个通知(无id){"jsonrpc":"2.0", "method":"subtract", "params":[42,23], "id":"2"}]

2. 服务器处理规则

  • 服务器会处理所有请求(可能并行或乱序),待全部处理完成后返回一个 响应数组
  • 每个请求(非通知)对应一个响应对象,但 通知(Notification,无id的请求)不会生成响应
  • 响应顺序可能与请求顺序不一致,客户端需通过 id 字段匹配请求与响应。

响应规则

1. 正常批处理响应

    • 返回一个包含所有非通知请求响应的数组,例如:
<-- [{"jsonrpc":"2.0", "result":7, "id":"1"},{"jsonrpc":"2.0", "result":19, "id":"2"}]

2. 全通知批处理

  • 如果所有请求都是通知(无 id),服务器 不返回任何内容(包括空数组)。

3. 错误处理

  • 整体错误:若批处理本身无效(如非 JSON、空数组、结构错误),返回单个错误响应,例如:
<-- {"jsonrpc":"2.0", "error":{"code":-32600, "message":"Invalid Request"}, "id":null}
  • 部分错误:若批处理中某些请求无效(如方法不存在、参数错误),每个错误请求生成独立错误响应,例如:
<-- [{"jsonrpc":"2.0", "error":{"code":-32601, "message":"Method not found"}, "id":"5"}]

关键优势

  • 高效性:减少多次网络往返的开销,适合需要批量操作的场景。
  • 灵活性:支持混合发送普通请求和通知,服务器可并行处理。
  • 容错性:单个请求失败不影响其他请求的处理。

2. 工具注释(tool annotations)

通过引入分层设计的ToolAnnotations机制,显著优化了工具行为的描述能力与系统可维护性。其核心优势及创新点如下:

职责分离与结构清晰化

  • 将工具属性明确划分为操作属性(如输入约束)与显示属性(如用户界面描述),通过继承DisplayAnnotations实现显示逻辑的独立封装。
  • 解耦功能与展示逻辑,避免模型提示(description)与用户可见信息的混淆,提升开发规范性与代码可读性。

可扩展性与灵活性增强

  • 通过可选属性设计,支持工具按需扩展功能描述,同时保持核心接口简洁。
  • 允许不同工具差异化配置(如权限控制、交互提示),适应复杂场景需求,降低协议升级的兼容性风险。

显示属性的标准化复用

  • 将通用显示配置(如标签、图标)抽象为DisplayAnnotations接口,供多工具继承复用。
  • 统一前端交互体验,减少重复代码,同时支持全局样式调整,提升开发效率。

意图导向的元数据设计

  • 明确区分面向模型的description(功能语义解释)与面向用户的显示属性(如多语言文案),精准传递信息。
  • 避免模型因“展示文案”干扰理解,同时让终端用户获得更友好的交互提示,兼顾系统性能与用户体验。

3. 个人总结

JSON-RPC Batch 本质是对现有协议的直接复用,属于技术延续性设计;

Tool Annotations 聚焦前端开发体验优化(如统一交互描述),虽未突破工具定义范式,但通过分层元数据提升了配置可维护性。

四、总结:OAuth与Streamable HTTP驱动的下一代云工具集成方案

MCP 通过整合OAuth 身份验证Streamable HTTP 传输协议,构建了一个安全、高效、可扩展的AI云工具通信框架,为未来的云原生应用和分布式系统提供了强大的基础设施支持。

1. OAuth 安全集成

  • 标准化身份验证:基于OAuth 2.0,确保客户端和服务端的安全认证,支持细粒度权限控制。
  • 无缝对接企业级SSO:可直接集成现有身份提供商(如Azure AD、Github、Google Auth),降低接入成本。

2. Streamable HTTP 的高效通信

  • 统一端点,减少协议碎片化:单一MCP端点支持请求/响应、流式推送、服务端主动通知,简化对接流程。
  • 智能传输模式:自动选择短连接(快速请求)或SSE长流(实时数据推送),优化网络资源使用。

MCP通过OAuth安全层 + Streamable HTTP传输层的组合,解决了之前AI工具在远程场景中的认证碎片化、协议模糊、实时性不足三大痛点,为AI的云原生时代提供了更灵活、更可靠、更易扩展的通信标准。

但是我有一点不太理解的是,为啥不直接定义一个 OpenAPI 呢。这样大家甚至可以直接脚本生成一对server和client,大大降低后续开发和版本更迭的难度。

对于MCP的基础知识,可以查看我的专栏:

相关文章:

  • 鸿蒙学习笔记01
  • 第三章支线三 ·异步幻境 · 时间之缝的挑战
  • Redis 知识点一
  • 进程优先级
  • Spring注解开发
  • 原型对象(Prototype)详解
  • 二叉树-226.翻转链表-力扣(LeetCode)
  • Argo CD 入门 - 安装与第一个应用的声明式同步
  • OC—UI学习-2
  • 全志v853跑通rtsp sample
  • 阿里云Alibaba Cloud安装Docker与Docker compose【图文教程】
  • 创新滑模观测器设计:改进趋近律与切换函数的永磁同步电机无传感器控制
  • 65、.NET 中DllImport的用途
  • React、Git、计网、发展趋势等内容——前端面试宝典(字节、小红书和美团)
  • Python环境搭建:pyenv-win的使用指南
  • leetcode56-合并区间
  • 如何将淘宝店铺商品搬到抖店去?利用 API 实现淘宝店铺商品到抖店的高效迁移
  • 分库分表的取舍
  • 机器学习算法_决策树
  • 【Java学习笔记】BigInteger 和 BigDecimal 类
  • wordpress for bae/西安seo排名外包
  • 最新手机网站推荐/网络推广方法怎么做
  • 好网站你知道/网络营销有哪些功能
  • wordpress 个人简介/seo是啥意思
  • 手机网站设置方法/优化关键词的公司
  • 临清建网站/营销和运营的区别是什么