{"record":{"id":"53ebdacbfa0432c9","repo":"sipeed/picoclaw","slug":"failed-to-load-mcp-servers-w","errorCode":null,"errorMessage":"failed to load MCP servers: %w","messagePattern":"failed to load MCP servers: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/agent/agent_mcp.go","lineNumber":119,"sourceCode":"\t\t\tfindValidServer = true\n\t\t}\n\t}\n\tif !findValidServer {\n\t\tlogger.WarnCF(\"agent\", \"MCP is enabled but no valid servers are configured, skipping MCP initialization\", nil)\n\t\treturn nil\n\t}\n\n\tal.mcp.initOnce.Do(func() {\n\t\tmcpManager := mcp.NewManager(mcp.WithRuntimeEvents(al.runtimeEvents))\n\n\t\tdefaultAgent := al.registry.GetDefaultAgent()\n\t\tworkspacePath := al.cfg.WorkspacePath()\n\t\tif defaultAgent != nil && defaultAgent.Workspace != \"\" {\n\t\t\tworkspacePath = defaultAgent.Workspace\n\t\t}\n\n\t\tif err := mcpManager.LoadFromMCPConfig(ctx, mcpCfg, workspacePath); err != nil {\n\t\t\tal.mcp.setInitErr(fmt.Errorf(\"failed to load MCP servers: %w\", err))\n\t\t\tlogger.WarnCF(\"agent\", \"Failed to load MCP servers, MCP tools will not be available\",\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"error\": err.Error(),\n\t\t\t\t})\n\t\t\tif closeErr := mcpManager.Close(); closeErr != nil {\n\t\t\t\tlogger.ErrorCF(\"agent\", \"Failed to close MCP manager\",\n\t\t\t\t\tmap[string]any{\n\t\t\t\t\t\t\"error\": closeErr.Error(),\n\t\t\t\t\t})\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Register MCP tools for all agents\n\t\tservers := mcpManager.GetServers()\n\t\tuniqueTools := 0\n\t\ttotalRegistrations := 0\n\t\tagentIDs := al.registry.ListAgentIDs()","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/agent/agent_mcp.go#L101-L137","documentation":"During one-time MCP initialization (ensureMCPInitialized), mcp.Manager.LoadFromMCPConfig starts/connects every enabled server under tools.mcp.servers; any failure is wrapped into this error and stored as the sync.Once init error. From then on every ensureMCPInitialized call — hence every dispatch — returns the same cached error, and the manager is closed so no MCP tools are registered.","triggerScenarios":"tools.mcp enabled with at least one enabled server, and a server fails to load: stdio command missing/not executable (command/args in MCPServerConfig), bad env_file, SSE/HTTP type with unreachable URL, failed auth (headers), or invalid transport type.","commonSituations":"command pointing at npx/uvx/python not installed in PATH (classic in containers/systemd); URL typo or missing auth header for remote servers; server binary changed its CLI args after an upgrade; one broken server poisoning all MCP tools because init is all-or-nothing.","solutions":["Read the wrapped inner error — it identifies the failing server and cause; fix that tools.mcp.servers entry","Run the server's exact command+args manually in the same environment to reproduce","For url-based servers, verify the URL is reachable and required headers (auth) are set","Temporarily set enabled=false on suspect servers to isolate which one fails, then re-enable one by one","Restart picoclaw after fixing config — the failure is cached by sync.Once and will not retry otherwise"],"exampleFix":"// config — before\n\"tools\": { \"mcp\": { \"enabled\": true, \"servers\": {\n  \"fetch\": { \"enabled\": true, \"command\": \"mcp-fetch\" } } } }\n\n// after — command must be an executable, args carry the rest\n\"tools\": { \"mcp\": { \"enabled\": true, \"servers\": {\n  \"fetch\": { \"enabled\": true, \"command\": \"uvx\", \"args\": [\"mcp-server-fetch\"] } } } }","handlingStrategy":"try-catch","validationCode":"for name, s := range cfg.Tools.MCP.Servers {\n    if !s.Enabled {\n        continue\n    }\n    if s.Type == \"\" || s.Type == \"stdio\" {\n        if s.Command == \"\" {\n            return fmt.Errorf(\"mcp server %q: stdio server needs a command\", name)\n        }\n        if _, err := exec.LookPath(s.Command); err != nil {\n            return fmt.Errorf(\"mcp server %q: command %q not in PATH: %w\", name, s.Command, err)\n        }\n    } else if s.URL == \"\" {\n        return fmt.Errorf(\"mcp server %q: %s server needs a url\", name, s.Type)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := al.Run(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to load MCP servers\") {\n        // one server is broken: log, disable tools.mcp (or the bad server), and restart\n        // rather than retrying — init error is cached by sync.Once\n        log.Printf(\"MCP unavailable: %v\", err)\n    } else {\n        return err\n    }\n}","preventionTips":["Smoke-test each MCP server command (exec.LookPath / dry run) in CI with the production config","Pin tool versions in args (e.g. npx -y package@1.2.3) so upstream releases cannot break startup","Remember the init error is cached: fixing config requires a restart, not a retry"],"tags":["go","picoclaw","mcp","config","startup","process"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}