main.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // fwh-agent-mcp:新 AI 助手的业务数据 MCP 服务(Streamable HTTP)。
  2. //
  3. // fwh-agent-mcp -set=readonly,ops -listen=127.0.0.1:8091
  4. //
  5. // 一个进程、一个端口加载多个工具集,每个工具集挂在 /mcp/<工具集>(只读工具集另挂 /mcp 兼容旧地址);
  6. // -set 省略时加载全部工具集。
  7. //
  8. // 配置读取独立的 ./config.agent-mcp.env(-config 可指定),不读主服务的 config.env;AGENT_MCP_TOKEN 必填,
  9. // AGENT_MCP_TOKEN_<工具集大写>(如 AGENT_MCP_TOKEN_OPS)可为单个工具集指定单独的令牌。
  10. package main
  11. import (
  12. "context"
  13. "flag"
  14. "fmt"
  15. "os"
  16. "os/signal"
  17. "strings"
  18. "syscall"
  19. "go.uber.org/zap"
  20. "fwh-toolbox-server/agentmcp"
  21. )
  22. func main() {
  23. setFlag := flag.String("set", strings.Join(agentmcp.AllSets, ","), "工具集,逗号分隔:"+strings.Join(agentmcp.AllSets, ","))
  24. listen := flag.String("listen", "", "监听地址,默认取 AGENT_MCP_LISTEN(127.0.0.1:8091)")
  25. configFile := flag.String("config", agentmcp.DefaultConfigFile, "配置文件路径")
  26. flag.Parse()
  27. sets, err := agentmcp.ParseSets(*setFlag)
  28. if err != nil {
  29. fmt.Fprintf(os.Stderr, "[fwh-agent-mcp] -set 无效:%v\n", err)
  30. os.Exit(1)
  31. }
  32. // 配置文件缺失时直接退出:config.LoadConfig 读不到文件会静默使用默认值,连错库也不易察觉
  33. settings, err := agentmcp.LoadSettings(*configFile)
  34. if err != nil {
  35. fmt.Fprintf(os.Stderr, "[fwh-agent-mcp] %v,拒绝启动(示例见 deploy/config.agent-mcp.env.example)\n", err)
  36. os.Exit(1)
  37. }
  38. if settings.Token == "" {
  39. fmt.Fprintln(os.Stderr, "[fwh-agent-mcp] AGENT_MCP_TOKEN 未配置,拒绝启动")
  40. os.Exit(1)
  41. }
  42. addr := settings.Listen
  43. if *listen != "" {
  44. addr = *listen
  45. }
  46. log := agentmcp.InitLogger(settings.LogPath)
  47. defer func() { _ = log.Sync() }()
  48. if err := agentmcp.InitInfra(*configFile); err != nil {
  49. log.Fatal("[agent-mcp] 初始化失败", zap.Error(err))
  50. }
  51. endpoints := make([]agentmcp.Endpoint, 0, len(sets))
  52. for _, set := range sets {
  53. s, tasks, err := agentmcp.NewServer(set, log, settings.MaxConcurrency)
  54. if err != nil {
  55. log.Fatal("[agent-mcp] 创建 MCP Server 失败", zap.String("set", set), zap.Error(err))
  56. }
  57. endpoints = append(endpoints, agentmcp.Endpoint{Set: set, Server: s, Tasks: tasks, Token: settings.TokenFor(set)})
  58. log.Info("[agent-mcp] 加载工具集",
  59. zap.String("set", set),
  60. zap.String("path", agentmcp.EndpointPath(set)),
  61. zap.Bool("ownToken", settings.SetTokens[set] != ""))
  62. }
  63. ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
  64. defer stop()
  65. log.Info("[agent-mcp] 启动", zap.Strings("sets", sets), zap.String("version", agentmcp.ServerVersion), zap.Int("maxConcurrency", settings.MaxConcurrency))
  66. if err := agentmcp.Serve(ctx, addr, agentmcp.Handler(endpoints, log), log); err != nil {
  67. log.Fatal("[agent-mcp] HTTP 服务异常退出", zap.Error(err))
  68. }
  69. log.Info("[agent-mcp] 已退出")
  70. }