Close Menu
    Facebook X (Twitter) Instagram
    Facebook X (Twitter) Instagram YouTube TikTok
    SantoTechSantoTech
    PODCAST
    • Início
      • Notícias
    • Colunistas
    • Editais
    • Startups
    • Eventos
    • Dicas
    • Vagas e jobs
    • Vídeos
    SantoTechSantoTech
    Home»Dicas»Construindo seu MCP com FastMCP

    Construindo seu MCP com FastMCP

    Dicas 06/02/2026Airton Lira JuniorPor Airton Lira Junior8 minutos de leitura
    MCP Tools em python
    screenshot 2

    #mcp #python #claude #docker

    INTRODUÇÃO:

    Se você usa inteligência artificial, sabe que ela tem um limite claro: ela é muito inteligente, mas vive presa dentro de uma caixa de texto. O Claude, por exemplo, pode escrever um poema sobre chuva, mas não sabe se está chovendo agora na minha cidade. Ele pode simular uma venda, mas não consegue dar baixa no meu estoque real. E por que estou dizendo isso, por que neste artigo eu vou te ensinar a criar ferramentas MCP com conexões API de clima e conexão com um banco de dados SQLite.

    Decidi resolver isso explorando o MCP (Model Context Protocol). A ideia era simples: dar “mãos” para a IA interagir com meus dados locais e APIs externas. O resultado foi um repositório que foi desde um script Python básico até uma aplicação dockerizada completa.

    Meu primeiro desafio foi arquitetural. Eu precisava de duas capacidades distintas:

    • Acessar um banco de dados SQLite local (uma operação síncrona).
    • Consultar uma API de clima na internet (uma operação assíncrona).

    Em vez de criar vários microsserviços complexos, unifiquei tudo em um único arquivo que chamei de “super_server.py”. Utilizando a biblioteca FastMCP, consegui misturar funções normais com funções “async” no mesmo agente. Isso permitiu que o Claude, em uma única resposta, verificasse que estava chovendo em Londres e, baseado nisso, sugerisse vender guarda-chuvas do meu banco de dados local.

    Ficando desta forma o código (Ao final vou disponibilizar o link no meu github):

    import sqlite3
    import os
    import httpx
    from mcp.server.fastmcp import FastMCP
    from dotenv import load_dotenv
    from typing import Annotated
    from pydantic import Field

    1. Carrega as variáveis do arquivo .env

    load_dotenv()

    2. Inicialização do Servidor

    server_name = os.getenv("MCP_SERVER_NAME", "Assistente Padrão")
    mcp = FastMCP(server_name)

    3. Configuração de Caminhos (Banco de Dados)

    BASE_DIR = os.path.dirname(os.path.abspath(file))
    db_name = os.getenv("DB_FILENAME", "loja.db")
    DB_PATH = os.path.join(BASE_DIR, db_name)

    4. URLs da API

    GEO_URL = os.getenv("GEO_API_URL")
    WEATHER_URL = os.getenv("WEATHER_API_URL")

    — BLOCO 1: FERRAMENTAS DE ESTOQUE —

        if not items:
            return "Nenhum produto encontrado."
    
        resultado = "ID | Produto | Preço (R$) | Estoque\n"
        resultado += "-" * 40 + "\n"
        for item in items:
            resultado += f"{item[0]} | {item[1]} | {item[2]:.2f} | {item[3]}\n"
        return resultado
    except Exception as e:
        return f"Erro ao acessar banco de dados: {str(e)}"
    @mcp.tool()
    def listar_produtos() -> str:
    """Lista todos os produtos do estoque com preços e quantidades."""
    try:
    with sqlite3.connect(DB_PATH) as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT id, nome, preco, estoque FROM produtos")
    items = cursor.fetchall()
    
    @mcp.tool()
    def vender_produto(
    nome_exato: str,
    quantidade: Annotated[int, Field(description="Quantidade vendida.")]
    ) -> str:
    """Registra uma venda e abate do estoque no banco de dados."""
    # Validação Manual (Soft Fail)
    if quantidade <= 0:
        return "Erro: A quantidade para venda deve ser maior que zero. Por favor, tente novamente com um valor positivo."
    
    try:
        with sqlite3.connect(DB_PATH) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT estoque FROM produtos WHERE nome = ?", (nome_exato,))
            res = cursor.fetchone()
    
            if not res:
                return f"Erro: Produto '{nome_exato}' não encontrado."
    
            estoque_atual = res[0]
            if estoque_atual < quantidade:
                return f"Estoque insuficiente. Restam apenas {estoque_atual}."
    
            novo_estoque = estoque_atual - quantidade
            cursor.execute("UPDATE produtos SET estoque = ? WHERE nome = ?", (novo_estoque, nome_exato))
            conn.commit()
    
        return f"Venda realizada! Saldo de '{nome_exato}': {novo_estoque}."
    except Exception as e:
        return f"Erro ao processar venda: {str(e)}"

    — BLOCO 2: FERRAMENTAS DE CLIMA —

    @mcp.tool()
    async def obter_previsao(cidade: str) -> str:
    """Consulta API externa para ver o clima atual (Async)."""
    async with httpx.AsyncClient() as client:
    try:
    # Busca Lat/Lon
    resp_geo = await client.get(GEO_URL, params={"name": cidade, "count": 1, "language": "pt"})
    resp_geo.raise_for_status()
    data_geo = resp_geo.json()
    
     if "results" not in data_geo:
                return f"Cidade '{cidade}' não encontrada."
    
            local = data_geo["results"][0]
    
            # Busca Clima
            params_clima = {
                "latitude": local["latitude"],
                "longitude": local["longitude"],
                "current": ["temperature_2m", "relative_humidity_2m"],
                "timezone": "auto"
            }
            resp_weather = await client.get(WEATHER_URL, params=params_clima)
            data_weather = resp_weather.json()
            curr = data_weather["current"]
    
            return (f"Clima em {local['name']}: {curr['temperature_2m']}°C, "
                    f"Umidade: {curr['relative_humidity_2m']}%")
    
        except Exception as e:
            return f"Erro na conexão: {str(e)}"

    — BLOCO 3: PROMPTS —

    @mcp.prompt()
    def assistente_vendas() -> str:
    “””Prompt pronto para atuar como vendedor proativo.”””
    return “””
    Você é um assistente de vendas inteligente.
    Sua missão é:
    1. Verificar o clima da cidade do usuário.
    2. Sugerir produtos do estoque que combinem com o clima.
    Use as ferramentas disponíveis para consultar os dados reais.
    “””

    if name == “main“:
    mcp.run()`

    Para que seja possivel utilizar esse custom MCP no seu Claude Desktop você deve alterar as configurações no claude_desktop_config.json que geralmente fica no diretório Roaming/claude.

    {
    "mcpServers": {
    "super-servidor-docker": {
    "command": "wsl.exe",
    "args": [
    "docker",
    "run",
    "-i",
    "--rm",
    "--env-file",
    "/home/airtonlirajr/Estudos/mcp_learning/.env",
    "mcp-super-server"
    ]
    }
    },
    "preferences": {
    "coworkScheduledTasksEnabled": false,
    "sidebarMode": "chat"
    }
    }

    Desta forma basta salvar e abrir novamente o Claude Desktop e veja o resultado que massa:

    image
    image

    OBS: Sim sou de JAMPA – João Pessoa

    Após tudo estar funcionando resolvi dockerizar o projeto com o seguinte Dockerfile:

    `# 1. Usa uma imagem oficial do Python, leve (slim)
    FROM python:3.11-slim

    2. Define variáveis de ambiente cruciais para Python em Docker

    Impede que o Python guarde logs em buffer (queremos ver erros na hora)

    ENV PYTHONUNBUFFERED=1

    Impede criação de arquivos .pyc desnecessários

    ENV PYTHONDONTWRITEBYTECODE=1

    3. Define a pasta de trabalho dentro do container

    WORKDIR /app

    4. Copia a lista de dependências e instala

    Fazemos isso ANTES de copiar o código para aproveitar o cache do Docker

    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt

    5. Copia todo o restante do código para dentro do container

    COPY . .

    6. Cria o banco de dados inicial (caso não exista) dentro do container

    RUN python criar_banco.py

    7. Comando padrão ao iniciar o container: rodar o servidor

    
    CMD ["python", "super_server.py"]`
    
    Também criei um script python que esta mencionado no Dockefile para alimentar meu SQLite com dados fictícios:
    
    `import sqlite3
    
    def setup_database():
    # Cria o arquivo 'loja.db'
    conn = sqlite3.connect("loja.db")
    cursor = conn.cursor()
    
    # Cria tabela de Produtos
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS produtos (
            id INTEGER PRIMARY KEY,
            nome TEXT NOT NULL,
            preco REAL NOT NULL,
            estoque INTEGER NOT NULL
        )
    """)
    
    # Insere dados de exemplo (se a tabela estiver vazia)
    cursor.execute("SELECT count(*) FROM produtos")
    if cursor.fetchone()[0] == 0:
        dados = [
            ("Notebook Gamer", 4500.00, 10),
            ("Mouse Sem Fio", 120.50, 50),
            ("Monitor 4K", 1800.00, 15),
            ("Teclado Mecânico", 350.00, 30),
            ("Cadeira Ergonômica", 850.00, 5)
        ]
        cursor.executemany("INSERT INTO produtos (nome, preco, estoque) VALUES (?, ?, ?)", dados)
        conn.commit()
        print("Banco de dados 'loja.db' criado com sucesso!")
    else:
        print("Banco de dados já existe.")
    
    conn.close()
    
    if name == "main":
    setup_database()`
    
    • Montagem de a imagem Docker e execução do server MCP no docker: Vamos mergulhar nos detalhes. No mundo do Docker, existem dois momentos principais: Construir (Build) e Rodar (Run).

    É como cozinhar: primeiro você prepara o prato (Build) e depois você serve o prato (Run). O Claude só consegue “comer” o prato se você souber servir corretamente.

    Aqui está a anatomia completa dos comandos que usamos:

    1. O Comando de Construção (docker build)
    docker build -t mcp-super-server .

    Este comando pega o seu Dockerfile (a receita) e o seu código Python e os funde em um arquivo estático e imutável chamado Imagem.

    • docker build: O comando base que diz “quero criar uma nova imagem”.
    • -t mcp-super-server: O “t” vem de Tag (etiqueta). Sem isso, sua imagem teria um nome aleatório tipo a1b2c3d4. Aqui estamos batizando ela de mcp-super-server para ficar fácil de chamar depois.
    • . (O Ponto Final): Muito importante. Esse ponto diz ao Docker: “Use os arquivos da pasta onde estou agora como contexto”. É aqui que ele acha o Dockerfile, o requirements.txt e o super_server.py
    1. O Comando de Execução (docker run) Este é o comando que o Claude executa. Ele pega a imagem (que está parada no disco) e cria um Container (um processo vivo na memória).
    docker run -i --rm --env-file .env mcp-super-server

    Cada “flag” (opção com traço) aqui foi escolhida cirurgicamente para o funcionamento do MCP

    CONCLUSÃO

    Basicamente, o que fizemos aqui foi dar um corpo físico para o cérebro da IA. Até ontem, o Claude era apenas um consultor inteligente preso numa janela de chat, sonhando com o mundo lá fora. Hoje, com o Docker e o MCP, você deu a ele permissão para tocar nesse mundo.

    Agora que você tem essa estrutura rodando, o “brinquedo” virou uma ferramenta poderosa. Pense no que dá para fazer apenas trocando as ferramentas que criamos:

    Leve para a Nuvem: Como seu agente já está num container, você pode hospedá-lo em serviços como Render ou Railway. Isso transformaria seu código local em um servidor online 24 horas. Imagine poder puxar o celular na rua, falar com o Claude e ele consultar seu banco de dados que está rodando seguro na nuvem.

    Automação da Vida Real: E se, em vez de consultar estoque, você criasse uma ferramenta para controlar as luzes da sua casa? O Claude poderia cruzar a informação de “hora do pôr do sol” da API de clima e acender a luz do seu escritório automaticamente.

    O Assistente Financeiro Definitivo: Você poderia substituir o banco de dados da loja pelo seu banco de dados financeiro pessoal. Imagine mandar a foto de uma nota fiscal para o chat, e o agente não apenas ler o valor, mas inserir o gasto na categoria correta do seu banco de dados SQL, verificar se você estourou o orçamento do mês e te dar um puxão de orelha, tudo em segundos.

    Você deixou de ser apenas um usuário que digita prompts para se tornar um arquiteto de sistemas inteligentes. A barreira técnica foi quebrada. O código está aí, modular, seguro e pronto. Agora é só escolher qual problema chato do seu dia a dia você quer que a IA resolva para você.

    Bebam agua, e me seguem no LinkedIn: https://www.linkedin.com/in/airton-de-souza-lira-junior-6b81a661/

    Repositório do Projeto: https://github.com/AirtonLira/mcp_learning

    aiengineer Claude claudecode docker mcp python
    Compartilhar. Facebook Twitter Pinterest LinkedIn Email Telegram WhatsApp Copiar link
    Airton Lira Junior

    Data Architect | 3x AWS | 1x Azure | 4x Databricks | Python | Golang | Machine Learning | AI Engineer

    Notícias relacionadas

    01/02/2026

    Desenvolver aplicações de AI com o melhor prompt e contexto.

    26/01/2026

    Anthropic lança aplicativos Claude interativos, incluindo Slack e outras ferramentas do local de trabalho

    08/01/2026

    Ataque via whatsapp espalha Trojan bancário Astaroth em todo o Brasil

    Siga nas redes
    • Facebook
    • Twitter
    • Instagram
    • YouTube
    • TikTok
    gobeejobs banner 300x250 santotech
    Em Destaque

    Qualitur: Governo da Paraíba inicia programação de seminários para fortalecer o turismo nos municípios

    EUA operam nova versão de Comando Cibernético

    Chamada de Trabalhos da Conferência Anprotec 2026 é prorrogada até 15 de fevereiro

    POP Linhas Aéreas: nova companhia pode reforçar aviação regional e conectar cidades pouco atendidas no Brasil

    Sobre nós
    Sobre nós

    Somos um portal de notícias desenvolvido com o propósito de mostrar a tecnologia, inovação, gestão, empreendedorismo e economia criativa para nosso estado, região, país e mundo.

    Fale Conosco: [email protected]
    Redação: +55 83 987931523

    Facebook X (Twitter) Instagram YouTube TikTok
    Últimas Noticias

    Construindo seu MCP com FastMCP

    Cuidado com os gurus de LinkedIn: marketing não faz milagre

    KASSUÁ é reconhecida como empresa destaque da Paraíba no Prêmio Top Master 2025

    coloque sua marca aqui 300x250
    © 2026 Santo Tech. por NIBWOZ.
    • Início
    • Colunistas
    • Editais
    • Startups
    • Eventos
    • Dicas
    • Vagas e jobs

    Digite o que busca acima e tecle Enter para procurar ou tecle Esc para cancelar.