DEV M3 · Claude Code, MCP & Integration — Resumen de estudio
Curso 3 de 5 · 21 pantallas, 8 secciones, 8 checkpoints, ~142 min
El problema de fondo: lo que funciona en tu máquina tiene que funcionar cuando otro lo ejecuta, en producción y contra sistemas reales. Permisos, contexto durable, empaquetado, MCP y autenticación empresarial.
1. Loop de Claude Code, permission modes y gates humanos
Loop: explore → plan → code. Primero lee y entiende, luego propone un plan y solo con tu aprobación edita y ejecuta. Plan mode lo mantiene en exploración (sin edits ni comandos).
| Modo | Auto-aprueba | Sigue pidiendo confirmación | Para qué |
|---|---|---|---|
| default | Solo lecturas | Todo edit y comando | Base para proyectos nuevos o desconocidos |
| acceptEdits | Lecturas, edits y comandos comunes de archivos (mkdir, touch, rm, rmdir, mv, cp, sed) dentro del directorio de trabajo | Otros comandos de shell, escrituras fuera del directorio, protected paths | Trabajo local confiable |
| plan | Solo lecturas | Todo, hasta que apruebas el plan | Explorar código sensible o desconocido |
| auto | Todo, pero un clasificador revisa cada acción | Bloquea por defecto: deploys y migraciones de producción, borrados masivos, exfiltración de credenciales, force-push a main | Menos prompts (research preview; depende del plan, el modelo y el admin) |
| dontAsk | Solo lo que está en las allow rules + comandos de solo lectura; niega todo lo demás | No hay cola de confirmación | CI y scripts cerrados |
| bypassPermissions | Todo, sin checks (también quita el guard de protected paths) | Solo rm -rf / y rm -rf ~ piden confirmación como último recurso | Solo en contenedores o VMs desechables |
Dónde vive la configuración:
- Usuario:
~/.claude/settings.json. Todos tus proyectos. - Proyecto:
.claude/settings.json, que se commitea. Todo el equipo. - Local:
.claude/settings.local.json. Personal y git-ignorado. - Enterprise:
managed-settings.json. Nadie puede sobrescribirla.
Una regla deny siempre gana a una allow, sea cual sea el modo. El control más durable es un deny a nivel enterprise (aplica incluso en bypass).
¿Dónde va el gate humano? Pregunta: ¿qué es lo peor si esto corre sin que nadie lo revise?
- Bajo riesgo y reversible (formato, edits en el directorio de trabajo) → sin gate (acceptEdits).
- Difícil de revertir o una ruta sensible (escritura fuera del directorio, comando destructivo, archivo protegido) → gate antes de ejecutar (deny rule, default o plan).
- Código marcado como sensible → el agente nunca es el único gate: una persona revisa antes del merge.
Revisión de código con IA: son hallazgos para priorizar, no un veredicto. Confía en lo que se puede probar con el diff (null check faltante, recurso sin cerrar) y verifica las líneas que cita. Lo que afirme sobre el runtime u otros sistemas es una hipótesis a probar. Dale las convenciones del equipo para que no tenga que adivinarlas.
⚠️ Watch out: con bypass para "solo renombrar endpoints", el patrón
/v1/legacy/coincidió también con/deploy/config/prod/y un script borró 3 archivos de producción. Lo que habría pedido confirmación era la ejecución del script (en acceptEdits, unrmdirecto dentro del directorio no pide confirmación; en default sí). Pon deny rules antes de cambiar de modo; si quieres menos prompts, usa auto en vez de bypass.
Checkpoint 1: piezas C (allow Bash(npm run:*), deny rm y git push) + D (deny Read(.env.production)). Gate: b, un humano aprueba el cambio al archivo de configuración de despliegue antes de escribirlo.
2. Contexto durable: CLAUDE.md, rules, hooks y subagents
- CLAUDE.md: se lee en cada sesión y se antepone al prompt.
/initgenera una versión inicial que debes validar.- Contenido: comandos de tests, convenciones del framework, rutas prohibidas, decisiones de estilo.
- Fallo principal: el tamaño. Cada línea diluye las demás. Por encima de unas pocas centenas de líneas, audítalo.
- Rules files (
.claude/rules/): guía específica por ruta. Lo que los acota es elpathsglob del frontmatter, no la carpeta. Sinpathscargan siempre, como CLAUDE.md.- "Nunca modificar el schema" → CLAUDE.md.
- "Todo SQL del módulo db con transacción explícita" →
.claude/rules/database.mdconpaths: ["src/db/*/.sql"].
- Hooks: scripts en eventos del ciclo de vida. Se ejecutan siempre, decida lo que decida el modelo (guardrail vs convención). Se configuran en settings o con
/hooks.- PreToolUse: antes de la tool. Puede bloquear con exit code 2 (la razón va a stderr y el agente la ve).
- PostToolUse: después. No bloquea; sirve para formatear, correr tests o hacer auditoría.
- UserPromptSubmit: antes de procesar el prompt (inyectar contexto o validar).
- Stop: al terminar la respuesta.
- Notification: cuando se pide permiso o tras 60 s inactivo.
- SessionStart / SessionEnd: inicialización y cierre.
- Subagents: contexto aislado; solo devuelven el resultado.
- Explore y Plan (built-in) omiten CLAUDE.md y el git status para ser rápidos. General-purpose los carga.
- Si una regla del proyecto debe respetarse → general-purpose o un subagent custom.
- Los subagents custom no ven los Skills salvo que los listes en su frontmatter (
.claude/agents).
| Mecanismo | Carga | Cuándo | Costo de contexto | Qué va ahí |
|---|---|---|---|---|
| CLAUDE.md | Archivo completo | Siempre | Persistente; se diluye | Restricciones universales |
| Rules file | Contenido | Al tocar rutas que coinciden (sin paths = siempre) | Solo cuando se activa | Guía por ruta |
| Hook | Ejecuta un script (no añade contexto) | En el evento | Mínimo | Guardrails, efectos automáticos, auditoría |
| Subagent | Solo la tarea | Al delegar | Devuelve un resumen | Exploración e investigación paralelizable |
⚠️ Watch out: con un CLAUDE.md de 847 líneas, la regla de "no tocar
/legacy/tokens/" (línea 347) quedó diluida y se editó igual. El historial y las notas archivadas no van ahí. La regla que no puedes permitirte diluir debería ser un hook.
Checkpoint 2: PreToolUse + un script que lee la tool call de stdin y sale con código 2 si la ruta es .env.production (razón en stderr).
3. Empaquetar workflows: Skills, comandos y plugins
El mismo SKILL.md en 4 runtimes:
| Runtime | Cómo carga | Dónde corre | Ojo |
|---|---|---|---|
| Claude Code | Se descubre en .claude/skills por coincidencia de descripción o por nombre | Tu terminal, con permisos y deny rules | Basado en el sistema de archivos |
| Messages API | Va con el request; headers beta de code-execution + skills | Contenedor de code execution de Anthropic | No asumas archivos ni tools locales |
| Agent SDK | Según settingSources / setting_sources | Tu proceso | Sorpresa típica: no carga porque settingSources nunca se configuró |
| Managed Agents | Se declara en el recurso del agente (header managed-agents-2026-04-01) | Sandbox de Anthropic | Sin ZDR ni BAA. Para cambiar los Skills, actualiza la definición |
3 reglas de portabilidad:
- La descripción es el criterio de coincidencia.
- No asumas un filesystem ni tools locales.
- Los subagents no heredan Skills.
- Comandos personalizados: hoy se recomiendan los Skills (invocas con
/skill-nameo se cargan solos)..claude/commands/es legacy. Para que solo corra cuando lo llames:disable-model-invocation: true. - Plugins: agrupan Skills, hooks, subagents y MCP servers en una unidad versionada.
- Sus comandos llevan el nombre del plugin como namespace (
/payments:run-tests). Renombrar el plugin renombra todos sus comandos. - Marketplaces: el oficial viene incluido; se agregan con
/plugin marketplace add <owner/repo>. - Enterprise: despliegue por managed settings, allowlist de marketplaces +
extraKnownMarketplacespara empujarlos a todos. El scope managed tiene prioridad y no se puede sobrescribir. - Riesgo: un plugin solo lleva lo que empaqueta. Si dependías de un deny rule o un hook local que no incluiste, esa protección no viaja.
- Sus comandos llevan el nombre del plugin como namespace (
| Capa | Para quién | Cuándo |
|---|---|---|
| Skill | Uso interactivo, individuo o equipo | Procedimiento que no debe ocupar contexto hasta que se necesite |
| Comando | Quien quiere un punto de entrada explícito | Procedimiento frecuente con nombre claro |
| Plugin | Equipo | Compartir una configuración versionada e instalable en un paso |
⚠️ Watch out: un Skill con
/Users/alexmorgan/projects/deploy-utils/validate.shse instaló bien en todas partes pero falló en todas menos en la máquina del autor; otro necesitabaDEPLOY_TOKENsin documentarlo. Usa$CLAUDE_PROJECT_DIR(scripts del proyecto) y${CLAUDE_PLUGIN_ROOT}(scripts del plugin), incluye los assets, documenta y valida las variables de entorno, y prueba en una máquina limpia.
Checkpoint 3: Claude Code → SKILL.md en .claude/skills · Messages API → headers beta + sin dependencias locales · Agent SDK → settingSources explícito · Managed → recurso de agente + header beta. Checkpoint 4: defecto C (ruta absoluta) · fix C ($CLAUDE_PROJECT_DIR).
4. Servidores MCP
- MCP: un servidor expone tools, resources y prompts a cualquier cliente MCP. Se construye una vez y se usa en todas partes.
- Resource: datos de solo lectura que el cliente pone en contexto directamente. Direct (dirección fija) o templated (con un parámetro en la dirección). Verifica que tu cliente los soporte.
- Prompt: plantilla verificada que se invoca por nombre, para que todos los clientes obtengan la misma calidad.
- Transportes: stdio (local, subproceso) · HTTP (remoto; el recomendado) · SSE (legacy).
- Costo de contexto: por defecto Claude Code difiere las definiciones de tools y las busca cuando hacen falta. Hay un modo opt-in que las carga al inicio si caben en ~10% de la ventana. Conecta solo lo que necesitas.
- Prompt caching:
- Breakpoint con
cache_control: ephemeral(hasta 4). Orden: tools → system → messages. - TTL de 5 min desde la última lectura; opcional 1 h con
ttl: "1h". - Un solo carácter distinto invalida la caché.
- Mínimo ~1,024 tokens para cachear.
- Breakpoint con
- RAG: clásico (chunks + embeddings indexados de antemano) vs agentic search (busca en el momento). Escala con costo plano por request, pero solo es tan bueno como lo que encuentra (usa nombres de archivo descriptivos).
Scopes:
- Local:
~/.claude.jsonbajo la ruta del proyecto. Personal, solo ese proyecto. - User: en tus settings personales. Todos tus proyectos, no se comparte.
- Project:
.mcp.jsonen la raíz, se commitea. Todo el equipo. Un servidor stdio arranca en la máquina de cada quien (cada uno necesita, por ejemplo, Node instalado). - Enterprise: managed settings, lo empuja el administrador.
- Permisos por tool:
mcp__server__tool. Puedes permitirmcp__github__create_issuey negar las tools de escritura. Un deny a una tool gana sobre un allow al servidor. En el API Connector,enabledpor tool decide si el modelo siquiera la ve (control de alcance y de costo de contexto). - GitHub MCP: HTTP remoto. Autenticación con Personal Access Token como Bearer, desde una variable de entorno, nunca inline en
.mcp.json. - Linear MCP: OAuth (flujo de login en el navegador; el token se guarda solo).
| Contexto | Transporte | Scope | Secretos |
|---|---|---|---|
| Herramienta local personal | stdio | Local | Solo variables de entorno |
| Servidor compartido del equipo | HTTP | Project (.mcp.json) | OAuth o variables de entorno; nunca keys en .mcp.json |
| Experimento personal | stdio o HTTP | Local | Variables de entorno |
| Despliegue a toda la org | HTTP | Enterprise | Los gestiona el admin; configuración bloqueada |
⚠️ Watch out: se commiteó una API key en
.mcp.json. En 48 h estaba en el repo, en 3 máquinas y en CI. Sobrescribir el archivo no la saca del historial → hay que rotarla (y la rotación rompió otros 2 servicios). Correcto:"Bearer ${WAREHOUSE_MCP_TOKEN}". Prevención en 2 capas: regla en CLAUDE.md + hook PreToolUse que bloquee credenciales inline.
Checkpoint 5: SQLite local = stdio + Local · búsqueda de código del equipo = HTTP + Project · experimento = stdio o HTTP + Local · escáner de seguridad para todos = HTTP + Enterprise.
5. Integración empresarial y autenticación
Preguntas que un prototipo ignora: ¿con qué identidad actúa el modelo y es auditable? ¿A qué datos accede y dónde salen? ¿Un admin puede bloquear la configuración? ¿Queda registro para una auditoría?
| Tipo de servicio | Autenticación | Dónde viven los secretos | Log | Quién bloquea la config |
|---|---|---|---|---|
| Remoto con identidad de usuario (SaaS) | OAuth (el 401 dispara el login en el navegador) | Token del proveedor guardado por el cliente | Hook PostToolUse → audit log | Admin vía managed settings |
| Remoto con identidad de servicio (API interna) | API key en variable de entorno (en CI la inyecta el runner) | Solo en el entorno, nunca en un config commiteado | Hook PostToolUse | Admin vía managed settings |
| Local (filesystem, base local) | Permisos del filesystem (stdio, sin red) | No hay credencial; deny rules | Hook PostToolUse | Deny rules en managed settings |
Manejo de secretos (3 prácticas):
- Separación: el config tiene la referencia, nunca el valor.
- Dónde vive el valor: variable de entorno (local o de corta vida) o un secret store (compartido o auditado; una rotación actualiza a todos).
- Rotación: periódica y de inmediato ante una sospecha de exposición. Un valor en código commiteado no se puede rotar limpiamente.
Además: alcance mínimo por credencial y un registro de qué servicio usa cada una.
Entornos regulados: configuración bloqueada por managed settings · audit hooks PostToolUse · residencia (endpoint HTTP regional + plataforma con región fija).
Modernización de código legacy:
- Plan mode para explorar.
- Hooks que bloqueen rutas sensibles.
- CLAUDE.md con los patrones nuevos (para que no "regrese" a los patrones legacy que lee).
- 3 preguntas antes de empezar:
- ¿Cuál es el radio de impacto si algo sale mal?
- ¿Cómo se auditan los cambios?
- ¿Quién aprueba cada fase?
⚠️ Watch out: OAuth funcionaba en staging y en producción daba redirect URI mismatch. Las redirect URIs se registran por host; muchas empresas exigen apps OAuth separadas por entorno. Inclúyelo en el checklist de despliegue.
Checkpoint 6: Fix B. El 401 indica una key rechazada y hay un secreto en texto plano en un archivo de ruta conocida → rotar + mover a una variable de entorno en el runner de CI y referenciarla. (A deja el mismo defecto de almacenamiento; C usa OAuth, que no corresponde a una cuenta de servicio.)
Tarea acumulativa (3 archivos, 3 bugs)
- settings.json:
bypassPermissionsen una estación de producción →acceptEdits(el deny de.env.productionestaba bien). - SKILL.md: ruta absoluta
/Users/priya/...→$CLAUDE_PROJECT_DIR/scripts/validate-migration.sh. - .mcp.json: key inline
sk-prod-...→Bearer ${WAREHOUSE_MCP_TOKEN}(y rotar la key expuesta).
Para recordar (7 takeaways)
- El permission mode es una decisión de riesgo, no de velocidad. Los deny rules cubren lo que el modo no cubre.
- Una revisión de código con IA da hallazgos que priorizar, no un veredicto.
- Un Skill es portable, pero hay que diseñarlo para que lo sea.
- Contexto durable = el mecanismo correcto para cada cosa (CLAUDE.md, rules, hooks, subagents).
- Una configuración compartible necesita componentes portables (rutas relativas, variables documentadas, prueba en una máquina limpia).
- Transporte y scope son decisiones independientes con consecuencias que dependen una de otra (un servidor stdio en
.mcp.jsonparece compartible y no lo es). - En empresas, identifica antes del despliegue: OAuth, variables de entorno, hooks de auditoría, managed settings.