← Volver al Blog

Hooks vs Skills vs MCP: 3 formas de extender Claude Code (cuándo usar cada una)

La primera vez que leí la documentación de Claude Code salí con la impresión de que Hooks, Skills y MCP eran tres sabores del mismo mecanismo, con nombres distintos. Agregué un poco de cada uno a mi ~/.claude/, los mezclé sin pensarlo mucho, y durante semanas no supe por qué unas reglas se cumplían siempre y otras se olvidaban a mitad de sesión.

No eran lo mismo. Cada uno se activa en un momento distinto del ciclo del agente, cobra tokens en un lugar distinto, y resuelve un problema distinto. Este artículo es el árbol de decisión que ahora uso para no tener que pensarlo cada vez.

La diferencia que importa (una frase)

El Hook se dispara solo cuando ocurre un evento. La Skill se dispara cuando la invocas (o cuando Claude decide que encaja). El MCP server expone un catálogo de herramientas desde el arranque de la sesión.

De ahí sale casi todo lo demás: dónde cobran tokens, qué pueden bloquear, qué pueden mantener.

Hooks, Skills y MCP se activan en momentos distintos del ciclo de Claude Code

Hooks: el harness que corre fuera del modelo

Un hook es un script que Claude Code ejecuta automáticamente en eventos del ciclo de vida. La referencia actual lista más de 30 eventos, entre ellos SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop y SessionEnd.

Configuración mínima en .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "./scripts/block-env-edits.sh" }
        ]
      }
    ]
  }
}

El script recibe un JSON por stdin con la llamada que Claude quiere hacer. Decide con su exit code: 0 deja pasar, 2 bloquea y manda el stderr al modelo como contexto. Cualquier otro código se trata como error no bloqueante: la acción sigue adelante y en la transcripción aparece un aviso <hook name> hook error.

Lo clave: el hook no paga tokens por existir. Solo entra al contexto si devuelve texto (por ejemplo, el stderr que inyecta cuando usa exit code 2). Es el único de los tres que puede bloquear una llamada antes de que ocurra.

Skills: procedimientos invocables con su carpeta

Una Skill es una carpeta con un SKILL.md y opcionalmente scripts, plantillas y ejemplos. Se activa con /nombre-skill o cuando el modelo detecta que la description encaja con tu petición. Vive en .claude/skills/ (proyecto), ~/.claude/skills/ (usuario) o dentro de un plugin.

Ejemplo mínimo ~/.claude/skills/review-pr/SKILL.md:

---
name: review-pr
description: Hacer code review de un PR. Usar cuando pidan revisión de PR.
allowed-tools: Bash(gh *) Read Grep
---

## Pasos
1. gh pr diff para obtener el diff
2. Leer los archivos modificados
3. Verificar lógica, edge cases, seguridad

El campo clave es description (sin él Claude no sabe cuándo activarla por match); name es opcional y, si lo omites, toma por defecto el nombre de la carpeta. El cuerpo del SKILL.md solo se carga cuando la Skill se invoca.

Un detalle que me costó entender: la description de cada Skill en alcance vive en el system prompt desde el minuto cero de la sesión. El cuerpo es lazy, la descripción no. Si tienes diez Skills habilitadas, hay diez descripciones pagando alquiler cada turno, aunque nunca se disparen.

MCP: catálogo de herramientas externas

Un servidor MCP es un proceso externo (en cualquier lenguaje) que habla el Model Context Protocol y expone tools, resources y prompts. Se declara en la configuración del cliente:

{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..." }
    }
  }
}

Al arrancar el cliente, se conecta a cada servidor y lee su lista de tools. Las definiciones (nombre, descripción, input schema) entran al contexto en el handshake inicial de la sesión. “Estar disponible” cuesta: el catálogo ocupa tokens de input desde que la sesión está cargada, aunque no uses ninguna tool.

El ejemplo oficial de GitHub usa la imagen que mantiene GitHub (github/github-mcp-server). El paquete viejo @modelcontextprotocol/server-github quedó deprecated en 2025; si lo ves en tutoriales antiguos, no es la referencia que corresponde a 2026.

Tabla comparativa

DimensiónHookSkillMCP
ActivaciónEvento del cicloInvocación / o match por descripciónSiempre disponible
Costo en contexto0 por existirname + description por turnoCatálogo completo al abrir sesión
LenguajeCualquier binario/scriptMarkdown + shellCualquiera con SDK MCP
Autenticación externaDentro del scriptNo aplica directoEstándar (env, OAuth)
Bloqueo determinísticoSí (exit code 2)NoNo
Mantiene estadoNo (proceso efímero)NoOpcional (proceso vivo)

Fíjate en la primera fila. El 90% de la decisión sale de ahí.

Árbol de decisión de 5 preguntas

Las hago en orden. El primer “sí” gana.

1. ¿Debe correr sin excepción? → Hook. Compliance interno, formato automático, tests pre-commit. Si tienes que recordar activarlo, no es un hook. El hook se dispara por el evento, no por tu memoria.

2. ¿Necesita datos de un servicio externo? → MCP. GitHub, Postgres, Notion, Slack, Linear. Si te encuentras copiando y pegando desde otra pestaña del navegador para que Claude los lea, es señal de que debería ser un MCP. El protocolo te da schemas tipados y auth estándar; tratar de replicarlo con curl dentro de una Skill funciona, pero pierdes la mitad de la gracia.

3. ¿Se repite más de 3 veces por semana? → Skill. Code review, changelog, mensaje de commit, generación de ADR. Procedimientos que no son automáticos (requieren tu intención) pero que son suficientemente frecuentes como para merecer un nombre invocable. Como bonus, el cuerpo solo se carga cuando los llamas, así que no inflan el contexto base.

4. ¿Es una regla transversal a varios prompts? → CLAUDE.md. Convenciones de nombres, estilo del proyecto, orden en que debe leer la documentación. Son restricciones blandas: el agente las cumple la mayoría de las veces y las olvida en el 10-20% restante. Suficiente para muchos casos. Si no te alcanza “casi siempre” y necesitas “sin excepción”, vuelve a la pregunta 1.

5. ¿Es algo que harás una sola vez? → Prompt. Script puntual, una migración, un refactor específico. No tiene sentido materializarlo en un archivo que vas a mirar una vez. Lo que estaba a punto de volverse Skill prematura se queda como prompt y ya.

Si no se dispara ninguna, probablemente no necesitas nada. No todo merece un mecanismo.

El error más común (al menos el mío)

El error que repito más seguido: escribir una Skill /lint-antes-de-commit cuando lo que de verdad quería era un hook PreToolUse. La Skill funciona, pero exige que yo me acuerde de llamarla. El hook se ejecuta siempre.

La diferencia entre “casi siempre” y “sin excepción” me cuesta cada vez que estoy distraído. Y estar distraído es el estado por defecto de cualquier sesión larga con Claude.

El error inverso (usar hook donde una Skill alcanzaba) es más barato: overengineering, pero el comportamiento sigue siendo determinístico.

Cuando no está claro, es CLAUDE.md

No todo necesita un mecanismo. Si lo que quieres es que Claude “comente las funciones complicadas”, eso es una línea en CLAUDE.md. Restricción blanda, el agente la recuerda la mayoría de las veces, y para muchos equipos es suficiente.

La pregunta que separa CLAUDE.md de hook/skill/mcp es: ¿necesito salir de la zona “va a pasar si nada falla” y entrar a la zona “pasa, punto”? Si sí, mecanismo. Si no, documentación.

Me pasó más de una vez tratar de blindar con un hook algo que una línea en CLAUDE.md habría cubierto. El hook funciona, pero cada hook agrega un lugar donde puede fallar algo (permisos, path, dependencias del script). Más mecanismos, más superficie de bug.

Resumen

  • Hook = determinismo alrededor del agente (eventos + exit codes).
  • Skill = procedimiento reutilizable que se activa cuando lo invocas.
  • MCP = catálogo de herramientas externas cargado al abrir la sesión.
  • CLAUDE.md = restricciones blandas, “casi siempre”.
  • Prompt = cosas de una sola vez.

El árbol son 5 preguntas en orden y gana la primera que diga que sí. Si ninguna se activa, probablemente lo mejor es no agregar nada.

Si quieres bajar en profundidad al eje Skills vs MCP (sin Hooks), lo cubrí con 5 tareas reales en Claude Code Skills vs MCP servers: cuándo usar cada uno. Este artículo extiende esa comparación a los tres mecanismos y añade el árbol de decisión.

Para configuraciones de hooks concretas con sus matchers y exit codes, Claude Code Hooks v2 en LatAm: 5 usos muestra ejemplos reales de producción.


ken imoto · WebRTC & Voice AI engineer · kenimoto.dev

Harness Engineering Libro relacionado Harness Engineering Harness Engineering desde cero — cinco interpretaciones (OpenAI, Anthropic, LangChain, Martin Fowler, academia) unificadas en un solo sistema para ingenieros en producción Ver la página del libro →