JuliusBrussee/caveman · error
could not install caveman-cloud MCP for
Error message
could not install caveman-cloud MCP for ${agent} What it means
installAgentNativeCloudMcp tries to register the caveman-cloud MCP server for the target agent ('claude' via the global MCP JSON config, 'codex' via installMcpForAgent). If the agent-specific installer reports it could not write the config, this error is thrown before the success marker is written.
Solutions
- Verify the agent (claude/codex) is installed and discoverable by the CLI.
- Check the agent's global config file for invalid JSON and fix or regenerate it.
- Fix permissions on the agent config file/directory.
- Run the agent once to create its config, then retry the MCP install.
Example fix
// before: claude_desktop_config.json is invalid JSON // after mv claude_desktop_config.json claude_desktop_config.json.bak claude --version # regenerates config caveman install # retry MCP registration
Defensive patterns
Strategy: validation
Validate before calling
const cfgPath = claudeGlobalConfigPath();
if (!existsSync(cfgPath)) throw new Error(`run claude once to create ${cfgPath}`);
JSON.parse(readFileSync(cfgPath, 'utf8')); // throws on malformed config
Try / catch
try { setupCloudMcp('claude') } catch (e) { if (String(e.message).startsWith('could not install caveman-cloud MCP')) { fixAgentConfig(); setupCloudMcp('claude'); } } Prevention
- Install the target agent CLI before registering MCP servers for it.
- Keep agent config files valid JSON — validate after hand edits.
- Ensure the agent config directory is writable by the installing user.
When it happens
Trigger: installMcpJson(claudeGlobalConfigPath(), ...) or installMcpForAgent(findAgent(agent)!, ...) returns false — typically because the agent config file could not be written/parsed/updated, or findAgent(agent) could not resolve the agent installation.
Common situations: Claude/Codex config file (e.g. claude_desktop_config.json) malformed or read-only; agent CLI not installed so findAgent fails; config directory missing or read-only.
Related errors
- could not remove caveman-cloud MCP for
- : MCP ownership journal failed; native config may already…
- mcpServers must be a JSON object; refusing to overwrite it
- MCP transaction failed and rolled back
- MCP transaction failed and safe recovery was blocked: …
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/153f4bea7b056507.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2691
exact_shape: keys.length === 2 && keys[0] === "args" && keys[1] === "command",
};
}
function agentNativeCloudMcpMatches(agent: "claude" | "codex", mcp: { command: string; args: string[] }): boolean {
if (agent === "codex") return codexMcpRegistrationMatches("caveman-cloud", mcp);
const actual = claudeMcpRegistration("caveman-cloud");
return actual.present && actual.exact_shape && actual.command === mcp.command && JSON.stringify(actual.args) === JSON.stringify(mcp.args);
}
function installAgentNativeCloudMcp(agent: "claude" | "codex", mcp: { command: string; args: string[] }): void {
if (agentNativeCloudMcpMatches(agent, mcp)) {
writeMcpServerMarker(agent, "caveman-cloud", mcp, "caveman_context");
return;
}
const installed = agent === "claude"
? installMcpJson(claudeGlobalConfigPath(), ["mcpServers", "caveman-cloud"], { command: mcp.command, args: mcp.args })
: installMcpForAgent(findAgent(agent)!, mcp, "caveman-cloud");
if (!installed) throw new Error(`could not install caveman-cloud MCP for ${agent}`);
writeMcpServerMarker(agent, "caveman-cloud", mcp, "caveman_context");
}
function uninstallAgentNativeCloudMcp(agent: "claude" | "codex"): void {
const removed = agent === "claude"
? removeMcpJson(claudeGlobalConfigPath(), ["mcpServers", "caveman-cloud"])
: uninstallMcpForAgent(findAgent(agent)!, "caveman-cloud");
if (!removed) throw new Error(`could not remove caveman-cloud MCP for ${agent}`);
try { unlinkSync(mcpServerMarkerPath(agent, "caveman-cloud")); } catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
}
function agentNativeSkillFiles(agent: "claude" | "codex"): Array<{ name: string; file: string; body: string }> {
const names = AGENT_SKILL_SUITES["agent-native"] ?? [];
const root = agent === "claude" ? join(claudeConfigDir(), "skills") : join(codexHomeDir(), "skills");
return names.map((name) => ({ name, file: join(root, name, "SKILL.md"), body: SKILLS[name]! }));
}View on GitHub (pinned to 3ee70a1026)