MCP (Model Context Protocol): como conectar LLMs a ferramentas externas

1. Introdução ao MCP e o Problema da Integração de LLMs

Modelos de linguagem de grande escala (LLMs) como GPT-4, Claude e LLaMA são extraordinariamente capazes em tarefas de raciocínio e geração de texto, mas operam como "ilhas de conhecimento" — seu treinamento é congelado em um ponto no tempo, sem acesso a dados dinâmicos, bancos de dados, APIs ou sistemas corporativos. Esse gargalo limita severamente aplicações práticas que exigem informações atualizadas ou ações no mundo real.

O Model Context Protocol (MCP), proposto inicialmente pela Anthropic em 2024, surge como uma solução padronizada para esse problema. Diferente de abordagens proprietárias como plugins OpenAI ou function calling específico de cada fornecedor, o MCP define um protocolo aberto para que LLMs possam descobrir, invocar e receber resultados de ferramentas externas de forma estruturada e segura.

2. Arquitetura Fundamental do MCP

A arquitetura MCP é composta por três elementos principais:

  • Cliente MCP: O próprio LLM ou o framework que o envolve (ex: agente LangChain, aplicação customizada)
  • Servidor MCP: Um serviço que expõe ferramentas, bancos de dados ou pipelines de processamento
  • Transporte e Contexto: O canal de comunicação e o formato padronizado das mensagens

O ciclo de vida de uma requisição MCP segue três etapas:

  1. Descoberta: O cliente solicita ao servidor a lista de ferramentas disponíveis com seus esquemas
  2. Invocação: O cliente chama uma ferramenta específica com parâmetros definidos
  3. Retorno de Contexto: O servidor retorna o resultado, que é injetado no contexto do LLM

Quanto aos modelos de transporte, o MCP suporta HTTP com Server-Sent Events (SSE) para comunicação unidirecional, WebSocket para comunicação bidirecional em tempo real, e mensageria customizada para ambientes de alta performance.

3. Implementando um Servidor MCP Básico

Vamos construir um servidor MCP simples em Python usando o SDK oficial. Primeiro, instale a biblioteca:

pip install mcp

A estrutura mínima de um servidor MCP:

from mcp.server import Server
from mcp.types import Tool, TextContent
import psycopg2

# Configuração do servidor
server = Server("postgres-consultor")

# Registro de ferramenta
@server.tool()
async def consultar_cliente(cpf: str) -> str:
    """
    Consulta dados de cliente por CPF no banco PostgreSQL.

    Args:
        cpf: CPF do cliente sem pontuação (11 dígitos)

    Returns:
        Dados do cliente em formato texto
    """
    conn = psycopg2.connect(
        host="localhost",
        dbname="clientes",
        user="admin",
        password="secret"
    )
    cursor = conn.cursor()
    cursor.execute("SELECT nome, email, saldo FROM clientes WHERE cpf = %s", (cpf,))
    resultado = cursor.fetchone()
    conn.close()

    if resultado:
        return f"Nome: {resultado[0]}, Email: {resultado[1]}, Saldo: R${resultado[2]:.2f}"
    return "Cliente não encontrado"

# Inicialização
if __name__ == "__main__":
    server.run(host="0.0.0.0", port=8000)

4. Conectando o LLM ao Servidor MCP

Para conectar um LLM ao servidor MCP, usamos o cliente MCP. Exemplo com LangChain:

from langchain_mcp import MCPClient
from langchain.chat_models import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_functions_agent

# Configuração do cliente MCP
mcp_client = MCPClient(
    server_url="http://localhost:8000",
    transport="sse"
)

# Descoberta de ferramentas
tools = await mcp_client.discover_tools()

# Configuração do LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)

# Criação do agente
agent = create_openai_functions_agent(llm, tools)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Exemplo de uso
resposta = agent_executor.invoke({
    "input": "Qual o saldo do cliente com CPF 12345678901?"
})
print(resposta["output"])

O handshake entre cliente e servidor ocorre automaticamente: o cliente solicita a lista de ferramentas, negocia capacidades (versão do protocolo, formatos suportados) e estabelece o canal de comunicação.

5. Padrões Avançados de Uso com MCP

Encadeamento de servidores: É possível orquestrar múltiplos servidores MCP para tarefas complexas:

from langchain_mcp import MCPOrchestrator

orquestrador = MCPOrchestrator()
orquestrador.add_server("postgres", "http://localhost:8000")
orquestrador.add_server("api-clima", "http://localhost:8001")
orquestrador.add_server("calculadora", "http://localhost:8002")

# O orquestrador decide qual servidor chamar baseado na intenção do usuário
resultado = await orquestrador.process("Calcule o frete para SP considerando o clima atual")

Tratamento de erros: Implemente timeouts e retentativas:

@server.tool(timeout=10, retries=3)
async def consultar_api_externa(parametro: str) -> str:
    try:
        # Lógica da ferramenta
        pass
    except TimeoutError:
        return "ERRO: Tempo limite excedido. Tente novamente."
    except Exception as e:
        return f"ERRO: {str(e)}"

Versionamento de esquemas: Use headers de versão para evoluir ferramentas sem quebrar clientes antigos.

6. Segurança e Governança no Ecossistema MCP

A segurança no MCP é implementada em múltiplas camadas:

  • Autenticação: Tokens JWT ou chaves de API entre cliente e servidor
  • Autorização: Controle de acesso baseado em contexto (ex: usuário só pode consultar seus próprios dados)
  • Contexto seletivo: O servidor pode filtrar dados sensíveis antes de retornar ao LLM

Exemplo de middleware de segurança:

from mcp.security import require_auth, rate_limit

@server.tool()
@require_auth(roles=["admin", "consultor"])
@rate_limit(max_requests=100, window_seconds=60)
async def consultar_relatorio_financeiro(mes: int, ano: int) -> str:
    # Lógica segura
    pass

Para auditoria, registre todas as chamadas MCP:

import logging
logging.basicConfig(filename='mcp_audit.log', level=logging.INFO)

@server.tool()
async def ferramenta_auditada(param: str) -> str:
    logging.info(f"Chamada: {param} | Usuário: {context.user_id}")
    resultado = await executar_ferramenta(param)
    logging.info(f"Resultado: {resultado[:100]}...")
    return resultado

7. MCP vs. Alternativas: Quando Adotar o Protocolo

Aspecto MCP RAG (Retrieval-Augmented Generation) Function Calling Nativo
Foco Ações e dados dinâmicos Consulta a bases de conhecimento estáticas Chamadas de função específicas do modelo
Portabilidade Alta (funciona com qualquer LLM que implemente o protocolo) Média (depende do pipeline de embeddings) Baixa (específico de cada fornecedor)
Performance Média (overhead do protocolo) Alta (busca vetorial otimizada) Alta (nativo do modelo)
Casos de uso Sistemas multi-ferramenta, agentes autônomos Chatbots com base de conhecimento Aplicações simples mono-fornecedor

Quando adotar MCP: Para sistemas que precisam integrar múltiplas ferramentas de diferentes provedores, especialmente em arquiteturas multi-modelo ou agentes autônomos que exigem descoberta dinâmica de capacidades.

8. Roadmap e Futuro do MCP

A adoção do MCP está crescendo rapidamente. Provedores como Anthropic (Claude), OpenAI (em fase experimental) e comunidades open-source já oferecem suporte nativo ao protocolo. Tendências incluem:

  • Agentes autônomos: MCP como padrão de facto para comunicação entre agentes e ferramentas
  • Sistemas multi-agente: Orquestração de múltiplos LLMs com diferentes especializações
  • Padronização de transportes: Evolução para QUIC e HTTP/3 para reduzir latência

Limitações atuais incluem latência em chamadas síncronas e desafios de escalabilidade em ambientes com milhares de servidores MCP. A comunidade trabalha em especificações para caching inteligente e roteamento otimizado.

Referências