Manager manages connections to MCP servers discovered from a workspace's .mcp.json file. It caches the aggregated tool list and proxies tool calls to the appropriate server.
| 75 | // workspace's .mcp.json file. It caches the aggregated tool list |
| 76 | // and proxies tool calls to the appropriate server. |
| 77 | type Manager struct { |
| 78 | ctx context.Context |
| 79 | cancel context.CancelFunc |
| 80 | execer agentexec.Execer |
| 81 | updateEnv func(current []string) ([]string, error) |
| 82 | |
| 83 | mu sync.RWMutex |
| 84 | logger slog.Logger |
| 85 | clock quartz.Clock |
| 86 | closed bool |
| 87 | servers map[string]*serverEntry |
| 88 | tools []workspacesdk.MCPToolInfo |
| 89 | snapshot map[string]fileSnapshot |
| 90 | serverGen uint64 |
| 91 | sf tailscalesingleflight.Group[string, struct{}] |
| 92 | |
| 93 | // startupSettled is closed once startup scripts reach a terminal |
| 94 | // state. Before that, missing MCP config files are unknown |
| 95 | // because startup scripts may still create them. |
| 96 | startupSettled chan struct{} |
| 97 | startupOnce sync.Once |
| 98 | |
| 99 | // firstSyncSettled records that a reload body reached a |
| 100 | // terminal result, successful or not. It gates whether callers |
| 101 | // may receive cached tools after reload errors. |
| 102 | firstSyncSettled bool |
| 103 | |
| 104 | // closedCh is closed by Close to unblock waiters that do not |
| 105 | // otherwise observe Close (the parent ctx is owned by the |
| 106 | // caller and may outlive Close). |
| 107 | closedCh chan struct{} |
| 108 | closeOnce sync.Once |
| 109 | |
| 110 | // lastPaths records the most recent config paths passed to |
| 111 | // Reload/Tools. The fsnotify-backed watcher uses these to |
| 112 | // drive its own reloads when ~/.mcp.json appears late on |
| 113 | // dual-agent workspaces. |
| 114 | lastPaths []string |
| 115 | |
| 116 | // watcher fires a debounced Reload when any watched config |
| 117 | // file is created, written, removed, or renamed. It is armed |
| 118 | // lazily on the first Reload call so tests that never call |
| 119 | // Reload do not pay for an extra goroutine and file |
| 120 | // descriptor. |
| 121 | watcher *configWatcher |
| 122 | watcherOnce sync.Once |
| 123 | watchDebounce time.Duration |
| 124 | |
| 125 | // connectStartedHook is a test hook invoked at the start of |
| 126 | // connectAll, before any client is dialed. Production code |
| 127 | // leaves this nil; tests set it to coordinate with an |
| 128 | // in-flight reload (for example, to verify Close()'s |
| 129 | // shutdown ordering does not stall on a stuck connect). |
| 130 | connectStartedHook func() |
| 131 | } |
| 132 | |
| 133 | // serverEntry pairs a server config with its connected client. |
| 134 | type serverEntry struct { |
nothing calls this directly
no outgoing calls
no test coverage detected