Browse Source

fix(mcp): 修复 SSE 端点带路径前缀时连接 404

HttpClientSseClientTransport 内部用 URI.resolve 拼接端点,对以 / 开头的
sseEndpoint 会整体替换 path,导致 /mcp-cdw/sse 被解析成 /sse 丢失前缀。
改为显式拆分 origin 与 path,分别作为 baseUri 与 sseEndpoint 传入,
并兼容用户填 base 或完整 SSE URL 两种写法。
master
wanghanlin 4 days ago
parent
commit
321bee93ff
  1. 22
      src/main/java/com/wok/supportbot/config/McpClientManager.java

22
src/main/java/com/wok/supportbot/config/McpClientManager.java

@ -464,11 +464,23 @@ public class McpClientManager {
if ("sse".equals(config.getTransportType())) { if ("sse".equals(config.getTransportType())) {
// 创建 SSE 传输层连接远程 MCP Server // 创建 SSE 传输层连接远程 MCP Server
// HttpClientSseClientTransport 会自动将 /sse 作为 SSE 端点附加到 baseUri
String serverUrl = config.getServerUrl().trim(); String serverUrl = config.getServerUrl().trim();
// 如果 URL /sse 结尾去掉后缀作为 baseUritransport 层会自动附加
String baseUri = serverUrl.replaceAll("/sse/?$", "");
HttpClientSseClientTransport.Builder transportBuilder = HttpClientSseClientTransport.builder(baseUri);
// 显式拆分 originscheme://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 服务 // 注入自定义请求头 Authorization / X-API-Key适配需要鉴权的远程 MCP 服务
Map<String, Object> headers = config.getHeaders(); Map<String, Object> headers = config.getHeaders();
if (headers != null && !headers.isEmpty()) { if (headers != null && !headers.isEmpty()) {
@ -481,7 +493,7 @@ public class McpClientManager {
HttpClientSseClientTransport transport = transportBuilder.build(); HttpClientSseClientTransport transport = transportBuilder.build();
client = buildSyncClient(transport); 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())) { } else if ("stdio".equals(config.getTransportType())) {
// 创建 stdio 传输层启动本地 MCP Server 进程 // 创建 stdio 传输层启动本地 MCP Server 进程

Loading…
Cancel
Save