MCPcopy Create free account
hub / github.com/diillson/chatcli / startMCPConfigWatcher

Method startMCPConfigWatcher

cli/cli.go:1699–1762  ·  view source on GitHub ↗

startMCPConfigWatcher boots an fsnotify watcher on the MCP config file's directory and triggers Manager.Reload on edits, so changes to mcp_servers.json take effect without restarting chatcli. We watch the directory rather than the file because most editors rewrite via rename (write to tmp, rename o

()

Source from the content-addressed store, hash-verified

1697// per-file watcher misses entirely. Events are debounced to avoid
1698// reloading mid-write.
1699func (cli *ChatCLI) startMCPConfigWatcher() {
1700 if cli.mcpManager == nil || cli.mcpConfigPath == "" {
1701 return
1702 }
1703 w, err := fsnotify.NewWatcher()
1704 if err != nil {
1705 cli.logger.Warn("MCP config hot-reload disabled: cannot create watcher", zap.Error(err))
1706 return
1707 }
1708 dir := filepath.Dir(cli.mcpConfigPath)
1709 if err := w.Add(dir); err != nil {
1710 cli.logger.Warn("MCP config hot-reload disabled: cannot watch dir",
1711 zap.String("dir", dir), zap.Error(err))
1712 _ = w.Close()
1713 return
1714 }
1715 cli.mcpWatcher = w
1716 cli.mcpWatcherDone = make(chan struct{})
1717
1718 go func() {
1719 var debounce *time.Timer
1720 fire := func() {
1721 diff, err := cli.mcpManager.Reload(cli.mcpCtx, cli.mcpConfigPath)
1722 if err != nil {
1723 cli.logger.Warn("MCP config reload failed", zap.Error(err))
1724 return
1725 }
1726 if len(diff.Started)+len(diff.Stopped)+len(diff.Updated) == 0 {
1727 return
1728 }
1729 cli.logger.Info("MCP config hot-reloaded",
1730 zap.Strings("started", diff.Started),
1731 zap.Strings("stopped", diff.Stopped),
1732 zap.Strings("updated", diff.Updated))
1733 }
1734 for {
1735 select {
1736 case <-cli.mcpWatcherDone:
1737 return
1738 case ev, ok := <-w.Events:
1739 if !ok {
1740 return
1741 }
1742 // Only react to events on the config file itself (the
1743 // directory watcher sees siblings too).
1744 if filepath.Clean(ev.Name) != filepath.Clean(cli.mcpConfigPath) {
1745 continue
1746 }
1747 if ev.Op&(fsnotify.Write|fsnotify.Create|fsnotify.Rename|fsnotify.Remove) == 0 {
1748 continue
1749 }
1750 if debounce != nil {
1751 debounce.Stop()
1752 }
1753 debounce = time.AfterFunc(400*time.Millisecond, fire)
1754 case err, ok := <-w.Errors:
1755 if !ok {
1756 return

Calls 9

StopMethod · 0.95
WarnMethod · 0.80
AddMethod · 0.80
ErrorMethod · 0.65
CloseMethod · 0.65
InfoMethod · 0.65
DirMethod · 0.45
StringMethod · 0.45
ReloadMethod · 0.45