package main import ( "context" "encoding/json" "strings" "time" "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/mcp" "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry" "git.yeij.top/AskaEth/Cyrene_v2/internal/config" "git.yeij.top/AskaEth/Cyrene_v2/internal/logger" ) // mcpConnectTimeout 约束每个 MCP server 的连接+发现握手,使挂死的 server 降级为 // 一条告警,而不是阻塞启动。 const mcpConnectTimeout = 15 * time.Second // wireMCP 读取 cfg.MCP.ServersJSON,连接每个已启用的 server,把发现到的工具注册进 // 能力注册表(KindTool,使 agent 可调用它们),并暴露一个 KindMCP 能力,让管理面板 // 的插件列表能枚举该 server。连接失败或未配置的 server 降级为一条告警,绝不阻塞 // 启动。 func (a *app) wireMCP() { log := logger.WithSource(a.log, "cmd/cyrene") servers, err := a.mcpServers() if err != nil { log.Warn("mcp config parse skipped", "error", err) return } if len(servers) == 0 { log.Debug("no mcp servers configured") return } for _, srv := range servers { if !srv.Enabled { continue } ctx, cancel := context.WithTimeout(context.Background(), mcpConnectTimeout) err := a.registerMCPServer(ctx, srv) cancel() if err != nil { log.Warn("mcp server skipped", "name", srv.Name, "error", err) } } } // mcpServers 从 cfg.MCP.ServersJSON 解析出已配置的 MCP server。 func (a *app) mcpServers() ([]config.MCPServer, error) { raw := strings.TrimSpace(a.cfg.MCP.ServersJSON) if raw == "" { return nil, nil } var servers []config.MCPServer if err := json.Unmarshal([]byte(raw), &servers); err != nil { return nil, err } return servers, nil } // registerMCPServer 连接单个 server,注册其工具,并以 "mcp:" 发布一个 // KindMCP 能力。它返回第一个错误以便调用方分类;注册中途失败时会清理已加入的内容。 func (a *app) registerMCPServer(ctx context.Context, srv config.MCPServer) error { log := logger.WithSource(a.log, "cmd/cyrene") reg := mcp.NewRegistry(a.caps, mcp.MCPConfig{ Name: srv.Name, Command: srv.Command, Args: srv.Args, URL: srv.URL, }, mcp.WithLogger(a.log)) if err := reg.Register(ctx); err != nil { _ = reg.Unregister(context.Background()) return err } if err := a.caps.Register(registry.Capability{ Name: "mcp:" + srv.Name, Kind: registry.KindMCP, Description: "MCP server " + srv.Name, Value: reg, }); err != nil { log.Warn("mcp capability register skipped", "name", srv.Name, "error", err) } a.mcpRegs = append(a.mcpRegs, reg) log.Info("mcp server registered", "name", srv.Name) return nil }