Capítulo 4 — Primitivas del cliente: comportamientos agénticos y control
Cuarta entrega del recorrido capítulo por capítulo de LLM Primer IV: Designing AI Cognition with MCP. Las primitivas del servidor exponen lo que el servidor puede ofrecer; las del cliente exponen lo que el host está dispuesto a prestarle de vuelta — y cada préstamo es una capacidad que el usuario concede y un riesgo que el host acepta.
Por qué existe este capítulo
Un servidor que sólo expone recursos, prompts y herramientas no sabe nada de su host: ni el modelo que ejecuta, ni los ficheros que ve, ni siquiera si el usuario está delante del teclado. Para muchas integraciones esa pared es intencional. Para categorías enteras de comportamiento útil es demasiado alta. Un servidor que necesita resumir un documento largo no debería tener que enviar su propio LLM. Un servidor que quiere operar sobre un proyecto debería saber sobre cuál. Un servidor que necesita el permiso del usuario para un paso destructivo debería poder pedirlo. Las primitivas del cliente son la forma en que MCP abre, en la pared, pequeños agujeros controlados.
Las tres primitivas — Sampling, Roots, Elicitation — extienden cada una el alcance del servidor hacia el territorio del host de manera precisa y negociada. Cada una es también una superficie de seguridad que el host acepta en nombre de su usuario, y se componen entre sí para producir un comportamiento más agéntico que la suma de las partes.
4.1 Sampling: tomar prestado el cerebro del host
Con sampling habilitado, un servidor puede pedirle al host que ejecute una llamada de inferencia y le devuelva el resultado. No envía modelo, no guarda clave de API y nunca se entera de qué modelo usó el host — manda mensajes más preferencias blandas (coste, velocidad, inteligencia), y el host ejecuta la llamada. Desde el punto de vista del servidor, el host se ha convertido en un endpoint LLM genérico.
La palanca es real. Un servidor de almacén documental puede ejecutar pequeños pasos de razonamiento dentro de su propia lógica — recuperar, ordenar, comparar — sin filtrar conocimiento de dominio al host ni enviar inferencia él mismo. El riesgo es igual de real. Un servidor malicioso puede usar el modelo del host — y el presupuesto del usuario — para hacer trabajo que el usuario nunca aprobó. El ataque clásico es un payload de sampling disfrazado de instrucción de usuario. El host es la única línea de defensa, razón por la cual los hosts maduros deniegan sampling por defecto salvo que el usuario haya hecho opt-in para ese servidor concreto, exponen para inspección el prompt de cada llamada, limitan llamadas por sesión y miden el coste contra el monedero del usuario, no contra el del servidor.
Una preocupación más sutil: sampling puede encapsular un bucle agéntico interno. Al host le parece una sola llamada de sampling; dentro del servidor, ha corrido un sub-agente entero. El patrón que conviene nombrar es el sub-agente acotado — el usuario concede un presupuesto de N llamadas, T segundos, X dólares; el servidor ejecuta lo que quiera dentro de ese sobre y devuelve un resultado o un parcial elegante. Sampling tampoco le da al servidor acceso a la conversación; sólo ve lo que él mismo envió, y un host que cuele contexto de conversación en los payloads de sampling ha debilitado la frontera de confianza independientemente de su intención.
4.2 Roots: fronteras de filesystem y ámbito de proyecto
Un root es una URI — habitualmente file://, aunque la especificación es general — que el host ha declarado dentro de ámbito. El servidor llama a roots/list y pregunta "¿con qué estoy trabajando?". El host anuncia una capacidad roots al inicializar y emite notifications/roots/list_changed cuando el usuario cambia de proyecto. La lista es sólo una lista; no hay lenguaje de permisos anidado, ni patrones glob, ni reglas de include/exclude.
El grano grueso es deliberado, y refleja una decisión de diseño transversal a MCP que conviene entender. Un lenguaje de permisos de grano fino en la capa de protocolo produce una falsa sensación de seguridad: los usuarios leen una lista larga de ámbitos y asumen que el protocolo la aplica, cuando en realidad el protocolo no puede impedir que el servidor se comporte mal de formas que el lenguaje nunca anticipó. Una primitiva de grano grueso respaldada por aislamiento externo — fronteras de proceso, monturas de contenedor, control de acceso a nivel de sistema operativo — es honesta sobre dónde vive realmente la aplicación. Los roots son un sistema de honor a nivel de protocolo, ejecutable a nivel de runtime cuando hay sandboxing en juego.
Dos consecuencias prácticas. Primera: cuando los roots cambian, los servidores bien educados descartan el estado cacheado relacionado con el root viejo — índices, ASTs parseados, suscripciones a ficheros vigilados — o filtran estado entre fronteras de proyecto. Segunda: los roots acotan lo que el servidor debería mirar, no lo que tiene permitido hacer. Un fichero sensible dentro de un root concedido — un volcado de credenciales, un envfile, correspondencia personal — sigue siendo sensible, y un servidor educado sigue aplicando juicio sobre qué hace aflorar.
4.3 Elicitation: dejar que el servidor haga una pregunta
Elicitation es la más nueva de las tres y la que refleja lo que los diseñadores aprendieron de la primera ola de despliegues agénticos. El servidor emite elicitation/create con un mensaje (la pregunta) y un requestedSchema (la forma de la respuesta esperada). El host renderiza la pregunta en su UI, recoge la respuesta, la valida y la devuelve. El servidor retoma su trabajo con la respuesta en la mano.
El esquema es lo que hace que elicitation sea más segura que los prompts libres. Un booleano no se puede contestar con prosa; un enum no se puede contestar con una cuarta opción. El host puede mostrar al usuario en una UI clara que le están pidiendo un sí/no, y rechazar cualquier otra cosa. La especificación restringe deliberadamente los esquemas a objetos planos de primitivas — para formularios de verdad, usa una herramienta cuyo esquema de argumentos sea el formulario, donde el usuario puede revisar los valores rellenados por el modelo antes de la invocación. Elicitation es para los casos de uno o dos campos.
El perfil de riesgo tiene forma de phishing: un servidor que muestra "el sistema requiere tu clave de acceso AWS para continuar" está intentando que el usuario teclee un secreto en el sitio equivocado. Los hosts lo mitigan con atribución clara — cada prompt de elicitation etiquetado con el servidor de origen, separado de la voz del asistente — y rechazando esquemas que tengan pinta de credencial. La cara positiva es el patrón de confirmación de herramienta destructiva: el primer trabajo de una herramienta es elicitar "¿estás seguro?" y sólo si se confirma actúa. Ésta es una de las prácticas más efectivas de endurecimiento MCP en producción.
4.4 Componiendo las tres
Las primitivas están diseñadas para componerse. Un servidor con las tres tiene, en efecto, un runtime de agente completo delegado al host: puede leer ámbito (roots), razonar sobre él (sampling), pedir aclaraciones (elicitation) y actuar a través de sus propias herramientas. Las combinaciones importan. Sampling más roots es un servidor agente autónomo; sampling más elicitation es un servidor conversacional sin alcance al filesystem; roots más elicitation es un ayudante determinista. Cada uno por separado es acotado; juntos se multiplican, y la UI de consentimiento de un host está en su mejor versión cuando puede nombrar la combinación que el usuario está concediendo en vez de pedir permiso para cada una por separado.
Lo que prepara el Capítulo 4
Las primitivas del servidor y las del cliente describen entre las dos todo lo que host y servidor pueden hacerse mutuamente. Lo que aún no hemos tocado es cómo viaja nada de esto por el cable. tools/list y sampling/createMessage no son sólo mensajes abstractos — viajan sobre un transporte, y la elección del transporte decide en silencio casi todas las propiedades operativas de una integración MCP. Los servidores también tienen que poder encontrarse: un host que quiere usar un servidor tiene que saber que existe, dónde vive y si confiar en lo que dice ser. El Capítulo 5 aborda ambas cosas.
Próximamente — Capítulo 5: Protocolos de transporte y descubrimiento. Los tres transportes que MCP soporta — stdio, SSE, Streamable HTTP — comparados con honestidad, y la capa de .well-known/mcp.json más Server Cards que convierte integraciones puntuales en algo que se parece a un ecosistema.