立众 發表於 2025-5-16 10:48:00

mcp~客户端与服务端的通讯技术

<h1 id="mcp通讯协议">mcp通讯协议</h1>
<ul>
<li>stdio</li>
<li>sse</li>
<li>streamable http</li>
</ul>
<h1 id="json_rpc">JSON_RPC</h1>
<p>MCP 的传输层负责将 MCP 协议消息转换为 JSON-RPC 格式进行传输,并将接收到的 JSON-RPC 消息转换回 MCP 协议消息</p>
<ul>
<li>请求</li>
</ul>
<pre><code>{
jsonrpc: "2.0",
id: number | string,
method: string,
params?: object
}
</code></pre>
<ul>
<li>响应</li>
</ul>
<pre><code>{
jsonrpc: "2.0",
id: number | string,
result?: object,
error?: {
    code: number,
    message: string,
    data?: unknown
}
}
</code></pre>
<h1 id="一-stdio">一 stdio</h1>
<p>本地化部署mcp server后,本机上的gpt工具集成了mcp client skd,然后通过本地进程与mcp server进行通讯</p>
<h1 id="二-sse">二 sse</h1>
<p>MCP 早期采用 HTTP+SSE(Server-Sent Events)实现客户端与服务器的通信,但存在以下问题:</p>
<ol>
<li>不支持断线恢复:SSE 连接中断后会话状态丢失,需重新开始。</li>
<li>服务器资源压力大:需为每个客户端维护长连接,高并发时资源消耗显著。</li>
<li>单向通信限制:服务器只能通过 SSE 端点单向推送消息,无法灵活处理双向交互。</li>
<li>基础设施兼容性差:CDN、防火墙等可能中断长连接,导致服务不可靠。</li>
</ol>
<h2 id="客户端和服务端通讯原理">客户端和服务端通讯原理</h2>
<ol>
<li>客户端向服务服务/sse节点发起get请求,它是一个长连接,<code>connection keep-alive</code>,<code>accept text/event-stream</code></li>
<li>服务端返回endpoint节点,并带上sessionId标识,之后服务端向客户端推送的数据,也是从这个/sse节点完成</li>
<li>客户端向endpoint节点发起post请求,将问题以请求体的形式发给mcp server</li>
<li>mcp server获取当前endpoint+sessionId,对请求体处理,并通过/sse接口推送到客户端</li>
</ol>
<p><img src="https://images.cnblogs.com/cnblogs_com/lori/2457803/o_250516011752_sse_endpoint.png" alt="" loading="lazy"></p>
<h2 id="sdk处理流程">sdk处理流程</h2>
<p><img src="https://images.cnblogs.com/cnblogs_com/lori/2457803/o_250516005635_8832c72a0bb5d007b594eed3771b8d37.png" alt="" loading="lazy"></p>
<p>实际工作过程总结</p>
<pre><code>连接建立
    客户端请求 /sse;
    服务端初始化 SseEmitter 和 McpServerSession,返回可用的消息接口地址。
会话初始化
    客户端通过 /message 发送 InitializeRequest,告知能力与标识;
    服务端处理后通过 SSE 返回 InitializeResponse。
资源管理
    客户端发起如 tools/list 请求;
    服务端从会话中查找状态,调用工具处理器并通过 SSE 返回结果。
调用工具
    客户端拼接 prompt 后发起 tools/call;
    服务端查找处理器执行逻辑,并通过 SSE 返回执行结果。
连接维持
    客户端周期性发送 ping;
    服务端返回 pong,用于保持连接活跃。
连接关闭
    客户端主动断开;
    服务端清理对应的连接与会话状态。
</code></pre>
<h2 id="java-webflux正确引用">java-webflux正确引用</h2>
<p>使用快照版1.0.0-SNAPSHO,引用包spring-ai-starter-mcp-server-webflux</p>
<pre><code> &lt;dependencies&gt;
      &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.ai&lt;/groupId&gt;
            &lt;artifactId&gt;spring-ai-starter-mcp-server-webflux&lt;/artifactId&gt;
      &lt;/dependency&gt;
&lt;/dependencies&gt;
    &lt;dependencyManagement&gt;
      &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework.ai&lt;/groupId&gt;
                &lt;artifactId&gt;spring-ai-bom&lt;/artifactId&gt;
                &lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
                &lt;type&gt;pom&lt;/type&gt;
                &lt;scope&gt;import&lt;/scope&gt;
            &lt;/dependency&gt;
      &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;
</code></pre>
<p>使用标准版1.0.0-M6,引用包<code>spring-ai-mcp-server-webflux-spring-boot-starter</code>会出现无sessionId参数的问题</p>
<h1 id="三-streamable-http">三 streamable http</h1>
<h2 id="streamable-http-通过以下设计解决了sse的问题">Streamable HTTP 通过以下设计解决了SSE的问题:</h2>
<ol>
<li>
<p>统一端点<br>
移除专用的 /sse 端点,所有通信通过单一端点(如 /mcp)完成,支持 POST 和 GET 请求。</p>
</li>
<li>
<p>按需流式传输<br>
服务器可灵活选择响应方式:</p>
<ul>
<li>普通 HTTP 响应:适用于简单请求(如计算任务)。</li>
<li>升级为 SSE 流:用于需持续推送的场景(如进度反馈)。</li>
<li>维持长连接:支持双向流式交互(如多轮对话)。</li>
</ul>
</li>
<li>
<p>会话标识与状态管理<br>
引入会话 ID 机制(通过 Mcp-Session-Id 头部传递),支持断线重连和状态恢复。服务器可选择无状态(Stateless)或有状态(Stateful)模式运行。</p>
</li>
<li>
<p>灵活初始化与恢复</p>
<ul>
<li>客户端可通过空 GET 请求主动初始化 SSE 流。</li>
<li>断线后,客户端可通过会话 ID 重新连接并恢复上下文。</li>
</ul>
</li>
</ol>
<h2 id="streamable-http-的优势">Streamable HTTP 的优势</h2>
<ol>
<li>兼容性与扩展性</li>
</ol>
<ul>
<li>纯 HTTP 实现,兼容 CDN、API 网关等现有基础设施。</li>
<li>支持无状态服务器,适合 Serverless 架构(如 AWS Lambda)。</li>
</ul>
<ol start="2">
<li>性能优化</li>
</ol>
<ul>
<li>复用 TCP 连接,减少高并发下的连接数(测试显示,1000 并发用户时连接数仅为 HTTP+SSE 的 1/10)。</li>
<li>平均响应时间更短(Streamable HTTP 为 0.0075s,HTTP+SSE 为 1.5112s)。</li>
</ul>
<ol start="3">
<li>客户端简化</li>
</ol>
<ul>
<li>相比 HTTP+SSE 需维护双通道,Streamable HTTP 客户端代码量减少 40% 以上,仅需处理统一端点。</li>
</ul>
<ol start="4">
<li>灵活部署</li>
</ol>
<ul>
<li>支持无状态模式,避免强制粘性会话(Sticky Session),便于水平扩展。</li>
<li>适用于云原生架构,如 Kubernetes 动态扩缩容。</li>
</ul>
<h2 id="典型应用场景">典型应用场景</h2>
<ul>
<li>无状态服务(如数学计算工具)</li>
</ul>
<p>客户端直接发送 POST 请求,服务器返回即时 HTTP 响应,无需维护会话。</p>
<ul>
<li>流式进度反馈(如大文件处理)</li>
</ul>
<p>服务器通过 SSE 流分阶段推送进度(如 10%、30%),完成后关闭连接。</p>
<ul>
<li>多轮对话 AI(如上下文感知助手)</li>
</ul>
<p>初始化会话后,通过会话 ID 维持上下文,支持多轮交互与断线恢复。</p>
<ul>
<li>弱网络环境</li>
</ul>
<p>网络中断后,客户端可携带会话 ID 重新连接,从断点继续任务。</p>
<h1 id="开发语言的选择">开发语言的选择</h1>
<p>mcp-java-sdk 暂未支持新版 Streamable HTTP 协议,(不过应该也快了,目前在分支PR上已经有了,https://github.com/modelcontextprotocol/java-sdk/commit/fdc11db29e23be3e8df38c812ea250a1b4fd3f1b#diff-31e16deaf3da3266ef0811b072b367a44c30e9c03c9e1fc738de6dc07d22d63d)需要继续使用SSE实现,当然你也可以采用pyton-sdk,它是有支持的。</p>
<ul>
<li>https://github.com/modelcontextprotocol/java-sdk</li>
<li>https://github.com/modelcontextprotocol/python-sdk</li>
</ul>
<p><img src="https://images.cnblogs.com/cnblogs_com/lori/2457803/o_250516010632_%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20250516090618.png" alt="" loading="lazy"></p>


</div>
<div id="MySignature" role="contentinfo">
    <p></p>
<div class="navgood">
<p>作者:仓储大叔,张占岭,<br>
荣誉:微软MVP<br>QQ:853066980</p>

<p><strong>支付宝扫一扫,为大叔打赏!</strong>
<br><img src="https://images.cnblogs.com/cnblogs_com/lori/237884/o_IMG_7144.JPG"></p>
</div><br><br>
来源:https://www.cnblogs.com/lori/p/18879637
頁: [1]
查看完整版本: mcp~客户端与服务端的通讯技术