CodeGym /Cursos /ChatGPT Apps /Formato de mensagens MCP: requests, replies, notification...

Formato de mensagens MCP: requests, replies, notifications, tools/resources/prompts

ChatGPT Apps
Nível 6 , Lição 1
Disponível

1. MCP e JSON‑RPC: o “fundamento chato” que você precisa entender uma vez

Na aula passada, falamos por que o MCP é necessário e como ele se encaixa na pilha do Apps SDK. Nesta aula, vamos focar na camada mais “chata” — o formato das mensagens MCP, para que você consiga ler com segurança logs JSON brutos e entender exatamente o que o ChatGPT envia ao seu servidor e o que ele responde.

O MCP usa JSON‑RPC 2.0 como transporte de dados: todas as requisições, respostas e notificações são objetos JSON comuns com um esquema previsível.

Ou seja, em vez de “cada serviço inventa seu próprio formato”, existe um contrato básico:

  • a requisição tem o campo obrigatório jsonrpc (geralmente "2.0"), um id exclusivo, um nome de método em string method e um objeto params com os parâmetros;
  • a resposta é vinculada à requisição pelo id e contém ou result, ou error;
  • notificações (notifications) se parecem com requisições, mas sem id, e não haverá resposta para elas.

Parece mais ou menos assim:


{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/list",
  "params": {
    "cursor": null
  }
}

Isto é um request. E a resposta em caso de sucesso:

{
  "jsonrpc": "2.0",
  "id": 42,
  "result": {
    "tools": [],
    "nextCursor": null
  }
}

Se você pensou “isso é só um RPC normal”, é isso mesmo. O MCP apenas fixa quais métodos existem (tools/list, tools/call, resources/list, prompts/list, …) e em qual formato eles esperam parâmetros e retornam dados.

É importante sentir: JSON‑RPC é a estrutura “requisição–resposta–notificação”. MCP é “quais requisições existem e o que vai dentro delas”.

2. Request: como o MCP pede para fazer algo

Vamos começar pelas requisições. Elas sempre vão na direção “alguém quer fazer algo”. Normalmente é cliente → servidor (ChatGPT → seu servidor MCP), mas o MCP também permite requisições no sentido inverso, quando o servidor pede ao cliente para fazer sampling ou elicitation. Nesta aula, nos interessa principalmente a variante clássica: o cliente pede ao servidor.

Qualquer MCP‑request tem três campos-chave:

  1. jsonrpc — a versão do protocolo JSON‑RPC, geralmente "2.0".
  2. id — o identificador da requisição; qualquer tipo JSON, mas na prática costuma ser número ou string. O principal é que para requisições ativas os id sejam únicos.
  3. method — uma string do tipo "tools/list" ou "tools/call". A especificação do MCP define o conjunto de métodos permitidos.

E há o objeto params, onde vivem os parâmetros do método específico.

Exemplo: requisição de lista de ferramentas

Imagine que o ChatGPT acabou de se conectar ao seu servidor MCP e quer saber quais tools ele pode chamar. Ele enviará uma requisição mais ou menos assim:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "cursor": null
  }
}

O campo cursor é necessário para paginação — se houver muitas ferramentas, o servidor pode entregá-las em partes.

Para o nosso aplicativo de estudo (seleção de presentes), aqui vai ser meio sem graça: uma ou duas ferramentas, mas o protocolo permanece o mesmo. Por enquanto, trate isso como um exemplo intuitivo; veremos as estruturas formais depois, na seção sobre tools.

Exemplo: chamada de ferramenta (tools/call)

Agora, algo um pouco mais interessante. Suponha que já temos a MCP‑tool suggest_gifts, que você planeja implementar na aula sobre o servidor MCP. Ela espera os parâmetros:

  • occasion — ocasião (Birthday, Wedding, …),
  • budget — um número em dólares,
  • recipient — uma string descrevendo para quem é o presente.

Decidindo usar essa ferramenta, o ChatGPT formará um MCP‑request:

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "suggest_gifts",
    "arguments": {
      "occasion": "birthday",
      "budget": 100,
      "recipient": "friend who loves board games"
    }
  }
}

Observe alguns detalhes.

Primeiro, o nome da ferramenta é o que você declarou no lado do servidor (server.registerTool("suggest_gifts", …)). Segundo, o objeto arguments deve corresponder ao JSON Schema que você fornecerá na descrição da ferramenta.

Se o GPT tentar enviar argumentos fora do schema (por exemplo, budget: "cem dólares"), o servidor pode retornar um erro no nível do protocolo ou da lógica de negócios, dependendo da implementação. Por enquanto, o principal é captar a forma geral dessa requisição; na seção sobre tools, abaixo, veremos essas mesmas mensagens de forma mais sistemática.

Requests para resources e prompts

Analogamente, existem requisições para resources e prompts. A especificação do MCP define os métodos:

  • resources/list — listar os recursos disponíveis;
  • resources/read (ou resources/get) — ler um recurso específico por URI;
  • prompts/list — obter a lista de prompts disponíveis;
  • prompts/get — obter o texto de um prompt específico.

Exemplo de requisição de leitura de um recurso com o catálogo de presentes:

{
  "jsonrpc": "2.0",
  "id": 15,
  "method": "resources/read",
  "params": {
    "uri": "mcp://gift-server/resources/gift_catalog"
  }
}

Por ora, basta lembrar duas coisas. Primeiro, para cada primitivo há os métodos */list e */get/*/read. Segundo, o nome do método sempre fica no campo string method, e todo o conteúdo — no objeto params.

3. Reply: como o MCP responde — result e error

A resposta (reply) está sempre vinculada à requisição pelo campo id. É como um correlationId em muitos sistemas distribuídos: você olha os logs e vê que a requisição com id=7 recebeu a resposta com id=7, então é o mesmo par.

O JSON‑RPC estabelece uma regra simples: na resposta, ou result, ou error, mas não ambos. O MCP, por cima disso, detalha a estrutura de result para diferentes métodos (tools/list, tools/call etc.) e recomenda códigos de erro.

Resposta bem-sucedida (result)

Vamos ver um exemplo de resposta bem-sucedida a tools/call da nossa suggest_gifts. O servidor processou tudo, encontrou presentes adequados e retorna a lista no campo result:

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Here are some gift ideas for your friend..."
      }
    ],
    "structuredContent": {
      "gifts": [
        { "name": "Board game: Catan", "price": 45 },
        { "name": "Dice set", "price": 20 }
      ]
    },
    "isError": false
  }
}

Aqui, alguns pontos são importantes.

  • Primeiro, content e structuredContent são aquelas partes da resposta de MCP‑tools que você já viu no Apps SDK. O modelo usa o texto de content, e seu widget renderiza os dados de structuredContent.
  • Segundo, o flag isError se refere ao resultado de negócio. Do ponto de vista do protocolo, tudo deu certo: o JSON é válido, o método existe, os argumentos foram processados. Mas a lógica de negócios pode dizer: “não encontrei nenhuma ideia de presente, do ponto de vista de UX isso é um erro”. Então você define isError: true e descreve o problema em content.
  • Terceiro, a especificação do MCP para diferentes métodos (tools/list, tools/call, */list, */get) descreve em detalhe quais campos devem estar em result. Por exemplo, para tools/list o servidor retorna um array de descrições de ferramentas com nomes, títulos, descrições e o JSON Schema dos argumentos de entrada.

Resposta com erro (error)

Se algo deu errado no nível do protocolo ou do servidor, em vez de result é retornado um objeto error. Normalmente ele tem:

  • code — o código numérico do erro;
  • message — a descrição legível;
  • data — dados adicionais opcionais (stack trace, detalhes, …).

Exemplo: o modelo chamou um método que não existe:

{
  "jsonrpc": "2.0",
  "id": 99,
  "error": {
    "code": -32601,
    "message": "Method not found: tools/col"
  }
}

O código -32601 é o clássico do JSON‑RPC para “method not found”.

Há uma distinção sutil, mas importante, entre dois tipos de erro.

Erro de protocolo — quando as regras do MCP/JSON‑RPC são violadas: método desconhecido, tipo incorreto no campo params, JSON inválido. Nesse caso, é apropriado retornar error no nível superior.

Erro de negócio — quando o protocolo foi respeitado, mas a operação em si falhou por um motivo de domínio: catálogo vazio, falta de permissão para um recurso específico, identificador de negócio inválido. Nesse caso, o MCP geralmente recomenda retornar um result válido, mas marcá-lo como isError: true e descrever o problema no conteúdo.

Essa separação ajuda muito o ChatGPT e as ferramentas de depuração: olhando os logs, você percebe imediatamente se foi uma quebra técnica ou uma negativa consciente da lógica de negócios.

4. Notifications: mensagens unidirecionais

Uma notificação (notification) é uma “carta sem expectativa de resposta”. No JSON‑RPC, notificações parecem requisições comuns sem o campo id. O cliente não deve enviar reply para elas.

No MCP, notificações são usadas para eventos: mudanças nas listas de tools/resources/prompts, progresso de operações longas, mensagens de log etc.

O exemplo mais simples que você certamente verá é a notificação de que a lista de ferramentas mudou. A especificação do MCP para tools descreve a capability listChanged e a notificação tools/list_changed, que o servidor envia se o conjunto de tools disponíveis mudou.

A notificação pode ser assim:

{
  "jsonrpc": "2.0",
  "method": "tools/list_changed",
  "params": {
    "reason": "New tool 'suggest_gift_cards' was added"
  }
}

Não é necessária resposta. Ao receber essa notificação, o cliente pode decidir: “ok, preciso chamar tools/list de novo e atualizar o cache de ferramentas”.

Outras notificações típicas do MCP (falaremos delas em detalhe no módulo sobre fluxos e eventos):

  • eventos de progresso (notifications/progress) para operações longas;
  • logs do servidor (notifications/logging/message);
  • mudanças em recursos (resources/list_changed) e prompts (prompts/list_changed).

Por enquanto, o importante é: notificação = requisição sem id e sem resposta esperada. Se você vir nos logs um JSON sem id, muito provavelmente é uma notification.

Insight

Foi constatado experimentalmente que o ChatGPT App ignora mensagens enviadas a ele (MCP‑notification). Contudo, considerando que o ChatGPT Apps está apenas no início do seu desenvolvimento, a probabilidade de suporte completo de todos os lados do protocolo MCP em um futuro próximo é muito alta. Portanto, recomendo estudar também este lado do protocolo MCP.

5. Como tools/resources/prompts aparecem nas mensagens

Agora, a melhor parte: como exatamente dentro das mensagens MCP são descritos aqueles tools, resources e prompts de que tanto falamos.

Tools: descrição e invocação

No nível do protocolo, tools têm dois processos principais:

  1. discovery — o cliente descobre quais ferramentas existem;
  2. invocation — o cliente chama uma ferramenta específica.

Já vimos rapidamente tools/list e tools/call acima. Agora veremos de forma mais sistemática: quais processos eles cobrem e o que exatamente é retornado em result.

5.1.1. Lista de ferramentas — tools/list

Já vimos o request para tools/list. Vamos analisar a estrutura da resposta. A especificação do MCP diz: em result.tools deve ser retornado um array de objetos, cada um descrevendo uma ferramenta. Uma ferramenta tem obrigatoriamente:

  • name — nome exclusivo pelo qual o tools/call será feito depois;
  • title — um título curto (visível para pessoas e para o modelo);
  • description — uma descrição mais detalhada do que a tool faz, como se você explicasse a um colega;
  • inputSchema — o JSON Schema para os argumentos da ferramenta.

Para nossa suggest_gifts, a resposta de tools/list pode ser assim (bem simplificada):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "suggest_gifts",
        "title": "Gift ideas generator",
        "description": "Suggests gift ideas for a given occasion and budget.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "occasion": { "type": "string" },
            "budget": { "type": "number" },
            "recipient": { "type": "string" }
          },
          "required": ["occasion", "budget"]
        }
      }
    ],
    "nextCursor": null
  }
}

Se você já escreveu o inputSchema no Apps SDK ao registrar a ferramenta, praticamente já viu esse objeto, só que “por cima” — como um objeto TypeScript. O MCP simplesmente o transmite pelo protocolo ao cliente.

5.1.2. Chamada da ferramenta — tools/call

Já tocamos no formato da chamada. A especificação do MCP descreve que params deve conter:

  • name — o nome da ferramenta;
  • arguments — um objeto que corresponda ao inputSchema.

Por exemplo:

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "suggest_gifts",
    "arguments": {
      "occasion": "wedding",
      "budget": 150,
      "recipient": "coworker from marketing"
    }
  }
}

E, em resposta, o servidor entrega um result com content, structuredContent e, opcionalmente, _meta (por exemplo, indicando openai/outputTemplate, se você quiser vincular essa tool a um widget específico).

Esse encadeamento tools/listtools/call é o ciclo básico de trabalho das MCP‑tools: primeiro discovery, depois uso.

Resources: dados endereçáveis

Resources no MCP são quaisquer pedaços de dados aos quais o cliente pode acessar por URI: arquivos, registros de BD, configs, catálogos etc.

Eles têm um conjunto padrão de operações:

  • resources/list — para descobrir quais recursos existem;
  • resources/read — para ler um recurso específico (ou parte dele).

Imagine o recurso gift_catalog, que descreve um catálogo básico de presentes: categorias, marcas, preços mínimos e máximos. O servidor pode anunciá-lo com o URI "mcp://gift-server/resources/gift_catalog".

A resposta a resources/list pode ser assim (simplificado):

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resources": [
      {
        "uri": "mcp://gift-server/resources/gift_catalog",	// apenas uma string única. MCP não é um protocolo.
        "name": "gift_catalog",
        "description": "Base catalog of gifts with categories and prices",
        "mimeType": "application/json"
      }
    ],
    "nextCursor": null
  }
}

E a leitura do recurso — resources/read:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "resources/read",
  "params": {
    "uri": "mcp://gift-server/resources/gift_catalog"
  }
}

A resposta pode conter o próprio conteúdo e metadados:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "contents": [
      {
        "uri": "mcp://gift-server/resources/gift_catalog",
        "mimeType": "application/json",
        "text": "{\"categories\":[\"boardgames\",\"books\"]}"
      }
    ]
  }
}

A ideia principal: um recurso é dado endereçável, enquanto tools são operações. O MCP torna ambos explícitos no protocolo.

Prompts: modelos reutilizáveis

Prompts são “dicas pré‑montadas” ou modelos que o servidor pode fornecer ao cliente. O MCP os trata como um primitivo que tem:

  • nome;
  • título/descrição legível;
  • conteúdo (com frequência um modelo de system‑prompt ou um conjunto de exemplos few‑shot).

E, previsivelmente, existem dois métodos:

  • prompts/list — descobrir quais prompts existem;
  • prompts/get — obter o conteúdo de um prompt.

Por exemplo, você quer definir um estilo especial para gerar mensagens de parabéns junto com o presente. Então, no servidor MCP, pode declarar o prompt gift_congrats_style.

A resposta a prompts/list pode ser assim:

{
  "jsonrpc": "2.0",
  "id": 10,
  "result": {
    "prompts": [
      {
        "name": "gift_congrats_style",
        "description": "Style guide for birthday congratulations in a friendly tone"
      }
    ]
  }
}

E prompts/get retornará o próprio texto (ou conteúdo estruturado), que o cliente pode então passar para a LLM como parte do system‑prompt. Exemplo de requisição e resposta:

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "prompts/get",
  "params": {
    "name": "gift_congrats_style"
  }
}
{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "prompt": {
      "name": "gift_congrats_style",
      "messages": [
        {
          "role": "system",
          "content": [
            {
              "type": "text",
              "text": "You are a friendly assistant that writes short, warm birthday congratulations..."
            }
          ]
        }
      ]
    }
  }
}

6. Como isso se conecta ao Apps SDK e ao nosso widget

Agora, o MCP‑JSON pode ainda parecer um pouco pesado. Vamos conectá‑lo ao que você já fez via Apps SDK.

Lembrando, no frontend do widget você pode ter o código:

// dentro de um componente React na sandbox do ChatGPT
async function fetchGifts() {
  const result = await window.openai.callTool("suggest_gifts", {
    occasion: "birthday",
    budget: 50,
    recipient: "friend who loves sci-fi"
  });

  console.log(result);
}

No nível do Apps SDK, isso é uma função conveniente que:

  1. sabe a URL do servidor MCP (a partir da configuração do app);
  2. consegue, pelo nome suggest_gifts, encontrar a descrição da ferramenta;
  3. empacota sua chamada em um MCP‑request tools/call;
  4. o envia pelo transporte escolhido (HTTP/SSE);
  5. aguarda o MCP‑reply, desempacota o result e o entrega a você como result em JavaScript.

Se desenharmos isso como um diagrama, fica mais ou menos assim:

sequenceDiagram
    participant Widget
    participant AppsSDK as Apps SDK
    participant MCP as MCP server

    Widget->>AppsSDK: window.openai.callTool("suggest_gifts", {...})
    AppsSDK->>MCP: JSON { id:7, method:"tools/call", params:{...} }
    MCP-->>AppsSDK: JSON { id:7, result:{ content, structuredContent } }
    AppsSDK-->>Widget: result (ToolOutput)
    Widget->>Widget: setState(toolOutput)

Entender o formato do MCP dá a você duas habilidades excelentes.

Primeiro, você pode observar de forma adequada os logs MCP brutos (por exemplo, no MCP Inspector, que terá uma aula separada) e ver: qual tools/call foi enviado, quais argumentos havia nele, e o que voltou no result ou error.

Segundo, ao projetar ferramentas e recursos, você pode pensar não só em termos de tipos TypeScript, mas também em termos de esquemas MCP: como isso ficará no JSON e quão conveniente será para outros clientes (por exemplo, agentes que também podem se conectar ao seu servidor MCP).

7. Mini‑prática: lendo e “consertando” MCP‑JSON

Para que o formato MCP fique natural, é melhor desmontar manualmente algumas mensagens. Vamos pegar um exemplo de diálogo completo tools/listtools/call → resultado.

O cliente quer a lista de ferramentas

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

O que vemos:

  • é um request (existe id);
  • o método é tools/list, então trata-se de discovery de ferramentas;
  • parâmetros vazios, sem paginação.

O servidor responde:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "suggest_gifts",
        "title": "Gift ideas generator",
        "description": "Suggests gift ideas",
        "inputSchema": { "type": "object", "properties": { "occasion": { "type": "string" } } }
      }
    ]
  }
}

Fica claro imediatamente que esta é a resposta àquela requisição (mesmo id: 1), o protocolo foi bem‑sucedido (result presente, error ausente) e agora o cliente sabe que existe a tool suggest_gifts.

O cliente chama a ferramenta

Depois, o cliente faz tools/call:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "suggest_gifts",
    "arguments": {
      "occasion": "anniversary"
    }
  }
}

Se o servidor também espera budget, mas o modelo não o informou, o servidor pode:

  • ou retornar um erro de protocolo (por exemplo, error com o código “invalid params”);
  • ou tomar uma decisão padrão (por exemplo, usar um orçamento médio) e retornar um result normal.

Nos termos que introduzimos acima, a primeira opção é um erro de protocolo (error no nível superior), a segunda já é da esfera da lógica de negócios: você ainda retorna um result válido e decide se considera tal situação um erro de negócio (isError: true) ou um comportamento normal.

A resposta em caso de erro nos argumentos poderia ser assim:

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32602,
    "message": "Missing required property 'budget' in arguments"
  }
}

Novamente, distinguimos isso de um erro de negócio: o protocolo foi violado (os argumentos não correspondem ao schema), por isso aqui cabe error.

Exemplo quebrado: procurando o bug

Aqui está um JSON que às vezes aparece entre iniciantes:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "tool": "suggest_gifts",
    "args": {
      "occasion": "birthday",
      "budget": 100
    }
  }
}

À primeira vista parece plausível, mas se você comparar com a especificação do MCP, notará que os campos tool e args não batem com os esperados name e arguments.

Um cliente/servidor MCP‑SDK provavelmente nunca vai gerar esse JSON, mas se você, sem conhecer a especificação, fizer a integração manualmente, um bug assim é bem possível. É exatamente por isso que no curso analisamos o protocolo “na unha”, e não apenas os wrappers do SDK.

8. Erros típicos ao trabalhar com mensagens MCP

Erro nº 1: confundir erros de protocolo com erros de negócio.
Muitas vezes, desenvolvedores, por hábito, colocam tudo que “deu errado” no error de nível superior — ausência de recurso, argumentos incorretos, queda do banco. No contexto do MCP, é útil separar: se a estrutura JSON e o schema da chamada foram violados (método errado, campos errados, tipos incorretos), isso é motivo para retornar error. Se a ferramenta simplesmente não conseguiu executar a operação de domínio (não há presentes para tal orçamento, usuário não encontrado), é melhor retornar um result válido com isError: true e uma mensagem clara em content. Assim, tanto o modelo do ChatGPT quanto as ferramentas de depuração conseguem diferenciar “o canal quebrou” de “o servidor recusou conscientemente”.

Erro nº 2: ignorar o campo id e a correlação de requisições.
Às vezes, nos logs do servidor MCP, dá para ver saída manual sem id ou com valores repetidos de id para requisições diferentes em atividade. Em um hello‑world monothread até pode “funcionar”, mas assim que surgem chamadas paralelas ou tentativas de nova entrega (retries), fica difícil entender a que requisição pertence cada resposta. O JSON‑RPC exige id exclusivo durante a vida da requisição, e o MCP se apoia nessa regra. Se você usa os SDKs oficiais, pode nem pensar em id, mas se você mesmo escreve transporte ou logging, não se esqueça de preservar e mostrar o id — é a primeira coisa que você vai usar para depurar bugs estranhos.

Erro nº 3: estruturas instáveis de result para o mesmo método.
Às vezes, é tentador “mudar um pouquinho” o formato da resposta dependendo da situação: às vezes retornar um array de presentes, às vezes um objeto com uma string, às vezes apenas text sem structuredContent. O modelo talvez suporte essas variações, mas seus widgets e quaisquer outros clientes MCP — provavelmente não. A especificação do MCP descreve para cada método uma estrutura previsível de result; procure segui‑la. Se precisar de outro formato, é melhor declarar uma tool ou versão separada, em vez de mudar o schema em tempo de execução.

Erro nº 4: campos em excesso ou faltando em params.
Um problema típico de implementações customizadas é adicionar em params algo que o MCP não espera, ou esquecer um campo obrigatório. Por exemplo, enviar toolName em vez de name em tools/call, ou resourceId em vez de uri em resources/read. O MCP‑SDK normalmente valida essas coisas e lança uma exceção compreensível, mas se você trabalha mais próximo do protocolo, pode demorar para descobrir por que “o servidor não me entende”. Uma boa prática é manter, ao lado do handler, um exemplo de JSON de requisição correto (da especificação ou de logs de um cliente funcionando) e comparar com o que você está enviando.

Erro nº 5: tentar usar notifications como “segundo canal de respostas”.
Às vezes, ao ver notifications, desenvolvedores começam a enviar resultados de operações via notificações em vez de replies comuns: “já estamos em MCP e temos SSE, vamos enviar tudo por notificações”. O problema é que notificações do JSON‑RPC por definição não são vinculadas a um id específico e não são percebidas pelo cliente como resposta a uma requisição. Como resultado, fica mais difícil depurar e é impossível entender a qual chamada de ferramenta uma mensagem específica pertence. Notificações são ótimas para eventos (mudou a lista de tools/resources/prompts, surgiu um novo progresso, chegou um log), mas não para respostas comuns a tools/call e semelhantes.

Erro nº 6: não olhar os logs e os inspetores do MCP.
O erro mais humano — tentar depurar a integração apenas pela interface do ChatGPT: “cliquei no botão, algo não chegou, resolvo depois”. Enquanto você não vê as mensagens MCP brutas (requests, replies, notifications), é difícil entender em que nível está o problema: o modelo não chamou a tool, o Apps SDK não chegou ao servidor MCP, o servidor retornou um JSON errado, ou tudo quebrou já na renderização do widget. MCP Inspector / Jam e logging estruturado de mensagens MCP são seus melhores amigos. Depois que você vir ao menos uma vez um tools/call e um tools/list reais nos logs, o formato de mensagens do MCP deixará de ser “mágica” e virará rotina de engenharia.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION