Model Context Protocol (MCP): Guia Completo para Construir Agentes de IA que Realmente Funcionam
Se você está construindo aplicações de IA em 2025, provavelmente bateu no mesmo muro que todo mundo: seu LLM é incrível gerando texto, mas quando tenta conectar com banco de dados real ou APIs, acaba juntando tudo com gambiarra e rezando pro prompt funcionar.
É aí que entra o Model Context Protocol (MCP)—um padrão aberto que está ficando tão fundamental pra desenvolvimento de IA quanto REST é pra desenvolvimento web. Criado pela Anthropic e agora adotado pela indústria toda, o MCP resolve a maior dor de cabeça da engenharia de IA: como dar pro seu agente acesso seguro e estruturado ao mundo exterior?
Neste guia a gente cobre o que é MCP, por que importa, como funciona e o mais importante—como implementar.
O Problema que o MCP Resolve
Antes de entrar no MCP, vamos ver que dor ele resolve.
O Inferno das Integrações
Desenvolvimento tradicional de apps de IA é mais ou menos assim:
┌─────────────────────────────────────────────────────────────┐
│ Sua Aplicação de IA │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ OpenAI │ │ Database │ │ Slack │ │
│ │ API │ │ Queries │ │ API │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ Parser Custom Parser Custom Parser Custom │
│ │ │ │ │
│ Gambiarra Gambiarra Gambiarra │
│ │ │ │ │
│ Error Handler Error Handler Error Handler │
│ │ │ │ │
│ └───────────────┴───────────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ Código Espaguete│ │
│ │ de Orquestração │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────┘
O que você precisa pra cada integração:
- Tratamento de autenticação customizado
- Parsing de resposta específico
- Prompt engineering pra explicar a ferramenta pro LLM
- Tratamento de erro diferente por integração
- Manutenção manual de schemas
Se um agente típico precisa de 10+ integrações, você tem um pesadelo de manutenção.
A Limitação do Function Calling
O function calling da OpenAI ajuda, mas é específico do vendor. Suas definições feitas com carinho pro GPT-4 não funcionam com Claude, Gemini ou o último modelo open source.
// Isso funciona pra OpenAI... const tools = [{ type: "function", function: { name: "get_weather", description: "Pegar clima atual", parameters: { type: "object", properties: { location: { type: "string" } } } } }]; // Mas Claude tem outro formato... // E Gemini outro... // E Llama outro...
O Que a Gente Precisa de Verdade
A solução ideal seria:
- Universal: Funciona independente do provedor de LLM
- Padronizado: Um padrão de integração pra qualquer fonte de dados
- Bidirecional: A IA pode consultar dados e receber atualizações
- Seguro: Autenticação e permissões integrados
- Descobrível: A IA aprende que ferramentas existem em runtime
O MCP oferece exatamente isso.
O Que é Model Context Protocol?
MCP é um protocolo aberto que padroniza como aplicações de IA se conectam a fontes de dados e ferramentas externas. Pensa nele como "USB pra IA"—um conector universal pra qualquer modelo se conectar a qualquer dado.
Arquitetura
MCP usa arquitetura cliente-servidor:
┌────────────────────────────────────────────────────────────────┐
│ Arquitetura MCP │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────────────────┐ │
│ │ MCP Client │ │ MCP Servers │ │
│ │ │ │ │ │
│ │ ┌───────────┐ │ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │ AI Model │ │ JSON-RPC│ │ GitHub │ │ Slack │ │ │
│ │ │(GPT/Claude│◄─┼─────────┼─►│ Server │ │ Server │ │ │
│ │ │ /Gemini) │ │ over │ └─────────┘ └─────────┘ │ │
│ │ └───────────┘ │ stdio/ │ │ │
│ │ │ SSE/WS │ ┌─────────┐ ┌─────────┐ │ │
│ │ ┌───────────┐ │ │ │Database │ │ Custom │ │ │
│ │ │Host App │ │ │ │ Server │ │ Server │ │ │
│ │ │(Seu App) │ │ │ └─────────┘ └─────────┘ │ │
│ │ └───────────┘ │ │ │ │
│ └─────────────────┘ └─────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
Componentes Core:
- MCP Client: Vive no seu app de IA. Descobre e conecta a servidores MCP.
- MCP Server: Expõe dados e ferramentas em formato padrão.
- Transport Layer: JSON-RPC 2.0 sobre stdio, SSE ou WebSockets.
Os Três Primitivos
MCP define três elementos core que cobrem quase toda interação IA-mundo exterior:
1. Resources
Dados estáticos ou dinâmicos que a IA pode ler. Pensa neles como "arquivos" acessíveis.
{ "uri": "file:///project/README.md", "name": "Project README", "mimeType": "text/markdown" }
2. Tools
Funções que a IA pode invocar pra realizar ações.
{ "name": "create_github_issue", "description": "Criar nova issue em repo do GitHub", "inputSchema": { "type": "object", "properties": { "repo": { "type": "string" }, "title": { "type": "string" }, "body": { "type": "string" } }, "required": ["repo", "title"] } }
3. Prompts
Templates de prompts reutilizáveis com parâmetros.
{ "name": "code_review", "description": "Review de código pra melhores práticas", "arguments": [ { "name": "code", "description": "O código pra revisar", "required": true } ] }
Por Que MCP Importa Agora
A Explosão de Agentes de IA
2025 é o ano dos agentes de IA. Do Operator da OpenAI às capacidades de computador do Claude, a IA tá saindo do chat pra ação autônoma. Mas tem um segredo sujo: IA autônoma só é tão boa quanto seu acesso ao mundo real.
Um agente de IA que não consegue de forma confiável:
- Ler sua codebase
- Consultar seu banco de dados
- Checar seu calendário
- Mandar mensagem pro time
...é só um chatbot muito caro.
MCP torna essas integrações confiáveis, consistentes e mantíveis.
O Momento da Padronização
Estamos num ponto de inflexão similar aos serviços web dos anos 2000. Naquela época CORBA, DCOM e protocolos proprietários competiam. REST venceu e de repente todo mundo podia fazer serviços interoperáveis.
MCP quer ser o REST das integrações de IA. Os players principais já tão dentro:
- Anthropic: Criou e mantém o protocolo
- Microsoft: Integrando no Copilot
- Cursor: Suporte nativo MCP na IDE
- Sourcegraph: Servidores MCP pra inteligência de código
Rodar um Servidor MCP é o Novo Servidor Web
Previsão ousada: até 2026, "Você sabe rodar um servidor MCP?" vai ser tão comum em entrevistas quanto "Você sabe fazer uma API REST?".
Por quê? Toda empresa com dados valiosos vai querer expor eles pra agentes de IA de forma controlada. Isso significa servidores MCP pra:
- Documentação interna
- Dados de clientes (com autorização)
- Processos de negócio
- Ferramentas de domínio
Construindo Seu Primeiro Servidor MCP
Mão na massa. Vamos construir um servidor MCP que expõe uma API de lista de tarefas.
Setup do Projeto
# Novo projeto mkdir mcp-todo-server cd mcp-todo-server npm init -y # Dependências npm install @modelcontextprotocol/sdk zod npm install -D typescript @types/node tsx
Estrutura Básica do Servidor
Crie src/index.ts:
import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; // Storage em memória interface Todo { id: string; title: string; completed: boolean; createdAt: Date; } const todos: Map<string, Todo> = new Map(); // Criar servidor MCP const server = new Server( { name: "todo-server", version: "1.0.0", }, { capabilities: { tools: {}, resources: {}, }, } ); // Lista de ferramentas disponíveis server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "create_todo", description: "Criar novo item de tarefa", inputSchema: { type: "object", properties: { title: { type: "string", description: "Título do item", }, }, required: ["title"], }, }, { name: "complete_todo", description: "Marcar tarefa como concluída", inputSchema: { type: "object", properties: { id: { type: "string", description: "ID da tarefa pra concluir", }, }, required: ["id"], }, }, { name: "delete_todo", description: "Deletar tarefa", inputSchema: { type: "object", properties: { id: { type: "string", description: "ID da tarefa pra deletar", }, }, required: ["id"], }, }, ], }; }); // Tratar chamadas de ferramentas server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; switch (name) { case "create_todo": { const id = crypto.randomUUID(); const todo: Todo = { id, title: args.title as string, completed: false, createdAt: new Date(), }; todos.set(id, todo); return { content: [ { type: "text", text: JSON.stringify({ success: true, todo }, null, 2), }, ], }; } case "complete_todo": { const todo = todos.get(args.id as string); if (!todo) { return { content: [ { type: "text", text: JSON.stringify({ error: "Tarefa não encontrada" }) }, ], isError: true, }; } todo.completed = true; return { content: [ { type: "text", text: JSON.stringify({ success: true, todo }, null, 2), }, ], }; } case "delete_todo": { const deleted = todos.delete(args.id as string); return { content: [ { type: "text", text: JSON.stringify({ success: deleted }, null, 2), }, ], }; } default: return { content: [ { type: "text", text: JSON.stringify({ error: "Ferramenta desconhecida" }) }, ], isError: true, }; } }); // Lista de recursos disponíveis server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: [ { uri: "todo://list", name: "Lista de Tarefas", description: "Lista atual de todos os itens", mimeType: "application/json", }, ], }; }); // Ler recursos server.setRequestHandler(ReadResourceRequestSchema, async (request) => { if (request.params.uri === "todo://list") { const todoList = Array.from(todos.values()); return { contents: [ { uri: "todo://list", mimeType: "application/json", text: JSON.stringify(todoList, null, 2), }, ], }; } throw new Error(`Recurso desconhecido: ${request.params.uri}`); }); // Iniciar servidor async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Servidor Todo MCP rodando em stdio"); } main().catch(console.error);
Configuração pro Claude Desktop
Pra usar com Claude Desktop, adicione no claude_desktop_config.json:
{ "mcpServers": { "todo": { "command": "npx", "args": ["tsx", "/path/to/mcp-todo-server/src/index.ts"] } } }
Agora o Claude pode:
- Criar tarefas: "Adiciona uma tarefa pra fazer compras"
- Completar tarefas: "Marca a tarefa de compras como feita"
- Ver tarefas: "O que tem na minha lista de tarefas?"
Padrões Avançados de MCP
Padrão 1: Integração com Banco de Dados
Uma das aplicações mais poderosas é dar à IA acesso de leitura (às vezes escrita) ao seu DB:
import { Pool } from 'pg'; const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "query_database") { const { query } = request.params.arguments as { query: string }; // IMPORTANTE: Validar e sanitizar query if (!isReadOnlyQuery(query)) { return { content: [{ type: "text", text: "Só queries SELECT são permitidas" }], isError: true, }; } try { const result = await pool.query(query); return { content: [{ type: "text", text: JSON.stringify(result.rows, null, 2), }], }; } catch (error) { return { content: [{ type: "text", text: `Erro na query: ${error.message}` }], isError: true, }; } } }); function isReadOnlyQuery(query: string): boolean { const normalized = query.trim().toLowerCase(); return normalized.startsWith('select') && !normalized.includes('into') && !normalized.includes('update') && !normalized.includes('delete') && !normalized.includes('insert') && !normalized.includes('drop') && !normalized.includes('alter'); }
Padrão 2: Integração OAuth
Pra APIs que precisam de autenticação de usuário:
import { OAuth2Client } from 'google-auth-library'; const oauth2Client = new OAuth2Client( process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET, 'http://localhost:3000/callback' ); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "list_calendar_events", description: "Listar próximos eventos do calendário", inputSchema: { type: "object", properties: { maxResults: { type: "number", description: "Máximo de eventos pra retornar", default: 10, }, }, }, }, ], }; });
Padrão 3: Operações Longas com Progresso
Pra operações que demoram, MCP suporta notificações de progresso:
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => { if (request.params.name === "analyze_codebase") { const files = await getAllFiles(request.params.arguments.path); const total = files.length; for (let i = 0; i < files.length; i++) { // Enviar atualização de progresso await extra.sendNotification({ method: "notifications/progress", params: { progressToken: request.params._meta?.progressToken, progress: i, total, }, }); await analyzeFile(files[i]); } return { content: [{ type: "text", text: `${total} arquivos analisados`, }], }; } });
Melhores Práticas de Segurança MCP
1. Validar Todas as Entradas
Nunca confie em dados da IA. Sempre valide:
import { z } from 'zod'; const CreateTodoSchema = z.object({ title: z.string().min(1).max(200), priority: z.enum(['low', 'medium', 'high']).optional(), }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "create_todo") { const parsed = CreateTodoSchema.safeParse(request.params.arguments); if (!parsed.success) { return { content: [{ type: "text", text: `Erro de validação: ${parsed.error.message}`, }], isError: true, }; } // parsed.data agora é type-safe e validado } });
2. Implementar Rate Limiting
Proteja de agentes de IA descontrolados:
import { RateLimiter } from 'limiter'; const limiter = new RateLimiter({ tokensPerInterval: 100, interval: 'minute', }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (!await limiter.tryRemoveTokens(1)) { return { content: [{ type: "text", text: "Limite de rate excedido. Tenta depois.", }], isError: true, }; } // Processar request... });
3. Log de Auditoria
Logue todas as invocações pra segurança e debug:
function logToolInvocation(name: string, args: unknown, result: unknown) { console.log(JSON.stringify({ timestamp: new Date().toISOString(), tool: name, arguments: args, result: result, })); }
4. Princípio do Menor Privilégio
Só exponha o necessário:
// RUIM: Expor acesso raw ao DB tools: [{ name: "execute_sql", description: "Executar qualquer query SQL", // Pesadelo de segurança! }] // BOM: Expor operações específicas tools: [ { name: "get_user_orders", description: "Pegar pedidos de usuário específico", inputSchema: { type: "object", properties: { userId: { type: "string" }, limit: { type: "number", maximum: 100 }, }, required: ["userId"], }, }, ]
MCP em Produção: Lições Aprendidas
Lição 1: Projete pra Falha
Agentes de IA chamam ferramentas de formas inesperadas. Construa defensivamente:
server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const result = await handleTool(request); return result; } catch (error) { // Retorna erro estruturado pra IA se recuperar return { content: [{ type: "text", text: JSON.stringify({ error: error.message, suggestion: "Tenta com outros parâmetros", validExamples: [ { title: "Fazer compras" }, { title: "Ligar pra mãe" }, ], }), }], isError: true, }; } });
Lição 2: Forneça Descrições Ricas
A qualidade das suas descrições impacta diretamente quão bem a IA usa as ferramentas:
// RUIM { name: "search", description: "Buscar itens", } // BOM { name: "search_products", description: `Buscar catálogo de produtos. Retorna até 20 produtos que casam. Suporta filtros de categoria, faixa de preço e disponibilidade. Resultados incluem nome, preço, status de estoque e URL da thumbnail. Pra melhores resultados usa termos específicos.`, inputSchema: { type: "object", properties: { query: { type: "string", description: "Query de busca. Ex: 'fones de ouvido sem fio'", }, }, }, }
Lição 3: Versione Seus Servidores
Mantenha compatibilidade backward quando evoluir:
const server = new Server( { name: "my-server", version: "2.1.0", // Semantic versioning }, { capabilities: { tools: {}, resources: {}, }, } ); // Suporta nomes antigos e novos durante migração server.setRequestHandler(CallToolRequestSchema, async (request) => { const name = request.params.name; // Tratar nome legado if (name === "old_tool_name") { console.warn("Deprecated: usa 'new_tool_name'"); return handleNewTool(request); } if (name === "new_tool_name") { return handleNewTool(request); } });
O Futuro do MCP
O Que Vem Por Aí
- Respostas Streaming: Suporte first-class pra outputs de ferramentas em streaming
- Ferramentas Multi-Modais: Ferramentas que retornam imagens, áudio ou vídeo
- Composição de Ferramentas: Combinar múltiplas ferramentas em workflows
- Segurança Aprimorada: Fluxos OAuth integrados e escopos de permissão
MCP vs. Alternativas
| Feature | MCP | OpenAI Functions | LangChain Tools |
|---|---|---|---|
| Vendor-agnostic | ✅ | ❌ | ✅ |
| Protocolo padrão | ✅ | ❌ | ❌ |
| Recursos integrados | ✅ | ❌ | ❌ |
| Notificações de progresso | ✅ | ❌ | Parcial |
| Servidores comunitários | Crescendo | N/A | Limitado |
Conclusão: O Momento de Aprender MCP é Agora
MCP ainda tá no começo, mas a trajetória é clara. Assim como saber REST era obrigatório pra qualquer dev web nos anos 2010, saber MCP tá ficando obrigatório pra devs de IA nos anos 2020.
Pontos chave:
- MCP = o padrão pra conectar IA com o mundo
- Começa com servidores simples — o SDK facilita
- Segurança primeiro — agentes de IA são imprevisíveis
- Descrições ricas importam — é documentação de API pra IA
- Projete pra falhas — ajuda a IA a se recuperar
Os times que dominarem MCP cedo vão ter vantagem significativa. Seus agentes vão ser mais capazes, confiáveis e mantíveis do que os que continuam juntando APIs com gambiarra.
A pergunta não é se você deveria aprender MCP—é se vai estar na frente ou correndo atrás.
Referência Rápida: Conceitos MCP
| Conceito | Descrição | Exemplo |
|---|---|---|
| Server | Expõe ferramentas e recursos | Servidor de acesso a DB |
| Client | Conecta a servidores, usado pela IA | Claude Desktop |
| Tool | Função chamável | create_github_issue |
| Resource | Dados legíveis | file:///project/README.md |
| Prompt | Template reutilizável | Template de code review |
| Transport | Camada de comunicação | stdio, SSE, WebSocket |
Recursos:
Explore ferramentas relacionadas
Experimente estas ferramentas gratuitas do Pockit