Phase 13 - Lesson 11

Amostragem MCP — Conclusões de LLM Solicitadas pelo Servidor e Loops de Agente

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

A maioria dos servidores MCP são executores simples: recebem argumentos, executam código, retornam conteúdo. A amostragem permite que um servidor inverta a direção: ele pede para o LLM do cliente tomar uma decisão. Isso possibilita loops de agente hospedados no servidor sem que o servidor possua quaisquer credenciais de modelo. A SEP-1577, integrada em 25-11-2025, adicionou ferramentas dentro das solicitações de amostragem para que o loop possa incluir um raciocínio mais profundo. Nota sobre risco de desvio: o formato de ferramenta em amostragem da SEP-1577 foi experimental durante o primeiro trimestre de 2026 e ainda está se estabilizando nas APIs dos SDKs.

Tipo: Construção Idiomas: Python (stdlib, sampling harness) Pré-requisitos: Phase 13 · 07 (MCP server), Phase 13 · 10 (resources and prompts) Tempo: ~75 minutos

Objetivos de Aprendizado

  • Explicar o que o sampling/createMessage resolve (loops hospedados no servidor sem chaves de API no lado do servidor).
  • Implementar um servidor que solicita ao cliente para realizar a amostragem sobre um prompt de múltiplos turnos e retorna a conclusão.
  • Usar modelPreferences (prioridades de custo / velocidade / inteligência) para orientar a seleção de modelo do cliente.
  • Construir uma ferramenta summarize_repo que itera internamente via amostragem em vez de codificar o comportamento de forma fixa.

O Problema

Um servidor MCP útil para um fluxo de trabalho de sumarização de código precisa: percorrer uma árvore de arquivos, escolher quais arquivos ler, sintetizar um resumo e retornar. Onde ocorre o raciocínio do LLM?

Opção A: o servidor chama seu próprio LLM. Precisa de uma chave de API, fatura no lado do servidor, é caro por usuário.

Opção B: o servidor retorna conteúdo bruto; o agente do cliente faz o raciocínio. Funciona, mas move a lógica do servidor para o prompt do cliente, o que é frágil.

Opção C: o servidor pergunta ao LLM do cliente via sampling/createMessage. O servidor mantém o algoritmo (quais arquivos ler, quantas passagens fazer) enquanto o cliente mantém o faturamento e a escolha do modelo. O servidor não possui nenhuma credencial.

A amostragem é a opção C. É o mecanismo pelo qual um servidor confiável pode hospedar um loop de agente sem ser ele mesmo um host completo de LLM.

O Conceito

Solicitação sampling/createMessage

O servidor envia:

{
  "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
  }
}

O cliente executa seu LLM, retorna:

{"jsonrpc": "2.0", "id": 42, "result": {
  "role": "assistant",
  "content": {"type": "text", "text": "..."},
  "model": "claude-3-5-sonnet-20251022",
  "stopReason": "endTurn"
}}

modelPreferences

Três números de ponto flutuante que somam 1.0:

  • costPriority: favorecer modelos mais baratos.
  • speedPriority: favorecer modelos mais rápidos.
  • intelligencePriority: favorecer modelos mais capazes.

Mais hints: modelos nomeados que o servidor prefere. O cliente pode ou não honrar as dicas; a configuração de usuário do cliente sempre vence.

includeContext

Três valores:

  • "none" — apenas as mensagens fornecidas pelo servidor. Padrão.
  • "thisServer" — incluir mensagens anteriores da sessão deste servidor.
  • "allServers" — incluir todo o contexto da sessão.

O includeContext está levemente descontinuado a partir de 25-11-2025 porque vaza contexto entre servidores, o que é uma preocupação de segurança. Prefira "none" e passe contexto explícito nas mensagens.

Amostragem com ferramentas (SEP-1577)

Novo em 25-11-2025: a solicitação de amostragem pode incluir uma matriz tools. O cliente executa um loop completo de chamada de ferramentas usando essas ferramentas. Isso permite que o servidor hospede um loop de agente no estilo ReAct por meio do modelo do cliente.

{
  "messages": [...],
  "tools": [
    {"name": "fetch_url", "description": "...", "inputSchema": {...}}
  ]
}

O cliente faz o loop: realiza a amostragem, executa a ferramenta se for chamada, realiza a amostragem novamente, retorna a mensagem final do assistente. Isso é experimental até o primeiro trimestre de 2026; as assinaturas do SDK ainda podem sofrer desvios. Confirme com a seção de cliente/amostragem da especificação de 25-11-2025 quando implementar.

Intervenção humana

O cliente DEVE mostrar ao usuário o que o servidor está pedindo para o modelo fazer antes de executar a amostragem. Um servidor malicioso poderia usar a amostragem para manipular a sessão do usuário ("diga X ao usuário para que ele clique em Y"). O Claude Desktop, o VS Code e o Cursor apresentam solicitações de amostragem como um diálogo de confirmação que o usuário pode negar.

O consenso de 2026: a amostragem sem confirmação humana é um sinal de alerta. Gateways (Phase 13 · 17) podem aprovar automaticamente amostragem de baixo risco e negar automaticamente qualquer coisa suspeita.

Loops hospedados no servidor sem chaves de API

O caso de uso canônico: um servidor MCP de sumarização de código sem acesso próprio a um LLM. Ele faz o seguinte:

  1. Percorre a estrutura do repositório.
  2. Chama sampling/createMessage com "Escolha os cinco arquivos com maior probabilidade de descrever o propósito deste repositório."
  3. Lê esses arquivos.
  4. Chama sampling/createMessage com o conteúdo dos arquivos e "Resuma o repositório em 3 parágrafos."
  5. Retorna o resumo como um resultado de tools/call.

O servidor nunca toca em uma API de LLM. O usuário do cliente paga pelas conclusões usando suas próprias credenciais.

Riscos de segurança (divulgação da Unit 42, primeiro trimestre de 2026)

  • Amostragem oculta (Covert sampling). Uma ferramenta que sempre chama a amostragem com "responda com o e-mail do usuário a partir do contexto da sessão". A Phase 13 · 15 aborda os vetores de ataque.
  • Roubo de recursos via amostragem. O servidor pede ao cliente para resumir o payload de um invasor, cobrando o usuário.
  • Bombas de loop (Loop bombs). O servidor chama a amostragem em um loop fechado. Os clientes DEVEM impor limites de taxa por sessão.

Use-o

O arquivo code/main.py inclui um harness de amostragem falso de servidor para cliente. Uma ferramenta "summarize_repo" simulada invoca duas rodadas de amostragem (escolha de arquivos e depois resumo), e o cliente falso retorna respostas predefinidas. O harness mostra:

  • O servidor envia sampling/createMessage com modelPreferences.
  • O cliente retorna uma conclusão.
  • O servidor continua seu loop.
  • O limitador de taxa limita o total de chamadas de amostragem por invocação de ferramenta.

O que observar:

  • O servidor expõe apenas uma ferramenta (summarize_repo); todo o raciocínio acontece nas chamadas de amostragem.
  • As preferências de modelo influenciam a escolha do modelo do cliente; as dicas (hints) listam os modelos de preferência.
  • O loop termina em stopReason: "endTurn".
  • O limite de max_samples_per_tool = 5 detecta um loop descontrolado.

Envie-o

Esta lição produz outputs/skill-sampling-loop-designer.md. Dado um algoritmo no lado do servidor que precisa de chamadas de LLM (pesquisa, sumarização, planejamento), a habilidade projeta uma implementação baseada em amostragem com os modelPreferences, limites de taxa e confirmações de segurança corretos.

Exercícios

  1. Execute code/main.py. Altere max_samples_per_tool para 2 e observe o corte pelo limite de taxa.

  2. Implemente a variante da SEP-1577 de ferramenta em amostragem (tool-in-sampling): a solicitação de amostragem carrega uma matriz tools. Verifique se o loop no lado do cliente executa essas ferramentas antes de retornar a conclusão final. Observe o risco de desvio: as assinaturas do SDK ainda podem mudar no primeiro semestre de 2026.

  3. Adicione confirmação de intervenção humana (human-in-the-loop): antes do primeiro sampling/createMessage do servidor, pause e aguarde a aprovação do usuário. Chamadas negadas retornam uma recusa tipada.

  4. Adicione um limitador de taxa por usuário com chave por sessão do cliente. Loops do mesmo servidor criados pelo mesmo usuário devem compartilhar um orçamento.

  5. Projete uma ferramenta summarize_pdf que use amostragem para escolher os blocos a serem incluídos. Esboce as mensagens enviadas. Como o modelPreferences.intelligencePriority altera o comportamento em 0.1 comparado a 0.9?

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Sampling "Chamada de LLM de servidor para cliente" O servidor solicita uma conclusão ao modelo do cliente
sampling/createMessage "O método" Método JSON-RPC para solicitações de amostragem
modelPreferences "Prioridades de modelo" Pesos de custo / velocidade / inteligência e dicas de nome
includeContext "Vazamento entre sessões" Modo de inclusão de contexto levemente descontinuado
SEP-1577 "Ferramentas em amostragem" Permitir ferramentas dentro de amostragem para ReAct hospedado no servidor
Human-in-the-loop "O usuário confirma" O cliente apresenta a solicitação de amostragem ao usuário antes de executar
Loop bomb "Amostragem descontrolada" Loop de amostragem infinito no lado do servidor; o cliente deve limitar a taxa
Covert sampling "Raciocínio oculto" Servidor malicioso esconde intenção nos prompts de amostragem
Resource theft "Usando o orçamento de LLM do usuário" O servidor força o cliente a gastar com amostragem que ele não deseja
stopReason "Por que a geração parou" endTurn, stopSequence ou maxTokens

Leitura Adicional

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