
Construa um Servidor MCP com Playwright Stealth para Navegação de IA
TL;DR
Para fornecer acesso confiável à web para agentes de IA, envolva o Playwright com o plugin playwright-stealth dentro de um servidor do Protocolo de Contexto de Modelo (MCP) baseado em Python. Esta arquitetura expõe uma ferramenta padrão browse_page para o LLM, renderiza páginas pesadas em JavaScript, mascara assinaturas padrão de navegadores headless e retorna Markdown limpo para economizar tokens. Quando a furtividade local falha contra proteções avançadas, transfira a renderização para uma API projetada para evasão de bots.
O Problema de Navegação Agente
Agentes de IA precisam de dados em tempo real para responder perguntas, analisar tendências ou extrair informações estruturadas. Bibliotecas HTTP padrão retornam HTML bruto. Se um site alvo depende de frameworks do lado do cliente para renderizar conteúdo, uma solicitação HTTP GET retorna um <body> vazio e um conjunto de arquivos JavaScript. O agente não vê nada útil.
Navegadores headless resolvem o problema de renderização. Ferramentas como Playwright e Puppeteer executam o JavaScript e constroem o Documento Objeto Modelo (DOM) final. No entanto, executar um navegador headless diretamente introduz um novo modo de falha. Aplicações web modernas usam impressão digital para detectar tráfego automatizado. Uma instância padrão do Playwright vaza propriedades que indicam que é um bot. A solicitação do agente é interceptada por um CAPTCHA ou uma página de bloqueio.
A solução requer três componentes. Primeiro, uma interface padrão para o agente solicitar dados da web. Segundo, um mecanismo de navegador para renderizar a página. Terceiro, modificações de furtividade para contornar a detecção básica de bots.
Compreendendo o Protocolo de Contexto de Modelo
O Protocolo de Contexto de Modelo (MCP) padroniza como aplicações de IA se conectam a fontes de dados. Em vez de escrever integrações de API personalizadas para cada novo framework de agente, os desenvolvedores constroem um servidor MCP. O servidor expõe recursos e ferramentas através de uma conexão JSON-RPC. O cliente do agente descobre essas capacidades e as invoca quando necessário.
Para navegação na web, um servidor MCP expõe uma ferramenta. O agente decide que precisa visualizar uma URL, chama a ferramenta com a URL como argumento e aguarda a resposta em texto. O servidor MCP gerencia o ciclo de vida do navegador, as solicitações de rede e a extração de conteúdo.
Configurando o Projeto
Vamos construir o servidor MCP usando Python. Você precisa do Python 3.10 ou superior. Crie um novo diretório e instale as dependências necessárias. Usamos o SDK oficial mcp, playwright para navegação, playwright-stealth para evasão e markdownify para converter HTML em texto.
```bash title="Terminal"
mkdir mcp-browser
cd mcp-browser
python -m venv venv
source venv/bin/activate
pip install mcp playwright playwright-stealth markdownify
playwright install chromium
## Arquitetando o Servidor MCP
Um servidor MCP lida com a inicialização, descobre ferramentas e as executa. O pacote Python `mcp` fornece uma classe `FastMCP` que simplifica o roteamento e o registro de ferramentas.
Definimos uma instância do servidor e registramos uma função `browse`. A função recebe uma string de URL e retorna o conteúdo da página. As dicas de tipo e as docstrings são críticas. O cliente do agente lê a docstring para entender quando e como usar a ferramenta.
```python title="server.py" {7-8,14-16}
from mcp.server.fastmcp import FastMCP
from playwright.async_api import async_playwright
from playwright_stealth import stealth_async
from markdownify import markdownify
# Inicializa o servidor MCP
mcp = FastMCP("StealthBrowser")
@mcp.tool()
async def browse(url: str) -> str:
"""
Busca e renderiza uma página da web.
Use esta ferramenta quando precisar ler conteúdo de uma URL específica.
Retorna o conteúdo da página em formato Markdown.
"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()
# Adicionaremos furtividade aqui em breve
await page.goto(url, wait_until="networkidle")
html_content = await page.content()
await browser.close()
# Converte para Markdown eficiente em tokens
text_content = markdownify(html_content, strip=['script', 'style'])
return text_content
if __name__ == "__main__":
mcp.run_stdio_async()
Esta implementação básica funciona para sites simples. A diretiva wait_until="networkidle" garante que o navegador aguarde a conclusão das solicitações XHR antes de despejar o HTML. Passamos o HTML bruto pelo markdownify para remover menus de navegação, scripts e CSS. Isso reduz a carga de tokens no LLM, tornando a resposta mais barata e rápida de processar.
Aplicando a Furtividade do Playwright
O servidor básico falha em domínios com proteção padrão contra bots. Scripts de segurança procuram a propriedade webdriver no objeto navigator. Eles verificam a presença de plugins padrão do navegador. Eles inspecionam a string do agente do usuário.
O pacote playwright-stealth injeta scripts na página antes que o conteúdo principal carregue. Esses scripts sobrescrevem as propriedades do navegador, simulam o array de plugins e patcham o objeto window.chrome para imitar uma sessão de usuário regular.
Vamos modificar a ferramenta browse para implementar a furtividade. Inicializamos as modificações de furtividade imediatamente após criar o objeto da página.
```python title="server.py" {11-12}
@mcp.tool()
async def browse(url: str) -> str:
"""
Busca e renderiza uma página da web.
Retorna o conteúdo da página em formato Markdown.
"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()
# Aplique patches de furtividade antes da navegação
await stealth_async(page)
try:
await page.goto(url, wait_until="networkidle", timeout=30000)
html_content = await page.content()
except Exception as e:
await browser.close()
return f"Erro ao carregar a página: {str(e)}"
await browser.close()
return markdownify(html_content, strip=['script', 'style'])
Chamando `await stealth_async(page)`, o plugin substitui os identificadores headless padrão. O navegador agora se reporta corretamente, mascara as flags de automação e tem uma maior probabilidade de carregar o conteúdo alvo sem acionar um CAPTCHA.
## Gerenciamento de Contexto e Desempenho
Lançar uma nova instância de navegador para cada solicitação adiciona uma latência significativa. Um início a frio leva vários segundos. Para um servidor MCP de produção, você deve manter uma instância de navegador persistente e abrir novos contextos para cada solicitação.
Um contexto de navegador é uma sessão isolada. Ele tem seus próprios cookies, cache e armazenamento local. Ao reutilizar o processo do navegador e criar contextos novos, você reduz o tempo de execução da ferramenta em até 60%.
```python title="optimized_server.py" {13-14,21-22}
from mcp.server.fastmcp import FastMCP
from playwright.async_api import async_playwright
from playwright_stealth import stealth_async
from markdownify import markdownify
mcp = FastMCP("StealthBrowser")
browser_instance = None
@mcp.lifespan()
async def manage_browser():
global browser_instance
playwright = await async_playwright().start()
browser_instance = await playwright.chromium.launch(headless=True)
yield
await browser_instance.close()
await playwright.stop()
@mcp.tool()
async def browse(url: str) -> str:
global browser_instanceEste artigo é essencial para empresas brasileiras que desejam integrar agentes de IA em suas operações. A implementação de um servidor MCP pode melhorar a coleta de dados em tempo real, essencial para análise de mercado e tomada de decisões. A capacidade de contornar proteções contra bots é crucial em um ambiente digital competitivo.
Noticias relacionadas

Eu dei acesso ao Claude ao Calculadora do Windows via MCP — Depois assisti ele corrigir sua própria alucinação
Um servidor MCP foi criado para permitir que Claude interaja com aplicativos de desktop do Windows. Durante um teste, o agente identificou um erro que se provou ser uma alucinação, demonstrando a capacidade de auto-correção ao verificar a tela real.

Integre YouTube com Claude usando MCP
Descubra como integrar o Claude com YouTube para facilitar a extração de transcrições e informações relevantes, melhorando a eficiência de estudantes, pesquisadores e criadores de conteúdo.

Por que agentes de codificação de IA precisam de uma espinha de tarefas
O artigo discute a necessidade de uma estrutura que permita que agentes de IA mantenham o contexto entre sessões de programação, evitando a repetição de decisões e tarefas. A solução proposta é o Shinobi, um servidor MCP que registra e recupera informações relevantes.
Gostou do conteudo?
Receba toda semana as principais novidades sobre WebMCP.