MCP Sampling: Claude Code 2.1.283 não suporta
Todo tutorial de MCP Sampling começa igual: “o servidor pede ao LLM do cliente para resumir, perguntar, decidir”. Liguei um servidor desses no meu Claude Code e pedi para ele chamar sampling/createMessage. Resposta em menos de 1 segundo:
McpError: Method not found
Antes de discutir elevação de privilégio, prompt injection via Sampling, ou “sete ataques possíveis”, tem uma pergunta mais chata: o cliente que você está usando responde a Sampling? No meu caso, Claude Code 2.1.283, a resposta é não. A porta nem abre.
Esse post é o registro de 1 request. É pouco, de propósito.
O que medi

| Item | Valor |
|---|---|
| cliente | claude-code 2.1.283 |
| protocolVersion | 2025-11-25 |
capabilities anunciadas | elicitation (form, url) + roots (listChanged) |
sampling em capabilities | ausente |
sampling/createMessage enviado | McpError: Method not found |
Dado bruto em results/sampling_probe.jsonl do experimento 046 do iris-lab. Duas linhas, de 21 de outubro de 2026.
Como medi
Escrevi um servidor MCP stdio em Python (sampling_probe.py, 34 linhas) que registra duas coisas quando a ferramenta é chamada:
- As
capabilitiesque o cliente anunciou noinitialize. - O que acontece quando o servidor chama
ctx.session.create_message(...)— ou seja, Sampling.
O trecho relevante:
@mcp.tool()
async def summarize_note(text: str, ctx: Context) -> str:
params = ctx.session.client_params
caps = params.capabilities.model_dump(exclude_none=True)
log({"event": "client_params", "capabilities": caps,
"protocolVersion": getattr(params, "protocolVersion", None)})
try:
r = await ctx.session.create_message(
messages=[SamplingMessage(role="user",
content=TextContent(type="text",
text="Reply with PONG."))],
max_tokens=20)
log({"event": "sampling_result", "ok": True, "result": r.model_dump()})
except Exception as e:
log({"event": "sampling_result", "ok": False,
"error": f"{type(e).__name__}: {e}"})
Rodei via claude -p com --strict-mcp-config --mcp-config sampling.mcp.json:
claude -p "Use the summarize_note tool and report what it returned." \
--model sonnet --strict-mcp-config --mcp-config sampling.mcp.json \
--allowedTools mcp__probe__summarize_note --output-format json < /dev/null
Uma execução. O log tem duas linhas. Não precisa de 100 iterações: capabilities é uma declaração do cliente no handshake, não varia por chamada.
O que o Claude Code anuncia (e o que não anuncia)
A linha de client_params do log, formatada:
{
"clientInfo": {"name": "claude-code", "version": "2.1.283"},
"protocolVersion": "2025-11-25",
"capabilities": {
"elicitation": {"form": {}, "url": {}},
"roots": {"listChanged": true}
}
}
Comparando com a spec MCP 2025-11-25, um cliente que suporta Sampling precisa anunciar sampling: {} no handshake. O Claude Code 2.1.283 anuncia elicitation e roots — e só.
elicitation é o oposto de Sampling, aliás. É o cliente pedindo que o usuário preencha algo (um formulário, uma URL de confirmação). Não é a mesma superfície.
O que Method not found quer dizer
Quando o servidor chama ctx.session.create_message(...), a biblioteca MCP envia a requisição JSON-RPC sampling/createMessage para o cliente. O cliente responde:
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}}
-32601 é “método não existe” do JSON-RPC. Não é “você não tem permissão”. Não é “o usuário rejeitou”. É “esse endpoint não está no meu dicionário”. A biblioteca Python converte isso em McpError e o try/except grava a linha de erro.
Resumindo: o Claude Code 2.1.283 não só deixa de declarar sampling nas capabilities — ele literalmente não tem o método implementado. O caminho “servidor pede ao LLM do cliente” não existe nesse cliente.
O que isso quebra do seu servidor MCP
Se o seu servidor MCP depende de Sampling, no Claude Code ele vai cair em uma das três:

1. Erro imediato. Você chama create_message sem try/except. Resultado: McpError: Method not found sobe até a ferramenta, a ferramenta falha, Claude vê a falha e tenta de novo (ou pede ajuda ao usuário). Lixo no histórico.
2. Fallback silencioso. Você embrulhou em try/except e no except chama a sua própria API Anthropic/OpenAI. Funciona, mas agora o servidor MCP está usando o modelo de outra conta, não o do cliente. Billing e política de uso mudam de lugar sem o usuário saber. Para servidores que recomendam Sampling como “jeito de usar o LLM do usuário”, isso é o oposto do design.
3. Degradação planejada. Você detecta sampling ausente no initialize e desliga as ferramentas que dependem dele (ou retorna estruturas sem o campo “resumido pelo LLM”). É o único caminho honesto quando um cliente não suporta. A spec permite negociação assimétrica justamente para isso.
A questão é: se você só testou com Claude Desktop (que, por fama de spec, suporta), não sabe em qual dos três você está no Claude Code até alguém reclamar. Mede antes.
O que não medi (e por quê)
- Claude Desktop. Não está nessa máquina. Não escrevo nada sobre o Claude Desktop aqui com base em “deve suportar”. Se precisar, meço separado.
- Outros clientes MCP (Cline, Cursor via MCP, etc.). Não testei. Cada um declara capabilities próprias — não vale assumir pelo mesmo motivo que não vale assumir pelo Claude Desktop.
- Versões anteriores do Claude Code. O que varia entre versões é exatamente o que
capabilitiesanuncia. Em 2.1.283, não ésampling. Em versões anteriores ou posteriores pode ser diferente — o seujsonlvai dizer. - O servidor na direção contrária (servidor que oferece Sampling ao invés de consumir). Sampling é cliente→quem-tem-o-LLM. Servidor não oferece.
Como reproduzir
git clone https://github.com/kenimo49/iris-lab
cd iris-lab/experiments/046-mcp-sampling-support
mkdir -p sandbox && cd sandbox
claude -p "Use the summarize_note tool on 'hello' and report what it returned." \
--model sonnet --strict-mcp-config --mcp-config ../sampling.mcp.json \
--allowedTools mcp__probe__summarize_note --output-format json < /dev/null
cat ../results/sampling_probe.jsonl
Ajuste o path dentro de sampling.mcp.json para onde você clonou. Se seu Claude Code anunciar sampling nas capabilities, troquei de time e você viu antes.
O que mudar no seu projeto hoje
- Grepa o seu servidor MCP por
create_message/sampling. Se existir, decide qual dos três caminhos (erro / fallback / degradação) você quer e implementa explicitamente. - No
initialize, lêclient.capabilities.sampling. Se vierNone/undefined, desliga as ferramentas Sampling-dependentes antes do primeirotools/list. - Se o seu README promete “usa o LLM do próprio usuário”, acrescenta “em clientes que suportam Sampling” e lista os que você mediu. Minha medida aqui é 1 cliente.
Para o lado da segurança (prompt injection via Sampling, elevação de privilégio em servidores que confiam no retorno do LLM), tem um post anterior que compara MCP com Knowledge Graph em custo de contexto e mostra onde os 27 mil tokens de handshake vão. A superfície de ataque muda quando a porta está fechada: você se preocupa com o canal errado se o canal não existe no seu cliente.
ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews
Livro relacionado Transformando LLMs de Mentirosos em Especialistas Engenharia de Contexto na Prática | RAG · MCP · CLAUDE.md · Agentic RAG, com benchmarks de ponta a ponta Ver a página do livro → Este artigo foi útil?