Muestreo y roots
Traducción automática
Esta página se tradujo automáticamente a partir de la documentación en inglés, y la página en inglés es la versión de referencia. Si algo no se lee bien, Traducciones explica cómo avisarnos.
Un handler puede pedirle al cliente conectado dos cosas más: una respuesta del propio modelo del cliente, el muestreo (sampling), y las carpetas del espacio de trabajo del cliente, los roots (directorios raíz).
Ambos siguen funcionando, en todas las versiones del protocolo que habla el SDK. Pero lee la advertencia antes de diseñar en torno a ellos:
Obsoletos según la especificación 2026-07-28
El muestreo y los roots están obsoletos a partir de 2026-07-28 (SEP-2577). Siguen siendo plenamente funcionales y permanecen en la especificación al menos doce meses antes de poder ser eliminados, pero las implementaciones nuevas no deberían basarse en ellos. Las migraciones sugeridas: integra directamente la API de tu proveedor de LLM en lugar del muestreo, y pasa los directorios mediante parámetros de herramientas, URI de recursos o la configuración del servidor en lugar de los roots. La lista completa del SDK está en Funcionalidades obsoletas.
Muestreo: toma prestado el modelo del cliente
Un resolutor devuelve Sample(...) y la herramienta recibe la respuesta del modelo, a través del mismo mecanismo de dependencias que ejecuta Elicit en Dependencias:
from typing import Annotated
from mcp.server import MCPServer
from mcp.server.mcpserver import Resolve, Sample
from mcp.types import CreateMessageResult, SamplingMessage, TextContent
mcp = MCPServer("Bookshop")
def draft_blurb(title: str) -> Sample:
prompt = f"Write a one-sentence blurb for the book {title!r}."
return Sample(
[SamplingMessage(role="user", content=TextContent(type="text", text=prompt))],
max_tokens=60,
)
@mcp.tool()
async def blurb(title: str, draft: Annotated[CreateMessageResult, Resolve(draft_blurb)]) -> str:
"""Draft a blurb for a book."""
return draft.content.text if draft.content.type == "text" else "No blurb."
Sample(messages, max_tokens=...)refleja los parámetros desampling/createMessage. El valor inyectado es elCreateMessageResultdel cliente; pasatoolsotool_choicey en su lugar será unCreateMessageResultWithTools.- El cliente debe haber declarado la capacidad
sampling(sampling.toolssi pasastoolsotool_choice). Si no lo hizo, la llamada falla con un error de protocolo-32021en lugar de enviar una solicitud que el cliente no puede manejar. Una sesión anterior a 2026 sin canal de retorno (back-channel) falla con su error habitual de falta de canal de retorno, ya que no hay nada por donde enviarla. - En
2026-07-28la solicitud se entrega dentro del flujo de varias idas y vueltas (Solicitudes de varias idas y vueltas, multi-round-trip); en2025-11-25es una solicitud independiente al cliente. El código es el mismo en ambos casos, pero ten en cuenta la regla de las varias idas y vueltas: la solicitud debe generarse idéntica en cada ronda de reintento, así que constrúyela solo a partir de los argumentos de la herramienta y otros datos estables. - Deja
include_contexttal cual: los valores distintos de"none"están a su vez obsoletos (SEP-2596) y necesitan una capacidad que casi ningún cliente declara.
Roots: ¿dónde va esto?
Los roots son las carpetas sobre las que, según el cliente, el servidor puede operar. Son una orientación informativa, no un mecanismo de control de acceso. Un resolutor devuelve ListRoots():
from typing import Annotated
from mcp.server import MCPServer
from mcp.server.mcpserver import ListRoots, Resolve
from mcp.types import ListRootsResult
mcp = MCPServer("Bookshop")
def workspace_roots() -> ListRoots:
return ListRoots()
@mcp.tool()
async def catalog_folder(roots: Annotated[ListRootsResult, Resolve(workspace_roots)]) -> str:
"""Pick the folder the catalog export should go to."""
if not roots.roots:
return "No workspace folders shared."
return str(roots.roots[0].uri)
- El
ListRootsResultinyectado lleva una lista de objetosRoot: un URIfile://y un nombre para mostrar opcional. - La condición es la misma que para el muestreo: sin una capacidad
rootsdeclarada, la llamada falla con-32021en lugar de enviar la solicitud.
Al otro lado del canal, el cliente responde ambas solicitudes con los callbacks que ya tiene: sampling_callback y list_roots_callback, que se tratan en Callbacks del cliente.
En conexiones de la generación 2025
ctx.session.create_message(...) y ctx.session.list_roots() siguen existiendo para el código que maneja la sesión directamente. Solo funcionan donde existe un canal de retorno (conexiones de la generación 2025 que no sean sin estado), y llamarlos lanza un aviso de obsolescencia. Los marcadores de resolutor de arriba son la forma admitida: eligen la entrega según la versión negociada y no emiten ningún aviso.
Resumen
- Devuelve
Sample(...)oListRoots()desde un resolutor; la herramienta recibe elCreateMessageResulto elListRootsResultcomo cualquier otra dependencia. - El cliente debe declarar la capacidad correspondiente o la llamada falla con
-32021en lugar de enviarse una solicitud. - Ambas funcionalidades están obsoletas en
2026-07-28: plenamente funcionales por ahora, equivocadas para diseños nuevos. Prefiere las API del proveedor frente al muestreo y los parámetros explícitos frente a los roots.
Informar cuánto lleva avanzado una herramienta lenta: Progreso.