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

mcp通讯协议

  • stdio
  • sse
  • streamable http

JSON_RPC

MCP 的传输层负责将 MCP 协议消息转换为 JSON-RPC 格式进行传输,并将接收到的 JSON-RPC 消息转换回 MCP 协议消息

  • 请求
{
  jsonrpc: "2.0",
  id: number | string,
  method: string,
  params?: object
}
  • 响应
{
  jsonrpc: "2.0",
  id: number | string,
  result?: object,
  error?: {
    code: number,
    message: string,
    data?: unknown
  }
}

一 stdio

本地化部署mcp server后,本机上的gpt工具集成了mcp client skd,然后通过本地进程与mcp server进行通讯

二 sse

MCP 早期采用 HTTP+SSE(Server-Sent Events)实现客户端与服务器的通信,但存在以下问题:

  1. 不支持断线恢复:SSE 连接中断后会话状态丢失,需重新开始。
  2. 服务器资源压力大:需为每个客户端维护长连接,高并发时资源消耗显著。
  3. 单向通信限制:服务器只能通过 SSE 端点单向推送消息,无法灵活处理双向交互。
  4. 基础设施兼容性差:CDN、防火墙等可能中断长连接,导致服务不可靠。

客户端和服务端通讯原理

  1. 客户端向服务服务/sse节点发起get请求,它是一个长连接,connection keep-alive,accept text/event-stream
  2. 服务端返回endpoint节点,并带上sessionId标识,之后服务端向客户端推送的数据,也是从这个/sse节点完成
  3. 客户端向endpoint节点发起post请求,将问题以请求体的形式发给mcp server
  4. mcp server获取当前endpoint+sessionId,对请求体处理,并通过/sse接口推送到客户端

sdk处理流程  

 

实际工作过程总结

连接建立
    客户端请求 /sse;
    服务端初始化 SseEmitter 和 McpServerSession,返回可用的消息接口地址。
会话初始化
    客户端通过 /message 发送 InitializeRequest,告知能力与标识;
    服务端处理后通过 SSE 返回 InitializeResponse。
资源管理
    客户端发起如 tools/list 请求;
    服务端从会话中查找状态,调用工具处理器并通过 SSE 返回结果。
调用工具
    客户端拼接 prompt 后发起 tools/call;
    服务端查找处理器执行逻辑,并通过 SSE 返回执行结果。
连接维持
    客户端周期性发送 ping;
    服务端返回 pong,用于保持连接活跃。
连接关闭
    客户端主动断开;
    服务端清理对应的连接与会话状态。

java-webflux正确引用

使用快照版1.0.0-SNAPSHO,引用包spring-ai-starter-mcp-server-webflux

 <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
        </dependency>
 </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

使用标准版1.0.0-M6,引用包spring-ai-mcp-server-webflux-spring-boot-starter会出现无sessionId参数的问题

三 streamable http

Streamable HTTP 通过以下设计解决了SSE的问题:

  1. 统一端点
    移除专用的 /sse 端点,所有通信通过单一端点(如 /mcp)完成,支持 POST 和 GET 请求。

  2. 按需流式传输
    服务器可灵活选择响应方式:

    • 普通 HTTP 响应:适用于简单请求(如计算任务)。
    • 升级为 SSE 流:用于需持续推送的场景(如进度反馈)。
    • 维持长连接:支持双向流式交互(如多轮对话)。
  3. 会话标识与状态管理
    引入会话 ID 机制(通过 Mcp-Session-Id 头部传递),支持断线重连和状态恢复。服务器可选择无状态(Stateless)或有状态(Stateful)模式运行。

  4. 灵活初始化与恢复

    • 客户端可通过空 GET 请求主动初始化 SSE 流。
    • 断线后,客户端可通过会话 ID 重新连接并恢复上下文。

Streamable HTTP 的优势

  1. 兼容性与扩展性
  • 纯 HTTP 实现,兼容 CDN、API 网关等现有基础设施。
  • 支持无状态服务器,适合 Serverless 架构(如 AWS Lambda)。
  1. 性能优化
  • 复用 TCP 连接,减少高并发下的连接数(测试显示,1000 并发用户时连接数仅为 HTTP+SSE 的 1/10)。
  • 平均响应时间更短(Streamable HTTP 为 0.0075s,HTTP+SSE 为 1.5112s)。
  1. 客户端简化
  • 相比 HTTP+SSE 需维护双通道,Streamable HTTP 客户端代码量减少 40% 以上,仅需处理统一端点。
  1. 灵活部署
  • 支持无状态模式,避免强制粘性会话(Sticky Session),便于水平扩展。
  • 适用于云原生架构,如 Kubernetes 动态扩缩容。

典型应用场景

  • 无状态服务(如数学计算工具)

客户端直接发送 POST 请求,服务器返回即时 HTTP 响应,无需维护会话。

  • 流式进度反馈(如大文件处理)

服务器通过 SSE 流分阶段推送进度(如 10%、30%),完成后关闭连接。

  • 多轮对话 AI(如上下文感知助手)

初始化会话后,通过会话 ID 维持上下文,支持多轮交互与断线恢复。

  • 弱网络环境

网络中断后,客户端可携带会话 ID 重新连接,从断点继续任务。

开发语言的选择

mcp-java-sdk 暂未支持新版 Streamable HTTP 协议,(不过应该也快了,目前在分支PR上已经有了,feat(client): makes possible to use StreamableHttpClientTransport in … · modelcontextprotocol/java-sdk@fdc11db · GitHub)需要继续使用SSE实现,当然你也可以采用pyton-sdk,它是有支持的。

 

 

 

<think>嗯,用户问的是Spring AI中的Model Context Protocol(MCP)客户端通过SSE连接服务端,连接不上。首先,我需要确认MCP在Spring AI中的具体定义和用途。可能用户提到的MCP是Spring AI项目中用于AI模型服务通信的某种协议,而SSE指的是Server-Sent Events,一种基于HTTP的服务器推送技术。 接下来,我应该先回想一下Spring AI的相关文档或者社区讨论,是否确实有MCP这个协议。假设存在的话,MCP可能负责管理客户端AI模型服务之间的通信,使用SSE来实现实时数据流传输。当客户端无法连接时,可能涉及多个方面的原因,比如网络问题、配置错误、服务端问题或客户端代码错误。 用户可能需要了解常见的排查步骤。首先检查网络连接,确保客户端能访问服务端地址和端口。然后查看服务端状态,确认服务是否正常运行,是否有足够的资源。接着检查SSE端点是否正确,URL是否无误,是否有必要的认证参数如API密钥。然后查看客户端代码,是否正确配置了SSE连接,事件监听是否正确注册,是否有异常处理。日志和错误信息也很重要,服务端客户端的日志可能会显示具体错误,比如401未授权或500内部错误。 另外,可能要考虑防火墙或代理设置是否阻止了SSE的长连接,因为SSE依赖长久的HTTP连接,某些网络设备可能会中断这类连接。还要检查服务端是否支持SSE,有些框架可能需要额外配置才能启用SSE功能。如果服务端使用了Spring Boot,可能需要检查相关的注解和配置是否正确,比如是否有@CrossOrigin允许跨域请求,因为浏览器中SSE可能会受到CORS策略的限制。 如果用户提供了更具体的错误信息,比如连接超时、拒绝连接,或者HTTP状态码,可以更精准地定位问题。例如,403 Forbidden可能意味着认证失败,而404 Not Found说明URL路径错误。此外,客户端的重试机制是否合理,是否在连接断开后尝试重新连接,这也是需要考虑的。 最后,可能需要建议用户使用工具如curl或Postman测试SSE端点,确认服务端是否正常发送事件,从而确定问题是出在客户端还是服务端。如果服务端没问题,再深入检查客户端代码,比如是否处理了onError事件,是否有未捕获的异常导致连接中断。 总结下来,回答需要分步骤指导用户排查可能的原因,并提供具体的检查点,帮助他们逐步定位和解决问题。同时,保持回答结构清晰,易于理解,避免使用过多技术 jargon,但又要足够详细覆盖常见问题点。在</think> Spring AI 中,**Model Context Protocol (MCP)** 是一个用于客户端 AI 模型服务之间通信的协议,通常结合 Server-Sent Events (SSE) 实现实时数据流传输。如果客户端通过 SSE 连接服务端时遇到连接问题,可能是由以下原因导致: --- ### **常见连接失败原因及排查步骤** #### 1. **网络或服务端状态** - **服务端未启动**:确保服务端应用已正确启动,监听指定端口。 - **网络不可达**:检查客户端能否访问服务端的 IP/域名和端口(如防火墙、代理、安全组规则)。 - **SSE 端点路径错误**:确认客户端请求的 URL 是否服务端暴露的 SSE 接口路径一致(例如 `/mcp/stream`)。 #### 2. **协议配置问题** - **SSE 支持未启用**:服务端需显式支持 SSE,例如在 Spring 中使用 `SseEmitter` 或响应类型 `text/event-stream`。 - **跨域限制 (CORS)**:浏览器环境下需配置服务端允许跨域请求(如 Spring 的 `@CrossOrigin` 注解或全局 CORS 配置)。 - **超时设置**:检查服务端 SSE 连接的 `timeout` 配置,避免过早断开。 #### 3. **认证权限** - **缺少认证头**:若服务端需要 API Key、Token 等认证信息,客户端需在请求头中添加(如 `Authorization: Bearer <token>`)。 - **事件监听未注册**:确保客户端正确订阅了 SSE 事件(如 `onmessage`, `onerror`)。 - **连接未保持**:SSE 是长连接,需避免客户端主动关闭或未处理重连逻辑。 - **示例代码错误**: ```javascript // 浏览器端 SSE 客户端示例 const eventSource = new EventSource('http://server:port/mcp/stream'); eventSource.onmessage = (event) => { console.log('Received data:', event.data); }; eventSource.onerror = (error) => { console.error('SSE Error:', error); // 检查此处输出的错误详情 }; ``` #### 5. **日志调试** - **服务端日志**:查看服务端是否有连接错误日志(如权限拒绝、资源不足)。 - **客户端日志**:通过浏览器控制台或客户端日志捕获具体错误(如 HTTP 状态码 404/403/500)。 - **工具测试**:使用 `curl` 或 Postman 直接调用 SSE 端点,验证服务端是否正常响应: ```bash curl -N http://server:port/mcp/stream ``` --- ### **典型解决方案** 1. **验证基础连接**:用 `ping` 或 `telnet` 测试服务端可达性。 2. **简化测试**:暂时关闭认证,确认是否为权限问题。 3. **检查 HTTP 头**: - 确保响应头包含 `Content-Type: text/event-stream`。 - 检查请求头是否携带必要参数(如 `Accept: text/event-stream`)。 4. **调整超时设置**:在服务端延长 SSE 连接的 `SseEmitter` 超时时间: ```java // Spring 服务端示例 @GetMapping("/mcp/stream") public SseEmitter streamData() { SseEmitter emitter = new SseEmitter(60_000L); // 设置 60 秒超时 // ... 发送数据逻辑 return emitter; } ``` 5. **处理重连机制**:在客户端代码中添加自动重连逻辑,应对网络波动。 --- 如果问题仍存在,建议提供具体的 **错误信息**、**代码片段** 和 **服务端配置**,以便进一步定位原因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值