@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 +132 -54
- package/config/ui-testing.json +18 -3
- package/docs/jev-browser-mcp.md +132 -54
- package/mcp_servers/jev-browser-npm/bin/jev-browser-mcp.cjs +1 -1
- package/mcp_servers/jev-browser-npm/src/config.mjs +55 -8
- package/mcp_servers/jev-browser-npm/src/flow.mjs +1125 -376
- package/mcp_servers/jev-browser-npm/src/jev-client.mjs +5 -4
- package/mcp_servers/jev-browser-npm/src/server.mjs +8 -12
- package/package.json +1 -1
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.
|
|
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": "
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
71
|
-
|
|
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
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- `
|
|
93
|
-
`
|
|
94
|
-
- `
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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.
|
|
159
|
-
|
|
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
|
|
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
|
-
`
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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.
|
|
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
|
package/config/ui-testing.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
3
|
"browser": {
|
|
4
|
-
"mode": "
|
|
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
|
-
"
|
|
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,
|
package/docs/jev-browser-mcp.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.
|
|
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": "
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
71
|
-
|
|
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
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- `
|
|
93
|
-
`
|
|
94
|
-
- `
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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.
|
|
159
|
-
|
|
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
|
|
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
|
-
`
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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.
|
|
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
|
|
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
|
|