Problemas na integração de servidor MCP: protocolo, transporte, permissões e schema

Guia em camadas para diagnosticar servidor MCP: versão do protocolo, transporte, execução, autorização, schema de tools e teste seguro com o Inspector.

Se um servidor MCP não conecta ou uma tool call termina com erro, não altere ao mesmo tempo a configuração do client, o código do server e as permissões. Primeiro identifique a camada que falhou. Siga esta ordem: versão do protocolo → transporte → inicialização e ambiente → permissions/auth → inputSchema → uma chamada read-only.

Em 23 de agosto de 2026, a versão atual verificada da especificação MCP é 2026-07-28. Ela não exige mais o antigo handshake obrigatório por initialize: o client pode usar server/discover, enquanto a versão do protocolo, os dados do client e suas capabilities seguem com as requisições em _meta. Implementações legacy 2025-11-25 ou anteriores usam outra sequência: initialize, resposta do servidor e depois notifications/initialized. Não combine essas duas épocas no mesmo intercâmbio.

Separe MCP da API do modelo desde o início. MCP conecta o client a tools e contexto; a chamada ao modelo pode seguir outra rota e usar outras credentials. Isole a camada do modelo com o guia da BetterToken: sua própria API Key e a interface OpenAI-compatible ou Anthropic-compatible escolhida fornecem uma rota separada e verificável, evitando procurar um erro do modelo dentro do MCP. Essa Key não é uma credential do servidor MCP, e a BetterToken não é um MCP host nem um MCP transport.

Classificação rápida da falha

Antes de abrir o Inspector, registre um sintoma e o último ponto confirmado:

  • o processo não inicia;
  • o processo executa, mas o client não recebe JSON-RPC;
  • o transporte responde, mas a versão ou as capabilities não coincidem;
  • o servidor retorna 401 ou 403;
  • tools/list funciona, mas a tool esperada não aparece;
  • a tool aparece, porém tools/call rejeita os arguments;
  • a chamada termina, mas o resultado não pode ser verificado.

Não anote API Key, bearer token, cookie, prompt completo nem conteúdo de arquivos privados. Para correlação, bastam horário, nome do servidor, método, id JSON-RPC, código de erro e uma mensagem sanitizada.

1. Determine a época do protocolo

Descubra qual versão é compatível com client, server e SDK. A mensagem Connected confirma o transporte e parte do discovery, mas não prova, sozinha, a negociação de 2026-07-28.

Em uma implementação moderna, confira três sinais:

  1. O SDK ou as release notes declaram explicitamente suporte a 2026-07-28.
  2. O trace contém server/discover ou outro caminho de discovery previsto pelo SDK.
  3. As requisições contêm _meta correto com versão, dados do client e capabilities.

Não copie manualmente o formato de _meta de outro SDK: o wire format exato deve ser gerado por um client compatível ou pelo SDK oficial. Se o server espera initialize, mas o client envia requisições autocontidas de 2026-07-28, há incompatibilidade de época, não erro na tool schema.

initialize legacy: apenas para 2025-11-25 e anteriores

Este é um request legacy mínimo. Não o adicione a um flow moderno 2026-07-28 “por garantia”.

{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": { "name": "mcp-diagnostic-client", "version": "1.0.0" } } }

Após uma resposta bem-sucedida, o legacy client envia notifications/initialized. Se esse intercâmbio for interrompido, compare primeiro as versões e a lista de capabilities. Ainda é cedo para seguir para tools/list.

2. Teste o transporte separado da semântica MCP

MCP define métodos e dados; o transporte cuida de inicialização, framing, entrega e cancelamento de requisições. Trocar stdio por HTTP não corrige um inputSchema inválido.

stdio

Com stdio, o client inicia o server como processo filho. As mensagens passam por stdin e stdout como documentos JSON-RPC UTF-8 delimitados por quebra de linha.

Verifique:

  1. command existe e executa com o mesmo usuário.
  2. Os argumentos são passados como itens separados, sem depender de aliases do shell.
  3. O diretório de trabalho contém os arquivos necessários ou os caminhos são absolutos.
  4. As variáveis necessárias estão disponíveis para o processo filho.
  5. stdout não contém banner, linhas de debug nem stack trace; os logs vão para stderr.

Um único console.log() acidental em stdout pode quebrar o framing antes que o client veja uma resposta JSON-RPC.

Streamable HTTP

Com Streamable HTTP, o client envia mensagens POST para um único endpoint MCP. A resposta pode ser JSON comum ou SSE limitado à requisição. Verifique URL exata, método HTTP, Content-Type, TLS, redirects, proxy e método de autenticação.

Faça o teste de transporte em loopback ou em ambiente isolado. Não examine um endpoint público de produção sem autorização. Se o POST retornar uma página HTML de login, um 301/302 para outro host ou resposta de reverse proxy, você ainda não chegou ao MCP.

3. Reproduza a inicialização no mesmo ambiente

Para stdio, execute primeiro o comando do server diretamente no mesmo diretório e com o mesmo usuário do MCP client. Não substitua isso por uma execução na IDE: PATH, cwd, runtime e permissões podem ser diferentes.

Verifique:

node --version pwd node ./dist/server.js

pwd não revela um secret sozinho, mas não publique o caminho se ele contiver nome de usuário ou de projeto privado. O comando do server deve aguardar JSON-RPC em stdin ou encerrar com erro claro em stderr. Uma saída imediata sem mensagem geralmente aponta para entrypoint incorreto, dependência ausente ou erro de inicialização tratado sem log.

A documentação oficial do Inspector CLI, verificada em 23 de agosto de 2026, exige Node.js 22.19.0 ou mais recente. Se a versão for inferior, pare e troque o runtime antes de continuar o diagnóstico.

4. Separe permissions e authentication

O código da resposta orienta a próxima verificação:

  • 401 Unauthorized: a credential está ausente, expirou ou foi rejeitada;
  • 403 Forbidden: a identity foi reconhecida, mas não tem o permission ou scope necessário;
  • 404: muitas vezes significa endpoint ou rota incorretos, não falta de permissão;
  • timeout: o server, proxy ou tool não terminou a tempo; isso não prova erro de auth.

Não desative permissions para um smoke test. Crie uma identity de teste separada com o menor scope e escolha uma tool read-only sem efeitos externos. O client deve permitir que uma pessoa negue a chamada; annotations da tool são dados não confiáveis e não substituem a policy.

Nos logs, preserve a decisão de auth (allowed/denied), o nome do scope e o correlation ID. Remova ou mascare a credential, o header Authorization e os cookies.

5. Valide a capability e o inputSchema

O server deve declarar a capability tools antes de atender tools/list. Cada tool precisa de nome exclusivo e de um objeto JSON Schema válido em inputSchema. Os arguments de tools/call devem corresponder a essa schema.

Declaração mínima de uma tool read-only:

{ "name": "echo", "description": "Retorna o texto recebido sem alterações", "inputSchema": { "type": "object", "properties": { "text": { "type": "string" } }, "required": ["text"], "additionalProperties": false } }

Erros comuns são simples: ausência do type: object raiz, campo obrigatório fora de properties, envio de número em vez de string pelo client, diferença de maiúsculas no nome de um argument ou duas tools anunciadas com o mesmo nome.

Depois de alinhar versão e transporte, teste o método com este payload JSON-RPC:

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

Em seguida, invoque exatamente uma tool:

{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "echo", "arguments": { "text": "MCP_OK_2026" } } }

Esses trechos mostram o payload dos métodos, não o bootstrap completo da conexão. No flow 2026-07-28, um client compatível adiciona em _meta os metadados exigidos pela requisição; no legacy flow, initialize ocorre primeiro. Não envie esses JSON manualmente para um endpoint de produção sem autorização.

6. Execute um teste seguro com o MCP Inspector CLI

Primeiro instale o Inspector como dependência fixada do projeto, com um lockfile confiável. A opção --no-install abaixo evita baixar uma versão atual aleatória durante o diagnóstico.

Liste as tools de um server stdio local:

npx --no-install @modelcontextprotocol/inspector --cli node ./dist/server.js --method tools/list

Faça uma chamada a echo:

npx --no-install @modelcontextprotocol/inspector --cli node ./dist/server.js \ --method tools/call \ --tool-name echo \ --tool-arg text=MCP_OK_2026

Para um endpoint Streamable HTTP de teste em loopback:

npx --no-install @modelcontextprotocol/inspector --cli \ http://127.0.0.1:3000/mcp \ --transport http \ --method tools/list

Não coloque token no histórico do shell, na URL ou no artigo. Se o endpoint exigir auth, configure a credential pelo mecanismo normal do Inspector no ambiente local, ou pare o teste e solicite uma identity de teste ao responsável pelo server. Os comandos acima não contêm nenhuma Key real de propósito.

Sintoma → verificação → correção

SintomaO que verificar primeiroCorreção mínima
spawn ENOENT ou processo não encontradoCaminho absoluto de command, runtime e PATH do processo clientIndicar um executable existente ou corrigir o ambiente de execução
O processo encerra imediatamentecwd, entrypoint, dependências e erro em stderrExecutar no diretório correto e retornar um non-zero exit claro
O client informa JSON parse errorSaída extra em stdout, UTF-8 e quebra de linhaManter apenas JSON-RPC em stdout e enviar logs a stderr
HTTP retorna HTML ou redirectURL MCP, proxy, TLS e rota POSTUsar um único endpoint MCP correto e corrigir a regra do proxy
Erro de versão antes de tools/listÉpoca do protocolo e suporte do SDKAtualizar o lado incompatível ou manter explicitamente o caminho legacy; não misturar handshakes
401 UnauthorizedPresença e validade da credentialObter uma credential de teste separada pelo processo aprovado
403 ForbiddenScope, resource policy e identityConceder apenas o scope necessário à identity de teste
tools/list → erro de método/capabilitySe a capability tools foi declaradaCorrigir a declaração antes de registrar tools
A tool não apareceNome exclusivo e registro efetivoRegistrar uma tool e reiniciar o server
tools/call rejeita argumentsinputSchema, tipos, required e maiúsculas dos nomesAdequar os arguments à schema; não a afrouxar para um objeto arbitrário
A chamada travaTimeout, cancellation e dependência externa da toolTrocar o teste por um echo local read-only e verificar a dependência depois

Critérios de aceitação

A integração passa na aceitação mínima quando todas as cinco condições são atendidas:

  1. Logs ou telemetry mostram a versão esperada e negociada do protocolo.
  2. O transporte preserva o framing: stdio não tem conteúdo extra em stdout, e HTTP responde no endpoint MCP.
  3. tools/list retorna uma tool esperada com inputSchema válido.
  4. tools/call é realmente invocado com text=MCP_OK_2026 e retorna MCP_OK_2026 sem alterações.
  5. O teste não desativou permissions, não expôs credentials e não produziu efeito externo.

Ver MCP_OK_2026 na resposta do modelo não basta. É preciso registrar a tool call com o id JSON-RPC correspondente, ou ter um registro do Inspector e o log sanitizado do server.

Condições de parada

Pare o diagnóstico e não avance à próxima camada se:

  • a época do protocolo compatível com qualquer uma das partes for desconhecida;
  • o Inspector quiser instalar uma versão não fixada do pacote sem revisão;
  • o teste exigir credential de produção, desativação de auth ou ampliação de scope;
  • a única tool disponível escrever em banco, enviar mensagem, alterar arquivo ou executar comando;
  • o endpoint HTTP pertencer a terceiro e a autorização de teste não estiver confirmada;
  • aparecerem nos logs Key, token, cookie, dados pessoais ou conteúdo de recurso privado;
  • tools/list estiver instável ou retornar schemas diferentes em execuções repetidas;
  • o server cair antes de produzir uma resposta JSON-RPC válida.

Nesses casos, preserve o sintoma sanitizado, as versões de client/server/SDK, o transporte, o correlation ID e um fragmento mínimo do erro. Isso basta para encaminhar o problema ao responsável pela camada correta sem distribuir permissões ou segredos desnecessários.

Fontes

A versão da especificação, os detalhes do transporte e a versão mínima do Node.js foram verificados em 23 de agosto de 2026. Consulte novamente a documentação oficial antes de repetir o diagnóstico após atualizar client, server, SDK ou Inspector.

Quer otimizar seu fluxo de trabalho com LLMs?

Conecte modelos por uma única API, gerencie chaves e controle os gastos com IA.