Phase 13 - Lesson 10

MCP Resources y Prompts — Exposición de Contexto Más Allá de las Herramientas

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

Las herramientas reciben el 90 por ciento de la atención de MCP. Las otras dos primitivas del servidor resuelven problemas diferentes. Los recursos exponen datos para lectura; los prompts exponen plantillas reutilizables como comandos de barra (slash-commands). Muchos servidores deberían usar recursos en lugar de envolver lecturas en herramientas, y prompts en lugar de codificar flujos de trabajo de forma fija en los prompts del cliente. Esta lección define la regla de decisión y recorre los mensajes resources/* y prompts/*.

Tipo: Build Idiomas: Python (stdlib, resource + prompt handler) Requisitos previos: Phase 13 · 07 (MCP server) Tiempo: ~45 minutos

Objetivos de aprendizaje

  • Decidir entre exponer una funcionalidad como una herramienta, un recurso o un prompt para un dominio determinado.
  • Implementar resources/list, resources/read, resources/subscribe y manejar notifications/resources/updated.
  • Implementar prompts/list y prompts/get con plantillas de argumentos.
  • Reconocer cuándo el host presenta los prompts como comandos de barra frente a contexto autoinyectado.

El problema

Un servidor MCP ingenuo para una aplicación de notas expone todo como herramientas: notes_read, notes_list, notes_search. Esto envuelve cada acceso a datos en una llamada a una herramienta impulsada por el modelo. Consecuencias:

  • El modelo debe decidir si llamar a notes_read para cada consulta que pueda beneficiarse del contexto.
  • El contenido de solo lectura no se puede suscribir ni transmitir al panel lateral del host.
  • Las IU del cliente (el panel de adjuntos de recursos de Claude Desktop, el selector "Include file" de Cursor) no pueden mostrar los datos.

La división correcta: exponer los datos como un recurso, exponer acciones mutables o calculadas como herramientas, exponer flujos de trabajo reutilizables de múltiples pasos como prompts. Cada primitiva tiene su propia facilidad de experiencia de usuario (UX affordance) y su patrón de acceso.

El concepto

Tools vs resources vs prompts — la regla de decisión

Funcionalidad Primitiva
El usuario desea buscar, filtrar o transformar datos tool
El usuario desea que el host incluya estos datos como contexto resource
El usuario desea un flujo de trabajo con plantilla que pueda volver a ejecutar prompt

Directriz: si el modelo se beneficiaría de llamarlo en cada consulta relacionada, es una herramienta. Si el usuario se beneficiaría de adjuntarlo a una conversación, es un recurso. Si un flujo de trabajo completo de múltiples pasos es la unidad que el usuario desea reutilizar, es un prompt.

Recursos

resources/list devuelve {resources: [{uri, name, mimeType, description?}]}. resources/read recibe {uri} y devuelve {contents: [{uri, mimeType, text | blob}]}.

Las URIs pueden ser cualquier cosa direccionable:

  • file:///Users/alice/notes/mcp.md
  • postgres://my-db/query/SELECT ...
  • notes://note-14 (esquema personalizado)
  • memory://session-2026-04-22/recent (específico del servidor)

contents[] admite tanto texto como binario. El binario utiliza blob como una cadena codificada en base64 más un mimeType.

Suscripciones a recursos

Declare {resources: {subscribe: true}} en las capacidades. El cliente llama a resources/subscribe {uri}. El servidor envía notifications/resources/updated {uri} cuando el recurso cambia. El cliente vuelve a leer.

Caso de uso: un servidor de notas cuyos recursos son archivos en disco; un monitor de archivos (file watcher) activa notificaciones de actualización; Claude Desktop vuelve a traer el archivo al contexto cuando se edita fuera del host.

Plantillas de recursos (adición de 2025-11-25)

resourceTemplates le permiten exponer un patrón de URI parametrizado: notes://{id} con id como un objetivo de autocompletado. El cliente puede autocompletar IDs en el selector de recursos.

Prompts

prompts/list devuelve {prompts: [{name, description, arguments?}]}. prompts/get recibe {name, arguments} y devuelve {description, messages: [{role, content}]}.

Un prompt es una plantilla que se llena para dar una lista de mensajes que el host proporciona a su modelo. Por ejemplo, un prompt code_review recibe un argumento file_path y devuelve una secuencia de tres mensajes: un mensaje del sistema, un mensaje del usuario con el cuerpo del archivo y un inicio del asistente con una plantilla de razonamiento.

Hosts y prompts

Claude Desktop, VS Code y Cursor exponen prompts como comandos de barra en la IU del chat. El usuario escribe /code_review y elige los argumentos en un formulario. El prompt del servidor es el contrato entre el "acceso directo del usuario" y el "prompt completo enviado al modelo".

No todos los clientes admiten prompts todavía; verifique la negociación de capacidades. Un servidor con capacidad de prompt declarada pero un cliente sin soporte para prompts simplemente no verá los comandos de barra.

La notificación "list changed"

Tanto los recursos como los prompts emiten notifications/list_changed cuando el conjunto muta. Un servidor de notas que acab de importar 20 nuevas notas emite notifications/resources/list_changed; el cliente vuelve a llamar a resources/list para capturar las adiciones.

Convenciones de tipos de contenido

Para texto: mimeType: "text/plain", text/markdown, application/json. Para binario: image/png, application/pdf, además del campo blob. Para MCP Apps (Lección 14): text/html;profile=mcp-app en una URI ui://.

Recursos dinámicos

Una URI de recurso no tiene que corresponder a un archivo estático. notes://recent puede devolver las últimas cinco notas en cada lectura. db://query/users/active puede ejecutar una consulta parametrizada. El servidor es libre de calcular el contenido de forma dinámica.

Regra: si el cliente puede almacenar en caché por URI, la URI debe ser estable. Si el cálculo es de un solo uso, la URI debe incluir una marca de tiempo o un nonce para que la caché del cliente no expire.

Suscripciones frente a polling

Los clientes con capacidad de suscripción reciben actualizaciones automáticas (push) del servidor a través de notifications/resources/updated. Los clientes previos a la suscripción o los hosts que no la admiten realizan polling volviendo a leer. Ambos cumplen con la especificación. La declaración de capacidad del servidor le dice al cliente cuál admite.

Costo de las suscripciones: estado por sesión en el servidor (quién está suscrito a qué). Mantenga el conjunto suscrito acotado; los clientes desconectados deben expirar por tiempo límite (timeout).

Prompts frente a prompts del sistema

Los prompts en MCP no son prompts del sistema. El prompt del sistema del host (sus propias instrucciones de funcionamiento) y los prompts de MCP (plantillas suministradas por el servidor e invocadas por el usuario) coexisten lado a lado. Un cliente bien portado nunca permite que un prompt del servidor anule su propio prompt del sistema; los superpone.

Usalo

code/main.py extiende el servidor de notas de la Lección 07 con:

  • Recursos por nota (notes://note-1, etc.) con soporte para resources/subscribe.
  • Un prompt review_note que se representa en una plantilla de tres mensajes.
  • Una simulación de monitor de archivos (file watcher) que emite notifications/resources/updated cuando se modifica una nota.
  • Un recurso dinámico notes://recent que siempre devuelve las últimas cinco notas.

Ejecute la demostración para ver el flujo completo.

Envíalo

Esta lección produce outputs/skill-primitive-splitter.md. Dado un servidor MCP propuesto, la habilidad categoriza cada capacidad como tool / resource / prompt con una justificación.

Ejercicios

  1. Ejecute code/main.py. Observe la lista inicial de recursos, luego active la edición de una nota y verifique que se active el evento notifications/resources/updated.

  2. Agregue un emisor de resources/list_changed: cuando se cree una nueva nota, envíe la notificación para que los clientes la vuelvan a descubrir.

  3. Diseñe tres prompts para un servidor MCP de GitHub: summarize_pr, triage_issue, release_notes. Cada uno con esquemas de argumentos. El cuerpo del prompt debe poder ejecutarse sin más modificaciones.

  4. Tome una herramienta existente en el servidor de la Lección 07 y clasifique si debe seguir siendo una herramienta o dividirse en un par de recurso y herramienta. Justifique en una oración.

  5. Lea las secciones server/resources y server/prompts de la especificación. Identifique el único campo en resources/read que rara vez se completa pero que es compatible con la especificación. Sugerencia: busque _meta en el contenido del recurso.

Términos clave

Término Lo que dice la gente Lo que realmente significa
Resource "Datos expuestos" Contenido direccionable por URI que el host puede leer
Resource URI "Puntero a datos" Identificador con prefijo de esquema (file://, notes://, etc.)
resources/subscribe "Monitorear cambios" Actualizaciones automáticas (push) del servidor con opt-in del cliente para una URI específica
notifications/resources/updated "Recurso cambiado" Señal al cliente de que un recurso suscrito tiene contenido nuevo
Resource template "URI parametrizada" Patrón de URI con sugerencias de autocompletado para el selector del host
Prompt "Plantilla de comando de barra" Plantilla con nombre de múltiples mensajes con espacios para argumentos
Prompt arguments "Entradas de plantilla" Parámetros tipados que el host recopila antes de la representación
prompts/get "Representar plantilla" El servidor devuelve la lista de mensajes completada
Content block "Bloque tipado" `{type: text
Slash-command UX "Acceso directo del usuario" El host presenta los prompts como comandos que comienzan con /

Lectura adicional

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