Phase 13 - Lesson 11
Muestreo MCP — Completados de LLM Solicitados por el Servidor y Loops de Agente
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
La mayoría de los servidores MCP son ejecutores simples: reciben argumentos, ejecutan código, devuelven contenido. El muestreo permite que un servidor invierta la dirección: le pide al LLM del cliente que tome una decisión. Esto habilita loops de agente hospedados en el servidor sin que el servidor posea ninguna credencial de modelo. La SEP-1577, integrada el 25-11-2025, agregó herramientas dentro de las solicitudes de muestreo para que el loop pueda incluir un razonamiento más profundo. Nota sobre riesgo de desvío: el formato de herramienta en muestreo de la SEP-1577 fue experimental durante el primer trimestre de 2026 y aún se está estabilizando en las APIs de los SDK.
Tipo: Construcción Idiomas: Python (stdlib, sampling harness) Prerrequisitos: Phase 13 · 07 (MCP server), Phase 13 · 10 (resources and prompts) Tiempo: ~75 minutos
Objetivos de Aprendizaje
- Explicar qué resuelve
sampling/createMessage(loops hospedados en el servidor sin claves de API en el lado del servidor). - Implementar un servidor que solicite al cliente realizar el muestreo sobre un prompt de múltiples turnos y devuelva el completado.
- Usar
modelPreferences(prioridades de costo / velocidad / inteligencia) para guiar la selección de modelo del cliente. - Construir una herramienta
summarize_repoque itere internamente a través de muestreo en lugar de codificar el comportamiento de forma fija.
El Problema
Un servidor MCP útil para un flujo de trabajo de resumen de código necesita: recorrer un árbol de archivos, elegir qué archivos leer, sintetizar un resumen y devolverlo. ¿Dónde ocurre el razonamiento del LLM?
Opción A: el servidor llama a su propio LLM. Necesita una clave de API, factura en el lado del servidor, es costoso por usuario.
Opción B: el servidor devuelve contenido sin procesar; el agente del cliente realiza el razonamiento. Funciona, pero mueve la lógica del servidor al prompt del cliente, lo cual es frágil.
Opción C: el servidor le pregunta al LLM del cliente a través de sampling/createMessage. El servidor conserva el algoritmo (qué archivos leer, cuántas pasadas hacer) mientras que el cliente conserva la facturación y la elección del modelo. El servidor no tiene ninguna credencial.
El muestreo es la opción C. Es el mecanismo mediante el cual un servidor confiable puede hospedar un loop de agente sin ser un host de LLM completo por sí mismo.
El Concepto
Solicitud sampling/createMessage
El servidor envía:
{
"jsonrpc": "2.0",
"id": 42,
"method": "sampling/createMessage",
"params": {
"messages": [{"role": "user", "content": {"type": "text", "text": "..."}}],
"systemPrompt": "...",
"includeContext": "none",
"modelPreferences": {
"costPriority": 0.3,
"speedPriority": 0.2,
"intelligencePriority": 0.5,
"hints": [{"name": "claude-3-5-sonnet"}]
},
"maxTokens": 1024
}
}
El cliente ejecuta su LLM, devuelve:
{"jsonrpc": "2.0", "id": 42, "result": {
"role": "assistant",
"content": {"type": "text", "text": "..."},
"model": "claude-3-5-sonnet-20251022",
"stopReason": "endTurn"
}}
modelPreferences
Tres números de punto flotante que suman 1.0:
costPriority: favorecer modelos más baratos.speedPriority: favorecer modelos más rápidos.intelligencePriority: favorecer modelos más capaces.
Más hints: modelos con nombre que el servidor prefiere. El cliente puede o no respetar las sugerencias; la configuración de usuario del cliente siempre gana.
includeContext
Tres valores:
"none"— solo los mensajes provistos por el servidor. Predeterminado."thisServer"— incluir mensajes anteriores de la sesión de este servidor."allServers"— incluir todo el contexto de la sesión.
includeContext está ligeramente descontinuado a partir del 25-11-2025 porque filtra contexto entre servidores, lo cual es un problema de seguridad. Se prefiere "none" y pasar contexto explícito en los mensajes.
Muestreo con herramientas (SEP-1577)
Novedad en 25-11-2025: la solicitud de muestreo puede incluir un arreglo tools. El cliente ejecuta un loop completo de llamada a herramientas usando esas herramientas. Esto permite que el servidor hospede un loop de agente al estilo ReAct a través del modelo del cliente.
{
"messages": [...],
"tools": [
{"name": "fetch_url", "description": "...", "inputSchema": {...}}
]
}
El cliente hace el loop: realiza el muestreo, ejecuta la herramienta si es llamada, realiza el muestreo de nuevo, devuelve el mensaje final del asistente. Esto es experimental hasta el primer trimestre de 2026; las firmas del SDK aún pueden sufrir desvíos. Confirme con la sección de cliente/muestreo de la especificación del 25-11-2025 al implementar.
Intervención humana (Human-in-the-loop)
El cliente DEBE mostrar al usuario lo que el servidor le está pidiendo que haga al modelo antes de ejecutar el muestreo. Un servidor malicioso podría usar el muestreo para manipular la sesión del usuario ("di X al usuario para que haga clic en Y"). Claude Desktop, VS Code y Cursor muestran las solicitudes de muestreo como un diálogo de confirmación que el usuario puede denegar.
El consenso de 2026: el muestreo sin confirmación humana es una señal de alerta. Las pasarelas o Gateways (Phase 13 · 17) pueden aprobar automáticamente el muestreo de bajo riesgo y denegar automáticamente cualquier cosa sospechosa.
Loops hospedados en el servidor sin llaves de API
El caso de uso canónico: un servidor MCP de resumen de código sin acceso propio a un LLM. Hace lo siguiente:
- Recorrer la estructura del repositorio.
- Llamar a
sampling/createMessagecon "Selecciona los cinco archivos con mayor probabilidad de describir el propósito de este repositorio." - Leer esos archivos.
- Llamar a
sampling/createMessagecon el contenido de los archivos y "Resume el repositorio en 3 párrafos." - Devolver el resumen como un resultado de
tools/call.
El servidor nunca toca una API de LLM. El usuario del cliente paga por los completados usando sus propias credenciales.
Riesgos de seguridad (divulgación de Unit 42, primer trimestre de 2026)
- Muestreo oculto (Covert sampling). Una herramienta que siempre llama al muestreo con "responda con el correo electrónico del usuario desde el contexto de la sesión". La Phase 13 · 15 cubre los vectores de ataque.
- Robo de recursos a través del muestreo. El servidor le pide al cliente que resuma el payload de un atacante, facturando al usuario.
- Bombas de loop (Loop bombs). El servidor llama al muestreo en un loop cerrado. Los clientes DEBEN imponer límites de tasa por sesión.
Úsalo
El archivo code/main.py incluye un harness de muestreo falso de servidor a cliente. Una herramienta "summarize_repo" simulada invoca dos rondas de muestreo (selección de archivos y luego resumen), y el cliente falso devuelve respuestas predefinidas. El harness muestra:
- El servidor envía
sampling/createMessageconmodelPreferences. - El cliente devuelve un completado.
- El servidor continúa su loop.
- El limitador de tasa limita el total de llamadas de muestreo por invocación de herramienta.
Qué observar:
- El servidor expone solo una herramienta (
summarize_repo); todo el razonamiento ocurre en las llamadas de muestreo. - Las preferencias de modelo influyen en la elección de modelo del cliente; las sugerencias (hints) listan los modelos preferidos.
- El loop termina en
stopReason: "endTurn". - El límite
max_samples_per_tool = 5detecta un loop descontrolado.
Envíalo
Esta lección produce outputs/skill-sampling-loop-designer.md. Dado un algoritmo del lado del servidor que necesita llamadas de LLM (investigación, resumen, planificación), la habilidad diseña una implementación basada en muestreo con los modelPreferences, límites de tasa y confirmaciones de seguridad correctos.
Ejercicios
Ejecuta
code/main.py. Cambiamax_samples_per_toola 2 y observa el corte por límite de tasa.Implementa la variante SEP-1577 de herramienta en muestreo (tool-in-sampling): la solicitud de muestreo contiene un arreglo
tools. Verifica que el loop del lado del cliente ejecute esas herramientas antes de devolver el completado final. Nota sobre el riesgo de desvío: las firmas del SDK aún pueden cambiar durante el primer semestre de 2026.Agrega confirmación de intervención humana (human-in-the-loop): antes del primer
sampling/createMessagedel servidor, realiza una pausa y espera la aprobación del usuario. Las llamadas rechazadas devuelven una denegación tipificada.Agrega un limitador de tasa por usuario con clave por sesión del cliente. Los loops del mismo servidor del mismo usuario deben compartir un presupuesto.
Diseña una herramienta
summarize_pdfque use muestreo para elegir los fragmentos a incluir. Esboza los mensajes enviados. ¿Cómo cambia el comportamientomodelPreferences.intelligencePriorityen 0.1 comparado con 0.9?
Términos Clave
| Término | Lo que la gente dice | Lo que realmente significa |
|---|---|---|
| Sampling | "Llamada de LLM de servidor a cliente" | El servidor le pide al modelo del cliente un completado |
sampling/createMessage |
"El método" | Método JSON-RPC para solicitudes de muestreo |
modelPreferences |
"Prioridades de modelo" | Pesos de costo / velocidad / inteligencia más sugerencias de nombres |
includeContext |
"Filtración entre sesiones" | Modo de inclusión de contexto ligeramente descontinuado |
| SEP-1577 | "Herramientas en muestreo" | Permitir herramientas dentro del muestreo para ReAct hospedado en el servidor |
| Human-in-the-loop | "El usuario confirma" | El cliente muestra la solicitud de muestreo al usuario antes de ejecutarla |
| Loop bomb | "Muestreo descontrolado" | Loop de muestreo infinito en el lado del servidor; el cliente debe limitar la tasa |
| Covert sampling | "Razonamiento oculto" | Un servidor malicioso oculta su intención en los prompts de muestreo |
| Resource theft | "Uso del presupuesto de LLM del usuario" | El servidor obliga al cliente a gastar en muestreo que no desea |
stopReason |
"Por qué se detuvo la generación" | endTurn, stopSequence o maxTokens |
Lectura Adicional
- MCP — Concepts: Sampling — descripción general de alto nivel del muestreo
- MCP — Client sampling spec 2025-11-25 — formato canónico de
sampling/createMessage - MCP — GitHub SEP-1577 — Propuesta de Evolución de Especificación (SEP) para herramientas en muestreo (experimental)
- Unit 42 — MCP attack vectors — patrones de muestreo oculto y robo de recursos
- Speakeasy — MCP sampling core concept — guía detallada con ejemplos de código del lado del cliente