From dc06c83ce5f2eb4c31b2b984a5d3721c9d3b0b3e Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Fri, 12 Sep 2025 17:16:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E7=99=BE=E5=BA=A6mcp?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat_api/CustomSseClientTransport.kt | 78 +++++++++++++++---- .../chat_api/SystemFunctionHandler.kt | 1 + 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt index a08ed5472..d13fbc37a 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt @@ -86,7 +86,7 @@ class CustomSseClientTransport( // 路径部分 val path = urlObj.path - + Log.e(TAG, "$serviceidString 解析成功: hostUrl:$hostUrl,path:$path,params:$params") Triple(hostUrl, path, params) } catch (e: Exception) { Log.e(TAG, "$serviceidString 解析URL失败: $url, ${e.message}") @@ -101,9 +101,10 @@ class CustomSseClientTransport( job = scope.launch(CoroutineName("CustomSseMcpClientTransport.collect#${hashCode()}")) { try { session.incoming.collect { event -> + Log.e(TAG, "$serviceidString event:${event.event}-${event.data}") when (event.event) { "error" -> { - Log.e(TAG, "$serviceidString SSE错误: ${event.data}") +// Log.e(TAG, "$serviceidString SSE错误: ${event.data}") isConnected.set(false) val exception = Exception("$serviceidString SSE Error: ${event.data}") _onError(exception) @@ -113,7 +114,7 @@ class CustomSseClientTransport( "open" -> { // SSE连接已打开 - Log.d(TAG, "$serviceidString SSE连接已打开") +// Log.d(TAG, "$serviceidString SSE连接已打开") isConnected.set(true) } "ping" -> { @@ -122,29 +123,73 @@ class CustomSseClientTransport( "endpoint" -> { try { val eventData = event.data ?: "" - + // 构建完整的端点URL - val fullEndpoint = if (eventData.contains(hostPart)) { - eventData - } else if (eventData.startsWith("/")) { - "$hostPart$eventData" - } else { - eventData + val fullEndpoint = when { + // 如果eventData已经包含完整的URL(包含协议) + eventData.startsWith("http://") || eventData.startsWith("https://") -> { + eventData + } + // 如果eventData包含hostPart但没有协议 + eventData.contains(hostPart.substringAfter("://")) -> { + if (eventData.startsWith("://")) { + "${hostPart.substringBefore("://")}$eventData" + } else { + "https://$eventData" + } + } + // 如果eventData以/开头,说明是路径 + eventData.startsWith("/") -> { + "$hostPart$eventData" + } + // 如果eventData不为空但不包含完整信息,尝试构建完整URL + eventData.isNotEmpty() -> { + if (hostPart.isNotEmpty()) { + // 如果eventData看起来像是路径片段,添加/前缀 + val path = if (!eventData.startsWith("/")) "/" + eventData else eventData + "$hostPart$path" + } else { + // 如果没有hostPart,尝试添加默认协议 + if (!eventData.contains("://")) { + "https://$eventData" + } else { + eventData + } + } + } + // 如果eventData为空,使用hostPart + else -> hostPart + } + + // 验证URL格式 + val validatedEndpoint = try { + val url = java.net.URL(fullEndpoint) + fullEndpoint + } catch (e: Exception) { + Log.w(TAG, "$serviceidString 端点URL格式可能有问题: $fullEndpoint, 尝试修复") + // 尝试修复URL + when { + !fullEndpoint.startsWith("http://") && !fullEndpoint.startsWith("https://") -> { + "https://$fullEndpoint" + } + else -> fullEndpoint + } } // 添加查询参数 val endpointWithParams = if (queryParams.isNotEmpty()) { - if (fullEndpoint.contains("?")) { + if (validatedEndpoint.contains("?")) { val queryString = queryParams.entries.joinToString("&") { "${it.key}=${it.value}" } - "$fullEndpoint&$queryString" + "$validatedEndpoint&$queryString" } else { val queryString = queryParams.entries.joinToString("&") { "${it.key}=${it.value}" } - "$fullEndpoint?$queryString" + "$validatedEndpoint?$queryString" } } else { - fullEndpoint + validatedEndpoint } + Log.d(TAG, "$serviceidString 处理endpoint事件: $endpointWithParams") endpoint.complete(endpointWithParams) } catch (e: Exception) { Log.e(TAG, "$serviceidString 处理endpoint事件失败: ${e.message}", e) @@ -174,7 +219,7 @@ class CustomSseClientTransport( } } } catch (e: CancellationException) { - Log.d(TAG, "$serviceidString SSE事件收集被取消") + Log.e(TAG, "$serviceidString SSE事件收集被取消 : ${e.message}", e) throw e } catch (e: Exception) { Log.e(TAG, "$serviceidString SSE连接异常断开: ${e.message}", e) @@ -219,11 +264,12 @@ class CustomSseClientTransport( * 启动传输层 */ override suspend fun start() { + if (!initialized.compareAndSet(false, true)) { Log.e(TAG, "$serviceidString 传输层已经启动,不能重复启动") error("CustomSseClientTransport already started!") } - + Log.d(TAG, "CustomSseClientTransport $serviceidString 启动") // 解析URL if (urlString != null) { val urlInfo = parseUrl(urlString) diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt index af83a46d0..e82e77bd2 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt @@ -1352,6 +1352,7 @@ private class UpdateUserPortraitHandler(private val context: Context?) : Functio context.sendBroadcast(intent) // 发送广播通知退出交互 return JSONObject().apply { + put("nocard", true) put("result", "更新成功!") }.toString() }