Content
# 🤖 Super MCP Agent: Documentação Completa do Projeto
Este documento consolida toda a jornada de aprendizado para construir um Agente de IA Autônomo utilizando o **Model Context Protocol (MCP)**. O projeto final consiste em um "Super Servidor" unificado capaz de orquestrar tarefas síncronas (Banco de Dados SQLite) e assíncronas (APIs Externas) em um ambiente híbrido Windows + WSL.
---
## 🏗️ Arquitetura do Sistema
* **Host (Cliente):** Claude Desktop (Windows)
* **Servidor:** Python 3.10+ rodando em WSL 2 (Ubuntu)
* **Protocolo:** MCP (Model Context Protocol) sobre Stdio
* **Banco de Dados:** SQLite (Persistência Local)
* **Rede:** `httpx` Async (Integração com Open-Meteo API)
---
## 📂 Estrutura de Arquivos Recomendada
```text
mcp_learning/
├── .venv/ # Ambiente Virtual Python
├── loja.db # Banco de Dados de Produtos (Gerado pelo script)
├── super_server.py # O CÓDIGO FINAL (Unificado)
├── criar_banco.py # Script de setup do banco
└── README.md # Este arquivo
💻 Códigos Fonte
1. Script de Setup do Banco (criar_banco.py)
Execute este script uma vez para gerar o arquivo loja.db.
import sqlite3
def setup_database():
conn = sqlite3.connect("loja.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS produtos (
id INTEGER PRIMARY KEY,
nome TEXT NOT NULL,
preco REAL NOT NULL,
estoque INTEGER NOT NULL
)
""")
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 'loja.db' criado com sucesso!")
else:
print("Banco já existe.")
conn.close()
if __name__ == "__main__":
setup_database()
2. O Super Servidor (super_server.py)
Este é o código principal que contém Tools (Sync/Async) e Prompts.
import sqlite3
import os
import httpx
from mcp.server.fastmcp import FastMCP
# Inicialização do Agente
mcp = FastMCP("Assistente Geral (Loja + Clima)")
# Configuração de Caminho Absoluto (CRÍTICO PARA O CLAUDE)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.path.join(BASE_DIR, "loja.db")
# URLs da API
GEO_URL = "[https://geocoding-api.open-meteo.com/v1/search](https://geocoding-api.open-meteo.com/v1/search)"
WEATHER_URL = "[https://api.open-meteo.com/v1/forecast](https://api.open-meteo.com/v1/forecast)"
# --- BLOCO 1: FERRAMENTAS DE ESTOQUE (Banco de Dados / Sync) ---
@mcp.tool()
def listar_produtos() -> str:
"""Lista todos os produtos do estoque com preços e quantidades."""
with sqlite3.connect(DB_PATH) as conn:
cursor = conn.cursor()
cursor.execute("SELECT id, nome, preco, estoque FROM produtos")
items = cursor.fetchall()
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
@mcp.tool()
def vender_produto(nome_exato: str, quantidade: int) -> str:
"""Registra uma venda e abate do estoque no banco de dados."""
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}."
# --- BLOCO 2: FERRAMENTAS DE CLIMA (API Externa / Async) ---
@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.
"""
if __name__ == "__main__":
mcp.run()
⚙️ Instalação e Configuração
1. Dependências (WSL)
No terminal WSL (Ubuntu):
uv init
uv add "mcp[cli]" httpx
python criar_banco.py
2. Configuração do Claude Desktop (Windows)
Arquivo: %APPDATA%\Claude\claude_desktop_config.json
Substitua SEU_USUARIO pelo seu usuário do Linux.
{
"mcpServers": {
"super-servidor": {
"command": "wsl.exe",
"args": [
"/home/SEU_USUARIO/Estudos/mcp_learning/.venv/bin/python",
"/home/SEU_USUARIO/Estudos/mcp_learning/super_server.py"
]
}
}
}
🐛 Troubleshooting: Lições Aprendidas
Durante o desenvolvimento, resolvemos os seguintes problemas críticos:
Bug do Caminho Relativo (SQLite):
Problema: O banco loja.db não era encontrado ou era criado vazio na pasta errada.
Solução: Uso de os.path.abspath(__file__) no código Python para forçar o caminho absoluto.
Bug da Conexão WSL:
Problema: Claude Desktop não conseguia rodar comandos uv ou python do Linux.
Solução: Configuração do JSON usando wsl.exe como ponte explícita.
Bug da "Preguiça" do Modelo:
Problema: O Claude usava a previsão do tempo do Google em vez da nossa ferramenta.
Solução: Uso de prompts explícitos ("Use EXCLUSIVAMENTE a ferramenta obter_previsao").
✅ Prompt de Validação Final
Para testar se tudo está conectado, cole isto no Claude:
"Utilize EXCLUSIVAMENTE a ferramenta obter_previsao para checar a temperatura de 'Londres'. Baseado APENAS no retorno dela, se estiver frio (<15°C), use listar_produtos para checar o estoque de 'Teclado Mecânico' e então use vender_produto para vender 1 unidade."
Autor: Airton Lira Junior - https://www.linkedin.com/in/airton-de-souza-lira-junior-6b81a661/
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
firecrawl
Firecrawl MCP Server enables web scraping, crawling, and content extraction.
markitdown
Python tool for converting files and office documents to Markdown.
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
Sequential Thinking
A structured MCP server for dynamic problem-solving and reflective thinking.
Fetch
Retrieve and process content from web pages by converting HTML into markdown format.