From 97a73a1cb6688fe56c51a6f2b5dfc03a646b1ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:06:41 +0800 Subject: [PATCH] Add files via upload --- internal/handler/external_mcp.go | 21 +++++++------- internal/handler/external_mcp_test.go | 10 +++++++ internal/handler/monitor.go | 40 ++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/internal/handler/external_mcp.go b/internal/handler/external_mcp.go index 662b7463..931c9e09 100644 --- a/internal/handler/external_mcp.go +++ b/internal/handler/external_mcp.go @@ -64,10 +64,7 @@ func (h *ExternalMCPHandler) GetExternalMCPs(c *gin.Context) { } toolCount := toolCounts[name] - errorMsg := "" - if status == "error" { - errorMsg = h.manager.GetError(name) - } + errorMsg := externalMCPStatusError(h.manager, name, status) result[name] = ExternalMCPResponse{ Config: cfg, @@ -115,20 +112,22 @@ func (h *ExternalMCPHandler) GetExternalMCP(c *gin.Context) { } } - // 获取错误信息 - errorMsg := "" - if status == "error" { - errorMsg = h.manager.GetError(name) - } - c.JSON(http.StatusOK, ExternalMCPResponse{ Config: cfg, Status: status, ToolCount: toolCount, - Error: errorMsg, + Error: externalMCPStatusError(h.manager, name, status), }) } +// externalMCPStatusError 在 error/disconnected 状态下返回最近错误(含断连原因)。 +func externalMCPStatusError(manager *mcp.ExternalMCPManager, name, status string) string { + if status != "error" && status != "disconnected" { + return "" + } + return manager.GetError(name) +} + // AddOrUpdateExternalMCP 添加或更新外部MCP配置 func (h *ExternalMCPHandler) AddOrUpdateExternalMCP(c *gin.Context) { var req AddOrUpdateExternalMCPRequest diff --git a/internal/handler/external_mcp_test.go b/internal/handler/external_mcp_test.go index 16c64ff7..e4cf3c1f 100644 --- a/internal/handler/external_mcp_test.go +++ b/internal/handler/external_mcp_test.go @@ -271,6 +271,16 @@ func TestExternalMCPHandler_DeleteExternalMCP(t *testing.T) { } } +func TestExternalMCPStatusError(t *testing.T) { + manager := mcp.NewExternalMCPManager(zap.NewNop()) + if got := externalMCPStatusError(manager, "x", "connected"); got != "" { + t.Fatalf("connected status should not return error, got %q", got) + } + if got := externalMCPStatusError(manager, "x", "connecting"); got != "" { + t.Fatalf("connecting status should not return error, got %q", got) + } +} + func TestExternalMCPHandler_GetExternalMCPs(t *testing.T) { router, handler, _ := setupTestRouter() diff --git a/internal/handler/monitor.go b/internal/handler/monitor.go index b2d08aac..81fc8630 100644 --- a/internal/handler/monitor.go +++ b/internal/handler/monitor.go @@ -77,8 +77,8 @@ func (h *MonitorHandler) Monitor(c *gin.Context) { // 解析状态筛选参数 status := c.Query("status") - // 解析工具筛选参数 - toolName := c.Query("tool") + // 解析工具筛选参数(兼容 mcp__tool 与内部 mcp::tool) + toolName := normalizeToolNameFilter(c.Query("tool")) executions, total := h.loadExecutionsWithPagination(page, pageSize, status, toolName) stats := h.loadStats() @@ -113,7 +113,7 @@ func (h *MonitorHandler) loadExecutionsWithPagination(page, pageSize int, status for _, exec := range allExecutions { matchStatus := status == "" || exec.Status == status // 支持部分匹配(模糊搜索) - matchTool := toolName == "" || strings.Contains(strings.ToLower(exec.ToolName), strings.ToLower(toolName)) + matchTool := toolNameFilterMatches(exec.ToolName, toolName) if matchStatus && matchTool { filtered = append(filtered, exec) } @@ -143,7 +143,7 @@ func (h *MonitorHandler) loadExecutionsWithPagination(page, pageSize int, status for _, exec := range allExecutions { matchStatus := status == "" || exec.Status == status // 支持部分匹配(模糊搜索) - matchTool := toolName == "" || strings.Contains(strings.ToLower(exec.ToolName), strings.ToLower(toolName)) + matchTool := toolNameFilterMatches(exec.ToolName, toolName) if matchStatus && matchTool { filtered = append(filtered, exec) } @@ -584,3 +584,35 @@ func (h *MonitorHandler) DeleteExecutions(c *gin.Context) { h.logger.Info("尝试批量删除内存中的执行记录", zap.Int("count", len(request.IDs))) c.JSON(http.StatusOK, gin.H{"message": "执行记录已删除(如果存在)"}) } + +// normalizeToolNameFilter 将模型侧 mcp__tool 转为内部存储用的 mcp::tool。 +func normalizeToolNameFilter(name string) string { + name = strings.TrimSpace(name) + if name == "" { + return name + } + if strings.Contains(name, "::") { + return name + } + if idx := strings.Index(name, "__"); idx > 0 { + return name[:idx] + "::" + name[idx+2:] + } + return name +} + +func toolNameFilterMatches(storedName, filter string) bool { + filter = strings.TrimSpace(filter) + if filter == "" { + return true + } + storedLower := strings.ToLower(storedName) + filterLower := strings.ToLower(filter) + if strings.Contains(storedLower, filterLower) { + return true + } + normFilter := strings.ToLower(normalizeToolNameFilter(filter)) + if normFilter != filterLower && strings.Contains(storedLower, normFilter) { + return true + } + return strings.Contains(strings.ReplaceAll(storedLower, "::", "__"), filterLower) +}