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

  1. Verify the agent's config file exists and contains the caveman-cloud entry under mcpServers.
  2. Fix file permissions or remove the entry manually if the config is hand-managed.
  3. Reinstall/re-detect the agent (findAgent must resolve it) and retry the uninstall.
  4. 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

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


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)