Principios básicos de los MCP: Solicitudes de apatrida y JSON-RPC
Type: Learn
Languages: Python
Prerequisites: Phase 13, Lessons 01 through 05
Time: ~55 minutes
Objetivos de aprendizaje
- Distinguir los primitivos del servidor de MCP de sus características del lado del cliente.
- Construir solicitudes y respuestas válidas de JSON-RPC 2.0 para MCP
2026-07-28¿ Qué ? - Agregue la versión del protocolo, las capacidades del cliente e identidad del cliente a cada solicitud.
- Usar
server/discovery manejar .UnsupportedProtocolVersionErrorsin dar una mano. - Recoger una solicitud independiente de la validación hasta un resultado completo.
El problema
Un servidor MCP puede recibir dos solicitudes consecutivas de diferentes clientes, con diferentes capacidades, en el mismo proceso o en el mismo servidor HTTP. Si el servidor recuerda lo que la solicitud anterior declaró, puede aplicar los permisos equivocados o devolver la forma incorrecta del cable.
MCP 2026-07-28El núcleo del protocolo es estatal. Un servidor debe decidir cómo manejar la solicitud actual de la solicitud actual, no del historial de conexión.
Esto cambia el modelo mental. La antigua secuencia era conexión primero, apretón de manos segundo, operaciones tercero.
- El cliente envía una solicitud de auto-descripción.
- El servidor valida la versión y las capacidades de esa solicitud.
- El servidor maneja el método.
- El servidor devuelve un resultado de tipografía o un error JSON-RPC.
La siguiente solicitud repite el mismo proceso desde cero.
El concepto
Primitivas del servidor
Los servidores MCP exponen tres primitivas primarias:
- ToolsLas acciones controladas por modelos, descubiertas con
tools/listy invocado contools/call¿ Qué ? - ResourcesLos datos de la información de la URI se encuentran en el
resources/listy recuperado conresources/read¿ Qué ? - Promptsson plantillas reutilizables, descubiertas con
prompts/listy se traduce conprompts/get¿ Qué ?
Las raíces, la toma de muestras y la tala permanecen en el 2026-07-28Es un esquema de compatibilidad, pero está desactualizado. Las nuevas implementaciones deben utilizar herramientas o recursos explícitos para las raíces, API directas de proveedores de modelos para la muestreo y stderr o OpenTelemetry para el registro. La obtención de datos sigue disponible a través de las solicitudes de viaje de ida y vuelta múltiples, donde un servidor devuelve una solicitud de entrada y el cliente retoma la operación original. Un servidor moderno nunca inicia una solicitud independiente de JSON-RPC.
Envase de JSON-RPC
MCP utiliza JSON-RPC 2.0:
- Solicitud:
{jsonrpc, id, method, params} - Respuesta:
{jsonrpc, id, result}o{jsonrpc, id, error} - Notificación:
{jsonrpc, method, params}sin ningunaid
La solicitud idcorrelaciona una respuesta. No crea una sesión de protocolo.
Metadatos requeridos de la solicitud
Cada solicitud moderna lleva un_metaobjeto dentro params¿Qué es esto ?
json{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "course-client",
"version": "1.0.0"
}
}
}
}Se requiere la versión del protocolo y las capacidades del cliente. Se recomienda la identidad del cliente. Se trata de datos de visualización y depuración auto-reportados, no de una credencial de seguridad.
El servidor no debe inferir ninguno de estos valores de una solicitud anterior, un proceso de estudio, una conexión HTTP o un encabezado de transporte solo.
Resultados completos y identidad del servidor
Cada resultado moderno exitoso incluyeresultType. Un resultado final normal utiliza "complete"Los servidores también deben identificarse en los metadatos de los resultados:
json{
"jsonrpc": "2.0",
"id": 7,
"result": {
"resultType": "complete",
"tools": [],
"ttlMs": 30000,
"cacheScope": "public",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "notes-server",
"version": "1.0.0"
}
}
}
}tools/list¿ Qué ?resources/list¿ Qué ?prompts/list¿ Qué ?resources/templates/list¿ Qué ?resources/read, y server/discoverLos resultados se pueden almacenar en caché.ttlMsy cacheScope. Un defecto seguro es ttlMs: 0y cacheScope: "private"Los elementos de la lista deben tener orden determinista para que las respuestas equivalentes produzcan claves de caché estables y contexto de modelo estable.
Descubrimiento sin apretar la mano
Cada servidor moderno debe implementarserver/discoverEl cliente puede llamar antes de otro método para obtener:
supportedVersions- servidor
capabilities - uso opcional
instructions - identidad del servidor en resultado
_meta - indicios de caché
El descubrimiento es útil, pero no es una puerta.tools/listEn primer lugar, porque esa solicitud ya cuenta con su versión y sus capacidades de protocolo.
Si la versión solicitada no es compatible, el servidor devuelve el código JSON-RPC -32022con:
json{
"requested": "2027-01-01",
"supported": ["2026-07-28"]
}El cliente selecciona una versión moderna compatible entre sí y vuelve a intentar con un nuevo ID de solicitud JSON-RPC.
Un ciclo de vida de la solicitud
Traza una solicitud moderna en este orden:
- Parsear un sobre JSON-RPC.
- Confirmarlo .
jsonrpc¿ Es verdad ?"2.0", unidexiste,methodes una cuerda, yparamses un objeto. - Requerir la cadena de versiones y el objeto de capacidad en
params._meta; los metadatos malformados o faltantes son-32602¿ Qué ? - En un límite HTTP, comparar la versión, el método y los encabezados de nombres aplicables con el cuerpo.
-32020incluso cuando uno de los dos valores de versión no esté soportado. - Una vez que se establezca la igualdad, rechace una versión coincidente pero no respaldada con
-32022¿ Qué ? - Compruebe las capacidades requeridas, luego viaja por
methody validar los argumentos específicos del método. - Autentique y autorice la operación de concreto antes de que su manipulador se ejecute.
- Regresa un resultado completo con identidad del servidor.
- Olvídate de los metadatos del protocolo.
Esta orden impide que dos componentes interpreten llamadas diferentes.Mcp-Name: notes.readmientras el origen ejecuta params.name: notes.deleteTambién mantiene entradas malformadas, confusión de encabezado, negociación de versiones, falla de capacidad, autorización y falla de manipulador como evidencia distinta.
Cerrar stdin o una respuesta HTTP termina la actividad de transporte. No termina una sesión de protocolo porque el MCP moderno no tiene sesión de protocolo.
Compatibilidad explícita con el legado
Versiones a través de 2025-11-25uso initialize¿ Qué ?notifications/initialized, las capacidades de conexión-escalado, y, en anteriores Streamable HTTP, sesiones de protocolo opcionales. Ese comportamiento sigue siendo relevante cuando un cliente de doble era habla con un servidor viejo.
Mantenga las eras separadas. Una solicitud moderna se identifica por los metadatos requeridos por solicitud. Una conexión heredada se selecciona solo a través del sendero de retroceso documentado. No envíe initializecomo el defecto para un 2026-07-28¿Qué es eso?
Instatado tiene por tanto un significado específico de la época.2026-07-28En el caso de las aplicaciones de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la ley, se puede considerar que la aplicación de la misma es una de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la aplicación de la ley.2025-11-25La implementación de una doble era no es una máquina de estado permisivo. Es un núcleo moderno sin estado junto a un adaptador heredado aislado, con una decisión de selección explícita antes de que se ejecute cualquiera de los paresores.
Ninguno de los dos significados prohíbe el estado de aplicación duradero. Un flujo de trabajo, tarea o borrador puede vivir detrás de un mango opaco en una tienda compartida. El cliente envía ese mango como entrada ordinaria, y cada réplica autentica y autoriza su uso. El contexto del protocolo no debe filtrarse a esa tienda como sustituto de la sesión eliminada.
Usalo
code/main.pycrea, valida, rastrea y envía mensajes MCP modernos sin un marco. ejecuta:
bashpython3 code/main.py
python3 -m unittest discover code/tests -vCuidado con tres invariantes en la salida:
- Cada solicitud repite su
_metalos campos. - Cada resultado exitoso es
resultType: "complete"y incluye la identidad del servidor. - El resultado de la lista está ordenado deterministicamente y tiene sugerencias explícitas de caché.
Envío
Esta lección nos lleva .outputs/skill-mcp-handshake-tracer.mdEl nombre histórico del archivo sigue siendo estable, pero el artefacto es ahora un rastreador de solicitudes sin estado. Audita cada mensaje de forma independiente y etiqueta el tráfico de apretones de manos heredados solo cuando está realmente presente.
Los ejercicios
- Cambiar la versión de protocolo de una solicitud a
2027-01-01Confirme que el código de error es-32022y los datos anuncian la versión compatible. - Retirada
io.modelcontextprotocol/clientCapabilitiesConfirmar que el servidor no reutiliza las capacidades de la primera solicitud. - Revuelve el registro de herramientas en memoria.
tools/listtodavía devuelve el mismo orden determinista. - Cambiar
cacheScopede lapublic¿ Qué ?privateExplicar qué contextos de autorización pueden reutilizar la respuesta en cada caso. - Añadir una opción
clientInfoEl requisito debe permanecer válido porque se recomienda la identidad del cliente, no se requiere.
Términos clave
| Term | Meaning |
|---|---|
| Stateless protocol | Every request supplies the metadata needed to interpret it |
| Request metadata | Version, client capabilities, and recommended client identity in params._meta |
server/discover | Mandatory server method for versions, capabilities, instructions, and identity |
resultType | Discriminator on every successful modern result |
| Cacheable result | Result that includes required ttlMs and cacheScope hints |
| Protocol era | Modern per-request metadata or legacy connection-scoped initialization |
| Transport lifetime | Process, connection, or response-stream lifetime, not protocol session state |
-32022 | Unsupported protocol version error with requested and supported versions |
Leer más
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.