MCP: Como Padronizar a Integração Entre LLMs e Ferramentas Externas
A Anthropic lançou o Model Context Protocol (MCP) em novembro de 2024 para resolver um problema que qualquer equipe integrando LLMs em sistemas reais já enfrentou: cada aplicação AI precisa reinventar como se conecta a bancos de dados, filesystems, APIs e ferramentas internas. O resultado? Código de integração fragmentado, difícil de manter e impossível de reutilizar entre projetos.
MCP propõe uma camada de protocolo aberta entre aplicações AI (clientes) e recursos externos (servidores). A promessa é direta: escreva um servidor MCP uma vez e qualquer cliente compatível pode usá-lo. O Claude Desktop já suporta nativamente, e empresas como Block (de Jack Dorsey) e o editor Zed anunciaram integração. Mas o protocolo está em versão 0.1.x dos SDKs — estamos nos estágios iniciais, com possíveis breaking changes à frente.
Este artigo explora a arquitetura do MCP, como implementar servidores customizados e o que considerar antes de adotar o protocolo em produção.
Arquitetura Cliente-Servidor e as Três Primitivas
MCP implementa uma arquitetura cliente-servidor onde aplicações AI atuam como clientes que se conectam a servidores MCP. Essa separação é deliberada: o servidor não precisa conhecer detalhes do LLM ou do cliente, e o cliente não precisa reimplementar lógica de acesso a dados. A comunicação acontece via JSON-RPC 2.0, um protocolo maduro de troca de mensagens estruturadas.
O protocolo define três primitivas fundamentais:
Resources representam dados acessíveis. Um servidor pode expor arquivos, registros de banco de dados ou conteúdo de APIs externas como resources. O cliente lista e lê esses recursos quando necessário. A documentação oficial menciona um limite soft de ~10MB por recurso (embora não seja um hard limit documentado formalmente).
Prompts são templates reutilizáveis de interação. Ao invés de cada aplicação manter seus próprios prompts para tarefas comuns, um servidor MCP oferece prompts padronizados que clientes podem invocar. Isso centraliza conhecimento de domínio no servidor.
Tools são funções executáveis que o LLM pode chamar. Aqui está o coração da integração: você define tools com JSON Schema especificando nome, descrição e parâmetros de entrada. O LLM decide quando e como chamar essas funções durante a execução.
Por que JSON-RPC 2.0? O protocolo oferece error handling padronizado com códigos como InvalidParams e InternalError, request/response IDs para correlação e suporte a notificações assíncronas. Para operações longas, MCP suporta progress tokens que permitem enviar progress notifications durante execução.
Implementando um Servidor MCP com TypeScript
A implementação usa o SDK oficial @modelcontextprotocol/sdk disponível via npm. Vou demonstrar um servidor básico que expõe uma tool para executar operações em filesystem:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import fs from "fs/promises";
const server = new Server(
{
name: "filesystem-server",
version: "0.1.0",
},
{
capabilities: {
tools: {},
},
}
);
server.setRequestHandler("tools/list", async () => {
return {
tools: [
{
name: "read_file",
description: "Read contents of a text file",
inputSchema: {
type: "object",
properties: {
path: {
type: "string",
description: "Path to the file to read",
},
},
required: ["path"],
},
},
],
};
});
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name !== "read_file") {
throw new Error(`Unknown tool: ${request.params.name}`);
}
const path = request.params.arguments?.path;
const content = await fs.readFile(path, "utf-8");
return {
content: [
{
type: "text",
text: content,
},
],
};
});
const transport = new StdioServerTransport();
await server.connect(transport);
O servidor define duas handlers essenciais: tools/list retorna metadados das tools disponíveis, e tools/call executa a tool solicitada. O JSON Schema em inputSchema é crucial — o LLM usa essa descrição para entender quando e como chamar a tool.
A escolha do transporte stdio significa que o servidor roda como processo separado comunicando via standard input/output. Isso simplifica deployment local mas adiciona overhead de serialização comparado a chamadas in-process. A especificação lista HTTP com Server-Sent Events (SSE) como transporte planejado para cenários remotos, mas ainda não está implementado nos SDKs oficiais.
Fluxo de Execução e Integração com Claude Desktop
O fluxo de execução de uma tool call segue este ciclo:
- Cliente envia
tools/listao servidor e recebe metadados das tools disponíveis - Cliente envia contexto da conversa ao LLM incluindo definições das tools
- LLM decide chamar uma tool e retorna nome + argumentos estruturados
- Cliente envia
tools/callao servidor com nome da tool e argumentos - Servidor executa a função e retorna resultado como content array
- Cliente injeta resultado no contexto e continua a conversa com o LLM
Os resultados retornam como arrays de content com tipos text ou image/resource. Essa estrutura permite respostas multimodais: uma tool pode retornar texto explicativo junto com uma imagem gerada.
Para integrar com Claude Desktop, você configura servidores MCP editando claude_desktop_config.json:
{
"mcpServers": {
"filesystem": {
"command": "node",
"args": ["/path/to/filesystem-server/build/index.js"],
"env": {
"ALLOWED_DIRECTORIES": "/Users/username/documents"
}
}
}
}
Essa abordagem declarativa separa configuração de deployment. Você pode ter servidores diferentes para ambientes de desenvolvimento e produção alterando apenas o arquivo de configuração, sem mudanças no código do servidor.
Uma limitação importante: hot-reload não é suportado nativamente. Mudanças no servidor exigem restart completo do cliente, o que adiciona fricção durante desenvolvimento iterativo.
Considerações Práticas de Adoção
MCP está em estágio inicial de desenvolvimento. A versão 0.1.x dos SDKs segue versionamento semântico, o que significa breaking changes possíveis antes da estabilização na versão 1.0. Se você está considerando uso em produção, precisa estar preparado para refatoração quando o protocolo evoluir.
A documentação oficial não especifica limites técnicos críticos: número máximo de tools por servidor, tamanho máximo de payloads ou timeouts padrão. Benchmarks públicos de performance também não estão disponíveis — você não tem dados de latência média de tool calls ou overhead de serialização JSON-RPC para comparar com alternativas como OpenAI Function Calling ou LangChain Tools.
O protocolo é stateless por design, com state gerenciado pelo cliente. Isso simplifica implementação de servidores mas transfere complexidade para o cliente quando você precisa manter contexto entre chamadas. Se sua aplicação precisa de memória conversacional ou state management sofisticado, você vai implementar isso fora do MCP.
Casos de produção públicos ainda são escassos em janeiro de 2025. Block anunciou adoção para integrar sistemas internos com AI assistants, mas métricas como tempo de implementação, ganhos de produtividade ou custos operacionais não foram divulgados. O repositório oficial tinha aproximadamente 10 servidores no lançamento, comparado a 100+ integrações pré-construídas do LangChain.
Streaming de respostas de tools não é suportado nativamente e está listado como planned feature. Se você precisa enviar resultados progressivos durante execução de uma tool longa, a alternativa atual é usar progress notifications — mas o resultado final ainda precisa ser enviado de uma vez.
Quando MCP Faz Sentido
MCP resolve um problema específico: padronizar como LLMs acessam recursos externos em ambientes onde múltiplas aplicações AI precisam compartilhar as mesmas integrações. Se você está construindo uma plataforma interna com vários agentes AI acessando os mesmos bancos de dados e APIs, o overhead de implementar servidores MCP pode se pagar na reutilização.
O protocolo também oferece vantagem em isolamento de responsabilidades. Equipes que gerenciam dados não precisam entender detalhes de implementação de LLMs. Elas expõem servidores MCP e aplicações AI consomem esses servidores sem acoplamento direto.
Mas se você está construindo uma aplicação standalone sem necessidade de compartilhar integrações, o overhead de arquitetura cliente-servidor pode não se justificar. Chamadas in-process são mais rápidas e simples de debugar. Frameworks como LangChain oferecem abstrações similares de tools sem adicionar camada de rede.
A decisão de adotar MCP agora versus esperar maturação do protocolo depende do seu apetite para trabalhar com especificações em evolução. A Anthropic criou uma especificação aberta e está ativamente desenvolvendo SDKs, mas você está apostando em direção futura ao invés de standard estabelecido.