Anatomia do MCP
Um servidor MCP expõe três tipos de capacidade que podem ser consultadas em tempo de execução: tools (ações), resources (leituras) e prompts (templates). O cliente descobre o catálogo por uma chamada de listagem.
Uma integração MCP tem quatro componentes principais: o cliente, o servidor, o transporte que os conecta e o catálogo exposto pelo servidor.
Cliente
É o processo que consome o catálogo. Em geral, uma LLM integrada a um agente ou a uma IDE. O cliente é universal: o mesmo código cliente se conecta a qualquer servidor MCP conforme a especificação, sem precisar de SDK específico.
Servidor
É o processo que expõe o catálogo. Pode ser um binário local, um container, um serviço remoto. A lógica do que cada ferramenta faz é responsabilidade do servidor. Do lado do cliente, a ferramenta aparece apenas como uma entrada na lista.
Transporte
A especificação define três transportes:
- stdio: o servidor é um processo filho do cliente, e a comunicação ocorre por stdin/stdout. Usado para servidores locais (ferramentas de sistema, acesso a arquivos, bancos de dados locais).
- Streamable HTTP: troca de mensagens HTTP com suporte a streaming de respostas e sessões persistentes. Usado para servidores remotos.
- SSE (Server-Sent Events): transporte mais antigo, mantido por compatibilidade.
Em qualquer transporte, o formato das mensagens é JSON-RPC 2.0.
Catálogo: tools, resources, prompts
Tools são ações. O cliente chama tools/call com o nome da ferramenta e os argumentos. O servidor executa e devolve o resultado. Podem alterar estado: enviar e-mail, criar ticket, rodar query de atualização.
Resources são leitura. O cliente chama resources/read com uma URI identificadora e recebe o conteúdo. Equivalem aos endpoints GET de uma API, com a diferença de que o cliente descobre as URIs disponíveis por resources/list.
Prompts são templates de mensagens. O servidor oferece receitas reutilizáveis com parâmetros, o cliente pede prompts/get e recebe uma sequência de mensagens já formatadas, que pode passar ao modelo diretamente.
Exemplo de resposta a tools/list
{
"tools": [
{
"name": "query_invoices",
"description": "Consulta faturas por data de vencimento, status e cliente.",
"inputSchema": {
"type": "object",
"properties": {
"due_date": { "type": "string", "format": "date" },
"status": { "type": "string", "enum": ["open", "paid"] },
"customer_id": { "type": "string" }
},
"required": ["due_date"]
}
},
{
"name": "send_email",
"description": "Envia um e-mail para o endereço informado.",
"inputSchema": {
"type": "object",
"properties": {
"to": { "type": "string", "format": "email" },
"subject": { "type": "string" },
"body": { "type": "string" }
},
"required": ["to", "subject", "body"]
}
}
]
}A descrição em linguagem natural de cada ferramenta é importante: ela é o sinal que a LLM usa para decidir qual chamar. Servidores bem escritos descrevem as ferramentas como se estivessem ensinando um programador novo, não como referência seca.