JuliusBrussee/caveman · error
could not remove caveman-cloud MCP for
Error message
could not remove caveman-cloud MCP for ${agent} What it means
uninstallAgentNativeCloudMcp removes the caveman-cloud MCP server entry from the agent's config (claude global MCP JSON or via uninstallMcpForAgent). If the removal reports failure, this error is thrown and the marker file is left in place so the uninstall can be retried.
Solutions
- Verify the agent's config file exists and contains the caveman-cloud entry under mcpServers.
- Fix file permissions or remove the entry manually if the config is hand-managed.
- Reinstall/re-detect the agent (findAgent must resolve it) and retry the uninstall.
- Delete the leftover MCP marker file after manually removing the entry so state stays consistent.
Example fix
// before // manual cleanup when remover fails: jq 'del(.mcpServers["caveman-cloud"])' claude_desktop_config.json > tmp && mv tmp claude_desktop_config.json rm ~/.caveman/claude-caveman-cloud-mcp.marker // after: state consistent, uninstall complete
Defensive patterns
Strategy: validation
Validate before calling
const cfgPath = claudeGlobalConfigPath();
if (existsSync(cfgPath)) {
const cfg = JSON.parse(readFileSync(cfgPath, 'utf8'));
if (!cfg.mcpServers?.['caveman-cloud']) console.log('entry already absent — nothing to remove');
} Try / catch
try { uninstallCloudMcp('claude') } catch (e) { if (String(e.message).startsWith('could not remove caveman-cloud MCP')) { removeEntryManually(); deleteMarkerFile(); } } Prevention
- Uninstall MCP entries through the CLI, not by hand-editing configs the CLI also manages.
- Check file permissions before uninstalling after user/account changes.
- Uninstall the MCP integration before removing the agent CLI itself.
When it happens
Trigger: removeMcpJson(claudeGlobalConfigPath(), ["mcpServers","caveman-cloud"]) or uninstallMcpForAgent(...) returns false — config file missing/unreadable/unwritable, malformed JSON, or the agent installation cannot be resolved.
Common situations: Agent config was already hand-edited removing the entry in a way the remover doesn't recognize; config file permissions changed; agent uninstalled before running the MCP uninstall.
Related errors
- could not install caveman-cloud MCP for
- mcpServers must be a JSON object; refusing to overwrite it
- : MCP ownership journal failed; native config may already…
- 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/775885188df9fcef.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:2699
}
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]! }));
}
function restoreAgentNativeBundleSkills(skills: AgentNativeBundleSkill[]): void {
for (const skill of [...skills].reverse()) {
const before = skill.before_base64 === null ? null : Buffer.from(skill.before_base64, "base64");
if (before) atomicWriteFile(skill.file, before);
else {
try { unlinkSync(skill.file); } catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;View on GitHub (pinned to 3ee70a1026)