O Problema que o MCP Resolve

Todo assistente de IA — Claude, Copilot, Cursor, qualquer um — acaba batendo na mesma parede: o modelo sabe muito, mas não pode fazer nada fora da sua janela de contexto. Ele não consegue ler seu banco de dados, consultar sua API interna ou saber que horas são, a menos que alguém construa explicitamente essa ponte.

Antes do MCP, cada equipe que construía uma ferramenta baseada em IA precisava criar suas próprias integrações do zero. Quer que o Claude pesquise no seu workspace do Notion? Escreva uma integração personalizada. Quer que ele consulte seu banco Postgres? Escreva outra. Cada integração era pontual, frágil e não reutilizável.

Model Context Protocol (MCP) é a resposta da Anthropic: um padrão aberto que define uma interface única e universal entre os hosts de IA e o mundo exterior. Construa um servidor MCP uma vez e qualquer cliente compatível — Claude Desktop, Claude Code, Cursor, sua própria aplicação — poderá usá-lo imediatamente.

Pense nisso como HTTP para ferramentas de IA. O HTTP não inventou a web, mas deu a cada navegador e servidor uma linguagem comum. O MCP faz o mesmo para a IA e os serviços com os quais ela precisa interagir.


Arquitetura em Três Partes

O MCP tem três papéis:

Host — A aplicação com a qual o usuário interage. Claude Desktop, Claude Code, Cursor ou sua própria aplicação personalizada. O host contém um cliente MCP que gerencia as conexões.

Cliente — Vive dentro do host. Mantém uma conexão 1:1 com um servidor MCP, gerencia a negociação do protocolo e roteia as requisições do modelo para o servidor e as respostas de volta.

Servidor — Um processo externo (local ou remoto) que expõe capacidades ao modelo. Esta é a parte que você constrói. Um servidor pode ser tão simples quanto um único arquivo Python.

┌──────────────────────────────────┐
             Host                 
  ┌──────────┐   ┌─────────────┐  
     LLM    │◄──│ MCP Client    
  └──────────┘   └──────┬──────┘  
└─────────────────────────┼────────┘
                            MCP Protocol
              ┌───────────▼──────────┐
                    MCP Server      
                (your code / tool)  
              └──────────────────────┘

O que os Servidores Podem Expor

Um servidor MCP pode expor três tipos de capacidades:

Ferramentas

Funções que o modelo pode invocar — o tipo mais comum e útil. O modelo decide quando chamar uma ferramenta com base na conversa, recebe o resultado e o incorpora à sua resposta.

@mcp.tool()
def query_database(sql: str) -> str:
    """Executa uma consulta SQL somente leitura e retorna os resultados em JSON"""
    ...

Recursos

Dados estruturados que o modelo pode ler — arquivos, conteúdos de banco de dados, respostas de APIs. Os recursos são identificados por URIs e lidos sob demanda.

@mcp.resource("logs://app/recent")
def get_recent_logs() -> str:
    """Retorna as últimas 100 linhas do log da aplicação"""
    ...

Prompts

Templates de prompts reutilizáveis que o host pode apresentar aos usuários. Úteis para padronizar fluxos de trabalho comuns.

@mcp.prompt()
def code_review(code: str) -> str:
    return f"Revise este código em busca de bugs, problemas de segurança e estilo:\n\n{code}"

Transporte: Como Clientes e Servidores se Comunicam

O MCP suporta dois mecanismos de transporte:

stdio — O servidor roda como subprocesso do host. A comunicação ocorre via stdin/stdout. É a abordagem padrão para ferramentas locais — sem configuração de rede, simples e rápido.

HTTP + SSE — O servidor roda como serviço HTTP. O cliente envia requisições via HTTP e recebe respostas em streaming via Server-Sent Events. Usado para servidores remotos ou quando é necessário um serviço de rede persistente.

Para desenvolvimento local e ferramentas pessoais, stdio é quase sempre a escolha certa.


Construindo seu Primeiro Servidor MCP em Python

Instale o SDK:

pip install mcp

A seguir, um servidor MCP completo e funcional que expõe algumas ferramentas úteis — consultar a hora atual, ler um arquivo e fazer uma busca web básica via API do DuckDuckGo:

# server.py
from datetime import datetime
from pathlib import Path
import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("dev-tools")


@mcp.tool()
def current_datetime() -> str:
    """Retorna a data e hora atuais."""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


@mcp.tool()
def read_file(path: str) -> str:
    """
    Lê um arquivo do sistema de arquivos e retorna seu conteúdo.

    Args:
        path: Caminho absoluto ou relativo para o arquivo.
    """
    try:
        return Path(path).read_text(encoding="utf-8")
    except FileNotFoundError:
        return f"Erro: arquivo não encontrado: {path}"
    except Exception as e:
        return f"Erro ao ler o arquivo: {e}"


@mcp.tool()
def web_search(query: str, max_results: int = 5) -> str:
    """
    Busca na web usando DuckDuckGo e retorna um resumo dos resultados.

    Args:
        query: A consulta de busca.
        max_results: Número de resultados a retornar (padrão 5).
    """
    url = "https://api.duckduckgo.com/"
    params = {"q": query, "format": "json", "no_redirect": 1}
    response = httpx.get(url, params=params, timeout=10)
    data = response.json()

    results = []
    for topic in data.get("RelatedTopics", [])[:max_results]:
        if "Text" in topic and "FirstURL" in topic:
            results.append(f"- {topic['Text']}\n  {topic['FirstURL']}")

    if not results:
        return f"Nenhum resultado encontrado para: {query}"
    return "\n".join(results)


@mcp.resource("env://system")
def system_info() -> str:
    """Retorna informações básicas do sistema."""
    import platform
    return (
        f"OS: {platform.system()} {platform.release()}\n"
        f"Python: {platform.python_version()}\n"
        f"Máquina: {platform.machine()}"
    )


if __name__ == "__main__":
    mcp.run()

Execute diretamente para verificar que inicia sem erros:

python server.py

Conectar ao Claude Desktop

O Claude Desktop lê a configuração do servidor MCP de um arquivo JSON:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Adicione seu servidor:

{
  "mcpServers": {
    "dev-tools": {
      "command": "python",
      "args": ["/caminho/absoluto/para/server.py"]
    }
  }
}

Reinicie o Claude Desktop. Um pequeno ícone de tomada aparecerá na interface de chat confirmando que o servidor está conectado. Agora você pode pedir ao Claude que use qualquer uma das suas ferramentas diretamente na conversa:

"Que horas são?" "Leia o arquivo em /home/usuario/notas.txt e faça um resumo." "Pesquise na web as últimas notícias sobre Rust 2025."

O Claude decide autonomamente quando invocar cada ferramenta. Você não precisa pedir explicitamente — ele usará a ferramenta certa quando o contexto exigir.


Conectar ao Claude Code

No Claude Code (este CLI), os servidores MCP são configurados por projeto ou globalmente. Adicione um servidor à configuração do projeto:

claude mcp add dev-tools python /caminho/absoluto/para/server.py

Ou edite .claude/settings.json diretamente:

{
  "mcpServers": {
    "dev-tools": {
      "command": "python",
      "args": ["/caminho/absoluto/para/server.py"]
    }
  }
}

Um Exemplo Mais Realista: Ferramentas para Banco de Dados

Aqui está um exemplo mais próximo de produção — um servidor MCP que expõe acesso somente leitura a um banco de dados SQLite:

# db_server.py
import sqlite3
import json
from mcp.server.fastmcp import FastMCP

DB_PATH = "app.db"
mcp = FastMCP("database")


@mcp.tool()
def list_tables() -> str:
    """Lista todas as tabelas do banco de dados."""
    with sqlite3.connect(DB_PATH) as conn:
        tables = conn.execute(
            "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
        ).fetchall()
    return json.dumps([t[0] for t in tables])


@mcp.tool()
def describe_table(table: str) -> str:
    """
    Retorna o esquema de uma tabela.

    Args:
        table: Nome da tabela.
    """
    with sqlite3.connect(DB_PATH) as conn:
        cols = conn.execute(f"PRAGMA table_info({table})").fetchall()
    return json.dumps([
        {"name": c[1], "type": c[2], "nullable": not c[3], "pk": bool(c[5])}
        for c in cols
    ], indent=2)


@mcp.tool()
def query(sql: str) -> str:
    """
    Executa uma consulta SQL SELECT somente leitura.

    Args:
        sql: Uma instrução SELECT. INSERT/UPDATE/DELETE são rejeitados.
    """
    sql_stripped = sql.strip().upper()
    if not sql_stripped.startswith("SELECT"):
        return "Erro: apenas consultas SELECT são permitidas."

    with sqlite3.connect(DB_PATH) as conn:
        conn.row_factory = sqlite3.Row
        rows = conn.execute(sql).fetchall()

    return json.dumps([dict(r) for r in rows], indent=2, default=str)


if __name__ == "__main__":
    mcp.run()

Com isso conectado ao Claude, você pode manter uma conversa em linguagem natural sobre seu banco de dados:

"Quais tabelas temos?" "Mostre-me os últimos 10 pedidos com valor acima de R$ 500." "Quantos usuários se registraram por mês este ano?"

O Claude traduz sua intenção para SQL, chama a ferramenta query e apresenta os resultados — sem que você precise escrever a consulta.


Considerações de Segurança

Os servidores MCP rodam com as mesmas permissões do processo que os inicia. Algumas regras básicas:

  • Exponha apenas o necessário. Não crie uma ferramenta genérica run_shell_command a menos que tenha uma razão muito sólida.
  • Valide as entradas. Trate os argumentos das ferramentas como qualquer outra entrada externa — eles vêm de um LLM que pode ser direcionado por usuários.
  • Aplique somente leitura onde for adequado. O exemplo de banco de dados acima rejeita tudo que não seja SELECT.
  • Cuidado com acesso a arquivos. Se construir uma ferramenta read_file, considere restringi-la a um diretório específico em vez de aceitar caminhos arbitrários.

A Perspectiva Global

O MCP ainda é jovem, mas a curva de adoção é íngreme. Nos poucos meses desde seu lançamento, centenas de servidores surgiram — para GitHub, Slack, Postgres, Kubernetes, navegadores web, bancos de dados vetoriais e mais. Como o protocolo é aberto, qualquer ferramenta que você construir funciona em todos os hosts compatíveis — hoje Claude Desktop e Claude Code, em breve muitos outros.

O padrão que ele habilita é poderoso: em vez de fazer fine-tuning de um modelo para conhecer seus sistemas específicos, você dá ao modelo a capacidade de consultar em tempo de execução. O modelo permanece geral; as ferramentas o tornam específico para o seu contexto. Essa separação é mais limpa, mais manutenível e mais fácil de auditar do que tentar integrar conhecimento de domínio nos pesos.


Recursos