diff --git a/internal/agent/coordinator.go b/internal/agent/coordinator.go index 943c3efc41b33ea9f261b4ffc7256b6f544beff9..985445e1dc0e0263b6faba388888bf30ec3bfb92 100644 --- a/internal/agent/coordinator.go +++ b/internal/agent/coordinator.go @@ -20,6 +20,7 @@ import ( "github.com/charmbracelet/crush/internal/agent/hyper" "github.com/charmbracelet/crush/internal/agent/prompt" "github.com/charmbracelet/crush/internal/agent/tools" + "github.com/charmbracelet/crush/internal/agent/tools/mcp" "github.com/charmbracelet/crush/internal/config" "github.com/charmbracelet/crush/internal/csync" "github.com/charmbracelet/crush/internal/history" @@ -411,6 +412,11 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan } } + // Wait for MCP initialization to complete before reading MCP tools. + if err := mcp.WaitForInit(ctx); err != nil { + return nil, fmt.Errorf("failed to wait for MCP initialization: %w", err) + } + for _, tool := range tools.GetMCPTools(c.permissions, c.cfg.WorkingDir()) { if agent.AllowedMCP == nil { // No MCP restrictions diff --git a/internal/agent/tools/mcp/init.go b/internal/agent/tools/mcp/init.go index bb43f7f157dc1cf2d094354a4e709e0beb1f52b6..e1e7d609efc86d0dcb510fa5963552f7d487a134 100644 --- a/internal/agent/tools/mcp/init.go +++ b/internal/agent/tools/mcp/init.go @@ -29,6 +29,8 @@ var ( sessions = csync.NewMap[string, *mcp.ClientSession]() states = csync.NewMap[string, ClientInfo]() broker = pubsub.NewBroker[Event]() + initOnce sync.Once + initDone = make(chan struct{}) ) // State represents the current state of an MCP client @@ -197,6 +199,18 @@ func Initialize(ctx context.Context, permissions permission.Service, cfg *config }(name, m) } wg.Wait() + initOnce.Do(func() { close(initDone) }) +} + +// WaitForInit blocks until MCP initialization is complete. +// If Initialize was never called, this returns immediately. +func WaitForInit(ctx context.Context) error { + select { + case <-initDone: + return nil + case <-ctx.Done(): + return ctx.Err() + } } func getOrRenewClient(ctx context.Context, name string) (*mcp.ClientSession, error) {