// Package agentmcp 是新 AI 助手使用的业务数据 MCP 服务(fwh-agent-mcp)。 // // 无用户状态:工具不接收、不推断调用者;由 AgentServer 后台登记为远程 HTTP 服务,经 MCP Gateway 转接给 Agent。 // 设计见 docs/ai-assistant-agentserver/agent-mcp.md。与旧助手的 cmd/mcp 相互独立。 package agentmcp import ( "fmt" "strings" "github.com/mark3labs/mcp-go/server" "go.uber.org/zap" "fwh-toolbox-server/agentmcp/kit" "fwh-toolbox-server/agentmcp/tools" ) const ( ServerName = "fwh-agent-mcp" ServerVersion = "1.0.0" SetReadOnly = "readonly" SetOps = "ops" ) // AllSets 全部工具集。一个进程可同时加载多个,各自挂在 EndpointPath(set) 上,共用一个端口。 var AllSets = []string{SetReadOnly, SetOps} // Tools 返回指定工具集。 func Tools(set string) ([]kit.Registrar, error) { switch set { case SetReadOnly: return tools.ReadOnly(), nil case SetOps: return tools.Ops(), nil } return nil, fmt.Errorf("未知的工具集:%s(可选 %s)", set, strings.Join(AllSets, " / ")) } // EndpointPath 工具集的 MCP 路径:/mcp/<工具集>。只读工具集另外挂在 /mcp 上,兼容已登记的地址。 func EndpointPath(set string) string { return "/mcp/" + set } // ParseSets 解析逗号分隔的工具集列表(去空白、去重,保持顺序);空串表示全部。 func ParseSets(s string) ([]string, error) { if strings.TrimSpace(s) == "" { return append([]string(nil), AllSets...), nil } var sets []string seen := map[string]bool{} for _, part := range strings.Split(s, ",") { set := strings.TrimSpace(part) if set == "" || seen[set] { continue } if _, err := Tools(set); err != nil { return nil, err } seen[set] = true sets = append(sets, set) } if len(sets) == 0 { return nil, fmt.Errorf("未指定工具集") } return sets, nil } // NewServer 创建 MCPServer 并注册工具集;同时返回其中的持久化长任务工具(交给 Handler 的 TaskRouter 处理任务协议)。 func NewServer(set string, log *zap.Logger, maxConcurrency int) (*server.MCPServer, []kit.TaskTool, error) { list, err := Tools(set) if err != nil { return nil, nil, err } var tasks []kit.TaskTool for _, t := range list { if tt, ok := t.(kit.TaskTool); ok { tasks = append(tasks, tt) } } opts := []server.ServerOption{ server.WithToolCapabilities(false), server.WithInputSchemaValidation(), server.WithToolHandlerMiddleware(kit.Middleware(log, maxConcurrency)), } if len(tasks) > 0 { // 声明支持以任务方式调用工具与取消(tasks.requests.tools.call、tasks.cancel);任务协议由 kit.TaskRouter 处理 opts = append(opts, server.WithTaskCapabilities(false, true, true)) } s := server.NewMCPServer(ServerName+"-"+set, ServerVersion, opts...) for _, t := range list { t.Register(s) } return s, tasks, nil }