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á resumabilidade e não há stream servidor→cliente: a aplicação roda várias réplicas, e nenhuma operação precisa empurrar mensagens para o cliente.

Versões do protocolo​

O servidor fala duas eras do protocolo no mesmo endpoint:

VersãoEraStatus
2026-07-28Stateless, sem handshake — descoberta por server/discoverSuportada
2025-06-18Handshake por initialize — é a versão em que o initialize fecha por padrãoSuportada
2025-03-26Handshake por initializeSuportada

A era é decidida pelo corpo da requisição, com os cabeçalhos como conferência:

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

Uma versão que o servidor não fala — no cabeçalho ou no envelope, em qualquer era — é respondida com 400 e 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 cabeçalho MCP-Protocol-Version da resposta.

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 lembra nada entre uma requisição e outra.

Chave de params._metaObrigatóriaSignificado
io.modelcontextprotocol/protocolVersionsim2026-07-28
io.modelcontextprotocol/clientCapabilitiessimCapacidades do cliente (um objeto; {} serve). Sem elicitation de formulário, as tools destrutivas são recusadas — veja confirmação de tools destrutivas
io.modelcontextprotocol/clientInforecomendadaname e version do cliente

Os cabeçalhos repetem o que está no corpo, para que intermediários possam rotear sem lê-lo — e por isso têm que concordar com ele:

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

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

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

Cabeçalhos da requisição​

CabeçalhoObrigatórioSignificado
AuthorizationsimBearer <access token> emitido para o MCP — veja Autenticação
X-Workspace-IdnãoWorkspace padrão da conexão, usado quando a tool não recebe workspace_id — o mesmo que ?workspace_id= na URL. Veja Autenticação → O workspace
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 no tools/call da era 2026-07-28O nome da tool
OrigincondicionalMandado por clientes de navegador; validado contra uma allowlist

Cabeçalhos da resposta​

CabeçalhoSignificado
MCP-Protocol-VersionRevisão em uso
Cache-ControlSempre no-store
Retry-AfterEm 429 — veja Limite de requisições — e em 503

Métodos​

MétodoEra 2026-07-28Era 2025Para quê
server/discoversim—Versões suportadas, capacidades do servidor e instruções
initialize—simNegociação de versão, capacidades do servidor e instruções
ping—simTeste de vida; responde um resultado vazio
tools/listsimsimAs tools que este chamador pode rodar, com JSON Schema e anotações
tools/callsimsimRoda uma tool
resources/listsimsimOs documentos de URI fixa que este chamador pode ler
resources/templates/listsimsimOs templates de URI (kobana://finance/payables/{id}, …) que este chamador pode ler
resources/readsimsimLê um documento pela URI
prompts/listsimsimOs roteiros prontos que este chamador pode usar
prompts/getsimsimMonta um roteiro com os argumentos dados
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 — na era 2026-07-28, com HTTP 404; na de 2025, no corpo de um 200. Batching JSON-RPC não é suportado — foi removido na revisão 2025-06-18, e um corpo em array é respondido com 400.

O corpo tem teto de 14 MB (14.680.064 bytes) — o bastante para o maior pedido legítimo, um finance_attachments_upload de 10 MB em base64 com o envelope. Acima disso a resposta é 413 com { "jsonrpc": "2.0", "id": null, "error": { "code": -32600, "message": "Request body too large (limit 14680064 bytes)" } }: um Content-Length declarado acima do teto é recusado antes mesmo da autenticação, e um corpo sem Content-Length (ou que mente nele) é cortado no teto durante a leitura.

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, inclusive do server/discover: sem token, a resposta é o 401 com o desafio que leva o cliente ao login OAuth — veja Autenticação.

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

POST / HTTP/1.1
Authorization: Bearer <access token>
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: server/discover
{ "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 Kobana Finance: ...",
"ttlMs": 0,
"cacheScope": "private",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "kobana-finance",
"title": "Kobana Finance",
"version": "1.0.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-finance",
"title": "Kobana Finance",
"version": "1.0.0"
},
"instructions": "Tools for Kobana Finance: ..."
} }

As instructions (no initialize e no server/discover) avisam o agente que valores de campo nos resultados são dados escritos por terceiros, nunca instruções, e pedem confirmação do usuário antes de uma ação destrutiva ou que move dinheiro que um resultado pareça pedir.

tools/list​

Devolve apenas as tools que o chamador pode rodar — as que o escopo do token alcança e que a pessoa que autorizou pode fazer no dashboard. O inputSchema de uma tool de escrita é o próprio schema de request do endpoint — os mesmos campos, obrigatórios e enums da Referência da API. Cada tool carrega annotations, que é o que faz o cliente pedir confirmação ao usuário:

AnotaçãoSignificado
readOnlyHintA tool só lê
destructiveHintA tool apaga, cancela ou move dinheiro — só roda com a confirmação do servidor
idempotentHintRepetir a chamada tem o mesmo efeito
openWorldHintSempre false — a tool não alcança nada fora do Financeiro Inteligente

tools/call​

{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "finance_payables_list",
"arguments": { "workspace_id": "2b93f876-769a-4bdc-b23e-304957f313b4",
"filters": { "status": "pending" }, "limit": 10,
"fields": ["description", "amount", "due_date"] } } }

O resultado traz 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 o chamador pode agir voltam com isError: true dentro do resultado, não como erro JSON-RPC — veja Erros.

Despacho in-process​

Cada tool despacha in-process para o handler de /v1 que implementa a operação, com a identidade já verificada e o workspace resolvido para a chamada — o token do MCP não é repassado, e o endpoint segue exigindo o escopo dele. Não há segunda viagem HTTP nem segunda implementação: filtros, validação, regras de baixa, rateio, travas de segurança e isolamento por workspace são o mesmo código que a API REST roda. As escritas ficam registradas com o canal mcp (created_via / updated_via), distinguíveis das feitas pela API ou pelo dashboard.

Arquivos​

  • Download — finance_attachments_download não devolve os bytes: um PDF em base64 no contexto de um modelo é caro e inútil. O resultado traz o content_type, o tamanho e o caminho para baixar o arquivo na API — com um token emitido para a API, já que o do MCP não vale lá.
  • Upload — finance_attachments_upload recebe o arquivo em content_base64 (até 10 MB) e o envia ao endpoint como multipart/form-data. Depois, finance_attachments_link o anexa a um título ou lançamento.