Playwright E2E MCP

Execute, depure e inspecione testes ponta a ponta do Playwright a partir de qualquer agente de IA: resultados estruturados com diagnósticos de falha em arquivo:linha, inspeção de DOM ao vivo, validação de seletores, diffs visuais e diagnóstico de testes instáveis.

Servidor MCP hospedado

npx add-mcp 'https://playwright-e2e-mcp.vercel.app/api/mcp'

Instala no Claude Code, Codex, Cursor e outros

Documentação

playwright-e2e-mcp

CI release MCP Registry

Um servidor MCP que permite que agentes de IA executem, depurem e inspecionem testes Playwright de ponta a ponta — com resultados estruturados, diagnósticos acionáveis de falhas e inspeção de DOM ao vivo.

run-test ──▶ get-failure ──▶ inspect-page ──▶ validate-selector ──▶ fix ──▶ re-run
   ▲                                                                    │
   └──────────────────────── list-tests ◀────────────────────────────────┘

Em vez de entregar ao agente a saída bruta do Playwright, este servidor transforma cada execução em resultados processáveis por máquina: estatísticas de aprovação/reprovação, mensagens por falha com file:line, um tipo de falha (asserção, timeout, travamento do navegador, erro de sintaxe, servidor de desenvolvimento morto, disco cheio…), e uma dica concreta de "como corrigir". Quando um teste falha porque um seletor não corresponde mais, o agente pode abrir a página ao vivo em um navegador headless, ver o DOM real com seletores CSS únicos e validar o seletor de substituição antes de executar novamente.

Demonstração

Endpoint hospedado — o que um round-trip de initialize + tools/list contra https://playwright-e2e-mcp.vercel.app/api/mcp retorna para um cliente que envia o token bearer (sem ele, apenas list-tests e get-failure são listados):

Token-protected endpoint: initialize handshake and all 8 tools

Uma execução de teste real — run-test servido via stdio por npx -y playwright-e2e-mcp contra o examples/sample-test.spec.ts incluído (saída real, sem edição):

run-test result: 4 passed, 0 failed, 5.1s

As imagens são renderizadas com node scripts/gen-demo-images.mjs: o cartão de execução de teste é uma captura real da saída; o cartão de endpoint é uma ilustração da listagem autenticada.

Instalação

Funciona com Claude Desktop, Claude Code, Cursor, Windsurf, Codex, Gemini CLI, Freebuff e qualquer outro cliente MCP — escolha a rota que preferir:

RotaComo
npm (canônica, mais rápida)npx -y playwright-e2e-mcp
MCP Registry (clientes com suporte a registry descobrem automaticamente)io.github.trajectiq-ai/E2E — listagem
Qualquer cliente, sem conta npmnpx -y github:trajectiq-ai/E2E#v0.1.2 (fixe uma tag de release)
Claude Desktop, sem configuração de Nodeclique duas vezes na extensão .mcpb
Clientes somente remotos (conectores ChatGPT)https://playwright-e2e-mcp.vercel.app/api/mcp

Detalhes e configuração por cliente: Instalação · Configuração do cliente MCP.


Ferramentas

FerramentaFinalidade
run-testExecuta testes Playwright e retorna estatísticas, falhas, diagnósticos e dicas
get-failureAnálise aprofundada de uma falha: stack, esperado/real, snapshot do DOM no momento da falha (do trace do Playwright), próximos passos
inspect-pageAbre uma URL sem interface gráfica e retorna o DOM renderizado: seletores, visibilidade, caixas, texto, saída do console, HTML
list-testsLista testes disponíveis (file, line, título completo, projetos) com filtragem
validate-selectorVerifica um seletor CSS em uma página ao vivo: validade, contagem de correspondências, exemplos de correspondências
generate-e2e-testGera um teste Playwright a partir de uma descrição usando os seletores reais do projeto, descobertos a partir de alterações recentes de arquivos
compare-visual-stateRegressão visual: captura de tela antes/depois de uma alteração e relata o que mudou e como as cores mudaram
diagnose-flakyExecuta um teste com falha 2–10 vezes com novas tentativas desabilitadas e retorna um veredito com evidências: CONSISTENTLY FAILING, FLAKY ou NOT REPRODUCING

run-test

ArgumentoTipoDescrição
projectRootstringDiretório do projeto dentro da raiz configurada (padrão: diretório de trabalho do servidor)
testFilesstring[]Arquivos/diretórios relativos à raiz; file:line suportado. Omita para executar tudo
grepstringExecuta apenas testes cujo título corresponda a esta regex
browserchromium | firefox | webkitProjeto Playwright a executar (comparado com os nomes de projeto da configuração)
headedbooleanJanela do navegador visível
timeoutMsnumberLimite rígido de tempo real para a execução (padrão 120000); toda a árvore de processos é encerrada após isso e resultados parciais são retornados
testTimeoutMsnumberTimeout por teste passado ao Playwright
workers / retriesnumberRepassados ao Playwright
configstringCaminho do playwright.config ou índice baseado em 1 quando o projeto tem vários
retryOnFailurebooleanRepete automaticamente falhas uma vez antes de relatá-las (padrão true; ignorado quando retries está definido)
lastFailedbooleanExecuta apenas testes que falharam na execução anterior (Playwright --last-failed) — o ciclo rápido de corrigir → executar novamente
argsstring[]Flags extras do Playwright de uma lista permitida (--repeat-each=N, --max-failures=N, --update-snapshots, --shard=1/3, --trace=on, …); valores vão após = e são verificados, e flags que recebem um caminho, como --config ou --output, são rejeitadas

Tratamento de flakiness: por padrão, o servidor injeta --retries=1 (a menos que a configuração já defina retries), então um teste que passa na nova tentativa é relatado como flaky, não como falha. Traces são capturados automaticamente (--trace=retain-on-failure) para que get-failure possa mostrar o DOM no momento da falha.

Exemplo de resultado:

## Playwright run — ❌ FAILED

**Command:** `playwright test --config playwright.config.ts tests/checkout.spec.ts --reporter=json`
**duration 4.2s · exit 1 · config `playwright.config.ts`**

| passed | failed | flaky | skipped | duration |
| ---: | ---: | ---: | ---: | ---: |
| 0 | 1 | 0 | 0 | 1.1s |

### ❌ 1 failing test(s)

### 1 of 1. checkout.spec.ts › pays with card
**File:** `checkout.spec.ts:5`  |  **failed · server-unreachable**

### ⚠️ SERVER_NOT_RUNNING
Your app (dev server) does not appear to be reachable. Start it in another terminal
(e.g. npm run dev / npm start), keep it running, then retry — or configure `webServer`
in playwright.config.* so Playwright starts it automatically.

get-failure

ArgumentoTipoDescrição
indexnumberÍndice de falha baseado em 1 da última execução (padrão 1)
projectRootstringUsado apenas ao reler o relatório armazenado

Retorna a mensagem/quadro de código, esperado vs. real, stack, tipo de falha com um diagnóstico, a saída do console do teste, o snapshot do DOM do trace do Playwright (além da ação que falhou, seu seletor e o log de ações que levaram a ela), as requisições de rede que falharam (4xx/5xx, endpoints mortos, sem resposta — com método, URL, status e tipo de recurso), os erros/avisos do console que a página registrou antes da falha, e próximos passos numerados (re-executar este único teste por file:line, modo headed/debug, validate-selector quando a mensagem mencionar um locator, …).

inspect-page

ArgumentoTipoDescrição
urlstringURL http(s) completa para abrir (obrigatório)
projectRootstringProjeto cujo Playwright inicia o navegador
selectorstringInspeciona correspondências deste seletor CSS em vez do DOM inteiro
waitForstringAguarda um seletor (CSS ou text=…) antes de inspecionar
waitUntilload | domcontentloaded | networkidleCondição de espera de navegação
includeHtmlbooleanInclui o HTML renderizado (limitado)
maxHtmlCharsnumberLimite de HTML, padrão 20000
timeoutMsnumberLimite geral, padrão 45000

Retorna o seletor CSS único de cada elemento, tag, visibilidade, caixa delimitadora, texto e atributos, além de mensagens do console capturadas (erros primeiro).

list-tests

ArgumentoTipoDescrição
projectRootstringDiretório do projeto
configstringCaminho da configuração ou índice baseado em 1
testDirstringRestringe a varredura a um diretório (deve permanecer dentro do projeto)
filterstringFiltro de substring sem diferenciar maiúsculas/minúsculas em file › title
limitnumberMáximo de testes retornados, padrão 500

Usa playwright test --list quando o Playwright funciona e recorre a uma varredura de código-fonte (mantendo o motivo) quando a instalação ou um arquivo de spec está quebrado.

validate-selector

ArgumentoTipoDescrição
urlstringPágina ao vivo para testar (obrigatório)
selectorstringSeletor CSS para validar (obrigatório)
projectRootstringProjeto cujo Playwright inicia o navegador
timeoutMsnumberLimite geral, padrão 45000

Vereditos: ✅ VALID — N matches (com uma amostra de correspondências), ✅ VALID — 0 matches (com conselhos de depuração), ❌ INVALID (erro de análise + correção), ou um aviso quando a entrada usa um mecanismo exclusivo do Playwright (text=, xpath=, >>, :has-text()), que não é CSS puro.

generate-e2e-test

ArgumentoTipoDescrição
descriptionstringO que o teste deve cobrir (obrigatório)
pageUrlstringPágina em que o teste começa (padrão: baseURL / webServer.url da configuração)
testDir / filestringOnde escrever o spec (padrão: testDir detectado + generated/<slug>.spec.ts); file deve terminar em .spec.* ou .test.*
writebooleanEscreve o arquivo no disco (padrão true)
overwritebooleanSubstitui um spec existente no caminho de destino; apenas specs que esta ferramenta gerou podem ser substituídos
liveInspectbooleanVerifica cruzadamente os seletores na página ao vivo (padrão ativado quando uma URL é conhecida)
projectRoot / configstringComo nas outras ferramentas

Lê as alterações recentes do agente (git status, recorrendo a git diff HEAD~1, depois mtimes recentes), extrai os locators que esses arquivos realmente declaram (data-testid, getByRole, aria-label, placeholder, id, name, texto do elemento), classifica seletores verificados como ativos primeiro, escreve um spec construído a partir deles e relata cada seletor com sua fonte file:line.

compare-visual-state

ArgumentoTipoDescrição
urlstringPágina para capturar (obrigatório)
namestringID da linha de base, ex.: checkout-page (letras, dígitos, . _ -)
actioncompare | baselinecompare (padrão) diffs; baseline recaptura a referência
selectorstringCaptura apenas este elemento
fullPagebooleanCaptura a página inteira rolável
tolerancenumberPercentual de pixels que podem diferir (padrão 0.1)
pixelThresholdnumberDelta de canal por pixel considerado diferente (padrão 60)
waitUntil / waitFor / timeoutMs—Como em inspect-page

A primeira chamada salva uma linha de base em .pw-mcp/visual/ (adicione-a ao .gitignore, ou faça commit para comparações em CI). Chamadas posteriores relatam contagens de pixels alterados, regiões mescladas ((x, y) 120×40 — 1,200 px), a mudança média de cor ("azul → vermelho"), e escrevem uma imagem de diff destacada em vermelho para revisão.

diagnose-flaky

ArgumentoTipoDescrição
testFilesstring[]Testes para diagnosticar (file:line suportado). Padrão: os testes que falharam na execução mais recente
runsnumberVezes para executá-los, 2–10 (padrão 3)
browser / headed / workers / config—Como em run-test
timeoutMsnumberLimite rígido de tempo real por execução (padrão 120000)
projectRootstringDiretório do projeto

Cada execução é feita com --retries=0 e nova tentativa automática desabilitada, então cada resultado é evidência honesta. A resposta contém uma tabela por execução (status, duração, primeira falha), a contagem de assinaturas de erro normalizadas distintas, e um dos seguintes:

  • ❌ FALHANDO CONSISTENTEMENTE — falhou em todas as execuções (mesmo erro → bug reproduzível, erros diferentes → ainda quebrado, apenas ruidoso). Corrija; não é flaky.
  • ⚠️ FLAKY — algumas execuções passaram. Inclui contagens de N of M e se as falhas compartilham uma assinatura (bug intermitente real) ou variam (instabilidade de timing/ambiente).
  • ✅ NÃO REPRODUZINDO — passou em todas as re-execuções; a falha original foi pontual.

A última execução é armazenada, para que get-failure possa analisá-la imediatamente depois.


Instalação

Requisitos:

  • Node.js ≥ 20 (o servidor é construído no MCP SDK v2 — a linha de especificação 2026-07-28)
  • Um projeto com @playwright/test instalado e navegadores disponíveis (npx playwright install chromium)

Nenhuma conta npm necessária — instale direto do GitHub (o script prepare compila dist/ automaticamente na instalação). Fixe uma tag de release: um github:trajectiq-ai/E2E não fixado executa o que estiver no branch padrão naquele momento.

npx -y github:trajectiq-ai/E2E#v0.1.2
npm install -D github:trajectiq-ai/E2E#v0.1.2 @playwright/test   # or as a project dependency
npx playwright install chromium

Ou pegue o tarball empacotado da página GitHub Releases do repositório e instale-o localmente:

npm install -D https://github.com/trajectiq-ai/E2E/releases/download/v0.1.2/playwright-e2e-mcp-0.1.2.tgz

Listado no MCP Registry oficial como io.github.trajectiq-ai/E2E — clientes que reconhecem o registry o descobrem lá, e cada tag de release v* republica a entrada do CI via server.json.

Configuração do cliente MCP

Claude Code / genérico (escopo do projeto):

{
  "mcpServers": {
    "playwright-e2e": {
      "command": "npx",
      "args": ["-y", "github:trajectiq-ai/E2E#v0.1.2"],
      "env": { "PW_MCP_PROJECT_ROOT": "/absolute/path/to/your/project" }
    }
  }
}

Claude Desktop / Cursor / Windsurf: adicione o mesmo bloco ao arquivo de configuração MCP deles. O servidor usa seu diretório de trabalho como raiz do projeto; defina PW_MCP_PROJECT_ROOT quando o cliente o iniciar em outro lugar (ex.: seu diretório home).

Codex / VS Code / CLIs do Copilot:

codex mcp add playwright-e2e -- npx -y github:trajectiq-ai/E2E#v0.1.2
code --add-mcp '{"name":"playwright-e2e","command":"npx","args":["-y","github:trajectiq-ai/E2E#v0.1.2"]}'

Os padrões do Codex conflitam com este servidor: o primeiro lançamento clona o repositório e executa tsc (medido em 30 s em um cache npx frio, contra um padrão de 10 s do startup_timeout_sec), e uma execução do Playwright com novas tentativas excede o padrão de 60 s do tool_timeout_sec. Aumente ambos em ~/.codex/config.toml:

[mcp_servers.playwright-e2e]
command = "npx"
args = ["-y", "github:trajectiq-ai/E2E#v0.1.2"]
startup_timeout_sec = 60
tool_timeout_sec = 600

Claude Desktop (um clique): baixe e clique duas vezes na Extensão de Desktop .mcpb anexada ao último release — o pacote inclui suas próprias dependências, então nenhuma configuração do Node é necessária. Na instalação, ele pede que você escolha sua raiz do projeto (obrigatório, sem padrão: escolha a pasta do projeto, não seu diretório home) e a conecta ao PW_MCP_PROJECT_ROOT, para que as ferramentas apontem para um projeto real desde a primeira chamada.

Claude Code:

claude mcp add playwright-e2e -- npx -y github:trajectiq-ai/E2E#v0.1.2

Gemini CLI / Qwen Code: cole o bloco mcpServers acima em .gemini/settings.json (Qwen Code: .qwen/settings.json) — ambos falam o mesmo formato de configurações MCP.

Freebuff / Codebuff (escopo do projeto): este repositório inclui um .agents/mcp.json commitado, então abrir o checkout no Freebuff anexa o servidor em todo o workspace — nenhuma configuração global necessária. Seus próprios projetos podem fazer o mesmo: coloque um mcp.json com o bloco acima no diretório .agents/ deles. O Freebuff pede que você confie no .agents/ de um repositório na primeira execução.

Todas as ferramentas incluem anotações de ferramenta MCP (readOnlyHint, destructiveHint, idempotentHint, openWorldHint), para que os clientes possam mostrar avisos de segurança precisos antes de executar qualquer coisa.

De um checkout local:

{
  "mcpServers": {
    "playwright-e2e": {
      "command": "node",
      "args": ["/path/to/playwright-e2e-mcp/dist/index.js"],
      "env": { "PW_MCP_PROJECT_ROOT": "/path/to/your/project" }
    }
  }
}

Endpoint hospedado (ChatGPT e clientes remotos)

Alguns clientes — conectores personalizados do ChatGPT especialmente — só aceitam servidores MCP HTTPS remotos e se recusam a iniciar um processo npx local. Este repositório inclui um bridge HTTP Streamable exatamente para esse caso:

Endpointhttps://playwright-e2e-mcp.vercel.app/api/mcp
TransporteMCP Streamable HTTP (JSON POST de entrada, JSON ou SSE de saída)
Autenticaçãotoken bearer opcional (PW_MCP_HTTP_TOKEN); sem ele, apenas ferramentas somente leitura são servidas
Fonteapi/mcp.ts → src/http.ts

O bridge executa o mesmo createServer() que o transporte stdio; o SDK atende cada requisição com uma instância de servidor nova, que é o que uma função serverless quer. test/http-bridge.test.mjs aciona o adaptador Node real via node:http, então um bridge quebrado falha no CI, não no ChatGPT.

Aberto vs. protegido por token. Quando a implantação não tem PW_MCP_HTTP_TOKEN, qualquer pessoa pode acessar a URL, então o bridge serve apenas list-tests e get-failure, em modo restrito: list-tests escaneia fontes em vez de executar playwright test --list (que executaria a configuração do projeto), chamadores não podem escolher outro projectRoot, e nada inicia um processo, aciona um navegador ou grava um arquivo. Defina PW_MCP_HTTP_TOKEN (pelo menos 16 caracteres; use um valor aleatório) para servir todas as oito ferramentas a clientes que enviarem Authorization: Bearer <token>; outras requisições recebem 401. Processos filhos iniciados via HTTP recebem apenas um ambiente na allowlist. PW_MCP_ALLOWED_HOSTS (separado por vírgulas, * para qualquer) limita o cabeçalho Host aceito; sem token e sem essa variável, apenas nomes localhost e os hostnames Vercel da própria implantação são aceitos (proteção contra DNS-rebinding).

Adicione ao ChatGPT: Configurações → Conectores → ative Avançado → Modo desenvolvedor → Criar conector personalizado → cole o endpoint acima → autenticação Nenhuma (ferramentas somente leitura).

O Codex também pode usar o transporte remoto em vez de iniciar npx, se você preferir não enviar o Playwright para todas as máquinas:

codex mcp add playwright-e2e-remote --url https://playwright-e2e-mcp.vercel.app/api/mcp

O que esperar: list-tests funciona e relata as especificações incluídas na implantação. Mesmo com um token, ferramentas que iniciam um navegador (run-test, inspect-page, validate-selector, diagnose-flaky, …) não podem baixar Chromium em uma função serverless, então elas retornam sua dica NO_PLAYWRIGHT normal. Use a instalação stdio para execuções reais; o endpoint hospedado é para descoberta e para clientes que não podem executar processos locais.

# verify the handshake without any client
curl -X POST https://playwright-e2e-mcp.vercel.app/api/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

Reimplante após uma mudança: mescle para main. A integração Git do Vercel implanta cada push, então não há token para gerenciar e nenhum passo de CLI — observe o status de commit Vercel para o resultado da implantação.

Configuração

Variável de ambientePadrãoPropósito
PW_MCP_PROJECT_ROOTcwd do servidorRaiz do projeto padrão para cada ferramenta
PW_MCP_ALLOWED_ROOTS—Diretórios extras que um chamador pode passar como projectRoot (separados por :, ; no Windows). Qualquer coisa fora desses e da raiz padrão é rejeitada
PW_MCP_HTTP_TOKEN—Apenas bridge HTTP: token bearer (16+ caracteres) que desbloqueia todas as ferramentas (veja acima)
PW_MCP_ALLOWED_HOSTSlocalhost + hostnames Vercel quando não há tokenApenas bridge HTTP: allowlist Host separada por vírgulas; * aceita qualquer
PW_MCP_PASSTHROUGH_ENV—Apenas bridge HTTP: variáveis extras separadas por vírgulas passadas às execuções de teste (ex.: BASE_URL)
PW_MCP_MAX_CHILDREN4Apenas bridge HTTP: quantas execuções de teste e sondas de navegador podem rodar ao mesmo tempo
PW_MCP_BLOCK_PRIVATE_URLSdesligado (ligado para o bridge HTTP)1 faz as ferramentas de URL recusarem endereços loopback, rede privada e metadados de nuvem, incluindo redirecionamentos e subrecursos
LOG_LEVELinfodebug | info | warn | error | silent
LOG_FORMATtexttext ou json (estruturado)

Os logs sempre vão para stderr — stdout é reservado para o protocolo MCP.

Fluxo de trabalho típico

  1. generate-e2e-test { "description": "checkout with a saved card" } — cria um spec a partir dos seus seletores reais (pulado se você escrever o teste você mesmo).
  2. list-tests — veja o que existe (tests/checkout.spec.ts:5 checkout › pays with card).
  3. run-test { "testFiles": ["tests/checkout.spec.ts"] } — execute-o; obtenha estatísticas + falhas (testes instáveis são automaticamente tentados novamente uma vez antes de serem chamados de falhas).
  4. get-failure { "index": 1 } — leia o quadro de código, esperado/real, o snapshot do DOM na falha do trace, as requisições de rede falhas, os erros de console da página e os próximos passos.
  5. Se parecer relacionado a seletores: inspect-page { "url": "http://localhost:3000/checkout" } para ver o DOM real, então validate-selector para provar que o seletor substituto funciona.
  6. Após mudar CSS/componentes: compare-visual-state { "url": "…", "name": "checkout" } para detectar regressões visuais não intencionais.
  7. Se uma falha parecer intermitente: diagnose-flaky { "runs": 3 } — obtenha o veredito de evidência (instável vs. consistentemente quebrado) antes de decidir o que corrigir.
  8. Corrija o spec ou o aplicativo, então execute novamente apenas o que falhou: run-test { "lastFailed": true }, e repita até ficar verde.

Casos de borda tratados

SituaçãoComportamento
Playwright não instaladoErro NO_PLAYWRIGHT com os comandos de instalação exatos para seu gerenciador de pacotes
Servidor de desenvolvimento não rodandoFalha classificada como server-unreachable / SERVER_NOT_RUNNING com uma dica "inicie seu servidor de desenvolvimento" (e conselho webServer)
Teste excede timeoutMsO grupo de processos é morto (SIGINT→SIGKILL no POSIX, taskkill /T /F no Windows) e resultados parciais são retornados
Navegador travaClassificado como browser-crash com orientação de nova tentativa / reinstalação
Barras invertidas no WindowsTodos os caminhos normalizados lexicalmente (C:\a\..\b → C:/b); testado por unidade em ambas as plataformas
Testes instáveisTestes com falha são automaticamente tentados novamente uma vez (--retries=1) antes de serem relatados; passes aparecem como instáveis com um aviso de estabilidade; diagnose-flaky decide instável-vs-quebrado com evidência de múltiplas execuções
Contexto de trace/DOM--trace=retain-on-failure é passado automaticamente, então get-failure pode mostrar o DOM exato no momento da falha — além das requisições de rede falhas (logs *.network) e erros de console do mesmo trace
Re-execuções lentas após uma correçãorun-test com lastFailed: true re-executa apenas os testes que falharam da última vez (--last-failed)
Vários arquivos playwright.configRetorna um menu numerado (MULTIPLE_CONFIGS); escolha com config: "2" ou um caminho
Erro de sintaxe em um specSYNTAX_ERROR com arquivo:linha; nada trava; list-tests cai para uma varredura de fonte
Cliente MCP desconectaAbortSignal por requisição mata a execução; o fim do stdin aciona o desligamento, e cada árvore filha rastreada é morta à força (killActiveChildren)
Disco cheioENOSPC detectado → DISK_FULL com uma dica "liberar espaço"; o registro nunca lança exceções
Caminhos maliciosos../../etc/passwd, caminhos absolutos fora da raiz, um projectRoot fora das raízes permitidas, symlinks que saem da raiz, URLs e bytes nulos são rejeitados com INVALID_PATH; argumentos extras de CLI devem ser flags do Playwright na allowlist

Notas de segurança

  • Sem shell: O Playwright é iniciado como node <playwright/cli.js> … com um array de argumentos — sem interpolação de comandos. args extras são limitados a uma lista de permissões de flags do Playwright, cada uma com um valor verificado (--flag=value), então um chamador não pode trocar por outro --config ou --output ou passar uma opção ao git através de --only-changed. Caminhos com um segmento começando com - são rejeitados, então um nome de arquivo de teste não pode ser lido como uma flag.
  • Sandbox de caminhos: caminhos do usuário devem permanecer dentro da raiz do projeto, verificados lexicalmente e novamente com symlinks resolvidos. Um projectRoot fornecido pelo chamador deve estar dentro de PW_MCP_PROJECT_ROOT (ou uma entrada de PW_MCP_ALLOWED_ROOTS).
  • Código gerado: generate-e2e-test apenas escreve arquivos *.spec.* / *.test.*, apenas sobrescreve specs cujo cabeçalho ele mesmo escreveu, nunca escreve através de um symlink, e escapa todo valor que coloca em strings ou comentários.
  • Ponte HTTP: ferramentas somente leitura, a menos que PW_MCP_HTTP_TOKEN esteja definido; processos filhos iniciados via HTTP recebem apenas um ambiente na lista de permissões (PATH, HOME, diretórios temporários, locale, CI, PLAYWRIGHT_*, npm_config_* sem credenciais embutidas, além de qualquer coisa em PW_MCP_PASSTHROUGH_ENV), no máximo PW_MCP_MAX_CHILDREN em execução por vez (um cliente desconectado libera seu slot imediatamente), e mensagens de erro internas não são retornadas aos clientes. A lista de permissões cobre apenas o ambiente do próprio filho: o código de teste roda como o mesmo usuário do SO, então no Linux ele ainda poderia ler o ambiente de inicialização do servidor a partir de /proc. É por isso que apenas detentores de tokens podem executar código do projeto; mantenha outros segredos fora do ambiente da ponte, ou execute-a sob um usuário separado.
  • Proteção SSRF: na ponte HTTP (ou com PW_MCP_BLOCK_PRIVATE_URLS=1) as ferramentas de URL recusam hosts que resolvem para endereços loopback, privados, link-local/metadata ou reservados, e roteiam o navegador através de um proxy local que aplica a mesma verificação a cada salto de redirecionamento e subrecurso; formas IPv6 que incorporam um endereço IPv4 (mapeado, NAT64, 6to4, Teredo) também são bloqueadas, e o UDP WebRTC é desabilitado para que uma página não possa alcançar a rede contornando o proxy. Está desligado para stdio por padrão porque abrir servidores de desenvolvimento http://localhost é para isso que essas ferramentas servem.
  • Limpeza: arquivos temporários de relatório/script são gravados no diretório temporário do SO e removidos; processos filhos são rastreados e encerrados no desligamento. A descompressão de rastreamento tem um orçamento de tamanho por arquivo, e PNGs são limitados a 16.384 px por lado e 50 M pixels.

Desenvolvimento

src/
├── index.ts            # bin entry point (--version/--help, main-module guard)
├── server.ts           # McpServer setup, tool registration, shutdown handling
├── tools/              # the eight tools + shared plumbing
├── utils/              # playwright-runner, report-parser, project-detector, path-utils,
│                       # logger, trace-reader (trace.zip → DOM/network/console),
│                       # image-diff (PNG codec + pixel diff), change-analyzer
└── types/              # shared interfaces and the ErrorKind taxonomy

Construído sobre @modelcontextprotocol/server v2 (a linha de especificação MCP 2026-07-28) com esquemas padrão Zod v4; cada ferramenta declara anotações de ferramenta da especificação.

npm install
npm run build   # tsc → dist/ (zero errors)
npm test        # build + test/run-tests.mjs (unit tests, any Node ≥20)
npm run e2e     # build + e2e/run.mjs: live MCP ↔ Playwright integration suite

Os testes cobrem o analisador de relatórios (JSON de amostra do Playwright, anexos de rastreamento), utilitários de caminho (caminhos Windows e macOS, sandboxing), o detector de projetos (fixtures de diretório temporário: descoberta de configuração, múltiplas configurações, instalação ausente, varredura de arquivos de teste), os helpers compartilhados de ferramentas, o leitor de rastreamento (trace.zip sintético: erro, ação falha, snapshot DOM, análise de requisição falha *.network, eventos de erro/aviso de console), o diff de imagem (round-trip PNG, regiões, mudança de cor, mudanças de dimensão), o analisador de mudanças (extração de seletores, caminhos git + mtime), a lógica de veredito flaky (assinaturas de falha, CONSISTENTLY FAILING / FLAKY / NOT REPRODUCING / NO TESTS RAN), a ponte HTTP (token, modo restrito, lista de permissões de Host), as regressões de segurança (fugas de sandbox, contrabando de argumentos, gravações via symlink, injeção de código, faixas SSRF, limpeza de ambiente, limites de decodificação), o manifesto .mcpb e os arquivos de configuração MCP.

Suíte de integração (npm run e2e)

Testes unitários provam a lógica; a suíte de integração prova o ciclo completo. Ela inicia o servidor real via stdio contra um aplicativo fixture ao vivo e um projeto Playwright sob e2e/fixture/, então o conduz exatamente como um cliente MCP e verifica ~40 comportamentos que só aparecem de ponta a ponta:

  • handshake de inicialização, 8 ferramentas, anotações de ferramenta da especificação e esquemas de entrada de objeto,
  • inspeção DOM ao vivo, validação de seletores CSS (correspondências, zero correspondências, sintaxe de engine, erros de análise), detecção de servidor morto,
  • regressão visual: baseline → comparação inalterada → detecção de diff blue → red,
  • estatísticas e linhas de meta de pass/fail/run-test lastFailed,
  • diagnósticos de rastreamento get-failure: DOM na falha, a requisição de rede 404, a mensagem console.error, diagnóstico e próximos passos,
  • nova tentativa automática transformando uma falha de primeira execução em PASSED (1 flaky),
  • veredito diagnose-flaky FLAKY (2 de 3 execuções) com novas tentativas desabilitadas,
  • generate-e2e-test escrevendo seu scaffold, além de caminhos de erro (caminho de teste ausente, ferramenta desconhecida, servidor inacessível).

A primeira execução precisa do navegador uma vez: npx playwright install chromium. CI executa a suíte no Ubuntu e Windows (veja .github/workflows/ci.yml).

Experimente o exemplo

Com o Playwright instalado no seu projeto:

npx playwright test examples/sample-test.spec.ts

ou peça ao seu agente para chamar run-test com "testFiles": ["examples/sample-test.spec.ts"] — ele acessa a página pública example.com, então verifica navegadores, rede e o pipeline MCP de uma só vez.

Licença

MIT