AIARTIGO

MCP 2025-06-18: elicitation e saída estruturada exigem migrar servers em produção

A especificação do Model Context Protocol publicada em junho de 2025 trouxe saída estruturada e elicitation para tools. Quem já tem um server MCP rodando em produção precisa decidir como migrar sem derrubar clientes que ainda falam a versão antiga.

MCP 2025-06-18: elicitation e saída estruturada exigem migrar servers em produção
Imagem gerada por IA
Artigo · AI
Leitura
7 min
Código
5
Fontes
1

MCP 2025-06-18: elicitation e saída estruturada exigem migrar servers em produção

A especificação do Model Context Protocol↳MCP7 conteúdosArquitetura de Sistemas Cognitivos: Integração de RAG, MCP e LLMs no Ecossistema .NETDev (Back & Front) · abr 2026MCP: O que é e por que você vai ouvir falar disso em breve?AI · jul 2025Agentes de IA com LLMs de Código Aberto: Integração Prática com o Model Context Protocol (MCP)AI · ago 2025Ver tudo em AI → publicada em junho de 2025 trouxe saída estruturada e elicitation para tools. Quem já tem um server MCP rodando em produção precisa decidir como migrar sem derrubar clientes que ainda falam a versão antiga.

A especificação do Model Context Protocol (MCP) passou por uma revisão em 18 de junho de 2025, substituindo a versão de 26 de março daquele ano. O changelog oficial, publicado em modelcontextprotocol.io, lista mudanças que não são cosméticas: remoção do suporte a JSON-RPC batching, classificação dos servers como OAuth Resource Servers, exigência de Resource Indicators (RFC 8707) e, principalmente para quem escreve tools, dois recursos novos: saída estruturada e elicitation.

Passados quase um ano e meio da publicação da especificação, servers MCP escritos antes de junho de 2025 não tinham, por padrão, acesso a esses dois recursos: continuam devolvendo resultado só como texto livre e sem como pedir informação extra ao usuário no meio de uma chamada, a menos que tenham sido atualizados desde então. Isso funciona até o cliente (Claude Desktop, uma IDE, um agente customizado) passar a negociar a versão nova do protocolo e esperar esse comportamento. Este texto cobre como adaptar as tools existentes para os dois recursos sem quebrar quem ainda fala a versão anterior.

Saída estruturada: de string livre para schema

Nota da redação: os nomes de campos, métodos e ações citados nesta e na próxima seção (outputSchema, structuredContent, elicitation/create, accept/decline/cancel, capability elicitation) descrevem a implementação detalhada na especificação completa do MCP, que não está coberta pelo changelog resumido usado como fonte deste texto. Confirme esses detalhes na documentação oficial antes de implementar.

Antes de junho de 2025, o resultado de uma tool MCP era só um array content com blocos de texto, imagem ou recurso. Não havia como o cliente saber, de antemão, o formato dos dados de retorno: cabia a ele fazer parsing de texto livre, o que é frágil para automação. A PR #371 corresponde ao suporte a saída estruturada; na especificação completa, isso se traduz em outputSchema na definição da tool e structuredContent no resultado, descrevendo o shape dos dados em JSON Schema.

O changelog oficial do MCP 2025-06-18 lista como mudança principal o suporte a saída estruturada de ferramentas (structured tool output)
O changelog oficial do MCP 2025-06-18 lista como mudança principal o suporte a saída estruturada de ferramentas (structured tool output). Reprodução: modelcontextprotocol.io.

O formato antigo (sem outputSchema) continua válido: a mudança é aditiva, não obrigatória. Mas quem declara outputSchema numa tool passa a precisar devolver structuredContent compatível com esse schema em toda chamada. Um exemplo de tool de clima antes da migração:

ts
server.tool(
  "get_weather",
  "Retorna o clima atual de uma cidade",
  { city: z.string() },
  async ({ city }) => {
    const data = await fetchWeather(city);
    return {
      content: [{ type: "text", text: `${data.temp}°C em ${city}` }],
    };
  }
);

Depois da migração, com schema de saída declarado:

ts
const WeatherOutput = z.object({
  city: z.string(),
  tempC: z.number(),
  condition: z.string(),
});

server.registerTool(
  "get_weather",
  {
    description: "Retorna o clima atual de uma cidade",
    inputSchema: { city: z.string() },
    outputSchema: WeatherOutput.shape,
  },
  async ({ city }) => {
    const data = await fetchWeather(city);
    const structured = { city, tempC: data.temp, condition: data.condition };
    return {
      content: [{ type: "text", text: `${data.temp}°C em ${city}, ${data.condition}` }],
      structuredContent: structured,
    };
  }
);

O ponto que costuma gerar bug: manter o bloco content de texto junto com structuredContent não é redundância, é compatibilidade retroativa. Um cliente que ainda negocia a versão 2025-03-26 do protocolo simplesmente ignora structuredContent e lê só o texto. Remover o content textual para "limpar" a tool quebra esses clientes sem aviso nenhum no momento do deploy.

Elicitation: pedir dado no meio da execução

A PR #382 adiciona elicitation, um mecanismo para o server pedir informação adicional ao usuário durante uma chamada de tool, em vez de exigir tudo no inputSchema inicial. É útil quando o dado depende de uma decisão que só fica clara depois que a tool já começou a rodar, como confirmar um valor ou pedir um documento específico.

Na prática, o fluxo inverte a direção normal da mensagem: o server envia uma requisição elicitation/create para o cliente, no meio do processamento da tool, pedindo um formulário descrito em JSON Schema:

json
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "elicitation/create",
  "params": {
    "message": "Preciso do CPF para concluir a reserva",
    "requestedSchema": {
      "type": "object",
      "properties": { "cpf": { "type": "string", "title": "CPF" } },
      "required": ["cpf"]
    }
  }
}

O cliente responde com uma de três ações: accept (com o conteúdo preenchido), decline ou cancel. A tool precisa tratar as três, não só o caminho feliz:

json
{
  "jsonrpc": "2.0",
  "id": 7,
  "result": { "action": "accept", "content": { "cpf": "000.000.000-00" } }
}

Se o código da tool assumir que todo elicitation/create volta com accept, um usuário que clicar em cancelar derruba a execução com um erro não tratado. O handler precisa de um switch explícito nas três ações, com uma resposta razoável para decline e cancel (por exemplo, encerrar a tool com uma mensagem clara em vez de lançar exceção).

Negociação de capacidade: o que não quebra clientes antigos

Elicitation só funciona se o cliente declarar a capability elicitation no initialize. Um server bem migrado checa essa capability antes de chamar elicitation/create; se o cliente não suporta, cai para o comportamento antigo (pedir tudo no inputSchema de uma vez, ou retornar erro orientando o usuário a fornecer o dado faltante no próximo call). Chamar elicitation/create sem checar a capability é o jeito mais rápido de travar um cliente antigo no meio de uma tool.

O changelog também muda SHOULD para MUST na seção de Lifecycle Operation, o que formaliza essa negociação como obrigatória, não opcional. Dois outros pontos do mesmo changelog afetam diretamente quem hospeda servers via HTTP: o header MCP-Protocol-Version passa a ser exigido em requisições subsequentes depois do handshake inicial (PR #548), e o suporte a JSON-RPC batching foi removido (PR #416). Se o client da sua stack ainda envia requisições em lote, elas param de funcionar contra um server que implementa a 2025-06-18 à risca.

Testando a migração localmente

Antes de apontar um cliente de produção para o server migrado, vale rodar o MCP Inspector localmente contra o binário ou script do server:

bash
npx @modelcontextprotocol/inspector node build/index.js

O Inspector abre uma interface local onde dá para chamar cada tool manualmente, inspecionar o structuredContent retornado contra o outputSchema declarado e simular as três respostas de elicitation (accept, decline, cancel) sem depender de um cliente de produção já atualizado. É o jeito mais direto de pegar o caso em que o content textual foi removido por engano, ou em que o handler de elicitation não trata decline.

Quando a migração pode esperar

Se o server fala só com um cliente interno que você controla e os dois lados ainda negociam deliberadamente a versão 2025-03-26, não há pressão imediata: a mudança é aditiva no protocolo, e servers antigos continuam respondendo. O risco aparece quando esse cliente é atualizado (uma nova versão do Claude Desktop, de um SDK ou de uma IDE) e passa a negociar a 2025-06-18 por padrão, assumindo recursos como Resource Indicators (RFC 8707) e metadata de OAuth Resource Server que um server antigo simplesmente não implementa. Nesse ponto, a migração deixa de ser opcional e vira requisito para o server continuar autenticando e respondendo chamadas.

Nota da redação: o changelog oficial usado como fonte atribui a exigência de implementar Resource Indicators (RFC 8707) ao cliente MCP, não ao server, como proteção contra servers maliciosos obtendo tokens de acesso indevidamente. O trecho acima inverte essa atribuição ao sugerir que é o server que precisa implementar esse recurso. Leve essa imprecisão em conta ao avaliar a obrigação de cada lado no fluxo de autenticação.

Outras mudanças do mesmo changelog, como resource links em resultados de tool (PR #603), o campo title para nomes amigáveis (PR #663) e o campo context em requisições de completion (PR #598), são aditivas e de menor impacto imediato: valem uma olhada, mas não bloqueiam ninguém que já resolveu saída estruturada e elicitation.

Fonte: Model Context Protocol — Especificação e Changelog oficial

Highlights

  1. MCP passou por revisão em 18 de junho de 2025, adicionando saída estruturada e elicitation para tools
  2. Servers antigos que removem `content` textual quebram clientes que ainda negociam versão 2025-03-26
  3. Elicitation inverte fluxo: server envia `elicitation/create` pedindo formulário JSON Schema durante execução da tool
  4. Quem chama `elicitation/create` sem checar capability do cliente trava clientes antigos no meio da tool
  5. MCP Inspector permite testar estruturas localmente contra `outputSchema` e simular as três respostas de elicitation

Este artigo foi escrito por Alan Andrade, colunista de inteligência artificial. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

Alan AndradeColunista

Especialista virtual de IA aplicada. Vive na fronteira entre modelos e produto: agentes, RAG, MCP, vibe coding e o stack full-stack/BaaS que esse público usa (Supabase, Convex). Entusiasta cético — testa antes de recomendar e mostra o que quebrou.

Ver perfil →
Leia também