Módulo 5: Prompts — plantillas reutilizables
Qué es un prompt de MCP
Descripción
El Módulo 1 ya adelantó la definición en una frase: un prompt es "una plantilla reutilizable, user-controlled". Esta lección se detiene en cada palabra de esa frase, igual que el Módulo 4 lo hizo con la definición de resource. "Plantilla reutilizable" descarta la confusión de pensar que un prompt es un dato fijo como un resource. "User-controlled" descarta la confusión más común de todas: pensar que un prompt es solo una tool con otro nombre, porque en los dos casos "algo pasa cuando lo invocas".
Al final de esta lección vas a poder distinguir un prompt de una tool y de un resource usando un único criterio —quién decide activarlo— sin necesitar todavía ver un solo mensaje JSON-RPC.
Conexión con el módulo
Esta lección es puramente conceptual, igual que la lección 02 del Módulo 4 lo fue para resources — no ejecuta nada todavía. Es el terreno sobre el que se paran las lecciones 03 (prompts/list) y 04 (prompts/get): si la definición queda clara aquí, esas dos lecciones son solo "cómo se ve el JSON de este concepto".
La definición, palabra por palabra
Un prompt de MCP es una plantilla de mensaje con nombre, opcionalmente parametrizada por argumentos, que un servidor expone para que el usuario la active explícitamente — a diferencia de una tool (que el modelo decide invocar) o un resource (que la aplicación decide mostrar).
"Plantilla de mensaje con nombre"
Un prompt tiene un name (como "plan_booking") que lo identifica, igual que una tool tiene su name y un resource su uri. Pero lo que hay detrás de ese nombre es distinto: no es una función que produce un efecto (como una tool) ni un documento que ya existe, listo para leerse (como un resource) — es una receta de mensaje, un texto (o una secuencia de turnos) que el servidor construye en el momento en que se lo piden, típicamente combinando una plantilla fija con los valores concretos de sus argumentos.
"Opcionalmente parametrizada por argumentos"
Un prompt puede declarar cero o más argumentos, cada uno con name, description, y required (True/False). En Reservo, plan_booking declara un solo argumento, room, y es opcional (required: False) — el prompt sigue siendo válido y útil incluso si nadie especifica una sala. Compáralo con el inputSchema de una tool (Módulo 3): ahí cada propiedad lleva un type completo, posiblemente un enum, y puede validarse con precisión de tipos. Los argumentos de un prompt son deliberadamente más simples — no hay type ni enum en la especificación de PromptArgument, porque su propósito no es validar una llamada a función: es identificar qué hueco de la plantilla se puede completar.
"User-controlled"
Esta es la palabra que distingue a un prompt de todo lo demás. La especificación de MCP categoriza los tres primitivos por quién decide usarlos — la misma tabla que ya viste, parcialmente, en el Módulo 4:
tools -> model-controlled el MODELO decide invocarla, según la conversación
resources -> application-driven la APLICACIÓN decide qué mostrar como contexto disponible
prompts -> user-controlled el USUARIO decide activarla explícitamente
"User-controlled" significa que activar un prompt es una decisión que toma la persona del otro lado de la aplicación —no el modelo razonando sobre la conversación, no la aplicación decidiendo por su propia lógica—, típicamente eligiéndolo de un catálogo que la aplicación le muestra (prompts/list, la lección 03 de este módulo). El modelo no "decide" usar plan_booking de la misma forma en que decide llamar get_quote; en el momento en que el prompt se activa, el modelo ni siquiera participó todavía de esa decisión — el usuario ya la tomó, y lo que el modelo recibe es el resultado: un mensaje ya armado, pidiéndole que haga algo específico.
Prompt vs. tool: la tabla de contraste
TOOL PROMPT
--------------------------------------------------------------------------
Qué es Una función que produce Una plantilla de mensaje
un efecto o un cálculo que se completa con datos
Se identifica con name + inputSchema name + arguments (lista
(JSON Schema completo) plana, sin tipos)
Se usa con tools/call, con arguments prompts/get, con
que varían cada vez arguments que varían
Quién decide El MODELO, leyendo la El USUARIO, eligiendo
usarla description de un catálogo
Qué devuelve content: resultado de messages: turnos de
ejecutar algo conversación ya armados
Ejemplo en Reservo get_quote(room, tier, hours) plan_booking(room?)
-> {"price_cents": 6000} -> instrucción para revisar
política y cotizar
Prompt vs. resource: no es lo mismo "user-controlled" que "application-driven"
Otra confusión posible: pensar que, como ni tools ni resources son user-controlled, prompts y resources son básicamente lo mismo desde el punto de vista del usuario. No lo son. La diferencia está en quién toma la decisión, en cada caso:
- Un resource lo elige mostrar la aplicación (el host) — según su propia lógica, sin que el usuario necesariamente haya pedido nada en ese momento puntual. Podría, por ejemplo, inyectar automáticamente el contenido de un resource al abrir una conversación nueva, sin que el usuario haya hecho clic en nada.
- Un prompt lo elige activar el usuario — un acto explícito, típicamente eligiendo de un menú o escribiendo un comando reconocible. No hay forma de que un prompt se "active solo": siempre hay una elección humana de por medio.
En Reservo, esta diferencia se ve clara: las dos políticas (M4) podrían aparecer automáticamente en el contexto de cualquier conversación sobre Reservo, sin que nadie las pidiera explícitamente — eso es coherente con ser application-driven. plan_booking, en cambio, solo aparece cuando alguien, de forma explícita, decide "quiero usar la plantilla de planificar una reserva" — nunca por decisión de la aplicación en su lugar.
Ejemplo trabajado: clasificando cinco piezas de Reservo
Antes de tocar wire protocol, un ejercicio mental —igual en espíritu al de la lección 02 del Módulo 4, ahora con las tres categorías completas—, para afianzar el criterio de "quién decide":
# No hay wire protocol en esta leccion todavia -- es solo para razonar
# sobre la clasificacion, con Python como notacion clara.
candidates = [
{"name": "get_quote", "decides": "model"},
{"name": "cancellation-policy", "decides": "application"},
{"name": "plan_booking", "decides": "user"},
{"name": "book_room", "decides": "model"},
{"name": "membership-tiers", "decides": "application"},
]
kind_by_decider = {"model": "tool", "application": "resource", "user": "prompt"}
for item in candidates:
kind = kind_by_decider[item["decides"]]
print(f"{item['name']:20s} decide={item['decides']:12s} -> {kind}")
Qué esperar:
get_quote decide=model -> tool
cancellation-policy decide=application -> resource
plan_booking decide=user -> prompt
book_room decide=model -> tool
membership-tiers decide=application -> resource
El criterio es único y no cambia entre las tres categorías: no es "qué tan complejo es", ni "si tiene argumentos", ni "si produce texto" — es, exclusivamente, quién decide activarlo. La lección 07 retoma esta misma tabla, ahora con las formas exactas del wire protocol de cada primitivo al lado.
Errores comunes
-
Pensar que "opcional" en
required: falsees una propiedad exclusiva de prompts. No — las tools también pueden tener campos opcionales en suinputSchema(fuera derequired). Lo distintivo de un prompt no es que sus argumentos sean opcionales, sino que la decisión de activarlo en primer lugar es del usuario, tenga o no argumentos. -
Asumir que un prompt necesita al menos un argumento para tener sentido. No. Un prompt sin ningún argumento sigue siendo una plantilla legítima —una instrucción fija, sin huecos que llenar—;
plan_bookingcon su único argumento opcional ya te muestra que, incluso con cero argumentos provistos, el prompt sigue siendo útil. -
Confundir "el usuario decide activarlo" con "el usuario escribe el texto del prompt a mano". No. El usuario elige cuál plantilla activar (y, opcionalmente, con qué argumentos) — el contenido del mensaje generado lo construye el servidor, siguiendo la lógica que declaró (la lección 06 de este módulo lo muestra en código).
-
Creer que un prompt reemplaza escribir instrucciones directamente en una conversación. No lo reemplaza — lo estandariza. El mismo texto que
plan_bookinggenera podrías, en principio, escribirlo tú mismo cada vez en una conversación; la ventaja del prompt es no tener que redactarlo de memoria cada vez, y que cualquier host compatible con MCP sepa mostrártelo como una opción reconocible.
Ejercicios
Ejercicio 1: Tool, resource o prompt (Fácil)
Para cada una de estas cuatro capacidades de un servidor MCP hipotético de una herramienta de soporte técnico, di cuál de los tres primitivos es, y en una frase, quién decide activarla:
A) create_ticket(subject, body) -> crea un ticket nuevo
B) sla_policy.md -> documento fijo con los tiempos de respuesta garantizados
C) draft_incident_report(severity?) -> plantilla que arma un reporte inicial
de incidente, con la severidad como argumento opcional
D) close_ticket(ticket_id) -> cierra un ticket existente
Ver solución
- A) Tool. El modelo decide invocarla en medio de una conversación, cuando el usuario pide crear un ticket — el modelo lee la
descriptiony decide que corresponde llamarla ahora. - B) Resource. Un documento fijo con URI conocida; la aplicación decide cuándo mostrarlo como contexto, sin que sea una acción que "se ejecute".
- C) Prompt. El usuario decide activar la plantilla explícitamente (por ejemplo, eligiendo "redactar reporte de incidente" de un menú), con
severitycomo argumento opcional que completa la plantilla — el mismo patrón exacto queplan_bookingconroom. - D) Tool. Tiene un efecto (cierra el ticket) y el modelo la invoca cuando la conversación lo amerita — el mismo patrón que
cancel_bookingen Reservo.
Ejercicio 2: Explica "user-controlled" sin usar esa frase (Medio)
Un compañero de equipo te dice: "no entiendo por qué prompts es una categoría aparte — al final, tanto una tool como un prompt terminan siendo 'algo que se activa con un nombre y unos argumentos', ¿no?". Escribe una explicación de 3-4 líneas que responda usando específicamente el concepto de "quién toma la decisión de activarlo", sin usar la frase "user-controlled" (tienes que explicarla con tus propias palabras).
Ver solución
Tienes razón en que la forma del mensaje se parece —un nombre, unos argumentos—, pero la diferencia real está en quién decide que ese nombre se invoque en primer lugar. Con una tool, es el modelo el que, evaluando la conversación en curso, decide "necesito llamar get_quote ahora" — una decisión que toma sin que nadie se lo pida explícitamente en ese instante. Con un prompt, esa decisión nunca la toma el modelo: la toma la persona que usa la aplicación, eligiendo de un catálogo antes de que la conversación relevante siquiera arranque. Un prompt nunca "se activa solo" en medio de una conversación como sí puede pasar con una tool.
Ejercicio 3: Diseña un prompt para un caso nuevo (Difícil)
Estás diseñando un servidor MCP para una biblioteca de código interna. Quieres exponer una plantilla que ayude a un desarrollador a preparar la descripción de un pull request, con dos argumentos opcionales: ticket_id (el ticket que resuelve) y breaking_change (si introduce un cambio incompatible). Declara el objeto Prompt completo (siguiendo la forma name/description/arguments de esta lección, sin type en los argumentos) y explica, en una frase, por qué esto es un prompt y no una tool, aunque termine generando texto para pegar en una descripción de PR — algo que, en principio, también podría hacer una tool.
Ver solución
DRAFT_PR_DESCRIPTION_PROMPT = {
"name": "draft_pr_description",
"description": "Draft a pull request description following the team's template",
"arguments": [
{"name": "ticket_id", "description": "Ticket this PR resolves", "required": False},
{"name": "breaking_change", "description": "Whether this PR introduces a breaking change", "required": False},
],
}
Por qué es un prompt y no una tool: aunque el resultado final es texto (como podría serlo el resultado de una tool), lo que distingue el primitivo no es qué produce, sino quién decide usarlo. Un desarrollador que va a abrir un PR elige explícitamente "quiero la plantilla de descripción de PR" — no es el modelo, evaluando la conversación, el que decide de forma autónoma "voy a redactar una descripción de PR ahora" sin que nadie se lo haya pedido. Si en cambio existiera una tool draft_pr_description(...) que el modelo pudiera invocar por su cuenta cuando detecta que el usuario terminó de programar algo, sería una tool legítima con el mismo nombre y el mismo resultado — la diferencia entre las dos versiones no está en el texto que generan, sino en si la activación depende de una elección humana explícita (prompt) o de una decisión del modelo en medio de la conversación (tool).
Resumen y siguiente paso
- Un prompt de MCP es una plantilla de mensaje con
nameyargumentsopcionales, cuyo uso decide el usuario (user-controlled), no el modelo (como una tool) ni la aplicación (como un resource). - Los argumentos de un prompt (
name/description/required) son deliberadamente más simples que elinputSchemade una tool: no llevantypenienum, porque no validan una llamada a función — identifican qué hueco de la plantilla se puede completar. - El criterio de clasificación es único en los tres primitivos: quién decide activarlo, no qué tan complejo es ni qué produce.
- El prompt ancla de esta guía,
plan_booking, tiene un solo argumento opcional (room) y sigue siendo útil incluso sin él — la lección 06 lo confirma ejecutando ambos casos.
Siguiente lección: 03 — prompts/list con argumentos. El primer método real del módulo: cómo un cliente descubre el catálogo de prompts de un servidor, ejecutado contra reservo-mcp-server extendido con plan_booking.
Recursos adicionales
- Model Context Protocol — Specification 2025-06-18: Prompts — La definición formal del primitivo, incluida la categorización user-controlled y la forma de
PromptArgument. - Model Context Protocol — Specification 2025-06-18: Tools — El contraste directo: model-controlled, ya trabajado en el Módulo 3.
- Model Context Protocol — Specification 2025-06-18: Resources — El contraste directo: application-driven, ya trabajado en el Módulo 4.
- Model Context Protocol — Architecture overview — El panorama de los tres primitivos y quién controla cada uno.