前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库MCP initialized 通知握手顺序竞态
AIAI AgentMCP 协议

MCP 为什么还要发送 initialized 通知,如何避免握手期间的请求竞态?

服务端已经返回能力,并不等于客户端已经检查完响应并准备好接收正常业务消息。

前端进阶之旅 · 一题精讲更新于 2026.09.06
AI Agent#MCP 协议#MCP
先看核心答案读代码示例
理解线索

响应和就绪是两个不同事件

  1. 等待响应客户端尚未确认协议版本与对方能力
  2. 本地准备校验响应并安装需要的接收处理器
  3. 通知就绪按发送顺序进入正常业务通信阶段

下面只展示就绪通知本身,前面仍必须有成功的 initialize 请求与响应。

核心回答

先记住这个答案

initialize 的响应让客户端拿到协议版本与服务端能力,notifications/initialized 则由客户端告知服务端自己已完成初始化并准备正常通信。它是一条没有 id 的通知,对端不返回 JSON-RPC 响应,客户端不能等待一个不存在的 initialized result。按 2025-11-25 生命周期要求,客户端在初始化响应前通常不发 ping 之外的请求,服务端在收到就绪通知前通常不主动发起常规业务请求,保留 ping 与日志等允许的交互;工程上应使用明确状态与有序发送队列落实这个阶段边界。

  • 就绪通知由客户端发送给服务端
  • 通知没有 id,也没有对应 JSON-RPC 响应
  • 用状态检查和有序队列管理握手期间的请求

为什么不能在收到响应字节时立刻开放所有动作

客户端可能还需要校验响应版本、保存连接能力,以及注册服务端反向请求的处理器。如果界面上的工具按钮在这些步骤完成前就变成可点,会出现同一个服务端偶尔成功、偶尔报告能力尚未准备好的启动竞态。

可以让业务请求通过统一入口检查连接状态:初始化期间排队或返回明确的未就绪错误,初始化失败则拒绝队列。不能让每个按钮各自判断一个含义模糊的 connected 布尔值,把传输已连接与协议可操作混在一起。

通知本身不携带请求标识JSON
{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

接收方不会为这条通知返回 JSON-RPC result。HTTP 传输对发送动作的状态码与 JSON-RPC 请求响应是两个层次,不能把传输确认当成通知新增了一次协议响应。

发送顺序比增加一个任意延迟更可靠

假设客户端把就绪通知和 tools/list 分别交给两个互不协调的异步发送任务,即使调用代码看似前后相邻,底层提交顺序也可能失去保证。更可靠的做法是使用 SDK 的连接完成语义,或在自建传输层统一串行安排初始化阶段的消息。

加入固定几百毫秒等待只能暂时掩盖竞争,在慢机器或断线恢复后仍可能失败。测试应主动延迟初始化响应和处理器注册,确认业务请求没有越过就绪边界,并检查失败时队列是否被清理而不是永久悬挂。

提前收到业务请求时不能编造统一错误码

生命周期规范约束消息发送时机,但没有保证每个服务端都会对所有提前请求返回同一个专用错误码。实际实现可能拒绝、关闭连接或采用自己的处理策略,客户端不应依赖某一种偶然的容错行为才能正常启动。

记录初始化请求标识、响应接收时间、就绪通知提交时间与首条业务消息,可用于定位顺序问题。恢复时应分清新会话重新握手和同一会话的传输恢复,避免在普通重试路径中不加判断地重复发送初始化流程。

回答前,多想一步

容易答错的地方

等待 initialized 的成功响应再放行队列
通知不对应 JSON-RPC 响应,这样设计会让队列永久等待;应按所用传输与 SDK 的发送完成和连接状态语义推进。
只要 TCP 或 HTTP 可通就说明协议已经就绪
网络通达只证明传输可用,协议版本、能力和反向处理器还可能没有准备好;界面和调用入口需要区分这些阶段。
试着用自己的话回答

面试官还会怎么问?

就绪通知可以带 id 方便排查吗?

不能用 id 把通知改成请求。追踪信息应放在允许的元数据或本地日志中,并保持接收方不需要为通知返回响应的语义。

握手阶段为什么允许 ping?

它用于检查连接的响应能力,不依赖普通工具或资源能力已经准备好。允许这种基础消息不等于其他业务请求也可以随时发送。

就绪通知发送失败后应该怎么办?

先将连接保持在未就绪或失败状态,再按传输恢复策略处理。不要直接放行业务调用,也不要把未知发送结果解释成服务端已经收到。

从一道题,走向一组知识

把知识连起来

MCP 协议

MCP initialize 怎样协商协议版本与能力,不兼容时怎么办?

先确认版本与能力,才能安全推进就绪状态

MCP 协议

MCP 的 JSON-RPC request、response、notification 怎样区分和关联?

理解通知没有响应与普通请求的关联机制

参考资料

  • MCP 2025-11-25:Lifecycle
  • MCP 2025-11-25:Base messages

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 为什么不能在收到响应字节时立刻开放所有动作
  3. 发送顺序比增加一个任意延迟更可靠
  4. 提前收到业务请求时不能编造统一错误码
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑