Files
qwen3-6-lora/data/raw/sanitized/plans/a-que-mcps-tienes-idempotent-rivest.md
T

6.3 KiB

Fix: los MCPs custom (gitea, docmost, github-personal, penpot, atlassian) dejaron de cargar

Context

El usuario preguntó a qué MCPs tenía acceso Claude Code en esta sesión. Solo apareció el conector cloud de Atlassian (vía claude.ai) — ninguno de los 5 servidores custom definidos en dev-environment/managed-mcp.json (gitea, docmost, github-personal, penpot, atlassian-vía-npx) está cargado. El usuario confirmó que antes sí funcionaban y no sabe por qué dejaron de hacerlo.

Investigación (todo lectura, sin cambios):

  1. claude mcp list solo lista los conectores cloud de claude.ai (Atlassian, Gmail, Google Drive, etc.) — cero rastro de gitea/docmost/github-personal/penpot/atlassian-custom. Esto confirma que Claude Code no está leyendo esos 5 servidores desde ninguna fuente.
  2. Existe un plan previo del propio usuario (~/.claude/plans/creo-que-hay-un-rosy-unicorn.md) que documenta la causa raíz genérica: settings.json no soporta la clave mcpServers (se ignora). Los MCP solo se leen desde .mcp.json, ~/.claude.json, --mcp-config, o el mecanismo enterprise /etc/claude-code/managed-mcp.json (ruta fija del sistema).
  3. En dev-environment/vscode-server/docker-compose.yaml (y su análogo en vscode-server-telus/docker-compose.yaml), el volumen monta managed-mcp.json en /home/aleleba/.claude/managed-mcp.json — una ruta que Claude Code nunca lee. Esa línea se agregó en el commit b81ffda pero con la ruta equivocada; el plan rosy-unicorn (que especifica la ruta correcta /etc/claude-code/managed-mcp.json) nunca se llegó a aplicar en el compose.
  4. La razón de que "antes funcionara": el commit HEAD de dev-environment/.claude.json (mismo archivo que se monta como ~/.claude.json dentro del contenedor) sí tiene el bloque mcpServers con los 5 servidores. Pero el archivo actual en disco (working tree, sin commitear) perdió por completo esa clave — el resto del archivo también cambió drásticamente (numStartups bajó de 11 a 2, aparecieron/desaparecieron decenas de feature flags tengu_*), lo que indica que Claude Code reescribió ese archivo (por ejemplo tras una actualización de versión) y no preservó la clave custom mcpServers que se había agregado manualmentente.

En resumen: el mecanismo que sí funcionaba (mcpServers dentro de ~/.claude.json) es frágil porque ese archivo lo administra/reescribe Claude Code y puede perder claves custom en cualquier reinicio o actualización — que es exactamente lo que pasó. El mecanismo robusto (/etc/claude-code/managed-mcp.json, que Claude Code no reescribe) está definido y documentado pero nunca se aplicó realmente en el compose.

Approach

Aplicar las dos capas de arreglo que el propio usuario ya había diseñado, pero que quedaron a medias — decisión confirmada con el usuario: usar directamente la ruta enterprise correcta (/etc/claude-code/managed-mcp.json) en vez de restaurar el mcpServers frágil dentro de ~/.claude.json.

1. Fix inmediato en este ambiente (sin recrear el contenedor)

Crear el archivo /etc/claude-code/managed-mcp.json directamente en el filesystem de este contenedor ya corriendo, con el mismo contenido (5 servidores) que dev-environment/managed-mcp.json. Al no venir de un volumen todavía, este archivo puntual no persiste si el contenedor se recrea — por eso el paso 2 es necesario para que sobreviva a futuros rebuilds/restarts.

2. Fix durable en ambos docker-compose (requiere recrear el contenedor — acción del usuario)

Corregir la ruta de montaje de managed-mcp.json en ambos docker-compose, de /home/aleleba/.claude/managed-mcp.json a /etc/claude-code/managed-mcp.json, tal como especifica rosy-unicorn.md:

Esto hace que el origen de verdad para estos 5 MCP sea un archivo que Claude Code trata como enterprise-managed (solo lectura para él) y por lo tanto no lo va a volver a pisar en una futura actualización — eliminando la causa raíz de fondo, no solo el síntoma.

Importante: este cambio de docker-compose no toma efecto hasta que el contenedor se recree (docker-compose up -d --force-recreate o equivalente), lo cual reinicia todo el entorno de desarrollo (VS Code server, túnel, sesión actual). Esta acción disruptiva no se ejecuta como parte de este plan — se deja documentada para que el usuario la corra cuando le convenga.

Nota de seguridad (fuera de alcance, solo aviso)

dev-environment/managed-mcp.json y dev-environment/.claude.json contienen tokens en texto plano (gitea, github, docmost, etc.) y ambos ya están commiteados al repo (no en .gitignore). Esto es preexistente, no introducido por este fix. Se menciona como riesgo a evaluar aparte (rotar tokens / gitignore / limpiar historial), no se toca en este plan.

Files to change

  1. /etc/claude-code/managed-mcp.json (dentro de este contenedor, fuera del repo) — crear con el contenido de dev-environment/managed-mcp.json (5 servidores). Fix inmediato, no persistente por sí solo.
  2. dev-environment/vscode-server/docker-compose.yaml — cambiar el target del volumen de managed-mcp.json de /home/aleleba/.claude/managed-mcp.json a /etc/claude-code/managed-mcp.json.
  3. dev-environment/vscode-server-telus/docker-compose.yaml — mismo cambio de ruta en la línea análoga.

Verification

  1. Tras crear el archivo en /etc/claude-code/managed-mcp.json: reiniciar la sesión/proceso de Claude Code (o claude CLI) dentro del contenedor y correr claude mcp list — deben aparecer gitea, docmost, github-personal, penpot y atlassian (el custom, vía npx) como Connected.
  2. Tras el fix durable (cuando el usuario recree cada contenedor con el compose corregido): cat /etc/claude-code/managed-mcp.json debe mostrar el JSON de los 5 servidores sin haber sido creado a mano, y claude mcp list debe seguir mostrándolos Connected incluso después de reinicios — confirmando que ya no depende de un paso manual ni de ~/.claude.json.