@diegosouzacdv/jev-browser-mcp 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,7 +17,7 @@ versão em produção, use o número explícito no argumento do pacote:
17
17
  "mcpServers": {
18
18
  "jev-browser": {
19
19
  "command": "npx",
20
- "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.6.1"],
20
+ "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.6.2"],
21
21
  "env": {
22
22
  "OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
23
23
  "JEV_BROWSER_MODE": "computer"
@@ -32,7 +32,7 @@ um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
32
32
  de configuração. Para instalar no projeto Node do próprio harness:
33
33
 
34
34
  ```sh
35
- npm install @diegosouzacdv/jev-browser-mcp@0.6.1
35
+ npm install @diegosouzacdv/jev-browser-mcp@0.6.2
36
36
  ```
37
37
 
38
38
  Se o harness executa o MCP repetidamente nesta máquina, instale uma versão
@@ -40,7 +40,7 @@ fixa globalmente para evitar a resolução e o download feitos pelo `npx` em cad
40
40
  inicialização:
41
41
 
42
42
  ```sh
43
- npm install --global @diegosouzacdv/jev-browser-mcp@0.6.1
43
+ npm install --global @diegosouzacdv/jev-browser-mcp@0.6.2
44
44
  ```
45
45
 
46
46
  Depois configure o servidor MCP com `command: "jev-browser-mcp"` e `args: []`.
@@ -49,7 +49,7 @@ Para atualizar, rode `npm install --global
49
49
 
50
50
  O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
51
51
  configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
52
- pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp@0.6.1 --install-browser`.
52
+ pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp@0.6.2 --install-browser`.
53
53
 
54
54
  O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
55
55
  persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
@@ -107,11 +107,17 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
107
107
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
108
108
  resultado esperado na tela.
109
109
 
110
- Cada plano pode usar:
111
-
112
- - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
113
- papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
114
- `text`, `test_id` ou `selector`;
110
+ Cada plano pode usar:
111
+
112
+ - `navigate` para mudar de página no meio do fluxo. Com a continuidade ligada,
113
+ um `initial_url` de mesma origem diferente da URL ativa produz erro claro; use
114
+ `navigate` ou `continue_from_current_page: false` para escolher o destino;
115
+ - `click`, `type`, `clear`, `hover`, `select_option`, `press`, `assert_*` e upload com
116
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
117
+ `text`, `test_id` ou `selector`;
118
+ - `name_match: "exact" | "contains" | "regex"` para controlar a comparação do
119
+ nome acessível; regex rejeita construções com backtracking excessivo. O papel
120
+ `switch` funciona em cliques, verificações e asserções;
115
121
  - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
116
122
  `within: {"row_containing":"..."}` para limitar por trecho e
117
123
  `within: {"row_containing_exact":"..."}` para exigir um elemento com o
@@ -128,25 +134,34 @@ Cada plano pode usar:
128
134
  - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
129
135
  em `warnings`; não é permitido enviar JavaScript nem coordenadas;
130
136
  - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
131
- - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
132
- `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
133
- valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
134
- - `wait_for_text`, `wait_for_value`, `wait_for_enabled` e `wait_for_condition`
135
- (`network_idle`, `hidden`, `text_hidden` ou `angular_idle`). `wait` recebe
137
+ - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
138
+ `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
139
+ valor apareça nas evidências. `text_env` lê o valor sensível de uma variável
140
+ de ambiente do processo MCP, sem colocá-lo no plano. Nesse modo, `\n` envia
141
+ Enter e `\t` envia Tab;
142
+ - `wait_for_text`, `wait_for_value`, `wait_for_enabled` e `wait_for_condition`
143
+ (`url`, `network_idle`, `hidden`, `text_hidden` ou `angular_idle`). `wait` recebe
136
144
  `ms` para uma pausa curta e limitada. `angular_idle` aguarda requisições
137
145
  `$http` e digest do AngularJS. `wait_for_text` aceita `fail_on: {"role":"alert"}` para
138
146
  interromper a espera assim que um alerta visível aparecer e incluir seu texto
139
147
  no erro. Se o alerta contiver o texto esperado, a etapa passa; caso contrário,
140
- o alerta interrompe a espera. `network_idle` aceita `url_contains` para
141
- aguardar só as requisições correspondentes;
142
- - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
143
- `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
144
- envia a tecla ao elemento focado; com alvo, usa o localizador informado;
148
+ o alerta interrompe a espera. `url` aguarda a URL conter `url_contains`.
149
+ `network_idle` aceita esse filtro e aguarda uma janela de silêncio usando
150
+ `ready_stable_ms`; WebSocket, EventSource e polling não relacionado não
151
+ bloqueiam a espera. Se não surgir requisição correspondente, o passo conclui
152
+ após a janela de silêncio;
153
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
154
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab`, `Shift+Tab`, `Space`,
155
+ `Backspace` ou `Delete`. `clear` limpa um campo sem exigir texto. Sem alvo,
156
+ `press` envia a tecla ao elemento focado; com alvo, usa o localizador informado;
145
157
  - `assert_text`, `assert_value`, `assert_visible`, `assert_hidden` e
146
158
  `assert_enabled`; `assert_text`
147
159
  pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
148
- - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
149
- dropzone;
160
+ - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
161
+ dropzone;
162
+ - `target_page: "popup"` para continuar no popup aberto com `expect_popup: true`;
163
+ locators semânticos também atravessam open Shadow DOM. Shadow DOM fechado não
164
+ é acessível ao Playwright;
150
165
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
151
166
  - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
152
167
  não repetem uma reação já no estado pedido e distinguem `Curtir` de
@@ -211,11 +226,12 @@ com `within: {"row_containing_exact":"{pedido}"}`, e use uma etapa
211
226
  `{"action":"extract","role":"cell","name":"{pedido}","within":{"row_containing_exact":"{pedido}"},"as":"documento"}`.
212
227
  A etapa seguinte pode localizar o mesmo documento com `name: "{documento}"`.
213
228
 
214
- Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
215
- localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
216
- aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
217
- `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
218
- esperar que ela termine.
229
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
230
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
231
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
232
+ `url_contains`. O filtro considera somente a atividade correspondente e termina
233
+ após a janela configurada sem atividade; também termina caso nenhuma requisição
234
+ correspondente apareça. Para validar status e corpo, prefira `assert_network`.
219
235
 
220
236
  Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
221
237
  container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
@@ -411,15 +427,17 @@ validadores.
411
427
 
412
428
  `browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
413
429
 
414
- - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
415
- harness e CI; o estado de autenticação é descartado ao final da chamada.
430
+ - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
431
+ harness e CI. O processo MCP conserva browser, contexto e página entre
432
+ chamadas; cookies, local storage e estado da página permanecem enquanto o
433
+ processo estiver ativo. Encerre o processo para descartar o contexto isolado.
416
434
  - `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
417
435
  persistente `browser.computer_user_data_dir`, separado por navegador. Não
418
436
  reutiliza o perfil pessoal já aberto. Faça login uma vez nesse perfil; os
419
437
  cookies permanecem nele entre chamadas.
420
438
 
421
- `browser.max_flow_steps` limita a soma de passos declarados entre os planos e
422
- `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
439
+ `browser.max_flow_steps` limita os passos de cada plano candidato; os planos
440
+ não são somados. `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
423
441
  `status`, o plano escolhido, as ações executadas, a última captura acessível e
424
442
  se o critério esperado apareceu. Quando existem asserções explícitas, `status`
425
443
  também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
@@ -457,9 +475,12 @@ O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
457
475
  `auto_angular_idle`, `login_url_contains`, `login_text`, `capture_console_errors`,
458
476
  `capture_network_errors`, `capture_network_error_bodies`, `ready_timeout_seconds`,
459
477
  `ready_network_idle`, `ready_stable_ms`, `ready_text`, `continue_from_current_page`,
460
- `reuse_page`, `step_timeout_seconds`, `max_flow_steps`, `return_snapshot`,
461
- `screenshot_on_failure`, `trace_on_failure`, `snapshot_include_hidden`,
462
- `stop_on_expected`, `dry_run`, `confirmation_token` e `report_path`. Sem override,
478
+ `reuse_page`, `step_timeout_seconds`, `max_flow_steps`, `return_snapshot`,
479
+ `screenshot_on_failure`, `screenshot_on_success`, `trace_on_failure`,
480
+ `trace_on_success`, `record_video`, `snapshot_include_hidden`, `stop_on_expected`,
481
+ `dry_run`, `confirmation_token`, `report_path`, `permissions`, `fake_media`,
482
+ `viewport`, `mobile`, `device_scale_factor`, `locale`, `timezone_id`,
483
+ `color_scheme`, `geolocation` e `allow_mutations`. Sem override,
463
484
  os padrões são lidos de `jev_browser_mcp` em
464
485
  `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
465
486
  captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
@@ -471,26 +492,33 @@ chamadas na mesma origem, não repete `page.goto` e consulta um snapshot atual
471
492
  sem esperar novamente por `load`/`networkidle`. As etapas continuam aguardando
472
493
  seus próprios alvos e condições. `reuse_page` segue como alias legado; defina
473
494
  `continue_from_current_page: false` para iniciar cada chamada em `initial_url`.
474
- Se a página atual e `initial_url` tiverem origens diferentes, o MCP navega para
475
- `initial_url`. Se forem da mesma origem, continua a página atual e avisa quando
476
- as URLs completas forem diferentes. `snapshot_scope` aceita `body`, `main` ou
477
- `dialog`; se `main` não existir, o snapshot usa `body`.
478
-
479
- `block_trackers: true` bloqueia analytics/trackers e os tipos de recurso
480
- configurados. Fontes ficam habilitadas por padrão para preservar ícones e
481
- glyphs; `block_fonts: true` bloqueia fontes separadamente. `busy_selectors`
482
- complementa `aria-busy="true"` ao aguardar overlays de carregamento.
495
+ Se a página atual e `initial_url` tiverem origens diferentes, o MCP navega para
496
+ `initial_url`. Se forem da mesma origem mas URLs completas diferentes, o MCP
497
+ recusa continuar silenciosamente e pede uma etapa `navigate` ou
498
+ `continue_from_current_page: false`. `snapshot_scope` aceita `body`, `main` ou
499
+ `dialog`; se `main` não existir, o snapshot usa `body`.
500
+
501
+ `block_trackers: true` bloqueia analytics/trackers e os tipos de recurso
502
+ configurados, mas preserva `media` quando há permissão de microfone ou
503
+ `fake_media`. Fontes ficam habilitadas por padrão para preservar ícones e
504
+ glyphs; `block_fonts: true` bloqueia fontes separadamente. `busy_selectors`
505
+ complementa `aria-busy="true"` ao aguardar overlays; elementos ocultos ou fora
506
+ da tela com esse atributo não seguram a prontidão da página.
483
507
  `auto_angular_idle` aguarda AngularJS depois de cliques e digitação quando a
484
508
  página expõe o injector. `login_url_contains` e `login_text` substituem a
485
509
  detecção padrão de autenticação. `local_only: true` recusa qualquer etapa que
486
- precisaria chamar o provedor Jev; use exatamente um plano com `fast_path: true`.
510
+ precisaria chamar o provedor Jev; use exatamente um plano com `fast_path: true`.
511
+ `allow_mutations: true` pula a confirmação humana somente para URLs em
512
+ `localhost`, `127.0.0.1` ou `::1`; use esse modo apenas em ambientes locais
513
+ controlados.
487
514
  `step_timeout_seconds` define o timeout padrão por etapa e cada etapa pode
488
515
  substituí-lo com `timeout_seconds`. `max_flow_steps` reduz o limite por chamada,
489
516
  sem superar o teto da configuração. `return_snapshot` aceita `full`, `diff` ou
490
517
  `none`; `diff` retorna linhas acessíveis novas desde o snapshot inicial.
491
518
 
492
- Com `capture_console_errors` e `capture_network_errors`, o retorno traz
493
- `console_errors` e `network_failures`, limitados em quantidade e tamanho.
519
+ Com `capture_console_errors` e `capture_network_errors`, o retorno traz
520
+ `console_errors` e `network_failures`, limitados em quantidade e tamanho.
521
+ Mensagens de erro idênticas do console são agrupadas em uma entrada com `count`.
494
522
  Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
495
523
  fragmentos, valores de formulário e nomes de arquivo são removidos ou
496
524
  sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
@@ -506,9 +534,49 @@ compartilhe os arquivos somente se o teste permitir.
506
534
 
507
535
  Screenshots por etapa usam `screenshot: true` no próprio passo; o MCP os grava
508
536
  depois que a ação termina. `options.report_path` pode apontar para `.md` ou
509
- JUnit `.xml` dentro da raiz de artefatos. O relatório inclui a versão, tempos,
510
- localizadores resolvidos, respostas verificadas por `assert_network`, falhas de
511
- rede e caminhos dos screenshots, para anexar a um PR ou card.
537
+ JUnit `.xml` dentro da raiz de artefatos. O relatório inclui a versão, tempos,
538
+ localizadores resolvidos, respostas verificadas por `assert_network`, falhas de
539
+ rede e caminhos dos screenshots, para anexar a um PR ou card.
540
+
541
+ `screenshot_on_success` grava a captura final em fluxos aprovados;
542
+ `trace_on_success` salva trace também em sucesso e `record_video` grava vídeo
543
+ WebM. Fluxos que digitam texto sensível suprimem screenshots, traces e vídeos
544
+ para não registrar credenciais. `performance_metrics` inclui métricas do
545
+ navegador quando disponíveis. `jev_browser_mcp.browser.max_tool_response_bytes`
546
+ impõe um teto global de bytes na resposta JSON da ferramenta; se necessário,
547
+ evidências volumosas são reduzidas e marcadas com `output_truncated: true`.
548
+
549
+ Para testar microfone, conceda permissão no escopo da chamada:
550
+
551
+ ```json
552
+ {
553
+ "options": {
554
+ "permissions": ["microphone"],
555
+ "fake_media": "fixtures/resposta-aluno.wav",
556
+ "block_trackers": true
557
+ }
558
+ }
559
+ ```
560
+
561
+ `fake_media` exige um WAV RIFF válido dentro de `JEV_BROWSER_UPLOAD_ROOT` e
562
+ respeita os mesmos limites de upload. O MCP adiciona as opções de dispositivo
563
+ falso do Chromium e concede permissão ao contexto. Sem esse arquivo, a
564
+ permissão de microfone usa o dispositivo autorizado pelo browser; no modo
565
+ `computer`, o sistema operacional ainda pode pedir acesso ao dispositivo.
566
+
567
+ As opções de emulação aceitam `viewport: {"width": 390, "height": 844}`,
568
+ `mobile: true`, `device_scale_factor`, `locale`, `timezone_id`,
569
+ `color_scheme: "dark"` e `geolocation: {"latitude": -23.55, "longitude": -46.63}`.
570
+ Informar geolocalização concede também a permissão `geolocation`.
571
+
572
+ `audit_accessibility` aceita `scope` com seletor CSS e `fail_on_impact` com
573
+ `minor`, `moderate`, `serious` ou `critical`. O padrão é `minor`; violações
574
+ abaixo do impacto escolhido continuam no relatório, mas não bloqueiam o passo.
575
+ `violations_count` e `blocking_violations_count` separam total e bloqueadoras.
576
+
577
+ Os cliques aguardam `DOMContentLoaded` quando acionam navegação completa e
578
+ tratam a destruição do contexto durante a troca de documento como navegação em
579
+ andamento, sem repetir o clique.
512
580
 
513
581
  Se o Chrome/Edge não iniciar porque o perfil persistente já está aberto, o erro
514
582
  identifica o PID que o mantém ocupado quando o sistema consegue associar o
@@ -565,18 +633,21 @@ sob demanda podem excedê-la. O MCP devolve `total_ms`, `browser_session_ms`,
565
633
  para localizar o custo. O teto observado em um fluxo sintético local anterior
566
634
  foi 6,411 s; isso não mede o Instagram nem garante o mesmo tempo em outros sites.
567
635
 
568
- O snapshot inicial, o fluxo, o resultado esperado e as descrições dos planos
569
- são enviados ao endpoint Decisions quando há mais de uma opção. Com fast-path,
570
- um plano não gera chamada remota. Os passos, valores digitados, valores
571
- esperados pelas asserções, caminhos e conteúdo dos arquivos não são enviados.
636
+ O snapshot inicial, o fluxo, o resultado esperado e as descrições dos planos
637
+ são enviados ao endpoint Decisions quando há mais de uma opção. Antes do envio,
638
+ valores dos controles são substituídos e hrefs têm query string e fragmento
639
+ removidos; padrões de PII também são mascarados. Com fast-path, um plano não
640
+ gera chamada remota. Os passos, valores digitados, valores esperados pelas
641
+ asserções, caminhos e conteúdo dos arquivos não são enviados.
572
642
  Não inclua segredos em `flow`, `expected_outcome` ou nas descrições. A resposta
573
643
  retorna o plano escolhido quando houver decisão, custo/confiança do provedor
574
644
  quando disponíveis e o snapshot final sanitizado. O fluxo passa quando o texto
575
645
  esperado aparece no snapshot ou quando todas as asserções declaradas passam.
576
646
 
577
- `network_idle` é uma espera limitada e opcional; páginas com polling ou conexões
578
- contínuas podem atingir o timeout. Prefira `wait_for_text` e asserções de
579
- elemento quando houver um sinal de interface específico.
647
+ `network_idle` é uma espera limitada e opcional. Polling e conexões contínuas
648
+ não relacionadas a `url_contains` não bloqueiam o modo filtrado; prefira
649
+ `wait_for_text` ou `assert_network` quando houver sinal de interface ou uma
650
+ resposta HTTP específica.
580
651
 
581
652
  Consulte a [introdução do Jev](https://docs.typesafe.ai/introduction) e o
582
653
  [tutorial da API Decisions no OpenRouter](https://openrouter.ai/docs/guides/community/jev-tutorial)
@@ -38,7 +38,14 @@
38
38
  "visibility_poll_interval_ms_default": 50,
39
39
  "capture_network_error_bodies_default": false,
40
40
  "max_network_error_body_bytes": 65536,
41
- "max_network_error_message_chars": 300,
41
+ "max_network_error_message_chars": 300,
42
+ "max_network_history_events": 4096,
43
+ "max_tool_response_bytes": 131072,
44
+ "max_viewport_width": 3840,
45
+ "max_viewport_height": 2160,
46
+ "accessibility_fail_on_impact_default": "minor",
47
+ "record_video_width": 1280,
48
+ "record_video_height": 720,
42
49
  "max_upload_files": 5,
43
50
  "max_upload_path_chars": 4096,
44
51
  "max_upload_file_bytes": 10485760,
@@ -53,7 +60,8 @@
53
60
  "max_frame_snapshots": 5,
54
61
  "fast_path_single_plan_default": true,
55
62
  "screenshot_on_failure_default": true,
56
- "trace_on_failure_default": false,
63
+ "trace_on_failure_default": false,
64
+ "trace_on_success_default": false,
57
65
  "capture_console_errors_default": true,
58
66
  "capture_network_errors_default": false,
59
67
  "block_trackers_default": false,
@@ -17,7 +17,7 @@ versão em produção, use o número explícito no argumento do pacote:
17
17
  "mcpServers": {
18
18
  "jev-browser": {
19
19
  "command": "npx",
20
- "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.6.1"],
20
+ "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.6.2"],
21
21
  "env": {
22
22
  "OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
23
23
  "JEV_BROWSER_MODE": "computer"
@@ -32,7 +32,7 @@ um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
32
32
  de configuração. Para instalar no projeto Node do próprio harness:
33
33
 
34
34
  ```sh
35
- npm install @diegosouzacdv/jev-browser-mcp@0.6.1
35
+ npm install @diegosouzacdv/jev-browser-mcp@0.6.2
36
36
  ```
37
37
 
38
38
  Se o harness executa o MCP repetidamente nesta máquina, instale uma versão
@@ -40,7 +40,7 @@ fixa globalmente para evitar a resolução e o download feitos pelo `npx` em cad
40
40
  inicialização:
41
41
 
42
42
  ```sh
43
- npm install --global @diegosouzacdv/jev-browser-mcp@0.6.1
43
+ npm install --global @diegosouzacdv/jev-browser-mcp@0.6.2
44
44
  ```
45
45
 
46
46
  Depois configure o servidor MCP com `command: "jev-browser-mcp"` e `args: []`.
@@ -49,7 +49,7 @@ Para atualizar, rode `npm install --global
49
49
 
50
50
  O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
51
51
  configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
52
- pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp@0.6.1 --install-browser`.
52
+ pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp@0.6.2 --install-browser`.
53
53
 
54
54
  O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
55
55
  persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
@@ -107,11 +107,17 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
107
107
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
108
108
  resultado esperado na tela.
109
109
 
110
- Cada plano pode usar:
111
-
112
- - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
113
- papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
114
- `text`, `test_id` ou `selector`;
110
+ Cada plano pode usar:
111
+
112
+ - `navigate` para mudar de página no meio do fluxo. Com a continuidade ligada,
113
+ um `initial_url` de mesma origem diferente da URL ativa produz erro claro; use
114
+ `navigate` ou `continue_from_current_page: false` para escolher o destino;
115
+ - `click`, `type`, `clear`, `hover`, `select_option`, `press`, `assert_*` e upload com
116
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
117
+ `text`, `test_id` ou `selector`;
118
+ - `name_match: "exact" | "contains" | "regex"` para controlar a comparação do
119
+ nome acessível; regex rejeita construções com backtracking excessivo. O papel
120
+ `switch` funciona em cliques, verificações e asserções;
115
121
  - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
116
122
  `within: {"row_containing":"..."}` para limitar por trecho e
117
123
  `within: {"row_containing_exact":"..."}` para exigir um elemento com o
@@ -128,25 +134,34 @@ Cada plano pode usar:
128
134
  - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
129
135
  em `warnings`; não é permitido enviar JavaScript nem coordenadas;
130
136
  - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
131
- - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
132
- `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
133
- valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
134
- - `wait_for_text`, `wait_for_value`, `wait_for_enabled` e `wait_for_condition`
135
- (`network_idle`, `hidden`, `text_hidden` ou `angular_idle`). `wait` recebe
137
+ - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
138
+ `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
139
+ valor apareça nas evidências. `text_env` lê o valor sensível de uma variável
140
+ de ambiente do processo MCP, sem colocá-lo no plano. Nesse modo, `\n` envia
141
+ Enter e `\t` envia Tab;
142
+ - `wait_for_text`, `wait_for_value`, `wait_for_enabled` e `wait_for_condition`
143
+ (`url`, `network_idle`, `hidden`, `text_hidden` ou `angular_idle`). `wait` recebe
136
144
  `ms` para uma pausa curta e limitada. `angular_idle` aguarda requisições
137
145
  `$http` e digest do AngularJS. `wait_for_text` aceita `fail_on: {"role":"alert"}` para
138
146
  interromper a espera assim que um alerta visível aparecer e incluir seu texto
139
147
  no erro. Se o alerta contiver o texto esperado, a etapa passa; caso contrário,
140
- o alerta interrompe a espera. `network_idle` aceita `url_contains` para
141
- aguardar só as requisições correspondentes;
142
- - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
143
- `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
144
- envia a tecla ao elemento focado; com alvo, usa o localizador informado;
148
+ o alerta interrompe a espera. `url` aguarda a URL conter `url_contains`.
149
+ `network_idle` aceita esse filtro e aguarda uma janela de silêncio usando
150
+ `ready_stable_ms`; WebSocket, EventSource e polling não relacionado não
151
+ bloqueiam a espera. Se não surgir requisição correspondente, o passo conclui
152
+ após a janela de silêncio;
153
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
154
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab`, `Shift+Tab`, `Space`,
155
+ `Backspace` ou `Delete`. `clear` limpa um campo sem exigir texto. Sem alvo,
156
+ `press` envia a tecla ao elemento focado; com alvo, usa o localizador informado;
145
157
  - `assert_text`, `assert_value`, `assert_visible`, `assert_hidden` e
146
158
  `assert_enabled`; `assert_text`
147
159
  pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
148
- - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
149
- dropzone;
160
+ - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
161
+ dropzone;
162
+ - `target_page: "popup"` para continuar no popup aberto com `expect_popup: true`;
163
+ locators semânticos também atravessam open Shadow DOM. Shadow DOM fechado não
164
+ é acessível ao Playwright;
150
165
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
151
166
  - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
152
167
  não repetem uma reação já no estado pedido e distinguem `Curtir` de
@@ -211,11 +226,12 @@ com `within: {"row_containing_exact":"{pedido}"}`, e use uma etapa
211
226
  `{"action":"extract","role":"cell","name":"{pedido}","within":{"row_containing_exact":"{pedido}"},"as":"documento"}`.
212
227
  A etapa seguinte pode localizar o mesmo documento com `name: "{documento}"`.
213
228
 
214
- Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
215
- localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
216
- aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
217
- `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
218
- esperar que ela termine.
229
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
230
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
231
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
232
+ `url_contains`. O filtro considera somente a atividade correspondente e termina
233
+ após a janela configurada sem atividade; também termina caso nenhuma requisição
234
+ correspondente apareça. Para validar status e corpo, prefira `assert_network`.
219
235
 
220
236
  Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
221
237
  container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
@@ -411,15 +427,17 @@ validadores.
411
427
 
412
428
  `browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
413
429
 
414
- - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
415
- harness e CI; o estado de autenticação é descartado ao final da chamada.
430
+ - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
431
+ harness e CI. O processo MCP conserva browser, contexto e página entre
432
+ chamadas; cookies, local storage e estado da página permanecem enquanto o
433
+ processo estiver ativo. Encerre o processo para descartar o contexto isolado.
416
434
  - `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
417
435
  persistente `browser.computer_user_data_dir`, separado por navegador. Não
418
436
  reutiliza o perfil pessoal já aberto. Faça login uma vez nesse perfil; os
419
437
  cookies permanecem nele entre chamadas.
420
438
 
421
- `browser.max_flow_steps` limita a soma de passos declarados entre os planos e
422
- `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
439
+ `browser.max_flow_steps` limita os passos de cada plano candidato; os planos
440
+ não são somados. `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
423
441
  `status`, o plano escolhido, as ações executadas, a última captura acessível e
424
442
  se o critério esperado apareceu. Quando existem asserções explícitas, `status`
425
443
  também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
@@ -457,9 +475,12 @@ O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
457
475
  `auto_angular_idle`, `login_url_contains`, `login_text`, `capture_console_errors`,
458
476
  `capture_network_errors`, `capture_network_error_bodies`, `ready_timeout_seconds`,
459
477
  `ready_network_idle`, `ready_stable_ms`, `ready_text`, `continue_from_current_page`,
460
- `reuse_page`, `step_timeout_seconds`, `max_flow_steps`, `return_snapshot`,
461
- `screenshot_on_failure`, `trace_on_failure`, `snapshot_include_hidden`,
462
- `stop_on_expected`, `dry_run`, `confirmation_token` e `report_path`. Sem override,
478
+ `reuse_page`, `step_timeout_seconds`, `max_flow_steps`, `return_snapshot`,
479
+ `screenshot_on_failure`, `screenshot_on_success`, `trace_on_failure`,
480
+ `trace_on_success`, `record_video`, `snapshot_include_hidden`, `stop_on_expected`,
481
+ `dry_run`, `confirmation_token`, `report_path`, `permissions`, `fake_media`,
482
+ `viewport`, `mobile`, `device_scale_factor`, `locale`, `timezone_id`,
483
+ `color_scheme`, `geolocation` e `allow_mutations`. Sem override,
463
484
  os padrões são lidos de `jev_browser_mcp` em
464
485
  `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
465
486
  captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
@@ -471,26 +492,33 @@ chamadas na mesma origem, não repete `page.goto` e consulta um snapshot atual
471
492
  sem esperar novamente por `load`/`networkidle`. As etapas continuam aguardando
472
493
  seus próprios alvos e condições. `reuse_page` segue como alias legado; defina
473
494
  `continue_from_current_page: false` para iniciar cada chamada em `initial_url`.
474
- Se a página atual e `initial_url` tiverem origens diferentes, o MCP navega para
475
- `initial_url`. Se forem da mesma origem, continua a página atual e avisa quando
476
- as URLs completas forem diferentes. `snapshot_scope` aceita `body`, `main` ou
477
- `dialog`; se `main` não existir, o snapshot usa `body`.
478
-
479
- `block_trackers: true` bloqueia analytics/trackers e os tipos de recurso
480
- configurados. Fontes ficam habilitadas por padrão para preservar ícones e
481
- glyphs; `block_fonts: true` bloqueia fontes separadamente. `busy_selectors`
482
- complementa `aria-busy="true"` ao aguardar overlays de carregamento.
495
+ Se a página atual e `initial_url` tiverem origens diferentes, o MCP navega para
496
+ `initial_url`. Se forem da mesma origem mas URLs completas diferentes, o MCP
497
+ recusa continuar silenciosamente e pede uma etapa `navigate` ou
498
+ `continue_from_current_page: false`. `snapshot_scope` aceita `body`, `main` ou
499
+ `dialog`; se `main` não existir, o snapshot usa `body`.
500
+
501
+ `block_trackers: true` bloqueia analytics/trackers e os tipos de recurso
502
+ configurados, mas preserva `media` quando há permissão de microfone ou
503
+ `fake_media`. Fontes ficam habilitadas por padrão para preservar ícones e
504
+ glyphs; `block_fonts: true` bloqueia fontes separadamente. `busy_selectors`
505
+ complementa `aria-busy="true"` ao aguardar overlays; elementos ocultos ou fora
506
+ da tela com esse atributo não seguram a prontidão da página.
483
507
  `auto_angular_idle` aguarda AngularJS depois de cliques e digitação quando a
484
508
  página expõe o injector. `login_url_contains` e `login_text` substituem a
485
509
  detecção padrão de autenticação. `local_only: true` recusa qualquer etapa que
486
- precisaria chamar o provedor Jev; use exatamente um plano com `fast_path: true`.
510
+ precisaria chamar o provedor Jev; use exatamente um plano com `fast_path: true`.
511
+ `allow_mutations: true` pula a confirmação humana somente para URLs em
512
+ `localhost`, `127.0.0.1` ou `::1`; use esse modo apenas em ambientes locais
513
+ controlados.
487
514
  `step_timeout_seconds` define o timeout padrão por etapa e cada etapa pode
488
515
  substituí-lo com `timeout_seconds`. `max_flow_steps` reduz o limite por chamada,
489
516
  sem superar o teto da configuração. `return_snapshot` aceita `full`, `diff` ou
490
517
  `none`; `diff` retorna linhas acessíveis novas desde o snapshot inicial.
491
518
 
492
- Com `capture_console_errors` e `capture_network_errors`, o retorno traz
493
- `console_errors` e `network_failures`, limitados em quantidade e tamanho.
519
+ Com `capture_console_errors` e `capture_network_errors`, o retorno traz
520
+ `console_errors` e `network_failures`, limitados em quantidade e tamanho.
521
+ Mensagens de erro idênticas do console são agrupadas em uma entrada com `count`.
494
522
  Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
495
523
  fragmentos, valores de formulário e nomes de arquivo são removidos ou
496
524
  sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
@@ -506,9 +534,49 @@ compartilhe os arquivos somente se o teste permitir.
506
534
 
507
535
  Screenshots por etapa usam `screenshot: true` no próprio passo; o MCP os grava
508
536
  depois que a ação termina. `options.report_path` pode apontar para `.md` ou
509
- JUnit `.xml` dentro da raiz de artefatos. O relatório inclui a versão, tempos,
510
- localizadores resolvidos, respostas verificadas por `assert_network`, falhas de
511
- rede e caminhos dos screenshots, para anexar a um PR ou card.
537
+ JUnit `.xml` dentro da raiz de artefatos. O relatório inclui a versão, tempos,
538
+ localizadores resolvidos, respostas verificadas por `assert_network`, falhas de
539
+ rede e caminhos dos screenshots, para anexar a um PR ou card.
540
+
541
+ `screenshot_on_success` grava a captura final em fluxos aprovados;
542
+ `trace_on_success` salva trace também em sucesso e `record_video` grava vídeo
543
+ WebM. Fluxos que digitam texto sensível suprimem screenshots, traces e vídeos
544
+ para não registrar credenciais. `performance_metrics` inclui métricas do
545
+ navegador quando disponíveis. `jev_browser_mcp.browser.max_tool_response_bytes`
546
+ impõe um teto global de bytes na resposta JSON da ferramenta; se necessário,
547
+ evidências volumosas são reduzidas e marcadas com `output_truncated: true`.
548
+
549
+ Para testar microfone, conceda permissão no escopo da chamada:
550
+
551
+ ```json
552
+ {
553
+ "options": {
554
+ "permissions": ["microphone"],
555
+ "fake_media": "fixtures/resposta-aluno.wav",
556
+ "block_trackers": true
557
+ }
558
+ }
559
+ ```
560
+
561
+ `fake_media` exige um WAV RIFF válido dentro de `JEV_BROWSER_UPLOAD_ROOT` e
562
+ respeita os mesmos limites de upload. O MCP adiciona as opções de dispositivo
563
+ falso do Chromium e concede permissão ao contexto. Sem esse arquivo, a
564
+ permissão de microfone usa o dispositivo autorizado pelo browser; no modo
565
+ `computer`, o sistema operacional ainda pode pedir acesso ao dispositivo.
566
+
567
+ As opções de emulação aceitam `viewport: {"width": 390, "height": 844}`,
568
+ `mobile: true`, `device_scale_factor`, `locale`, `timezone_id`,
569
+ `color_scheme: "dark"` e `geolocation: {"latitude": -23.55, "longitude": -46.63}`.
570
+ Informar geolocalização concede também a permissão `geolocation`.
571
+
572
+ `audit_accessibility` aceita `scope` com seletor CSS e `fail_on_impact` com
573
+ `minor`, `moderate`, `serious` ou `critical`. O padrão é `minor`; violações
574
+ abaixo do impacto escolhido continuam no relatório, mas não bloqueiam o passo.
575
+ `violations_count` e `blocking_violations_count` separam total e bloqueadoras.
576
+
577
+ Os cliques aguardam `DOMContentLoaded` quando acionam navegação completa e
578
+ tratam a destruição do contexto durante a troca de documento como navegação em
579
+ andamento, sem repetir o clique.
512
580
 
513
581
  Se o Chrome/Edge não iniciar porque o perfil persistente já está aberto, o erro
514
582
  identifica o PID que o mantém ocupado quando o sistema consegue associar o
@@ -565,18 +633,21 @@ sob demanda podem excedê-la. O MCP devolve `total_ms`, `browser_session_ms`,
565
633
  para localizar o custo. O teto observado em um fluxo sintético local anterior
566
634
  foi 6,411 s; isso não mede o Instagram nem garante o mesmo tempo em outros sites.
567
635
 
568
- O snapshot inicial, o fluxo, o resultado esperado e as descrições dos planos
569
- são enviados ao endpoint Decisions quando há mais de uma opção. Com fast-path,
570
- um plano não gera chamada remota. Os passos, valores digitados, valores
571
- esperados pelas asserções, caminhos e conteúdo dos arquivos não são enviados.
636
+ O snapshot inicial, o fluxo, o resultado esperado e as descrições dos planos
637
+ são enviados ao endpoint Decisions quando há mais de uma opção. Antes do envio,
638
+ valores dos controles são substituídos e hrefs têm query string e fragmento
639
+ removidos; padrões de PII também são mascarados. Com fast-path, um plano não
640
+ gera chamada remota. Os passos, valores digitados, valores esperados pelas
641
+ asserções, caminhos e conteúdo dos arquivos não são enviados.
572
642
  Não inclua segredos em `flow`, `expected_outcome` ou nas descrições. A resposta
573
643
  retorna o plano escolhido quando houver decisão, custo/confiança do provedor
574
644
  quando disponíveis e o snapshot final sanitizado. O fluxo passa quando o texto
575
645
  esperado aparece no snapshot ou quando todas as asserções declaradas passam.
576
646
 
577
- `network_idle` é uma espera limitada e opcional; páginas com polling ou conexões
578
- contínuas podem atingir o timeout. Prefira `wait_for_text` e asserções de
579
- elemento quando houver um sinal de interface específico.
647
+ `network_idle` é uma espera limitada e opcional. Polling e conexões contínuas
648
+ não relacionadas a `url_contains` não bloqueiam o modo filtrado; prefira
649
+ `wait_for_text` ou `assert_network` quando houver sinal de interface ou uma
650
+ resposta HTTP específica.
580
651
 
581
652
  Consulte a [introdução do Jev](https://docs.typesafe.ai/introduction) e o
582
653
  [tutorial da API Decisions no OpenRouter](https://openrouter.ai/docs/guides/community/jev-tutorial)