@diegosouzacdv/jev-browser-mcp 0.2.0 → 0.3.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 +315 -1775
- package/config/ui-testing.json +45 -40
- package/docs/jev-browser-mcp.md +354 -291
- package/mcp_servers/jev-browser-npm/src/accessibility.mjs +38 -0
- package/mcp_servers/jev-browser-npm/src/config.mjs +151 -141
- package/mcp_servers/jev-browser-npm/src/flow.mjs +990 -769
- package/mcp_servers/jev-browser-npm/src/server.mjs +12 -12
- package/package.json +32 -34
package/docs/jev-browser-mcp.md
CHANGED
|
@@ -1,291 +1,354 @@
|
|
|
1
|
-
# Automação de tela com Jev e Playwright
|
|
2
|
-
|
|
3
|
-
## Instalar em outros harnesses com npm/npx
|
|
4
|
-
|
|
5
|
-
O repositório também contém um pacote Node independente do harness. Ele fala
|
|
6
|
-
MCP por `stdio`, executa o Playwright no mesmo processo e pode ser iniciado por
|
|
7
|
-
qualquer harness que aceite `command` e `args` para um servidor MCP. O pacote
|
|
8
|
-
usa o mesmo `config/ui-testing.json` deste repositório; não precisa instalar o
|
|
9
|
-
Python do orquestrador. As opções específicas do pacote ficam isoladas no
|
|
10
|
-
bloco `jev_browser_mcp` para preservar o contrato do servidor Python.
|
|
11
|
-
|
|
12
|
-
Instale a versão publicada do npm diretamente no harness. Para fixar uma
|
|
13
|
-
versão em produção, use o número explícito no argumento do pacote:
|
|
14
|
-
|
|
15
|
-
```json
|
|
16
|
-
{
|
|
17
|
-
"mcpServers": {
|
|
18
|
-
"jev-browser": {
|
|
19
|
-
"command": "npx",
|
|
20
|
-
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.
|
|
21
|
-
"env": {
|
|
22
|
-
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
|
|
23
|
-
"JEV_BROWSER_MODE": "harness"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
O formato de interpolação de variáveis varia por harness. Injete a chave por
|
|
31
|
-
um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
|
|
32
|
-
de configuração. Para instalar no projeto Node do próprio harness:
|
|
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
|
|
43
|
-
`JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
|
|
44
|
-
estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
|
|
45
|
-
e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
|
|
46
|
-
nome de variável declarado em `jev.credential_env`.
|
|
47
|
-
|
|
48
|
-
Uma aplicação Node também pode importar `createJevBrowserServer` por
|
|
49
|
-
`@diegosouzacdv/jev-browser-mcp/server` e conectar o servidor ao transporte MCP
|
|
50
|
-
que ela já utiliza.
|
|
51
|
-
|
|
52
|
-
O pacote é montado
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- `
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
e
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
`
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
1
|
+
# Automação de tela com Jev e Playwright
|
|
2
|
+
|
|
3
|
+
## Instalar em outros harnesses com npm/npx
|
|
4
|
+
|
|
5
|
+
O repositório também contém um pacote Node independente do harness. Ele fala
|
|
6
|
+
MCP por `stdio`, executa o Playwright no mesmo processo e pode ser iniciado por
|
|
7
|
+
qualquer harness que aceite `command` e `args` para um servidor MCP. O pacote
|
|
8
|
+
usa o mesmo `config/ui-testing.json` deste repositório; não precisa instalar o
|
|
9
|
+
Python do orquestrador. As opções específicas do pacote ficam isoladas no
|
|
10
|
+
bloco `jev_browser_mcp` para preservar o contrato do servidor Python.
|
|
11
|
+
|
|
12
|
+
Instale a versão publicada do npm diretamente no harness. Para fixar uma
|
|
13
|
+
versão em produção, use o número explícito no argumento do pacote:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"jev-browser": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.3.1"],
|
|
21
|
+
"env": {
|
|
22
|
+
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
|
|
23
|
+
"JEV_BROWSER_MODE": "harness"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
O formato de interpolação de variáveis varia por harness. Injete a chave por
|
|
31
|
+
um secret manager ou pelo ambiente do processo; não grave a chave no arquivo
|
|
32
|
+
de configuração. Para instalar no projeto Node do próprio harness:
|
|
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
|
|
43
|
+
`JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
|
|
44
|
+
estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
|
|
45
|
+
e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
|
|
46
|
+
nome de variável declarado em `jev.credential_env`.
|
|
47
|
+
|
|
48
|
+
Uma aplicação Node também pode importar `createJevBrowserServer` por
|
|
49
|
+
`@diegosouzacdv/jev-browser-mcp/server` e conectar o servidor ao transporte MCP
|
|
50
|
+
que ela já utiliza.
|
|
51
|
+
|
|
52
|
+
O pacote é montado em uma pasta temporária isolada: o publicador usa o campo
|
|
53
|
+
`files` do `package.json` para copiar somente o código Node, a configuração
|
|
54
|
+
compartilhada e esta documentação, que também vira o `README.md` da raiz do
|
|
55
|
+
pacote. Assim, o npm não inclui o README geral do orquestrador na página do MCP.
|
|
56
|
+
Para gerar e conferir o pacote antes de publicar, execute
|
|
57
|
+
`npm run pack:jev-browser-mcp`; para publicar uma versão já autenticada no npm, execute
|
|
58
|
+
`npm run publish:jev-browser-mcp`. A instalação por npm é a recomendada; use a
|
|
59
|
+
referência GitHub somente quando precisar experimentar uma revisão ainda não
|
|
60
|
+
publicada.
|
|
61
|
+
|
|
62
|
+
### Contrato do pacote
|
|
63
|
+
|
|
64
|
+
O executável oferece `choose_next_action` e `run_browser_flow`, mantém uma
|
|
65
|
+
sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
|
|
66
|
+
passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
|
|
67
|
+
hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
|
|
68
|
+
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
|
+
Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
|
|
73
|
+
`stderr` para não misturar com JSON-RPC.
|
|
74
|
+
|
|
75
|
+
O modo `computer` grava cookies no perfil exclusivo configurado, e conteúdo da
|
|
76
|
+
página pode conter instruções maliciosas. O Jev recebe a captura acessível com
|
|
77
|
+
uma instrução para tratar esse conteúdo como dado não confiável; não inclua
|
|
78
|
+
segredos no fluxo, no resultado esperado ou nas descrições dos planos.
|
|
79
|
+
|
|
80
|
+
Para um fluxo conhecido, o LLM do harness procura o cenário e os critérios de
|
|
81
|
+
aceitação no projeto e chama `jev_browser.run_browser_flow` com planos
|
|
82
|
+
candidatos declarativos. O MCP abre uma única sessão do Playwright, navega para
|
|
83
|
+
a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
|
|
84
|
+
plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
|
|
85
|
+
resultado esperado na tela.
|
|
86
|
+
|
|
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`;
|
|
95
|
+
- `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
|
|
96
|
+
dropzone;
|
|
97
|
+
- `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.
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"action": "click",
|
|
109
|
+
"role": "button",
|
|
110
|
+
"name": "Add to cart",
|
|
111
|
+
"within": {"role": "group", "name": "Sauce Labs Backpack"}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{"action":"click","role":"button","name":"Add to cart","index":0}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Captura de downloads
|
|
120
|
+
|
|
121
|
+
Marque o clique que deve iniciar um download com `expect_download: true`. O
|
|
122
|
+
Playwright começa a aguardar o evento antes do clique; após a transferência
|
|
123
|
+
terminar, o MCP verifica o tamanho, sanitiza o nome sugerido e copia o arquivo
|
|
124
|
+
para `JEV_BROWSER_ARTIFACT_DIR` (ou para o diretório de artefatos configurado).
|
|
125
|
+
O resultado inclui a lista `downloaded_files`, com nome, caminho local e bytes;
|
|
126
|
+
cada passo também contém o arquivo capturado. Os limites contam arquivos e bytes
|
|
127
|
+
por fluxo. A checagem de tamanho acontece depois da transferência do navegador,
|
|
128
|
+
antes de copiar para a pasta de artefatos.
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{"action":"click","role":"button","name":"Export report","expect_download":true}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`jev_browser_mcp.browser.max_download_files`, `max_download_file_bytes`,
|
|
135
|
+
`max_download_total_bytes` e `max_download_timeout_seconds` definem os limites.
|
|
136
|
+
O diretório de artefatos deve ser local e protegido: arquivos baixados podem
|
|
137
|
+
conter dados da aplicação.
|
|
138
|
+
|
|
139
|
+
### Auditoria automatizada de acessibilidade
|
|
140
|
+
|
|
141
|
+
Use `audit_accessibility` depois de colocar a página no estado que deseja
|
|
142
|
+
verificar:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{"action":"audit_accessibility","standard":"wcag2aa"}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
O MCP usa `@axe-core/playwright` com as tags WCAG 2.0 e 2.1 A/AA. O retorno
|
|
149
|
+
resume as violações por regra, impacto e quantidade de nós, sem copiar HTML ou
|
|
150
|
+
trechos da página. Qualquer violação reprova esse fluxo. A auditoria automática
|
|
151
|
+
encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
|
|
152
|
+
com revisão manual e testes com usuários assistivos.
|
|
153
|
+
|
|
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.
|
|
160
|
+
|
|
161
|
+
Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
|
|
162
|
+
asserções são aceitos. `comment` também é aceito em planos e passos, mas é
|
|
163
|
+
ignorado e não é enviado ao Jev. Campos fora do contrato continuam sendo
|
|
164
|
+
recusados.
|
|
165
|
+
|
|
166
|
+
### Upload de arquivos
|
|
167
|
+
|
|
168
|
+
Defina `JEV_BROWSER_UPLOAD_ROOT` como uma pasta absoluta que contenha os arquivos
|
|
169
|
+
de fixture. Cada caminho passado ao fluxo também precisa ser absoluto; o MCP
|
|
170
|
+
resolve links simbólicos e recusa qualquer arquivo fora dessa raiz. Só aceita
|
|
171
|
+
arquivos regulares, até 5 arquivos por passo, 10 MiB por arquivo e 25 MiB no
|
|
172
|
+
total do passo, conforme `jev_browser_mcp.browser` em `config/ui-testing.json`.
|
|
173
|
+
Os bytes são lidos e validados no processo local antes de serem entregues ao
|
|
174
|
+
Playwright. O MCP não envia esses bytes ao Jev nem os inclui diretamente na
|
|
175
|
+
resposta; texto que o próprio site exibir na interface ainda pode aparecer no
|
|
176
|
+
snapshot devolvido ao harness.
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{"action":"upload_file","target":"input","label":"Nota fiscal","file_path":"/fixtures/nota.pdf"}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Para uma área de arrastar, use o papel e o nome acessível da dropzone. Para um
|
|
183
|
+
botão que abre a janela nativa, use `target: "button"`; sem `target`, a presença
|
|
184
|
+
de `label` seleciona o input e `role`/`name` seleciona esse botão.
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{"action":"upload_file","target":"dropzone","role":"region","name":"Anexos","file_paths":["/fixtures/a.pdf","/fixtures/b.png"]}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Se `JEV_BROWSER_UPLOAD_ROOT` não estiver definido, a ação recusa a execução. O
|
|
191
|
+
limite evita que um plano transforme o MCP em leitor arbitrário de arquivos do
|
|
192
|
+
computador.
|
|
193
|
+
|
|
194
|
+
Exemplo de chamada:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"flow": "Adicionar o produto ao carrinho e confirmar o resumo",
|
|
199
|
+
"initial_url": "http://127.0.0.1:4173/products/coffee",
|
|
200
|
+
"expected_outcome": "Coffee added to cart",
|
|
201
|
+
"options": {
|
|
202
|
+
"fast_path": true,
|
|
203
|
+
"snapshot_scope": "main",
|
|
204
|
+
"capture_network_errors": true,
|
|
205
|
+
"screenshot_on_failure": true
|
|
206
|
+
},
|
|
207
|
+
"candidate_plans": {
|
|
208
|
+
"add_and_confirm": {
|
|
209
|
+
"description": "Adicionar o produto visível ao carrinho e abrir o resumo",
|
|
210
|
+
"steps": [
|
|
211
|
+
{"action": "click", "role": "button", "name": "Add to cart"},
|
|
212
|
+
{"action": "wait_for_text", "text": "Coffee added to cart"},
|
|
213
|
+
{"action": "click", "role": "link", "name": "View cart"},
|
|
214
|
+
{"action": "assert_text", "role": "heading", "name": "Order summary", "expected": "Coffee"}
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
O plano é montado pelo LLM do harness, mas o Jev escolhe qual plano fornecido
|
|
222
|
+
deve executar usando o fluxo e o snapshot inicial. O Jev não cria ações, nomes
|
|
223
|
+
de controles ou valores de formulário. Valores de `type` são usados localmente
|
|
224
|
+
pelo Playwright e são removidos do texto enviado ao provedor e da evidência de
|
|
225
|
+
retorno. Use valores de teste; autenticação deve ficar no perfil de navegador
|
|
226
|
+
configurado.
|
|
227
|
+
|
|
228
|
+
O MCP também mantém `choose_next_action` para fluxos exploratórios em que o
|
|
229
|
+
harness precisa inspecionar e decidir entre ações uma por vez. Esse caminho é
|
|
230
|
+
mais lento porque exige uma nova decisão e uma nova chamada de ferramenta por
|
|
231
|
+
ação; prefira `run_browser_flow` quando os passos esperados puderem ser
|
|
232
|
+
descritos antes da execução.
|
|
233
|
+
|
|
234
|
+
## Configuração
|
|
235
|
+
|
|
236
|
+
Edite `config/ui-testing.json`. URL, modelo do provedor, variável de credencial
|
|
237
|
+
e limites compartilhados ficam nos blocos `browser` e `jev`. As opções próprias
|
|
238
|
+
do pacote Node ficam no bloco opcional `jev_browser_mcp`, que não altera o
|
|
239
|
+
contrato lido pelo servidor Python. Preserve a estrutura completa exigida pelos
|
|
240
|
+
validadores.
|
|
241
|
+
|
|
242
|
+
`browser.mode` aceita `harness` ou `computer`:
|
|
243
|
+
|
|
244
|
+
- `harness` usa Chrome headless e perfil isolado, adequado a execuções do
|
|
245
|
+
harness e CI; o estado de autenticação é descartado ao final da chamada.
|
|
246
|
+
- `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
|
|
247
|
+
persistente `browser.computer_user_data_dir`, separado por navegador. Não
|
|
248
|
+
reutiliza o perfil pessoal já aberto. Faça login uma vez nesse perfil; os
|
|
249
|
+
cookies permanecem nele entre chamadas.
|
|
250
|
+
|
|
251
|
+
`browser.max_flow_steps` limita a soma de passos declarados entre os planos e
|
|
252
|
+
`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.
|
|
259
|
+
|
|
260
|
+
`jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
|
|
261
|
+
seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
|
|
262
|
+
de uma pasta absoluta escolhida pelo operador.
|
|
263
|
+
`jev_browser_mcp.browser.max_upload_files`, `max_upload_path_chars`,
|
|
264
|
+
`max_upload_file_bytes` e `max_upload_total_bytes` limitam quantidade e tamanho.
|
|
265
|
+
Não configure a raiz como o disco inteiro ou a pasta home: use uma pasta de
|
|
266
|
+
fixtures dedicada.
|
|
267
|
+
|
|
268
|
+
Os limites de download ficam no mesmo bloco: `max_download_files`,
|
|
269
|
+
`max_download_file_bytes`, `max_download_total_bytes` e
|
|
270
|
+
`max_download_timeout_seconds`. `jev_browser_mcp.jev.max_accessibility_violations`
|
|
271
|
+
limita quantas descrições de violações axe entram no resultado; a contagem total
|
|
272
|
+
continua informada mesmo quando a lista é truncada.
|
|
273
|
+
|
|
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`.
|
|
280
|
+
|
|
281
|
+
`block_trackers: true` bloqueia os domínios e tipos de recurso listados na
|
|
282
|
+
configuração (analytics, Hotjar, fontes externas e mídia). Isso pode alterar o
|
|
283
|
+
layout ou o comportamento do site, então a opção é desligada por padrão.
|
|
284
|
+
|
|
285
|
+
Com `capture_console_errors` e `capture_network_errors`, o retorno traz
|
|
286
|
+
`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
|
|
290
|
+
`screenshot_path`. `trace_on_failure: true` também grava um `.zip` compatível
|
|
291
|
+
com o Trace Viewer do Playwright e retorna `trace_path`. O diretório padrão é
|
|
292
|
+
`~/.cache/orquestrador/jev-browser-artifacts`; `JEV_BROWSER_ARTIFACT_DIR` pode
|
|
293
|
+
substituí-lo por uma pasta absoluta fora do pacote. Screenshots e traces podem
|
|
294
|
+
conter dados visíveis da aplicação: mantenha o diretório local protegido e
|
|
295
|
+
compartilhe os arquivos somente se o teste permitir.
|
|
296
|
+
|
|
297
|
+
`harness_browser` e `computer_browser` aceitam `chrome` ou `msedge`.
|
|
298
|
+
`computer_user_data_dir` deve ficar fora do repositório e conter `{browser}`;
|
|
299
|
+
o diretório persistente armazena dados de login e é resolvido sob a pasta home
|
|
300
|
+
do usuário quando começa com `~`. O Playwright MCP fica desabilitado até
|
|
301
|
+
`ORQUESTRADOR_MCP_PLAYWRIGHT_ENABLED=1` ser configurado no ambiente do harness.
|
|
302
|
+
|
|
303
|
+
Defina o valor secreto na variável indicada por `jev.credential_env`, usando o
|
|
304
|
+
secret manager ou ambiente do processo que inicia o harness. Não grave a chave
|
|
305
|
+
em `config/ui-testing.json`. `provider_url` é o endpoint HTTPS completo da API
|
|
306
|
+
Decisions. O cliente não
|
|
307
|
+
segue redirects e recusa URL com credencial, query string ou fragmento. O Jev
|
|
308
|
+
fica indisponível quando a política de MCP está em modo offline.
|
|
309
|
+
|
|
310
|
+
Na primeira execução, aqueça uma vez o cache local do pacote declarado em
|
|
311
|
+
`browser.playwright_mcp_package` com `npx --yes <pacote> --help`. O MCP inicia
|
|
312
|
+
depois com `--offline`, evitando uma consulta ao registry npm em cada fluxo.
|
|
313
|
+
Quando a versão configurada mudar, aqueça o novo pacote uma vez.
|
|
314
|
+
|
|
315
|
+
## Desempenho e evidência
|
|
316
|
+
|
|
317
|
+
O pacote Node usa a decisão remota do Jev para escolher entre múltiplos planos.
|
|
318
|
+
Com exatamente um plano e `fast_path` ligado (padrão), executa esse plano sem
|
|
319
|
+
chamar a API Decisions; `jev_decisions` fica em zero. Inclua o fluxo completo em
|
|
320
|
+
um plano candidato para evitar chamadas separadas ao harness; seleção,
|
|
321
|
+
navegação, ações e asserções ficam em uma chamada MCP. O servidor Python
|
|
322
|
+
`mcp_servers/jev_browser_server.py` mantém seu fluxo próprio e usa uma decisão
|
|
323
|
+
remota do Jev por chamada. A sessão Playwright fecha antes de o MCP Python
|
|
324
|
+
retornar. O perfil do modo `computer` preserva o login para chamadas seguintes;
|
|
325
|
+
nesse servidor o processo e a janela não são reutilizados. O pacote Node mantém
|
|
326
|
+
o browser aquecido até o harness encerrar o processo. O snapshot enviado ao Jev
|
|
327
|
+
e devolvido ao harness remove o rodapé e, se ainda exceder o limite, mantém o
|
|
328
|
+
início e o fim da captura com um marcador de truncamento. `snapshot_scope` pode
|
|
329
|
+
limitar a captura a `main` ou `dialog`; iframes nomeados contidos nesse escopo
|
|
330
|
+
também podem ser incluídos.
|
|
331
|
+
|
|
332
|
+
A chamada composta aquecida deve ficar dentro da meta de 20 segundos em páginas
|
|
333
|
+
que respondem normalmente; a inicialização fria, páginas lentas, MFA e conteúdo
|
|
334
|
+
sob demanda podem excedê-la. O MCP devolve `total_ms`, `browser_session_ms`,
|
|
335
|
+
`navigation_ms`, `initial_snapshot_ms`, `jev_decision_ms` e `browser_plan_ms`
|
|
336
|
+
para localizar o custo. O teto observado em um fluxo sintético local anterior
|
|
337
|
+
foi 6,411 s; isso não mede o Instagram nem garante o mesmo tempo em outros sites.
|
|
338
|
+
|
|
339
|
+
O snapshot inicial, o fluxo, o resultado esperado e as descrições dos planos
|
|
340
|
+
são enviados ao endpoint Decisions quando há mais de uma opção. Com fast-path,
|
|
341
|
+
um plano não gera chamada remota. Os passos, valores digitados, valores
|
|
342
|
+
esperados pelas asserções, caminhos e conteúdo dos arquivos não são enviados.
|
|
343
|
+
Não inclua segredos em `flow`, `expected_outcome` ou nas descrições. A resposta
|
|
344
|
+
retorna o plano escolhido quando houver decisão, custo/confiança do provedor
|
|
345
|
+
quando disponíveis e o snapshot final sanitizado. O fluxo passa quando o texto
|
|
346
|
+
esperado aparece no snapshot ou quando todas as asserções declaradas passam.
|
|
347
|
+
|
|
348
|
+
`network_idle` é uma espera limitada e opcional; páginas com polling ou conexões
|
|
349
|
+
contínuas podem atingir o timeout. Prefira `wait_for_text` e asserções de
|
|
350
|
+
elemento quando houver um sinal de interface específico.
|
|
351
|
+
|
|
352
|
+
Consulte a [introdução do Jev](https://docs.typesafe.ai/introduction) e o
|
|
353
|
+
[tutorial da API Decisions no OpenRouter](https://openrouter.ai/docs/guides/community/jev-tutorial)
|
|
354
|
+
para os tipos de resposta e autenticação.
|