Phase 13 - Lesson 06

Fundamentos de MCP — Primitivos, Ciclo de Vida, Base JSON-RPC

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Cada integración antes de MCP era única. El Model Context Protocol, lanzado originalmente por Anthropic en noviembre de 2024 y ahora bajo la tutela de la Agentic AI Foundation de la Linux Foundation, estandariza el descubrimiento y la invocación para que cualquier cliente pueda comunicarse con cualquier servidor. La especificación 2025-11-25 define seis primitivos (tres del servidor, tres del cliente), un ciclo de vida de tres fases y un formato de transmisión JSON-RPC 2.0. Al aprender estos conceptos, el resto del capítulo de MCP de esta fase se convertirá simplemente en lectura de documentación.

Tipo: Aprender Lenguajes: Python (stdlib, parser JSON-RPC) Prerrequisitos: Fase 13 · 01 a 05 (la interfaz de herramientas y llamada de funciones) Tiempo: ~45 minutos

Objetivos de Aprendizaje

  • Nombrar los seis primitivos de MCP (herramientas, recursos y prompts en el servidor; raíces, muestreo y elicitación en el cliente) y dar un caso de uso para cada uno.
  • Explicar el ciclo de vida de tres fases (inicialización, operación y cierre) e indicar quién envía cada mensaje en cada fase.
  • Analizar y emitir sobres de solicitud, respuesta y notificación de JSON-RPC 2.0.
  • Explicar qué es la negociación de capacidades en la fase de initialize y qué deja de funcionar sin ella.

El Problema

Antes de MCP, cada agente que utilizaba herramientas tenía su propio protocolo. Cursor tenía un sistema de herramientas similar al formato de MCP, pero incompatible. Claude Desktop se lanzó con otro diferente. La extensión Copilot de VS Code tenía un tercero. Un equipo que creaba una herramienta de "consulta Postgres" tenía que escribirla tres veces, cada una para la API de un host diferente. Reutilizarla requería copiar código.

El resultado fue una explosión cámbrica de integraciones únicas y un tope en la velocidad de evolución del ecosistema.

MCP resuelve esto estandarizando el formato de transmisión. Un único servidor MCP funciona en cualquier cliente MCP: Claude Desktop, ChatGPT, Cursor, VS Code, Gemini, Goose, Zed, Windsurf y más de 300 clientes para abril de 2026. Más de 110 millones de descargas mensuales de SDK. Más de 10,000 servidores públicos. La Linux Foundation asumió la tutela en diciembre de 2025 bajo la nueva Agentic AI Foundation.

La revisión de la especificación utilizada en esta fase es la 2025-11-25. Añade Tasks asíncronas (SEP-1686), elicitación en modo URL (SEP-1036), muestreo con herramientas (SEP-1577), consentimiento de alcance incremental (SEP-835) y semántica de indicador de recursos de OAuth 2.1. Las lecciones de la Fase 13 · 09 a 16 cubren estas extensiones. Esta lección se detiene en la base.

El Concepto

Tres primitivos del servidor

  1. Herramientas. Acciones llamables. El mismo ciclo de cuatro pasos de la Fase 13 · 01.
  2. Recursos. Datos expuestos. Contenido de solo lectura direccionable por URI: file:///path, db://query/..., esquemas personalizados.
  3. Prompts. Plantillas reutilizables. Comandos de barra inclinada en la interfaz del host; el servidor proporciona la plantilla y el cliente completa los argumentos.

Tres primitivos del cliente

  1. Raíces. El conjunto de URIs que el servidor tiene permitido acceder. El cliente las declara; el servidor las respeta.
  2. Muestreo. El servidor solicita al modelo del cliente realizar una finalización. Permite bucles de agentes hospedados en el servidor sin claves API en el lado del servidor.
  3. Elicitación. El servidor solicita información estructurada al usuario del cliente durante la ejecución. Formularios o URLs (SEP-1036).

Cada capacidad en MCP pertenece exactamente a uno de estos seis primitivos. Las lecciones de la Fase 13 · 10 a 14 cubren cada una en detalle.

Formato de transmisión: JSON-RPC 2.0

Cada mensaje es un objeto JSON con estos campos:

  • Solicitudes: {jsonrpc: "2.0", id, method, params}.
  • Respuestas: {jsonrpc: "2.0", id, result | error}.
  • Notificaciones: {jsonrpc: "2.0", method, params} — sin id, no se espera respuesta.

La especificación base tiene aproximadamente 15 métodos, agrupados por primitivo. Los más importantes son:

  • initialize / initialized (handshake)
  • tools/list, tools/call
  • resources/list, resources/read, resources/subscribe
  • prompts/list, prompts/get
  • sampling/createMessage (servidor a cliente)
  • notifications/tools/list_changed, notifications/resources/updated, notifications/progress

Ciclo de vida de tres fases

Fase 1: inicialización.

El cliente envía initialize con sus capabilities y clientInfo. El servidor responde con sus propias capabilities, serverInfo y la versión de la especificación que utiliza. El cliente envía notifications/initialized cuando ha procesado la respuesta. A partir de aquí, cualquiera de los lados puede enviar solicitudes según las capacidades negociadas.

Fase 2: operación.

Bidirecional. El cliente llama a tools/list para descubrir y a tools/call para invocar. El servidor puede enviar sampling/createMessage si declaró esa capacidad. El servidor puede enviar notifications/tools/list_changed cuando su conjunto de herramientas cambie. El cliente puede enviar notifications/roots/list_changed cuando el usuario cambie el alcance de la raíz.

Fase 3: cierre.

Cualquiera de los lados cierra el transporte. No existe un método estructurado de cierre en MCP; el transporte (stdio o HTTP con Stream, Fase 13 · 09) lleva la señal de fin de conexión.

Negociación de capacidades

Las capabilities en el handshake initialize son el contrato. Ejemplo de un servidor:

{
  "tools": {"listChanged": true},
  "resources": {"subscribe": true, "listChanged": true},
  "prompts": {"listChanged": true}
}

El servidor declara que puede emitir notificaciones tools/list_changed y que soporta resources/subscribe. El cliente está de acuerdo declarando las suyas propias:

{
  "roots": {"listChanged": true},
  "sampling": {},
  "elicitation": {}
}

Si el cliente no declara sampling, el servidor no debe llamar a sampling/createMessage. Simétricamente: si el servidor no declara resources.subscribe, el cliente no debe intentar suscribirse.

Esto es lo que evita la fragmentación del ecosistema. Un cliente que no soporta muestreo sigue siendo un cliente MCP válido; un servidor que no llama a sampling sigue siendo un servidor MCP válido. Simplemente no usan esa característica juntos.

Contenido estructurado y formatos de error

tools/call devuelve un array content de bloques tipados: text, image, resource. La lección de la Fase 13 · 14 añade MCP Apps (interfaz interactiva ui://) a esa lista.

Los errores utilizan códigos de error JSON-RPC. Las adiciones definidas por la especificación: -32002 "Resource not found", -32603 "Internal error", además de datos específicos de MCP en error.data.

Capacidades del cliente vs detalles de la llamada de herramienta

Una confusión común: capabilities.tools es si el cliente soporta notificaciones de cambio en la lista de herramientas. Si el cliente LLAMARÁ a herramientas específicas es una elección en tiempo de ejecución guiada por su modelo, no un indicador de capacidad. El indicador de capacidad es el contrato a nivel de especificación. La elección del modelo es ortogonal.

¿Por qué JSON-RPC y no REST?

JSON-RPC 2.0 (2010) es un protocolo bidireccional ligero. REST es iniciado por el cliente. MCP necesitaba mensajes iniciados por el servidor (muestreo, notificaciones), por lo que JSON-RPC con su forma simétrica de solicitud/respuesta era una opción natural. JSON-RPC también se integra limpiamente sobre stdio y WebSocket/HTTP con Stream sin reinventar la forma de solicitud de HTTP.

Use It

code/main.py incluye un parser y emisor mínimo de JSON-RPC 2.0, luego recorre manualmente la secuencia initializetools/listtools/callshutdown, imprimiendo cada mensaje. No hay transporte real; solo el formato de los mensajes. Compare con la especificación vinculada en Lecturas Adicionales para verificar cada sobre.

Qué observar:

  • initialize declara capacidades en ambas direcciones; la respuesta contiene serverInfo y protocolVersion: "2025-11-25".
  • tools/list devuelve un array tools; cada entrada tiene name, description e inputSchema.
  • tools/call utiliza params.name y params.arguments.
  • El content de la respuesta es un array de bloques {type, text}.

Ship It

Esta lección produce outputs/skill-mcp-handshake-tracer.md. Dada una transcripción tipo pcap de una interacción cliente-servidor de MCP, la skill anota cada mensaje con qué primitivo, qué fase del ciclo de vida y de qué capacidad depende.

Ejercicios

  1. Ejecute code/main.py. Identifique la línea donde ocurre la negociación de capacidades y describa qué cambiaría si el servidor no declarara tools.listChanged.

  2. Extienda el parser para manejar notifications/progress. El formato del mensaje: {method: "notifications/progress", params: {progressToken, progress, total}}. Emítalo mientras una llamada tools/call de larga duración está en progreso y confirme que el manejador del cliente mostraría una barra de progreso.

  3. Lea la especificación de MCP 2025-11-25 de principio a fin; el documento completo tiene unas 80 páginas. Identifique el único indicador de capacidad que la mayoría de los servidores NO necesitan. Pista: se relaciona con la suscripción de recursos.

  4. Dibuje en un papel a qué primitivo pertenecería una función hipotética de "tarea programada" (cron job). (Pista: el servidor quiere que el cliente lo invoque a una hora programada. Ninguno de los seis primitivos encaja hoy.) El roadmap de MCP para 2026 tiene un borrador de SEP para esto.

  5. Analice el registro de sesión de un servidor MCP de código abierto en GitHub. Cuente los mensajes de solicitud, respuesta y notificación. Calcule qué proporción del tráfico es de ciclo de vida en comparación con el de operación.

Términos Clave

Término Lo que la gente dice Lo que realmente significa
MCP "Model Context Protocol" Protocolo abierto para el descubrimiento e invocación de herramientas por modelos
Primitivo del servidor "Lo que expone un servidor" herramientas (acciones), recursos (datos), prompts (plantillas)
Primitivo del cliente "Lo que un cliente permite que usen los servidores" raíces (alcance), muestreo (callbacks de LLM), elicitación (entrada del usuario)
JSON-RPC 2.0 "El formato de transmisión" Sobres simétricos de solicitud/respuesta/notificación
Handshake initialize "Negociación de capacidades" Primer par de mensajes; servidores y clientes declaran las funciones que soportan
tools/list "Descubrimiento" El cliente solicita al servidor su conjunto de herramientas actual
tools/call "Invocación" El cliente solicita al servidor ejecutar una herramienta con argumentos
notifications/*_changed "Eventos de mutación" El servidor le dice al cliente que su lista de primitivos ha cambiado
Bloque de contenido "Resultado tipado" `{type: "text"
SEP "Spec Evolution Proposal" Propuesta de borrador con nombre (por ejemplo, SEP-1686 para Tasks asíncronas)

Lecturas Adicionales

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).