Arquitetura de servidor MCP explicada com diagramas: do host à chamada de ferramenta
Um servidor MCP fica entre uma aplicação de IA e os sistemas que ela precisa acessar. Este artigo descreve todo o caminho em diagramas: host, cliente, servidor, transporte, handshake JSON-RPC, chamada de ferramenta, tratamento de erros e segurança, com um conector real de imagem e vídeo como exemplo prático.
Seu assistente de IA pode redigir um contrato em segundos, mas não consegue ler sua agenda, consultar seu banco de dados ou redimensionar uma foto sozinho. O Model Context Protocol, abreviado como MCP, preenche essa lacuna com um único contrato compartilhado entre as aplicações de IA e os sistemas ao redor delas. Um servidor MCP é o pequeno programa do outro lado desse contrato: ele anuncia o que consegue fazer, espera pelas requisições e devolve os resultados em um formato previsível. Este artigo desenha essa arquitetura peça por peça. Cada diagrama é texto simples, então funciona bem ao ser copiado e colado em um README, em um documento de design ou em um pull request.
Por que o MCP existe
Antes do MCP, cada aplicação de IA que quisesse acessar um banco de dados, uma agenda ou um sistema de arquivos precisava de seu próprio conector personalizado. Cada conector trazia sua própria autenticação, seu próprio formato de erro e seus próprios bugs. Três aplicações e três ferramentas já significavam nove integrações, e a grade cresce a cada novo produto de qualquer lado. O MCP substitui essa grade por um protocolo compartilhado, então a conta muda de aplicações vezes ferramentas para aplicações mais ferramentas.
Before MCP: one custom connector for every pair
App A ──► Database App B ──► Database App C ──► Database
App A ──► Calendar App B ──► Calendar App C ──► Calendar
App A ──► Files App B ──► Files App C ──► Files
3 apps x 3 tools = 9 connectors to build and maintain
With MCP: one shared protocol in the middle
App A ──┐ ┌── Database server
App B ──┼──── MCP (JSON-RPC) ─────┼── Calendar server
App C ──┘ └── Files server
3 clients + 3 servers = 6 pieces
A palavra servidor engana as pessoas. Um servidor MCP não é um modelo de linguagem e não pensa. É um programa comum, escrito em TypeScript, Python ou em qualquer linguagem com uma biblioteca JSON, que envolve uma capacidade real e a descreve em um formato que qualquer cliente compatível consegue ler. O modelo nunca precisa saber como funciona o driver do seu banco de dados. Ele só precisa saber que existe uma ferramenta chamada run_query e quais argumentos ela aceita.
Os três papéis em um só diagrama
O MCP define três papéis, e confundi-los é a origem da maior parte da confusão. Eis o quadro completo antes dos detalhes.
┌──────────── HOST (the AI application) ────────────┐
│ The LLM picks a tool, the host routes the call │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ client 1 │ │ client 2 │ │ client 3 │ │
│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
└────────┬───────────────┬───────────────┬──────────┘
│ session │ session │ session
┌─────┴──────┐ ┌─────┴──────┐ ┌─────┴──────┐
│ Server A │ │ Server B │ │ Server C │
│ files │ │ GitHub │ │ image tool │
└────────────┘ └────────────┘ └────────────┘
O host controla a conversa
O host é a aplicação que a pessoa realmente usa: um app de chat para desktop, um assistente de IDE ou um agente personalizado. Ele executa o modelo de linguagem, decide a quais servidores se conectar e mostra ao usuário o que está prestes a acontecer. Modelos de raciocínio como Claude Sonnet 5, GPT 5.6 Sol e Gemini 3.1 Pro ficam dentro do host, mas nunca falam MCP diretamente. O host faz a tradução entre o formato de chamada de ferramentas do modelo e o protocolo, e é por isso que um único servidor funciona com vários modelos diferentes.
O cliente mantém uma sessão
Dentro do host, é criado um cliente MCP para cada servidor. Cada cliente mantém uma sessão com estado, de um para um, com exatamente um servidor, lembra das capacidades que os dois lados acordaram e encaminha cada mensagem. Um host conectado a três servidores executa três clientes, como mostra o diagrama. Se uma sessão cair, as outras duas continuam funcionando.
O servidor faz o trabalho
O servidor MCP envolve um sistema real: um banco de dados Postgres, uma conta do GitHub, uma pasta de documentos ou uma API de imagens. Ele se mantém deliberadamente pequeno. Declara o que oferece, valida a entrada, executa a ação e devolve uma saída estruturada. Ele nunca vê a conversa completa, apenas as requisições enviadas a ele, uma escolha de design que protege a privacidade e mantém os servidores reutilizáveis.
Um resumo rápido para você fixar acima da mesa:
Host: é dono do modelo, da interface do usuário e dos prompts de consentimento.
Cliente: um por servidor, fala o protocolo e guarda o estado da sessão.
Servidor: expõe capacidades, executa a ação e devolve os resultados.
O que um servidor expõe
Um servidor oferece três blocos de construção, chamados primitivas. Elas diferem em um detalhe que molda todo o design: quem decide quando cada uma é usada.
Primitiva
Controlada por
Uso típico
Exemplos de métodos
Ferramentas
O modelo
Executar uma ação ou calcular um resultado
tools/list, tools/call
Recursos
A aplicação
Fornecer contexto somente leitura, como arquivos ou registros
resources/list, resources/read
Prompts
O usuário
Modelos reutilizáveis, muitas vezes exibidos como comandos de barra
prompts/list, prompts/get
Ferramentas executam ações
Uma ferramenta tem um nome, uma descrição em linguagem simples e um inputSchema escrito em JSON Schema. O modelo lê a descrição para decidir se a ferramenta se encaixa no pedido, e o schema mantém os argumentos válidos. As descrições merecem esforço real, porque uma descrição vaga obriga o modelo a adivinhar. Dê às ferramentas nomes de verbos, mantenha cada uma restrita e devolva apenas os campos de que o modelo precisa. Uma ferramenta chamada search_orders com três argumentos tipados é melhor do que uma única ferramenta do_anything com um campo de texto livre. Os resultados das ferramentas não se limitam a texto: podem trazer imagens, áudio ou links, e é por isso que geradores de mídia se encaixam tão naturalmente no protocolo. Uma ferramenta de imagem pode envolver o Flux 2 Pro ou o Seedream 4.5, e uma ferramenta de vídeo pode envolver o Veo 3.1 ou o Kling v3 Video.
Recursos fornecem contexto
Recursos são dados somente leitura endereçados por URI, como file:///reports/q3.md ou postgres://db/customers/schema. O host escolhe quais anexar ao contexto do modelo, então os recursos servem bem para documentos, schemas e logs. Depois que um cliente assina um recurso, o servidor pode anunciar mudanças com notifications/resources/updated.
Prompts oferecem modelos
Prompts são modelos de mensagem parametrizados que o usuário escolhe de propósito, geralmente em um menu de comandos de barra. Um prompt como revise este pull request devolve uma lista pronta de mensagens, para que cada integrante da equipe comece com a mesma redação e o mesmo checklist.
O tráfego também flui no sentido contrário. Os servidores podem pedir ajuda ao cliente por meio de sampling (solicitar uma completação ao modelo do host), roots (perguntar quais diretórios estão no escopo) e elicitation (pedir ao usuário uma informação que falta). Os hosts decidem se permitem cada um deles.
💡 Regra prática: se a ação altera algo no mundo, crie uma ferramenta. Se apenas fornece informação, comece com um recurso.
Transportes: stdio ou Streamable HTTP
O transporte define como os bytes trafegam entre cliente e servidor. As mensagens permanecem idênticas nos dois casos: requisições, respostas e notificações JSON-RPC 2.0. Há dois transportes padrão.
stdio para servidores locais
stdio: the host starts the server as a child process
┌────────┐ stdin: requests ┌───────────┐
│ Client │ ─────────────────────► │ Server │
│ │ ◄───────────────────── │ process │
└────────┘ stdout: responses └───────────┘
stderr: logs only
Com stdio, o host inicia o servidor como um processo filho e troca mensagens JSON-RPC delimitadas por nova linha pela entrada e saída padrão. A configuração é uma única linha de comando, a latência é mínima e as credenciais chegam por variáveis de ambiente. Uma regra pega muitos autores de primeira viagem: o servidor nunca deve imprimir nada além de mensagens de protocolo na stdout. Os logs vão para stderr, ou o fluxo se corrompe e a sessão morre.
Streamable HTTP para os remotos
Streamable HTTP: one URL, many clients
┌──────────┐ POST /mcp ┌────────────┐
│ Client A │ ───────────────────► │ │
└──────────┘ ◄─────────────────── │ Server │
┌──────────┐ JSON or SSE reply │ (web app) │
│ Client B │ ───────────────────► │ │
└──────────┘ ◄─────────────────── └────────────┘
Streamable HTTP atende muitos clientes a partir de um único endpoint. O cliente envia cada mensagem como um POST HTTP, e o servidor responde com JSON simples ou abre um stream de Server-Sent Events quando precisa enviar várias mensagens. Um identificador de sessão viaja no cabeçalho Mcp-Session-Id. Esse transporte substituiu o antigo design HTTP mais SSE na revisão 2025-03-26 da especificação, e é a escolha certa para servidores hospedados, produtos multiusuário e qualquer coisa atrás de um balanceador de carga. A autorização é construída sobre OAuth, então um servidor pode responder 401 e apontar o cliente para o seu servidor de autorização. Servidores que ainda rodam o design anterior podem continuar compatíveis servindo os dois endpoints durante uma migração, mas um projeto novo deve começar com Streamable HTTP.
Pergunta
stdio
Streamable HTTP
Onde o servidor roda?
Na mesma máquina do host
Em qualquer lugar acessível por URL
Usuários por servidor
Um
Muitos
Credenciais
Variáveis de ambiente
OAuth ou cabeçalhos HTTP
Ideal para
Ferramentas de desenvolvedor, arquivos locais
Produtos hospedados, serviços compartilhados
Principal armadilha
Saída indesejada na stdout
Gerenciamento de sessão atrás de proxies
Uma divisão prática: distribua um build stdio para os desenvolvedores que querem testar o servidor em um minuto, e um build Streamable HTTP para todo o resto. O código das ferramentas permanece o mesmo. Só muda o ponto de entrada.
Uma chamada de ferramenta, passo a passo
Eis uma única requisição desde o momento em que o usuário digita até o momento em que a resposta aparece.
User Host + LLM MCP client MCP server
│ │ │ │
├─ asks for image ───► │ │
│ │ picks a tool │ │
│ ├─ tool request ────► │
│ │ ├─ tools/call ──────►
│ │ │ │ does the work
│ │ ◄─ text, isError ───┤
│ ◄─ result ──────────┤ │
◄─ answer + URL ─────┤ │ │
│ │ │ │
Passo 1: o handshake
Toda sessão começa com initialize. O cliente envia a versão do protocolo que suporta, junto com suas próprias capacidades. O servidor responde com a versão que escolheu e as capacidades que oferece. Em seguida, o cliente envia uma mensagem notifications/initialized e o tráfego normal começa. Se as versões não puderem ser conciliadas, o cliente se desconecta em vez de adivinhar.
O cliente envia tools/list, o host entrega os schemas ao modelo, e o modelo decide se chama alguma delas. Quando a lista de ferramentas de um servidor muda em tempo de execução, ele envia notifications/tools/list_changed para que o cliente atualize. Uma chamada fica assim:
O MCP separa dois tipos de falha. Um erro de protocolo é um objeto de erro JSON-RPC, por exemplo o código -32602 para parâmetros inválidos ou um nome de ferramenta desconhecido. Um erro de execução da ferramenta é um resultado normal com isError: true e uma mensagem que o modelo consegue ler. O segundo tipo é o que mais importa. Quando uma ferramenta responde prompt too long, o modelo pode encurtar o prompt e tentar de novo, mas só se o erro chegar a ele como texto, e não como uma sessão derrubada. Qualquer um dos lados também pode enviar notifications/cancelled para abandonar uma requisição lenta.
Execute o servidor no MCP Inspector (npx @modelcontextprotocol/inspector) antes que qualquer modelo o use. O Inspector lista as ferramentas, permite disparar chamadas manualmente e mostra o tráfego JSON-RPC bruto, para que você consiga separar bugs de protocolo de bugs de prompt.
3 erros comuns de design
A maior parte dos problemas em produção remonta às mesmas três escolhas:
Uma ferramenta gigante. Uma ferramenta chamada do_anything com um argumento de texto livre obriga o modelo a adivinhar. Divida-a em verbos restritos, como search_orders e refund_order, cada um com argumentos tipados.
Resultados prolixos. Devolver um bloco de 40.000 tokens consome a janela de contexto do modelo. Devolva os campos de que o modelo precisa e ofereça um link para um recurso com o restante.
Estado oculto. Se uma ferramenta só funciona depois que outra já foi executada, diga isso na descrição, ou o modelo as chamará na ordem errada.
Um servidor real: ferramentas de imagem e vídeo
Um caso concreto mostra por que as escolhas de arquitetura importam. O PicassoIA oferece um conector MCP cujas ferramentas geram e editam imagens e vídeos em suas próprias GPUs. Trabalhos de imagem e vídeo levam de segundos a minutos, o que quebra a visão ingênua de chamar uma ferramenta, esperar pela resposta. Hosts e SDKs costumam impor um tempo limite de requisição, então um servidor que bloqueia até a renderização terminar falharia justamente quando o trabalho está quase pronto.
Jobs assíncronos por trás de uma ferramenta simples
O conector expõe ferramentas chamadas generate_image, edit_image, generate_video_picassoia, generate_video_seedance, get_generation, cancel_generation, list_models, list_generations e get_account. Uma chamada de geração devolve de imediato um ID de predição e um tempo estimado. Depois disso, o modelo chama get_generation após a espera sugerida, e de novo a cada nova dica, até que o status indique succeeded ou failed. A chamada da ferramenta continua curta enquanto o trabalho pesado roda como job em segundo plano, em um worker de GPU.
Um servidor que fica na frente de uma fila de GPU precisa protegê-la. O PicassoIA informa um teto de cinco predições simultâneas por conta, compartilhado entre credenciais de API e conexões MCP. Um servidor bem construído transforma um teto assim em um resultado de ferramenta claro, como cinco jobs em execução, tente de novo em 30 segundos, em vez de deixar as requisições se acumularem atrás dele. O modelo consegue ler essa mensagem e esperar, o que é muito melhor do que um timeout.
Quatro hábitos tornam um servidor assíncrono agradável de usar a partir de um agente:
Responda rápido. Devolva um ID em menos de um segundo e nunca bloqueie por minutos.
Sugira a espera. Diga ao modelo quando consultar de novo, para que ele não sobrecarregue a ferramenta de status.
Torne a falha definitiva. Um job que falhou continua com falha, e a mensagem diz por quê.
Ofereça uma ferramenta de cancelamento. Usuários mudam de ideia, e trabalho na fila custa dinheiro.
Onde a segurança entra
O MCP move capacidade, e por isso também move risco. O protocolo define o formato da conversa, mas o host e o servidor carregam a responsabilidade. Seis verificações pegam a maioria dos problemas antes do lançamento:
Consentimento do usuário. O host deve mostrar qual ferramenta está prestes a rodar e perguntar antes de qualquer ação com efeitos colaterais.
Privilégio mínimo. Dê a uma ferramenta somente de leitura uma credencial somente de leitura e mantenha as ações poderosas em um servidor separado.
Validação de entrada. Trate todo argumento como não confiável. Valide também no servidor, de acordo com o schema, e não apenas no cliente.
Prompt injection. O texto dentro do resultado de uma ferramenta ou de um recurso pode conter instruções. O host deve tratá-lo como dado, nunca como um comando do usuário.
Tratamento de segredos. Nunca coloque credenciais em descrições ou resultados de ferramentas. Servidores stdio as leem do ambiente, e servidores HTTP usam OAuth.
Logs de auditoria. Grave logs estruturados com um ID de requisição no stderr ou em um serviço de logs, para que cada chamada de ferramenta possa ser rastreada depois.
A implantação segue a mesma lógica. Fixe a versão do protocolo nos seus testes, rode o servidor no Inspector no CI e coloque os servidores remotos atrás de um gateway que cuide de TLS, limites de taxa e OAuth, para que o código das ferramentas fique focado nas ferramentas.
Experimente você mesmo a geração de imagens e vídeos
Os diagramas ficam mais fáceis de lembrar quando você pode ver uma chamada de ferramenta gerar algo real. Abra o PicassoIA, escreva um prompt para uma foto da sua mesa, de uma sala de servidores ou de um esboço em quadro branco, e gere a imagem com o Seedream 4.5 ou o GPT Image 2. Depois, anime seu quadro favorito com o Veo 3.1 ou o Kling v3 Video. Se seu host suportar conexões MCP, adicione o conector do PicassoIA e deixe seu assistente executar o job enquanto você acompanha as etapas de consulta do diagrama acima.
Teste três prompts e mude uma coisa de cada vez: o ângulo da câmera, a direção da luz ou a lente. As diferenças mostram o quanto um prompt preciso importa, da mesma forma que uma descrição de ferramenta precisa importa para um modelo. Explore todos os modelos disponíveis em picassoia.com/en/all-models e comece sua primeira geração hoje mesmo.