From 321bee93ffb7d813e268d7f4fb3dae65b2d93b8b Mon Sep 17 00:00:00 2001 From: wanghanlin <1533525126@qq.com> Date: Thu, 20 Aug 2026 16:52:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(mcp):=20=E4=BF=AE=E5=A4=8D=20SSE=20?= =?UTF-8?q?=E7=AB=AF=E7=82=B9=E5=B8=A6=E8=B7=AF=E5=BE=84=E5=89=8D=E7=BC=80?= =?UTF-8?q?=E6=97=B6=E8=BF=9E=E6=8E=A5=20404?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HttpClientSseClientTransport 内部用 URI.resolve 拼接端点,对以 / 开头的 sseEndpoint 会整体替换 path,导致 /mcp-cdw/sse 被解析成 /sse 丢失前缀。 改为显式拆分 origin 与 path,分别作为 baseUri 与 sseEndpoint 传入, 并兼容用户填 base 或完整 SSE URL 两种写法。 --- .../supportbot/config/McpClientManager.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/wok/supportbot/config/McpClientManager.java b/src/main/java/com/wok/supportbot/config/McpClientManager.java index 2e8e5cb..b97a96d 100644 --- a/src/main/java/com/wok/supportbot/config/McpClientManager.java +++ b/src/main/java/com/wok/supportbot/config/McpClientManager.java @@ -464,11 +464,23 @@ public class McpClientManager { if ("sse".equals(config.getTransportType())) { // 创建 SSE 传输层:连接远程 MCP Server - // HttpClientSseClientTransport 会自动将 /sse 作为 SSE 端点附加到 baseUri String serverUrl = config.getServerUrl().trim(); - // 如果 URL 以 /sse 结尾,去掉后缀作为 baseUri(transport 层会自动附加) - String baseUri = serverUrl.replaceAll("/sse/?$", ""); - HttpClientSseClientTransport.Builder transportBuilder = HttpClientSseClientTransport.builder(baseUri); + + // 显式拆分 origin(scheme://host:port)与 path,分别作为 baseUri 与 sseEndpoint。 + // 注意:HttpClientSseClientTransport 内部用 URI.resolve 拼接,对以 / 开头的 sseEndpoint + // 会整体替换 path,因此不能把「去掉 /sse 的完整 URL」当 baseUri(否则 /mcp-cdw/sse 会 + // 被 resolve 成 /sse,丢失路径前缀)。这里把 origin 作为 baseUri、完整 path 作为 sseEndpoint。 + java.net.URI uri = java.net.URI.create(serverUrl); + String baseUri = uri.getScheme() + "://" + uri.getAuthority(); + String ssePath = uri.getPath() == null ? "" : uri.getPath(); + // 规范化:去掉末尾 / 后,确保 path 以 /sse 结尾(兼容用户填 base 或完整 SSE URL 两种写法) + ssePath = ssePath.replaceAll("/+$", ""); + if (!ssePath.endsWith("/sse")) { + ssePath = ssePath + "/sse"; + } + + HttpClientSseClientTransport.Builder transportBuilder = + HttpClientSseClientTransport.builder(baseUri).sseEndpoint(ssePath); // 注入自定义请求头(如 Authorization / X-API-Key),适配需要鉴权的远程 MCP 服务 Map headers = config.getHeaders(); if (headers != null && !headers.isEmpty()) { @@ -481,7 +493,7 @@ public class McpClientManager { HttpClientSseClientTransport transport = transportBuilder.build(); client = buildSyncClient(transport); - log.info("正在初始化 SSE MCP 客户端: id={}, url={}, headers={}", config.getId(), baseUri, headers != null ? headers.keySet() : "无"); + log.info("正在初始化 SSE MCP 客户端: id={}, url={}, headers={}", config.getId(), baseUri + ssePath, headers != null ? headers.keySet() : "无"); } else if ("stdio".equals(config.getTransportType())) { // 创建 stdio 传输层:启动本地 MCP Server 进程