SlimAtlas

Um servidor MCP que fornece capacidades de automação de navegador extremamente leves usando o navegador Lightpanda. Este servidor permite que LLMs interajam com páginas da web por meio de automação de navegador.

Documentação

SlimAtlas AI Logo

SlimAtlas AI

Um servidor MCP standalone extremamente leve para automação de navegador eficiente em tokens para agentes de IA, projetado para rodar em servidores.

~5x menos memória que Chromium. ~25x snapshots menores que HTML bruto.

Funciona com Linux e macOS.

Construído com Bun, Puppeteer e Lightpanda.

license MIT bun 1.3.11 TypeScript 5.9

Recursos

  • Automação de Navegador: Navegue, clique, digite, preencha formulários e avalie JavaScript
  • Leve por Padrão: ~5x menos memória que Chromium, ~25x snapshots menores que HTML bruto
  • Snapshots de Página: Obtenha snapshots compactos de árvore de acessibilidade em YAML com IDs de nó únicos para direcionamento preciso de elementos
  • Contexto Otimizado para LLM: Snapshots são reduzidos ao essencial semântico, mantendo o uso de contexto mínimo para que você possa caber mais páginas e sessões mais longas na mesma janela
  • Navegador de Fallback Configurável: Modelo de dois níveis — navegador leve primeiro, depois escala para Chrome com interface, Browserless ou Browserbase na nuvem apenas quando o padrão é detectado como bot, falha ou expira.
  • Limitação de Taxa: Fique abaixo do radar. Imponha um atraso mínimo configurável entre requisições a domínios específicos com padrões curinga (*, *.reddit.com) além de jitter opcional, para que seu agente se ajuste ao ritmo em vez de bombardear um site e acionar suas defesas anti-bot.
  • Suporte a Proxy: Roteie cada requisição através de um proxy HTTP com uma única configuração PROXY_SERVER — aplicada automaticamente a ambas as camadas de navegador, para que seu IP real nunca toque o alvo. Suporta autenticação básica inline (http://user:pass@host:port).
  • Gerenciamento Robusto de Sessões: Serialização por sessão, limite opcional de sessões (MAX_SESSIONS), recuperação de falhas no meio da sessão com replay de histórico e desligamento gracioso.
  • Gerenciamento de Sessões: Reutilize sessões em múltiplas operações com IDs de sessão únicos
  • Multiplataforma: Funciona em Linux e macOS, com fallback configurável para navegador real quando necessário

Benchmark

SlimAtlas foi avaliado contra Playwright MCP (Chromium headless e com interface) usando slim-atlas-bench — 25 sites reais em 5 categorias, 3 execuções cada (225 no total), todos rodando em Docker no localhost.

Configuração: Cada serviço roda como um servidor MCP em seu próprio contêiner Docker. O harness de benchmark mede a latência por chamada de ferramenta (navegar + snapshot) via langchain-mcp-adapters, e captura a RAM do contêiner via API de estatísticas do Docker. Snapshots são estimados em tokens a ~4 caracteres/token (mesma metodologia da linha de base de HTML bruto).

Métrica (mediana)SlimAtlasPlaywright HeadlessPlaywright Headful
Navegar + Snapshot (ms)1.3831.116687
RAM do Contêiner (MB)124635815
Tokens do Snapshot4149401.843

SlimAtlas troca velocidade de navegação por uso drasticamente menor de recursos. Chromium é mais rápido no carregamento de páginas, mas usa 5–6x mais RAM e produz 2–4x mais tokens por snapshot — os dois custos que dominam em escala em fluxos de trabalho de agentes.

Resultados

Tokens do Snapshot
Snapshot Tokens
Uso de Memória
Memory Usage

Instalação

Requer Bun ≥1.1.

# Install dependencies
bun install

O binário do navegador é baixado automaticamente na primeira execução.

Navegador de fallback: Nível 1 é sempre o navegador leve. Nível 2 é FALLBACK_BROWSER — um de headful (Chrome com interface), browserbase (nuvem), browserless (nuvem), ou none (padrão, sem fallback). Quando o padrão falha, expira ou é detectado como bot, a sessão alterna uma vez para o fallback configurado. Chrome é empacotado pelo Puppeteer; Browserbase/Browserless exigem credenciais de API (veja abaixo).

Uso

Executar o Servidor MCP

# Standalone HTTP server (default)
bun run src/index.ts --port=8080

# Remote, authenticated
MCP_AUTH_TOKEN=s3cret bun run src/index.ts --host=0.0.0.0 --port=8080

SlimAtlas expõe um único endpoint MCP /mcp Streamable HTTP. Cada cliente recebe sua própria sessão via cabeçalho mcp-session-id; MAX_SESSIONS limita a concorrência. Aponte seu cliente MCP para ele:

{
  "mcpServers": {
    "slimatlas": {
      "url": "http://localhost:8080/mcp",
      "transport": "http"
    }
  }
}

Com autenticação:

{
  "mcpServers": {
    "slimatlas": {
      "url": "http://your-host:8080/mcp",
      "transport": "http",
      "headers": { "Authorization": "Bearer s3cret" }
    }
  }
}

Dica: Use --host=0.0.0.0 para expor remotamente, mas sempre defina MCP_AUTH_TOKEN ao fazer isso. O servidor fala apenas HTTP simples — termine TLS na frente (Caddy/nginx) ou o token Bearer viaja pela rede em texto claro.

Docker

A imagem inclui o binário Lightpanda no momento da construção, então o contêiner inicia autocontido e nunca baixa novamente:

docker build -t slimatlas .
docker run -p 8080:8080 -e MCP_AUTH_TOKEN=s3cret slimatlas
# -> http://localhost:8080/mcp

Fixei uma versão do Lightpanda para builds reproduzíveis (qualquer tag lightpanda-io/browser — padrão nightly):

docker build --build-arg LIGHTPANDA_VERSION=0.3.3 -t slimatlas:0.3.3 .

Multi-arquitetura é tratada automaticamente — o build detecta a arquitetura do contêiner via uname -m (x86_64 → lightpanda-x86_64-linux, aarch64 → lightpanda-aarch64-linux), então o binário sempre corresponde à plataforma em construção.

Apple Silicon (Macs M-series): passe --platform linux/arm64 para construir/executar nativamente. Sem isso, o Docker Desktop pode usar amd64 por padrão e executar o contêiner sob Rosetta, o que falha ao iniciar o binário Lightpanda (rosetta error: failed to open elf …).

docker build --platform linux/arm64 --build-arg FALLBACK_BROWSER=headful -t slimatlas .
docker run --platform linux/arm64 --name slimatlas -p 8080:8080 -e MCP_AUTH_TOKEN=s3cret -e PLUGINS=document-export -e LIGHTPANDA_POOL_SIZE=20 -e CHROME_POOL_SIZE=10 -e SKIP_LIGHTPANDA_DOMAINS=reddit.com -e RATE_LIMIT_DOMAINS=reddit.com -e RATE_LIMIT_MIN_DELAY_MS=10000 slimatlas

Nota sobre sites com verificação anti-bot (Reddit, sites atrás de Cloudflare): em linux/arm64 a imagem usa Debian Chromium como fallback, que as barreiras anti-bot atuais (ex: "Prove sua humanidade" do Reddit, "Só um momento..." do Cloudflare) servem um desafio interativo independentemente das configurações de stealth. Verificado contra Reddit: o mesmo contêiner em linux/amd64 — que fixa Chrome-for-Testing (padrão 131.0.6778.204; builds estáveis atuais são bloqueados) — renderiza threads normalmente. Prefira a imagem amd64 para alvos com verificação anti-bot (em Macs M-series ela roda sob Rosetta; Lightpanda funciona lá pois o binário x86_64 é incluído no momento da construção).

Escolha do mecanismo / proxy: AMBAS as camadas de navegador roteiam através de PROXY_SERVER (mesmas credenciais; Lightpanda via auth inline --http-proxy, Chrome via --proxy-server + page.authenticate). Reddit renderiza através de Lightpanda com proxy diretamente; quando uma sessão encontra um desafio, a camada de detecção de bot a escala para o fallback Chrome 131. Adicione -e SKIP_LIGHTPANDA_DOMAINS=reddit.com para forçar threads diretamente para Chrome.

Notas sobre proxy: PROXY_SERVER aceita http://user:pass@host:port ou o formato do dashboard host:port:user:pass (normalizado internamente). Sessões persistentes (formato gate.<provider>:port:user-sessid-xxx:pass) funcionam através da mesma variável de ambiente. -e PROXY_BYPASS_DOMAINS=a.com,b.com roteia domínios listados DIRETO no Chrome (para sites cujo Cloudflare desaprova mais suas saídas de proxy do que seu próprio IP).

Exemplo completo de produção — configuração verificada contra Reddit e uma rajada paralela de páginas de estatísticas:

docker build --platform linux/amd64 --build-arg FALLBACK_BROWSER=headful -t slimatlas .
docker rm -f slimatlas
docker run -d --name slimatlas -p 8080:8080 \
  -e MCP_AUTH_TOKEN=s3cret \
  -e PLUGINS=document-export \
  -e CHROME_POOL_SIZE=6 \
  -e RATE_LIMIT_DOMAINS=reddit.com \
  -e RATE_LIMIT_MIN_DELAY_MS=10000 \
  -e TZ=America/New_York \
  -e PROXY_SERVER="http://user:pass@proxy-host:port" \
  -e PROXY_BYPASS_DOMAINS=cloudflare-heavy-site.com \
  slimatlas

Omita PROXY_SERVER, PROXY_BYPASS_DOMAINS e TZ se você não usa proxy. CHROME_POOL_SIZE importa: o padrão de 1 serializa toda sessão escalada por desafio e causa timeouts no cliente quando uma sessão vaza. A versão fixada do Chrome é substituível no momento da construção com --build-arg CHROME_CFT_VERSION=<version> se a barreira de um site começar a sinalizá-lo.

Variante com fallback com interface. A imagem padrão executa apenas Lightpanda (FALLBACK_BROWSER=none). Para habilitar o fallback Chrome com interface (necessário apenas se você definir FALLBACK_BROWSER=headful em tempo de execução), construa a variante com interface — ela adiciona as bibliotecas de runtime do Chrome + Xvfb (~150MB) e predefine FALLBACK_BROWSER=headful:

docker build --build-arg LIGHTPANDA_VERSION=0.3.3 FALLBACK_BROWSER=headful -t slimatlas:headful .
docker run -p 8080:8080 -e MCP_AUTH_TOKEN=s3cret -e PLUGINS=document-export slimatlas:headful

Xvfb é iniciado lentamente dentro do contêiner na primeira sessão que escala para Chrome com interface — sem entrypoint ou xvfb-run manual necessário.

Plugin de exportação de documentos (PDF/PPTX). browser_print_pdf e browser_export_pptx vêm no plugin document-export e estão desabilitados por padrão — habilite com -e PLUGINS=document-export (ou a flag --plugins=document-export). Ambas as ferramentas forçam o fallback para Chrome real, então precisam de uma imagem que realmente tenha um: use a variante com interface acima. Na imagem padrão apenas com Lightpanda, as ferramentas aparecem na lista mas toda chamada falha (No fallback browser configured). Guia de criação de plugins: docs/plugins.md.

Modo Stdio

Para clientes MCP que iniciam o servidor como subprocesso (local, cliente único), use transporte stdio:

bun run src/index.ts
{
  "mcpServers": {
    "slimatlas": {
      "command": "bun",
      "args": ["run", "path/to/mcp/src/index.ts"]
    }
  }
}

Configuração

Adicione à configuração do seu cliente MCP:

{
  "mcpServers": {
    "slimatlas": {
      "command": "bun",
      "args": ["run", "path/to/mcp/src/index.ts"]
    }
  }
}

Dica: Defina FALLBACK_BROWSER=none para usar apenas o navegador leve e propagar erros honestamente. Use headful ou browserbase para habilitar um fallback de navegador real.

Veja docs/configs.md para todas as variáveis de ambiente e flags de CLI.

Navegador de fallback

FALLBACK_BROWSERNavegador Nível 2Notas
none (padrão)—Apenas navegador leve; erros propagam honestamente
headfulChrome com interfaceJanela real no macOS; precisa de xvfb em Linux headless
browserbaseBrowserbase na nuvemRequer BROWSERBASE_API_KEY + BROWSERBASE_PROJECT_ID

Pule o navegador padrão para domínios conhecidamente difíceis com SKIP_LIGHTPANDA_DOMAINS (separados por vírgula, ciente de subdomínios). Hosts correspondentes iniciam diretamente no navegador de fallback. Requer FALLBACK_BROWSER != none (caso contrário, a lista é ignorada com um aviso).

Limitação de taxa

Ritmo educado e anti-detecção para seu agente. RateLimiter impõe um atraso mínimo em todo o servidor entre chamadas browser_navigate aos domínios que você lista, com jitter aleatório opcional para que o ritmo não seja um intervalo fixo e identificável. Buckets são chaveados por host em todas as sessões (porque o site alvo vê seu IP, não suas sessões), e padrões suportam curingas:

PadrãoCorrespondênciasBucket
*Todo hostCada host limitado independentemente
*.reddit.comApenas subdomínios (www.reddit.com, old.reddit.com) — não reddit.comTodos os subdomínios correspondentes compartilham um bucket
g2.comg2.com + seus subdomíniosApex + subdomínios compartilham um bucket

Desabilitado por padrão. Habilite com uma lista de domínios não vazia e um atraso não zero:

# Via CLI flags
bun run src/index.ts --rate-limit-domains=*.reddit.com,g2.com --rate-limit-min-delay-ms=2000 --rate-limit-jitter-ms=1500

# Or via environment / .env
RATE_LIMIT_DOMAINS=*.reddit.com,g2.com
RATE_LIMIT_MIN_DELAY_MS=2000
RATE_LIMIT_JITTER_MS=1500

Proxy

Mantenha seu IP real longe do alvo. Defina um único PROXY_SERVER e SlimAtlas roteia todo o tráfego HTTP de ambas as camadas de navegador através dele — sem necessidade de configuração por navegador:

  • Navegador leve (nível 1) — encaminhado via sua flag nativa --http-proxy.
  • Fallback Chrome (nível 2) — aplicado via --proxy-server na inicialização.
# Via CLI flag
bun run src/index.ts --proxy-server=http://host:8080

# Or via environment / .env
PROXY_SERVER=http://user:pass@host:8080

Autenticação básica inline (http://user:pass@host:port) é suportada na camada do navegador leve. Para proxies com allowlist de IP (sem credenciais), funciona em ambas as camadas. (Autenticação Chrome por página via page.authenticate está no roadmap.)

Flags de CLI

Toda variável de ambiente também pode ser passada como uma flag de CLI em minúsculas no formato --flag=value. Flags de CLI sobrescrevem variáveis de ambiente. Flags desconhecidas fazem o servidor encerrar na inicialização. Consulte docs/configs.md para a lista completa.

bun run src/index.ts --fallback-browser=headful --lightpanda-pool-size=3 --skip-lightpanda-domains=g2.com --navigate-timeout=60000

Para usar flags a partir de um cliente MCP, adicione-as ao array args:

{
  "mcpServers": {
    "slimatlas": {
      "command": "bun",
      "args": [
        "run",
        "path/to/mcp/src/index.ts",
        "--fallback-browser=headful",
        "--skip-lightpanda-domains=g2.com,linkedin.com",
        "--chrome-pool-size=3"
      ]
    }
  }
}

Fluxo de Uso

# Example: Navigate, snapshot, and interact with a page

# 1. Navigate to a URL (creates a new session automatically)
result = mcp.call("browser_navigate", {"url": "https://example.com"})
# Returns: session_id: abc1, result: Navigated to https://example.com. Title: Example Domain

# 2. Take a snapshot to see the page structure
snapshot = mcp.call("browser_snapshot", {"session_id": "abc1"})
# Returns YAML with node IDs like: 0: {type: div, children: ...}

# 3. Click a node by ID (from the snapshot)
mcp.call("browser_click", {"session_id": "abc1", "nodeId": 2})

# 4. Type into a search box
mcp.call("browser_type", {"session_id": "abc1", "nodeId": 5, "text": "search query"})

# 5. Close the session when done
mcp.call("browser_close", {"session_id": "abc1"})

Ferramentas Disponíveis

As ferramentas principais do browser_* abaixo estão sempre disponíveis. Duas ferramentas adicionais de pipeline — browser_print_pdf e browser_export_pptx — acompanham o plugin document-export e estão desabilitadas por padrão (-e PLUGINS=document-export / --plugins=document-export); consulte docs/plugins.md.

FerramentaDescriçãoValor
browser_navigateNavegar para uma URL com estratégia de espera configurávelPonto de entrada para todas as interações web. Suporta load, domcontentloaded, networkidle0, networkidle2
browser_snapshotObter árvore de acessibilidade YAML com IDs de nó únicosRepresentação estruturada da página ideal para compreensão por LLM. IDs de nó permitem direcionamento preciso para cliques/digitação
browser_view_nodeVisualizar conteúdo específico de nó por ID (texto ou imagem)Inspecionar elementos individuais sem reler a página inteira. Retorna imagens como base64 para verificação visual
browser_clickClicar em elemento por ID de nó ou seletor CSSID de nó (do snapshot) é recomendado em vez de seletores CSS por confiabilidade e simplicidade
browser_typeDigitar texto em um elemento com atraso opcional de teclasSimula digitação humana. Use para caixas de busca, formulários e entradas de texto
browser_fillPreencher um elemento de entrada com um valor instantaneamenteMais rápido que browser_type para campos de formulário. Limpa o valor existente antes de digitar
browser_go_backNavegar para trás no histórico do navegadorEssencial para fluxos de múltiplas etapas e correção de erros de navegação
browser_go_forwardNavegar para frente no histórico do navegadorComplementa browser_go_back para navegação bidirecional
browser_reloadRecarregar a página atualAtualizar conteúdo dinâmico ou recuperar de estado obsoleto da página
browser_get_page_infoObter URL e título da página atualManeira rápida de verificar sucesso de navegação e contexto atual
browser_closeFechar sessão do navegador e liberar recursosImportante para limpeza. Sessões fecham automaticamente por timeout, mas fechamento explícito é recomendado

Ferramentas de plugin (somente com PLUGINS=document-export):

FerramentaDescriçãoValor
browser_print_pdfImprimir página atual ou documento HTML fornecido em PDF base64Apenas para pipelines de geração de documentos/relatórios — NÃO para pesquisa/navegação de agentes. Força o fallback de Chrome real (FALLBACK_BROWSER); aceita um session_id fornecido pelo chamador (criar → imprimir → browser_close)
browser_export_pptxConverter página atual ou documento HTML fornecido em .pptx base64 via dom-to-pptxApenas para pipelines de geração de apresentações. Slides são os elementos que correspondem a selector (padrão .slide) no tamanho final de pixel (ex.: 1920x1080); with_previews=true também retorna PNGs por slide. Força o fallback de Chrome real; o chamador fecha a sessão com browser_close

Executando Testes

# Run all tests
bun test

# Run tests in watch mode
bun test --watch

Requisitos

  • Bun ≥1.1
  • Linux ou macOS (baixa automaticamente) ou Chrome/Chromium (fallback)

Licença

MIT