A tela ClaudIA > Servidores MCP permite conectar ferramentas externas aos seus agentes usando o Model Context Protocol (MCP). Este artigo descreve exatamente o que a plataforma exige de um servidor para que ele passe no teste de conexão e funcione em produção.
A ClaudIA usa um subconjunto pequeno e bem definido do protocolo. Se o seu servidor cumprir os pontos abaixo, ele vai funcionar.
1. Transporte: Streamable HTTP
A ClaudIA fala apenas o transporte Streamable HTTP da especificação MCP (revisão 2025-03-26 ou mais recente).
Na prática, isso significa:
- Um único endpoint HTTP (por exemplo,
https://seu-host/mcp) que aceitaPOSTcom um corpo JSON-RPC 2.0. - A resposta pode ser
Content-Type: application/json(um único objeto JSON) ouContent-Type: text/event-stream(SSE). Os dois formatos são aceitos. - O servidor pode ser stateless ou stateful (devolvendo o header
Mcp-Session-Idnoinitialize). Ambos funcionam.
O que não funciona:
- Servidores stdio (o formato dos tutoriais para Claude Desktop). Eles não têm URL HTTP.
- O transporte HTTP+SSE antigo (protocolo 2024-11-05), com endpoints separados
/ssee/messages. A ClaudIA não faz fallback para esse formato.
A maioria dos quickstarts públicos ensina stdio ou SSE. Confira qual transporte o seu framework está usando antes de testar.
2. Handshake e métodos usados
A cada uso, a ClaudIA abre uma sessão nova e executa, nesta ordem:
initialize: o servidor precisa responder comcapabilities.toolsdeclarado.notifications/initializedtools/list: para descobrir as ferramentas.tools/call: quando o agente decide usar uma ferramenta.
Nenhum outro recurso do protocolo é consumido: resources, prompts, sampling, elicitation, roots e a notificação tools/list_changed são ignorados. O servidor não precisa implementá-los.
Como cada chamada abre uma sessão nova, o servidor precisa aceitar muitas sessões curtas sem problema.
3. URL
- Cole a URL completa do endpoint MCP, com o path (ex.:
https://seu-host/mcpouhttps://seu-host/v1/minha-api/mcp). - A URL é usada exatamente como colada. A plataforma não adiciona
/mcpautomaticamente. - Apenas
httpehttpssão aceitos.
4. Autenticação
| Tipo escolhido na tela | O que o servidor recebe |
|---|---|
| Nenhum | Nenhum header de autenticação |
| Bearer Token | Authorization: Bearer <token> |
| API Key | X-Api-Key: <token> |
Você também pode adicionar cabeçalhos personalizados. Os nomes Authorization, X-Api-Key e X-Authorization são reservados e não podem ser usados como cabeçalho personalizado.
Se o servidor responder 401 ou 403, o teste de conexão mostra "Falha na autenticação".
5. Formato das ferramentas
Cada item retornado em tools/list precisa ter:
name: identificador único. Use apenas letras minúsculas, números,_e-. A ClaudIA prefixa o nome com o identificador do servidor, então nomes curtos e descritivos funcionam melhor.description: texto claro do que a ferramenta faz e quando usar. É isso que o modelo lê para decidir chamar a ferramenta.inputSchema: JSON Schema do tipoobjectdescrevendo os parâmetros.
Exemplo mínimo:
{
"name": "consultar_pedido",
"description": "Retorna o status de um pedido a partir do número informado pelo cliente.",
"inputSchema": {
"type": "object",
"properties": {
"numero_pedido": { "type": "string", "description": "Número do pedido" }
},
"required": ["numero_pedido"]
}
}
6. Formato do resultado de tools/call
- Retorne o resultado em
contentcomo blocos{"type": "text", "text": "..."}. É esse texto que o agente lê. structuredContenté aceito, mas o agente usa apenas o bloco de texto. Se usarstructuredContent, mantenha também o JSON serializado em um blocotext, como a especificação recomenda.- Para erros de negócio (pedido não encontrado, API externa indisponível), retorne
isError: truecom a explicação emcontent. O agente recebe a mensagem e consegue reagir.
7. Tempo limite
| Etapa | Limite |
|---|---|
| Conexão TCP/TLS | 5 segundos |
initialize e tools/list |
30 segundos |
tools/call em produção |
180 segundos |
Um servidor que demora mais que isso aparece como "Servidor inacessível" no teste ou como falha de ferramenta na conversa.
8. O que o botão "Testar conexão" faz
O teste executa exatamente o mesmo initialize + tools/list que o agente executa em produção, com a URL, o tipo de autenticação e os cabeçalhos informados na tela. Se passar, o servidor será chamado dessa mesma forma. Nada é salvo durante o teste.
| Mensagem na tela | Causa provável |
|---|---|
| Servidor inacessível | DNS, porta fechada, TLS inválido, timeout, ou o servidor respondeu 404/405 ao POST (sintoma típico de servidor SSE antigo ou stdio) |
| A resposta do servidor não é uma resposta MCP válida | O corpo não é JSON-RPC 2.0, ou o initialize não declarou capabilities.tools |
| O servidor retornou um erro | O servidor respondeu com um error JSON-RPC ao initialize ou ao tools/list |
| Falha na autenticação | 401 ou 403 |
9. Exemplos mínimos
Python (FastMCP, SDK oficial)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("meu-servidor", stateless_http=True)
@mcp.tool()
def consultar_pedido(numero_pedido: str) -> str:
"""Retorna o status de um pedido a partir do número informado pelo cliente."""
return f"Pedido {numero_pedido}: em transporte"
if __name__ == "__main__":
mcp.run(transport="streamable-http")
O endpoint fica em http://host:8000/mcp. Publique atrás de HTTPS e cole essa URL na ClaudIA.
TypeScript (SDK oficial)
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";
const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
const server = new McpServer({ name: "meu-servidor", version: "1.0.0" });
server.registerTool(
"consultar_pedido",
{
description: "Retorna o status de um pedido a partir do número informado pelo cliente.",
inputSchema: { numero_pedido: z.string() },
},
async ({ numero_pedido }) => ({
content: [{ type: "text", text: `Pedido ${numero_pedido}: em transporte` }],
}),
);
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
res.on("close", () => { transport.close(); server.close(); });
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
app.listen(3000);
Checklist rápido
- [ ] Endpoint único aceitando
POSTJSON-RPC (Streamable HTTP) - [ ]
initializeresponde comcapabilities.tools - [ ]
tools/listretornaname,descriptioneinputSchema - [ ]
tools/callretornacontentcom blocostext - [ ] Autenticação via
Authorization: BearerouX-Api-Key, conforme escolhido na tela - [ ] Responde em menos de 30 segundos ao
initializee aotools/list - [ ] URL completa, com path, em HTTPS