Pular para o conteúdo principal

Transporte

Streamable HTTP, stateless. Uma mensagem JSON-RPC 2.0 por POST, uma resposta JSON. Não há Mcp-Session-Id, não há resumability e não há stream servidor→cliente: a aplicação roda com várias réplicas, e toda operação longa já responde 202 e termina em um worker em segundo plano, não no canal MCP.

Versões de protocolo​

O servidor fala duas eras do protocolo no mesmo endpoint:

VersãoEraSituação
2026-07-28Stateless, sem handshake — descoberta por server/discoverSuportada
2025-06-18Handshake por initialize — o padrão quando o cliente não envia o headerSuportada
2025-03-26Handshake por initializeSuportada

A era é decidida pelo body da requisição, com os headers servindo de conferência:

  • params._meta carrega io.modelcontextprotocol/protocolVersion → era 2026-07-28 (veja abaixo).
  • Sem esse envelope, com um MCP-Protocol-Version de 2025 ou sem o header → era 2025, com initialize.
  • MCP-Protocol-Version: 2026-07-28 sem o envelope → 400 com -32602. O servidor não cai silenciosamente para a era antiga: você pediu a semântica stateless e receberia a outra.

Uma versão que o servidor não fala — no header ou no envelope, em qualquer era — recebe 400 com o erro JSON-RPC -32022, listando as suportadas:

{ "jsonrpc": "2.0", "id": 1, "error": {
"code": -32022,
"message": "Unsupported protocol version",
"data": { "supported": ["2026-07-28", "2025-06-18", "2025-03-26"], "requested": "1999-01-01" }
} }

A versão em uso volta no header de resposta MCP-Protocol-Version.

Era 2026-07-28​

Não há handshake: toda requisição carrega a própria versão e as capacidades do cliente em params._meta, e o servidor não guarda nada entre uma requisição e a seguinte.

Chave de params._metaObrigatóriaSignificado
io.modelcontextprotocol/protocolVersionsim2026-07-28
io.modelcontextprotocol/clientCapabilitiessimAs capacidades do cliente (um objeto; {} basta). Declarar elicitation liga a confirmação de tools destrutivas
io.modelcontextprotocol/clientInforecomendadaname e version do cliente

Os headers repetem o que está no body, para que intermediários possam rotear sem lê-lo — e por isso precisam concordar com ele:

HeaderPrecisa ser igual a
MCP-Protocol-VersionA versão do envelope
Mcp-MethodO method da mensagem
Mcp-NameSó em tools/call: params.name, cru ou como =?base64?…?=

Qualquer divergência é 400 com -32020 (Header mismatch: …). clientCapabilities ausente é 400 com -32602.

Os resultados nessa era sempre carregam resultType: "complete" e o servidor em _meta["io.modelcontextprotocol/serverInfo"]. server/discover, tools/list, resources/list, resources/templates/list, resources/read e prompts/list também carregam ttlMs: 0 e cacheScope: "private": o que volta é filtrado pelo escopo e pelas permissões de quem chama, então não pode ser reaproveitado nem compartilhado. Uma tools/call de tool destrutiva pode voltar com resultType: "input_required" — veja Confirmação de tools destrutivas.

Headers de requisição​

HeaderObrigatórioSignificado
AuthorizationsimBearer <access token> emitido para o servidor MCP — veja Autenticação
Content-Typesimapplication/json
Acceptrecomendadoapplication/json
MCP-Protocol-Versionsim na era 2026-07-28; recomendado na de 2025Revisão do protocolo
Mcp-Methodsim na era 2026-07-28O método da mensagem
Mcp-Namesim numa tools/call da era 2026-07-28O nome da tool
X-Workspace-IdcondicionalWorkspace sobre o qual agir, quando a organização tem mais de um
OrigincondicionalEnviado por clientes de navegador; validado contra uma allowlist

Headers de resposta​

HeaderSignificado
MCP-Protocol-VersionRevisão negociada
X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-ResetVeja Limite de requisições
Cache-ControlSempre no-store
Retry-AfterEm 429 e em 503

Métodos​

MétodoEra 2026-07-28Era 2025Finalidade
server/discoversim—Versões suportadas, capacidades do servidor e instruções
initialize—simNegociação de versão, capacidades do servidor e instruções
ping—simChecagem de vida; responde um resultado vazio
tools/listsimsimTools que quem chama pode executar, com JSON Schema e annotations
tools/callsimsimExecuta uma tool
resources/listsimsimOs documentos de URI fixa que quem chama pode ler
resources/templates/listsimsimOs templates de URI (kobana://inbox/emails/{id}, …) que quem chama pode ler
resources/readsimsimLê um documento por URI
prompts/listsimsimOs prompts prontos que quem chama pode usar
prompts/getsimsimRenderiza um prompt com os argumentos informados
completion/completesimsimSugestões para um argumento de prompt ou de template

Resources, prompts e completions estão em Resources e prompts.

Qualquer outro método é -32601 Method not found — com HTTP 404 na era 2026-07-28, no body de um 200 na de 2025. Batching JSON-RPC não é suportado — foi removido na revisão 2025-06-18, e um body em array recebe 400.

O body da requisição é limitado a 1 MB (1.048.576 bytes); acima disso a resposta é 413 com -32600 — veja Erros. Nenhuma tool precisa de mais: arquivos nunca trafegam pelo MCP.

Uma notificação (mensagem sem id, como notifications/initialized) é aceita com 202 e corpo vazio, nas duas eras.

A autenticação vem antes de qualquer método, server/discover incluído: sem token, a resposta é o desafio 401 que manda o cliente para o login OAuth — veja Autenticação.

server/discover (era 2026-07-28)​

{ "jsonrpc": "2.0", "id": 1, "method": "server/discover",
"params": { "_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": { "name": "my-client", "version": "1.0.0" }
} } }
{ "jsonrpc": "2.0", "id": 1, "result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28", "2025-06-18", "2025-03-26"],
"capabilities": { "tools": {}, "resources": {}, "prompts": {}, "completions": {} },
"instructions": "Tools for the Kobana Autonomous Inbox: ...",
"ttlMs": 0,
"cacheScope": "private",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "kobana-autonomous-inbox",
"title": "Kobana Autonomous Inbox",
"version": "0.1.0"
}
}
} }

initialize (handshake da era 2025)​

{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": { "protocolVersion": "2025-06-18" } }
{ "jsonrpc": "2.0", "id": 1, "result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": { "listChanged": false },
"resources": { "subscribe": false, "listChanged": false },
"prompts": { "listChanged": false },
"completions": {}
},
"serverInfo": {
"name": "kobana-autonomous-inbox",
"title": "Kobana Autonomous Inbox",
"version": "0.1.0"
},
"instructions": "Tools for the Kobana Autonomous Inbox: ..."
} }

As instructions (em initialize e server/discover) avisam o agente de que os valores de campos nos resultados — sobretudo o assunto e o corpo de um e-mail — são dados escritos por terceiros, nunca instruções, e pedem que ele confirme com o usuário antes de uma ação destrutiva que um resultado pareça solicitar. Elas também dizem que tools destrutivas exigem o protocolo 2026-07-28 com elicitation, e que confirmation_required significa que o cliente não consegue executá-las — não é algo para tentar de novo.

tools/list​

Devolve apenas as tools que quem chama consegue executar, filtradas pelo escopo do token e pelas permissões da pessoa. Toda tool carrega annotations, que orientam os pedidos de confirmação do cliente:

AnnotationSignificado
readOnlyHintA tool apenas lê
destructiveHintA tool exclui dados, envia algo para fora (teste ou reenvio de webhook, reprocessamento de e-mail), rotaciona um segredo ou muda quem pode enviar para uma inbox. Só roda depois da confirmação do servidor
idempotentHintRepetir a chamada tem o mesmo efeito
openWorldHintSempre false — a tool não alcança nada fora do Inbox Autônomo

tools/call​

{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "emails_list", "arguments": { "status": "processed", "limit": 10 } } }

O resultado carrega a resposta JSON do endpoint como conteúdo de texto:

{ "jsonrpc": "2.0", "id": 2, "result": {
"content": [{ "type": "text", "text": "{ \"data\": [ ... ], \"meta\": { \"next_cursor\": \"...\" } }" }]
} }

Erros sobre os quais quem chama pode agir voltam com isError: true dentro do resultado, e não como erro JSON-RPC — veja Erros.

Despacho in-process​

Toda tool despacha in-process para o route handler de /api/v1 dono da operação, com a identidade já verificada — o token MCP não é repassado, e o endpoint continua exigindo seu próprio escopo e sua própria permissão. Ids nos argumentos são codificados no path, então um id não consegue alcançar outra rota. Não há round trip HTTP nem uma segunda implementação: filtros de listagem, casamento de upsert, validação, soft-delete e isolamento multi-tenant são o mesmo código que a API REST executa, então uma tool não consegue divergir do endpoint que espelha.