bootstrapMCP wires up the MCP manager + config watcher during chatcli startup. Pulled out of NewChatCLI so the auto-enable rule, the LoadConfig-tolerates-failure path, and the watcher handoff are testable in isolation. Safe no-op when MCP is not enabled by the env var and neither the config file nor
(ctx context.Context, logger *zap.Logger)
| 1655 | // start the watcher so the user can fix the file in place and have |
| 1656 | // it picked up on save instead of having to restart chatcli. |
| 1657 | func (cli *ChatCLI) bootstrapMCP(ctx context.Context, logger *zap.Logger) { |
| 1658 | mcpEnabled := os.Getenv("CHATCLI_MCP_ENABLED") == "true" |
| 1659 | mcpConfigPath := resolveMCPConfigPath() |
| 1660 | if !mcpEnabled && shouldAutoEnableMCP(mcpConfigPath) { |
| 1661 | mcpEnabled = true |
| 1662 | } |
| 1663 | if !mcpEnabled { |
| 1664 | return |
| 1665 | } |
| 1666 | mcpMgr := mcp.NewManager(logger) |
| 1667 | if err := mcpMgr.LoadConfig(mcpConfigPath); err != nil { |
| 1668 | logger.Warn("Failed to load MCP config (will retry on file change)", |
| 1669 | zap.String("path", mcpConfigPath), zap.Error(err)) |
| 1670 | } |
| 1671 | // The MCP manager outlives any single request; its lifecycle is governed |
| 1672 | // by mcpCancel (fired in cleanup). Detach request cancellation while |
| 1673 | // inheriting context values. |
| 1674 | mcpCtx, mcpCancelFn := context.WithCancel(context.WithoutCancel(ctx)) |
| 1675 | cli.mcpManager = mcpMgr |
| 1676 | cli.mcpCancel = mcpCancelFn |
| 1677 | cli.mcpConfigPath = mcpConfigPath |
| 1678 | cli.mcpCtx = mcpCtx |
| 1679 | go func() { |
| 1680 | _ = mcpMgr.StartAll(mcpCtx) |
| 1681 | statuses := mcpMgr.GetServerStatus() |
| 1682 | tools := mcpMgr.GetTools() |
| 1683 | logger.Info("MCP manager initialized (client mode)", |
| 1684 | zap.Int("servers", len(statuses)), |
| 1685 | zap.Int("tools", len(tools))) |
| 1686 | }() |
| 1687 | cli.startMCPConfigWatcher() |
| 1688 | cli.initChannelTriggers() |
| 1689 | } |
| 1690 | |
| 1691 | // startMCPConfigWatcher boots an fsnotify watcher on the MCP config |
| 1692 | // file's directory and triggers Manager.Reload on edits, so changes |