@diegosouzacdv/jev-browser-mcp 0.3.1 → 0.4.1

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,10 +17,10 @@ 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.3.1"],
20
+ "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.4.0"],
21
21
  "env": {
22
22
  "OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
23
- "JEV_BROWSER_MODE": "harness"
23
+ "JEV_BROWSER_MODE": "computer"
24
24
  }
25
25
  }
26
26
  }
@@ -31,15 +31,18 @@ O formato de interpolação de variáveis varia por harness. Injete a chave por
31
31
  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
- ```sh
35
- npm install @diegosouzacdv/jev-browser-mcp
36
- npx --yes @diegosouzacdv/jev-browser-mcp --install-browser
37
- ```
38
-
39
- No modo `harness`, a instalação baixa uma vez o Chrome/Edge que o Playwright
40
- controlará. No modo `computer`, o pacote abre o Chrome/Edge instalado e usa um
41
- perfil persistente exclusivo em `browser.computer_user_data_dir`; personalize
42
- as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
34
+ ```sh
35
+ npm install @diegosouzacdv/jev-browser-mcp
36
+ ```
37
+
38
+ O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
39
+ configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
40
+ pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp --install-browser`.
41
+
42
+ O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
43
+ persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
44
+ instalação baixa uma vez o Chrome/Edge que o Playwright controlará. Personalize
45
+ as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
43
46
  `JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
44
47
  estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
45
48
  e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
@@ -66,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
66
69
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
67
70
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
68
71
  raiz local configurada e reações idempotentes a um comentário único. Também
69
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
70
- JavaScript enviado pelo harness, seletores livres nem coordenadas. Ele usa a
71
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
74
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
75
+ são o último recurso e geram um aviso no resultado. Ele usa a
76
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
77
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
73
78
  `stderr` para não misturar com JSON-RPC.
74
79
 
@@ -84,24 +89,50 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
84
89
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
85
90
  resultado esperado na tela.
86
91
 
87
- Cada plano pode usar:
88
-
89
- - `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
90
- - `wait_for_text` e `wait_for_condition` (`network_idle`, limitado pelo timeout
91
- de ação configurado);
92
- - `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
93
- `Enter`, `Escape` ou `Tab`;
94
- - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`;
92
+ Cada plano pode usar:
93
+
94
+ - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
95
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
96
+ `text`, `test_id` ou `selector`;
97
+ - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
98
+ e `within: {"row_containing":"..."}` para limitar a ação à linha certa;
99
+ - `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
100
+ o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
101
+ com `opacity: 0`;
102
+ - `name: ""` com `index` não negativo para controles sem nome. O resultado
103
+ inclui um aviso porque a posição pode mudar entre execuções;
104
+ - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
105
+ em `warnings`; não é permitido enviar JavaScript nem coordenadas;
106
+ - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
107
+ - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
108
+ `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
109
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
110
+ - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
111
+ `text_hidden`); `network_idle` aceita `url_contains` para aguardar só as
112
+ requisições correspondentes;
113
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
114
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
115
+ envia a tecla ao elemento focado; com alvo, usa o localizador informado;
116
+ - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
117
+ pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
95
118
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
96
119
  dropzone;
97
120
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
98
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
99
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
100
- `Descurtir`.
101
-
102
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
103
- container acessível único, como uma linha ou card. `index` escolhe uma ocorrência
104
- zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
122
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
123
+ `Descurtir`.
124
+
125
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
126
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
127
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
128
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
129
+ esperar que ela termine.
130
+
131
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
132
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
133
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
134
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
135
+ controle próximo ao texto visível do rótulo.
105
136
 
106
137
  ```json
107
138
  {
@@ -113,8 +144,40 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
113
144
  ```
114
145
 
115
146
  ```json
116
- {"action":"click","role":"button","name":"Add to cart","index":0}
117
- ```
147
+ {"action":"click","role":"button","name":"Add to cart","index":0}
148
+ ```
149
+
150
+ Exemplos para controles legados sem nome acessível:
151
+
152
+ ```json
153
+ {"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
154
+ {"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
155
+ {"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
156
+ {"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
157
+ {"action":"click","role":"button","name":"","index":0}
158
+ {"action":"click","selector":"#save-document"}
159
+ ```
160
+
161
+ O reconhecimento retorna `unnamed_controls` com papel, posição, rótulo mais
162
+ próximo e um trecho HTML sanitizado dos controles interativos sem nome. O
163
+ snapshot também resume campos de formulário com `id`, `name`, valor, estado
164
+ desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
165
+ sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
166
+ é `false` por padrão; defina `true` somente quando precisar inspecionar campos
167
+ ocultos também.
168
+
169
+ Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
170
+ localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
171
+ `textbox`, `searchbox` ou `combobox`.
172
+
173
+ Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
174
+ Valores dentro de campos não contam como resultado visível. `stop_on_expected:
175
+ true` habilita parada antecipada quando o texto esperado aparece fora dos
176
+ campos; mantenha `false` para fluxos com várias etapas.
177
+
178
+ Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
179
+ de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
180
+ e erro.
118
181
 
119
182
  ### Captura de downloads
120
183
 
@@ -151,12 +214,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
151
214
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
152
215
  com revisão manual e testes com usuários assistivos.
153
216
 
154
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
155
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
156
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
157
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
158
- próximos quando o snapshot os encontrar. O plano não aceita JavaScript enviado
159
- pelo harness, coordenadas ou seletores livres.
217
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
218
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
219
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
220
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
221
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
222
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
223
+ JavaScript enviado pelo harness nem coordenadas.
160
224
 
161
225
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
162
226
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -239,9 +303,9 @@ do pacote Node ficam no bloco opcional `jev_browser_mcp`, que não altera o
239
303
  contrato lido pelo servidor Python. Preserve a estrutura completa exigida pelos
240
304
  validadores.
241
305
 
242
- `browser.mode` aceita `harness` ou `computer`:
306
+ `browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
243
307
 
244
- - `harness` usa Chrome headless e perfil isolado, adequado a execuções do
308
+ - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
245
309
  harness e CI; o estado de autenticação é descartado ao final da chamada.
246
310
  - `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
247
311
  persistente `browser.computer_user_data_dir`, separado por navegador. Não
@@ -250,12 +314,15 @@ validadores.
250
314
 
251
315
  `browser.max_flow_steps` limita a soma de passos declarados entre os planos e
252
316
  `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
253
- `status`, o plano escolhido, as ações executadas, a última captura acessível e
254
- se o critério esperado apareceu. Quando existem asserções explícitas, `status`
255
- também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
256
- esse resultado e `expected_outcome_visible` continua descrevendo somente o
257
- texto global. `incomplete` significa que nenhum critério foi comprovado;
258
- confiança do Jev não substitui essa verificação.
317
+ `status`, o plano escolhido, as ações executadas, a última captura acessível e
318
+ se o critério esperado apareceu. Quando existem asserções explícitas, `status`
319
+ também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
320
+ esse resultado e `expected_outcome_visible` continua descrevendo somente o
321
+ texto global. `incomplete` significa que nenhum critério foi comprovado;
322
+ confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
323
+ espera da SPA; `warnings` registra capturas vazias durante transições; e
324
+ `failed_step` identifica índice, ação, alvo, timeout e erro resumido quando uma
325
+ etapa falha.
259
326
 
260
327
  `jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
261
328
  seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
@@ -271,12 +338,20 @@ Os limites de download ficam no mesmo bloco: `max_download_files`,
271
338
  limita quantas descrições de violações axe entram no resultado; a contagem total
272
339
  continua informada mesmo quando a lista é truncada.
273
340
 
274
- O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
275
- `block_trackers`, `capture_console_errors`, `capture_network_errors`,
276
- `screenshot_on_failure` e `trace_on_failure`. Sem override, os padrões são lidos
277
- de `jev_browser_mcp` em `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
278
- captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
279
- de recursos ficam desligados. `snapshot_scope` aceita `body`, `main` ou `dialog`.
341
+ O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
342
+ `block_trackers`, `capture_console_errors`, `capture_network_errors`,
343
+ `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
344
+ `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
345
+ `trace_on_failure`, `snapshot_include_hidden` e `stop_on_expected`. Sem override,
346
+ os padrões são lidos de `jev_browser_mcp` em
347
+ `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
348
+ captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
349
+ de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
350
+ acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
351
+ acessível estável. `ready_text` pode identificar o conteúdo que marca a
352
+ prontidão. `reuse_page: true` pula a navegação somente quando a página e
353
+ `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
354
+ `dialog`.
280
355
 
281
356
  `block_trackers: true` bloqueia os domínios e tipos de recurso listados na
282
357
  configuração (analytics, Hotjar, fontes externas e mídia). Isso pode alterar o
@@ -284,9 +359,12 @@ layout ou o comportamento do site, então a opção é desligada por padrão.
284
359
 
285
360
  Com `capture_console_errors` e `capture_network_errors`, o retorno traz
286
361
  `console_errors` e `network_failures`, limitados em quantidade e tamanho.
287
- Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
288
- fragmentos, valores de formulário e nomes de arquivo são removidos ou
289
- sanitizados. Em falhas, `screenshot_on_failure` salva screenshot local e retorna
362
+ Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
363
+ fragmentos, valores de formulário e nomes de arquivo são removidos ou
364
+ sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
365
+ 4xx/5xx da mesma origem, limita o corpo e inclui apenas o campo textual
366
+ `message`, também sanitizado. Em falhas, `screenshot_on_failure` salva
367
+ screenshot local e retorna
290
368
  `screenshot_path`. `trace_on_failure: true` também grava um `.zip` compatível
291
369
  com o Trace Viewer do Playwright e retorna `trace_path`. O diretório padrão é
292
370
  `~/.cache/orquestrador/jev-browser-artifacts`; `JEV_BROWSER_ARTIFACT_DIR` pode
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
3
  "browser": {
4
- "mode": "harness",
4
+ "mode": "computer",
5
5
  "harness_browser": "chrome",
6
6
  "playwright_mcp_package": "@playwright/mcp@0.0.79",
7
7
  "computer_browser": "chrome",
@@ -22,8 +22,23 @@
22
22
  },
23
23
  "jev_browser_mcp": {
24
24
  "browser": {
25
- "max_action_timeout_seconds": 8,
26
- "max_upload_files": 5,
25
+ "max_action_timeout_seconds": 8,
26
+ "ready_timeout_seconds_default": 15,
27
+ "max_ready_timeout_seconds": 60,
28
+ "ready_network_idle_default": true,
29
+ "ready_stable_ms_default": 400,
30
+ "max_ready_stable_ms": 2000,
31
+ "post_step_ready_timeout_seconds_default": 5,
32
+ "max_step_timeout_seconds": 60,
33
+ "key_delay_ms_default": 30,
34
+ "reuse_page_default": false,
35
+ "stop_on_expected_default": false,
36
+ "snapshot_include_hidden_default": false,
37
+ "visibility_poll_interval_ms_default": 50,
38
+ "capture_network_error_bodies_default": false,
39
+ "max_network_error_body_bytes": 65536,
40
+ "max_network_error_message_chars": 300,
41
+ "max_upload_files": 5,
27
42
  "max_upload_path_chars": 4096,
28
43
  "max_upload_file_bytes": 10485760,
29
44
  "max_upload_total_bytes": 26214400,
@@ -17,10 +17,10 @@ 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.3.1"],
20
+ "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.4.0"],
21
21
  "env": {
22
22
  "OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
23
- "JEV_BROWSER_MODE": "harness"
23
+ "JEV_BROWSER_MODE": "computer"
24
24
  }
25
25
  }
26
26
  }
@@ -31,15 +31,18 @@ O formato de interpolação de variáveis varia por harness. Injete a chave por
31
31
  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
- ```sh
35
- npm install @diegosouzacdv/jev-browser-mcp
36
- npx --yes @diegosouzacdv/jev-browser-mcp --install-browser
37
- ```
38
-
39
- No modo `harness`, a instalação baixa uma vez o Chrome/Edge que o Playwright
40
- controlará. No modo `computer`, o pacote abre o Chrome/Edge instalado e usa um
41
- perfil persistente exclusivo em `browser.computer_user_data_dir`; personalize
42
- as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
34
+ ```sh
35
+ npm install @diegosouzacdv/jev-browser-mcp
36
+ ```
37
+
38
+ O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
39
+ configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
40
+ pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp --install-browser`.
41
+
42
+ O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
43
+ persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
44
+ instalação baixa uma vez o Chrome/Edge que o Playwright controlará. Personalize
45
+ as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
43
46
  `JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
44
47
  estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
45
48
  e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
@@ -66,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
66
69
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
67
70
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
68
71
  raiz local configurada e reações idempotentes a um comentário único. Também
69
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
70
- JavaScript enviado pelo harness, seletores livres nem coordenadas. Ele usa a
71
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
74
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
75
+ são o último recurso e geram um aviso no resultado. Ele usa a
76
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
77
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
73
78
  `stderr` para não misturar com JSON-RPC.
74
79
 
@@ -84,24 +89,50 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
84
89
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
85
90
  resultado esperado na tela.
86
91
 
87
- Cada plano pode usar:
88
-
89
- - `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
90
- - `wait_for_text` e `wait_for_condition` (`network_idle`, limitado pelo timeout
91
- de ação configurado);
92
- - `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
93
- `Enter`, `Escape` ou `Tab`;
94
- - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`;
92
+ Cada plano pode usar:
93
+
94
+ - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
95
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
96
+ `text`, `test_id` ou `selector`;
97
+ - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
98
+ e `within: {"row_containing":"..."}` para limitar a ação à linha certa;
99
+ - `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
100
+ o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
101
+ com `opacity: 0`;
102
+ - `name: ""` com `index` não negativo para controles sem nome. O resultado
103
+ inclui um aviso porque a posição pode mudar entre execuções;
104
+ - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
105
+ em `warnings`; não é permitido enviar JavaScript nem coordenadas;
106
+ - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
107
+ - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
108
+ `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
109
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
110
+ - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
111
+ `text_hidden`); `network_idle` aceita `url_contains` para aguardar só as
112
+ requisições correspondentes;
113
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
114
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
115
+ envia a tecla ao elemento focado; com alvo, usa o localizador informado;
116
+ - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
117
+ pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
95
118
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
96
119
  dropzone;
97
120
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
98
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
99
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
100
- `Descurtir`.
101
-
102
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
103
- container acessível único, como uma linha ou card. `index` escolhe uma ocorrência
104
- zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
122
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
123
+ `Descurtir`.
124
+
125
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
126
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
127
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
128
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
129
+ esperar que ela termine.
130
+
131
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
132
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
133
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
134
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
135
+ controle próximo ao texto visível do rótulo.
105
136
 
106
137
  ```json
107
138
  {
@@ -113,8 +144,40 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
113
144
  ```
114
145
 
115
146
  ```json
116
- {"action":"click","role":"button","name":"Add to cart","index":0}
117
- ```
147
+ {"action":"click","role":"button","name":"Add to cart","index":0}
148
+ ```
149
+
150
+ Exemplos para controles legados sem nome acessível:
151
+
152
+ ```json
153
+ {"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
154
+ {"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
155
+ {"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
156
+ {"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
157
+ {"action":"click","role":"button","name":"","index":0}
158
+ {"action":"click","selector":"#save-document"}
159
+ ```
160
+
161
+ O reconhecimento retorna `unnamed_controls` com papel, posição, rótulo mais
162
+ próximo e um trecho HTML sanitizado dos controles interativos sem nome. O
163
+ snapshot também resume campos de formulário com `id`, `name`, valor, estado
164
+ desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
165
+ sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
166
+ é `false` por padrão; defina `true` somente quando precisar inspecionar campos
167
+ ocultos também.
168
+
169
+ Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
170
+ localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
171
+ `textbox`, `searchbox` ou `combobox`.
172
+
173
+ Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
174
+ Valores dentro de campos não contam como resultado visível. `stop_on_expected:
175
+ true` habilita parada antecipada quando o texto esperado aparece fora dos
176
+ campos; mantenha `false` para fluxos com várias etapas.
177
+
178
+ Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
179
+ de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
180
+ e erro.
118
181
 
119
182
  ### Captura de downloads
120
183
 
@@ -151,12 +214,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
151
214
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
152
215
  com revisão manual e testes com usuários assistivos.
153
216
 
154
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
155
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
156
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
157
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
158
- próximos quando o snapshot os encontrar. O plano não aceita JavaScript enviado
159
- pelo harness, coordenadas ou seletores livres.
217
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
218
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
219
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
220
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
221
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
222
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
223
+ JavaScript enviado pelo harness nem coordenadas.
160
224
 
161
225
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
162
226
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -239,9 +303,9 @@ do pacote Node ficam no bloco opcional `jev_browser_mcp`, que não altera o
239
303
  contrato lido pelo servidor Python. Preserve a estrutura completa exigida pelos
240
304
  validadores.
241
305
 
242
- `browser.mode` aceita `harness` ou `computer`:
306
+ `browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
243
307
 
244
- - `harness` usa Chrome headless e perfil isolado, adequado a execuções do
308
+ - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
245
309
  harness e CI; o estado de autenticação é descartado ao final da chamada.
246
310
  - `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
247
311
  persistente `browser.computer_user_data_dir`, separado por navegador. Não
@@ -250,12 +314,15 @@ validadores.
250
314
 
251
315
  `browser.max_flow_steps` limita a soma de passos declarados entre os planos e
252
316
  `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
253
- `status`, o plano escolhido, as ações executadas, a última captura acessível e
254
- se o critério esperado apareceu. Quando existem asserções explícitas, `status`
255
- também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
256
- esse resultado e `expected_outcome_visible` continua descrevendo somente o
257
- texto global. `incomplete` significa que nenhum critério foi comprovado;
258
- confiança do Jev não substitui essa verificação.
317
+ `status`, o plano escolhido, as ações executadas, a última captura acessível e
318
+ se o critério esperado apareceu. Quando existem asserções explícitas, `status`
319
+ também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
320
+ esse resultado e `expected_outcome_visible` continua descrevendo somente o
321
+ texto global. `incomplete` significa que nenhum critério foi comprovado;
322
+ confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
323
+ espera da SPA; `warnings` registra capturas vazias durante transições; e
324
+ `failed_step` identifica índice, ação, alvo, timeout e erro resumido quando uma
325
+ etapa falha.
259
326
 
260
327
  `jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
261
328
  seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
@@ -271,12 +338,20 @@ Os limites de download ficam no mesmo bloco: `max_download_files`,
271
338
  limita quantas descrições de violações axe entram no resultado; a contagem total
272
339
  continua informada mesmo quando a lista é truncada.
273
340
 
274
- O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
275
- `block_trackers`, `capture_console_errors`, `capture_network_errors`,
276
- `screenshot_on_failure` e `trace_on_failure`. Sem override, os padrões são lidos
277
- de `jev_browser_mcp` em `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
278
- captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
279
- de recursos ficam desligados. `snapshot_scope` aceita `body`, `main` ou `dialog`.
341
+ O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
342
+ `block_trackers`, `capture_console_errors`, `capture_network_errors`,
343
+ `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
344
+ `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
345
+ `trace_on_failure`, `snapshot_include_hidden` e `stop_on_expected`. Sem override,
346
+ os padrões são lidos de `jev_browser_mcp` em
347
+ `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
348
+ captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
349
+ de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
350
+ acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
351
+ acessível estável. `ready_text` pode identificar o conteúdo que marca a
352
+ prontidão. `reuse_page: true` pula a navegação somente quando a página e
353
+ `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
354
+ `dialog`.
280
355
 
281
356
  `block_trackers: true` bloqueia os domínios e tipos de recurso listados na
282
357
  configuração (analytics, Hotjar, fontes externas e mídia). Isso pode alterar o
@@ -284,9 +359,12 @@ layout ou o comportamento do site, então a opção é desligada por padrão.
284
359
 
285
360
  Com `capture_console_errors` e `capture_network_errors`, o retorno traz
286
361
  `console_errors` e `network_failures`, limitados em quantidade e tamanho.
287
- Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
288
- fragmentos, valores de formulário e nomes de arquivo são removidos ou
289
- sanitizados. Em falhas, `screenshot_on_failure` salva screenshot local e retorna
362
+ Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
363
+ fragmentos, valores de formulário e nomes de arquivo são removidos ou
364
+ sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
365
+ 4xx/5xx da mesma origem, limita o corpo e inclui apenas o campo textual
366
+ `message`, também sanitizado. Em falhas, `screenshot_on_failure` salva
367
+ screenshot local e retorna
290
368
  `screenshot_path`. `trace_on_failure: true` também grava um `.zip` compatível
291
369
  com o Trace Viewer do Playwright e retorna `trace_path`. O diretório padrão é
292
370
  `~/.cache/orquestrador/jev-browser-artifacts`; `JEV_BROWSER_ARTIFACT_DIR` pode
@@ -10,7 +10,7 @@ Usage:
10
10
  jev-browser-mcp --help Show this help
11
11
 
12
12
  Configuration is read from config/ui-testing.json. Set OPENROUTER_API_KEY in
13
- the environment and use JEV_BROWSER_MODE=harness or computer to choose a browser.
13
+ the environment. The default mode is computer; use JEV_BROWSER_MODE=harness to select isolated headless mode.
14
14
  For upload_file, set JEV_BROWSER_UPLOAD_ROOT to a dedicated fixture directory.
15
15
  `;
16
16