on main help sign in
fix: mcps loading in non interactive mode (#1894)
da3e44cKujtim Hoxha
internal/agent/coordinator.go+6
@@ -20,6 +20,7 @@ import (
20 "github.com/charmbracelet/crush/internal/agent/hyper"
20 "github.com/charmbracelet/crush/internal/agent/hyper"
21 "github.com/charmbracelet/crush/internal/agent/prompt"
21 "github.com/charmbracelet/crush/internal/agent/prompt"
22 "github.com/charmbracelet/crush/internal/agent/tools"
22 "github.com/charmbracelet/crush/internal/agent/tools"
23+ "github.com/charmbracelet/crush/internal/agent/tools/mcp"
23 "github.com/charmbracelet/crush/internal/config"
24 "github.com/charmbracelet/crush/internal/config"
24 "github.com/charmbracelet/crush/internal/csync"
25 "github.com/charmbracelet/crush/internal/csync"
25 "github.com/charmbracelet/crush/internal/history"
26 "github.com/charmbracelet/crush/internal/history"
@@ -411,6 +412,11 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
411 }
412 }
412 }
413 }
413
414
415+ // Wait for MCP initialization to complete before reading MCP tools.
416+ if err := mcp.WaitForInit(ctx); err != nil {
417+ return nil, fmt.Errorf("failed to wait for MCP initialization: %w", err)
418+ }
419+
414 for _, tool := range tools.GetMCPTools(c.permissions, c.cfg.WorkingDir()) {
420 for _, tool := range tools.GetMCPTools(c.permissions, c.cfg.WorkingDir()) {
415 if agent.AllowedMCP == nil {
421 if agent.AllowedMCP == nil {
416 // No MCP restrictions
422 // No MCP restrictions
internal/agent/tools/mcp/init.go+14
@@ -29,6 +29,8 @@ var (
29 sessions = csync.NewMap[string, *mcp.ClientSession]()
29 sessions = csync.NewMap[string, *mcp.ClientSession]()
30 states = csync.NewMap[string, ClientInfo]()
30 states = csync.NewMap[string, ClientInfo]()
31 broker = pubsub.NewBroker[Event]()
31 broker = pubsub.NewBroker[Event]()
32+ initOnce sync.Once
33+ initDone = make(chan struct{})
32)
34)
33
35
34// State represents the current state of an MCP client
36// State represents the current state of an MCP client
@@ -197,6 +199,18 @@ func Initialize(ctx context.Context, permissions permission.Service, cfg *config
197 }(name, m)
199 }(name, m)
198 }
200 }
199 wg.Wait()
201 wg.Wait()
202+ initOnce.Do(func() { close(initDone) })
203+}
204+
205+// WaitForInit blocks until MCP initialization is complete.
206+// If Initialize was never called, this returns immediately.
207+func WaitForInit(ctx context.Context) error {
208+ select {
209+ case <-initDone:
210+ return nil
211+ case <-ctx.Done():
212+ return ctx.Err()
213+ }
200}
214}
201
215
202func getOrRenewClient(ctx context.Context, name string) (*mcp.ClientSession, error) {
216func getOrRenewClient(ctx context.Context, name string) (*mcp.ClientSession, error) {