Spring AI MCP Server接入百炼问题排查

Spring AI MCP Server接入百炼问题排查

问题背景

在将基于Spring AI的MCP(Model Context Protocol)服务接入阿里云百炼平台时,遇到一个奇怪的问题:MCP服务在trae客户端上可以正常工作,但在百炼平台上却无法正常使用。具体表现为百炼平台发送第二个请求时,服务端接收不到请求体,导致请求失败。

公司有个AI对话智能体的需求,作为负责这个需求的后端开发,开发阶段被这个问题困扰了好久,不过最终还是然我找到原因了。所以写一篇博客分享一下,避免大家后续使用Spring MCP Server 接入百炼时踩坑!

问题现象

正常情况(trae客户端)

trae客户端每个请求都创建新的连接:

  1. 第一个连接发送initialize请求 → 响应后关闭连接
  2. 第二个连接发送notifications/initialized请求 → 响应后关闭连接
  3. 第三个连接发送tools/list请求 → 正常处理

异常情况(百炼平台)

百炼一直会提示:"获取工具异常,请确认MCP是否正常运行"

复制代码
"获取工具异常,请确认MCP是否正常运行
错误码:11200001
RequestId: dce6eab1-b35c-4471-bc97-d764639dff73

分析日志后发现是由于百炼平台会尝试复用连接导致的:

  1. 第一个连接发送initialize请求 → 响应后服务器关闭连接
  2. 在同一个连接上尝试发送第二个请求 → 但是此时MCP服务端Netty已经关闭链接了,这时候即使收到请求头,但是Netty的channel可能已经半关闭了,无法再继续接收请求内容,也无法正常响应内容。百炼那边等待超时就抛出异常了!

日志分析

从服务端日志可以看到关键信息:

log 复制代码
# 第一个请求正常处理
2025-12-13T11:43:58.745+08:00 INFO  REQUEST_BODY_DEBUG : MCP Request Body (207 bytes): {"jsonrpc":"2.0","method":"initialize","id":"3fe559ae-0",...}

# 服务器响应后关闭连接
2025-12-13T11:43:58.750+08:00 DEBUG r.n.http.server.HttpServerOperations : Last HTTP packet was sent, terminating the channel

# 第二个请求到达,但请求体为空
2025-12-13T11:44:58.805+08:00 INFO  REQUEST_BODY_DEBUG : MCP Request Body (0 bytes): 
2025-12-13T11:44:58.808+08:00 ERROR WebFluxStreamableServerTransportProvider : Failed to deserialize message: No content to map due to end-of-input

问题定位

通过深入分析日志,我们发现问题出现在几个方面:

1. HTTP/1.1连接复用问题

  • 服务器在发送完第一个响应后立即关闭了连接(terminating the channel
  • 百炼平台认为连接仍然可用,尝试复用连接发送第二个请求
  • 由于连接已关闭,第二个请求的请求体无法被正确传输

2. 客户端-服务器行为不一致

  • trae:为每个请求创建新连接,符合服务器预期
  • 百炼:尝试复用连接以提升性能,但与服务器行为冲突

3. 协议处理差异

  • trae使用协议版本:2025-06-18
  • 百炼使用协议版本:2025-03-26
  • trae的capabilities为空对象
  • 百炼的capabilities包含roots.listChanged=true

排查过程

第一阶段:基础排查

  1. 检查协议兼容性:确认两个协议版本都支持
  2. 检查日志级别:启用DEBUG级别日志
  3. 对比请求差异:分析trae和百炼的请求头、请求体差异

第二阶段:深入分析

  1. 添加请求体调试过滤器
java 复制代码
@Component
@Order(1)
public class RequestBodyDebugFilter implements WebFilter {
    // 记录请求头和请求体内容
}
  1. 发现关键证据
  • 第二个请求的Content-Length: 54,但实际接收到的body是0字节
  • 请求在开始处理后等待60秒超时
  1. 排除可能性
  • 排除100-continue问题(百炼没有发送Expect头)
  • 排除缓冲区大小问题
  • 排除JSON解析问题

第三阶段:问题根源确认

通过对比分析和日志追踪,确认问题是:
服务器在HTTP/1.1连接上过早关闭连接,但客户端仍尝试复用该连接

解决方案

最终解决方案:响应头中告诉百炼,链接已经关闭

java 复制代码
@Component
@Order(Integer.MIN_VALUE)
public class ForceConnectionCloseFilter implements WebFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        
        if (path.equals("/mcp")) {
            // 在响应头中强制设置Connection: close
            exchange.getResponse().getHeaders().set("Connection", "close");
            log.info("Forcing connection close for MCP request on connection: {}", 
                     exchange.getRequest().getId());
        }
        
        return chain.filter(exchange);
    }
}

方案原理

  1. 显式通信 :通过Connection: close头明确告诉客户端不要复用连接
  2. 客户端适配:百炼平台看到这个头后会为每个请求创建新连接
  3. 消除歧义:避免客户端和服务器对连接状态的理解不一致

其他尝试方案(未成功)

  1. 调整Netty配置尝试保持连接
  2. 修改HTTP解码器参数
  3. 添加Expect: 100-continue处理
  4. 调整连接超时时间

技术要点总结

1. HTTP/1.1连接管理

  • 默认情况下,HTTP/1.1支持连接复用(keep-alive)
  • 服务器可以通过Connection: close头显式关闭连接
  • Spring WebFlux/Netty在特定情况下可能过早关闭连接

2. Spring WebFlux行为

  • Reactive编程模型对连接管理有特殊处理
  • Netty默认配置可能不适合所有客户端
  • 需要显式配置来处理连接复用

3. 客户端差异

  • 不同HTTP客户端对连接复用的实现策略不同
  • 有些客户端更激进地尝试复用连接
  • 服务器需要能够处理各种客户端行为

经验教训

  1. 不要假设客户端行为一致:不同的HTTP客户端实现可能有显著差异
  2. 连接管理要显式:模糊的连接管理容易导致问题
  3. 日志是最好的调试工具:详细的日志可以快速定位问题
  4. 简单方案往往最有效 :复杂的配置调整不如简单的Connection: close
  5. 理解底层协议:对HTTP协议的理解有助于解决这类问题

结论

通过添加ForceConnectionCloseFilter,我们成功地解决了Spring AI MCP Server接入百炼平台的问题。这个问题的核心在于客户端和服务器对HTTP/1.1连接复用的行为不一致。解决方案虽然简单,但背后涉及对HTTP协议、Spring WebFlux连接管理和客户端兼容性的深入理解。

相关推荐
刘立军8 小时前
程序员应该熟悉的概念(4)MCP能做什么
人工智能·mcp
默 语11 小时前
用Java撸一个AI聊天机器人:从零到一的踩坑实录
java·人工智能·spring·ai·机器人·spring ai
面壁的熊猫1 天前
cursor+cline+MCP(论文agent)
vscode·agent·cursor·mcp
Light601 天前
再见,REST API?你好,MCP Server!AI时代后端开发新范式
java·人工智能·rest api·ai agent·spring ai·mcp
蛐蛐蜉蝣耶1 天前
Spring AI与MCP集成实践:构建智能应用的新方式
人工智能·微服务·java开发·spring ai·mcp
IT空门:门主2 天前
Spring AI的教程,持续更新......
java·人工智能·spring·spring ai
百罹鸟2 天前
现如今的AI IDE:提示词策略与MCP Server使用感悟
前端·人工智能·mcp
rockingdingo2 天前
利用 OneKey MCP Router Python SDK构建多领域大模型Function Call多工具调用数据集
网络·windows·python·ai agent·mcp
DO_Community3 天前
DigitalOcean 远程 MCP 正式上线,让基础设施“开口说话”
ai·agent·mcp