@diegosouzacdv/jev-browser-mcp 0.5.0 → 0.6.0

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.
@@ -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.5.0"],
20
+ "args": ["--yes", "@diegosouzacdv/jev-browser-mcp@0.6.0"],
21
21
  "env": {
22
22
  "OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
23
- "JEV_BROWSER_MODE": "computer"
23
+ "JEV_BROWSER_MODE": "computer"
24
24
  }
25
25
  }
26
26
  }
@@ -31,30 +31,30 @@ 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
- Se o harness executa o MCP repetidamente nesta máquina, instale uma versão
39
- fixa globalmente para evitar a resolução e o download feitos pelo `npx` em cada
40
- inicialização:
41
-
42
- ```sh
43
- npm install --global @diegosouzacdv/jev-browser-mcp@0.5.0
44
- ```
45
-
46
- Depois configure o servidor MCP com `command: "jev-browser-mcp"` e `args: []`.
47
- Para atualizar, rode `npm install --global
48
- @diegosouzacdv/jev-browser-mcp@<versão>` e reinicie o processo do harness.
49
-
50
- O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
51
- configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
52
- pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp --install-browser`.
53
-
54
- O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
55
- persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
56
- instalação baixa uma vez o Chrome/Edge que o Playwright controlará. Personalize
57
- as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
34
+ ```sh
35
+ npm install @diegosouzacdv/jev-browser-mcp
36
+ ```
37
+
38
+ Se o harness executa o MCP repetidamente nesta máquina, instale uma versão
39
+ fixa globalmente para evitar a resolução e o download feitos pelo `npx` em cada
40
+ inicialização:
41
+
42
+ ```sh
43
+ npm install --global @diegosouzacdv/jev-browser-mcp@0.6.0
44
+ ```
45
+
46
+ Depois configure o servidor MCP com `command: "jev-browser-mcp"` e `args: []`.
47
+ Para atualizar, rode `npm install --global
48
+ @diegosouzacdv/jev-browser-mcp@<versão>` e reinicie o processo do harness.
49
+
50
+ O padrão `computer` exige Chrome ou Edge instalado. Se optar por `harness`,
51
+ configure `JEV_BROWSER_MODE=harness` antes de instalar o navegador gerenciado
52
+ pelo Playwright com `npx --yes @diegosouzacdv/jev-browser-mcp --install-browser`.
53
+
54
+ O padrão é `computer`: o pacote abre o Chrome/Edge instalado e usa um perfil
55
+ persistente exclusivo em `browser.computer_user_data_dir`. No modo `harness`, a
56
+ instalação baixa uma vez o Chrome/Edge que o Playwright controlará. Personalize
57
+ as escolhas com `JEV_BROWSER_MODE`, `JEV_BROWSER_CHANNEL` e
58
58
  `JEV_BROWSER_PROFILE`. O browser permanece aquecido enquanto o processo MCP
59
59
  estiver ativo e fecha quando o harness encerra o processo. `JEV_PROVIDER_URL`
60
60
  e `JEV_MODEL` podem substituir os valores centrais; a credencial continua no
@@ -64,28 +64,28 @@ Uma aplicação Node também pode importar `createJevBrowserServer` por
64
64
  `@diegosouzacdv/jev-browser-mcp/server` e conectar o servidor ao transporte MCP
65
65
  que ela já utiliza.
66
66
 
67
- O pacote é montado em uma pasta temporária isolada: o publicador usa o campo
68
- `files` do `package.json` para copiar somente o código Node, a configuração
69
- compartilhada e esta documentação, que também vira o `README.md` da raiz do
70
- pacote. Assim, o npm não inclui o README geral do orquestrador na página do MCP.
71
- Para gerar e conferir o pacote antes de publicar, execute
72
- `npm run pack:jev-browser-mcp`; para publicar uma versão já autenticada no npm, execute
73
- `npm run publish:jev-browser-mcp`. A instalação por npm é a recomendada; use a
74
- referência GitHub somente quando precisar experimentar uma revisão ainda não
75
- publicada.
67
+ O pacote é montado em uma pasta temporária isolada: o publicador usa o campo
68
+ `files` do `package.json` para copiar somente o código Node, a configuração
69
+ compartilhada e esta documentação, que também vira o `README.md` da raiz do
70
+ pacote. Assim, o npm não inclui o README geral do orquestrador na página do MCP.
71
+ Para gerar e conferir o pacote antes de publicar, execute
72
+ `npm run pack:jev-browser-mcp`; para publicar uma versão já autenticada no npm, execute
73
+ `npm run publish:jev-browser-mcp`. A instalação por npm é a recomendada; use a
74
+ referência GitHub somente quando precisar experimentar uma revisão ainda não
75
+ publicada.
76
76
 
77
77
  ### Contrato do pacote
78
78
 
79
- O executável oferece `choose_next_action` e `run_browser_flow`, mantém uma
79
+ O executável oferece `browser_health`, `choose_next_action` e `run_browser_flow`, mantém uma
80
80
  sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
81
81
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
82
82
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
83
83
  raiz local configurada e reações idempotentes a um comentário único. Também
84
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
85
- JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
86
- aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
87
- são o último recurso e geram um aviso no resultado. Ele usa a
88
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
84
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
85
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
86
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
87
+ são o último recurso e geram um aviso no resultado. Ele usa a
88
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
89
89
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
90
90
  `stderr` para não misturar com JSON-RPC.
91
91
 
@@ -101,111 +101,114 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
101
101
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
102
102
  resultado esperado na tela.
103
103
 
104
- Cada plano pode usar:
105
-
106
- - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
107
- papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
108
- `text`, `test_id` ou `selector`;
109
- - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
110
- `within: {"row_containing":"..."}` para limitar por trecho e
111
- `within: {"row_containing_exact":"..."}` para exigir um elemento com o
112
- texto exato na linha, sem casar com `15287210` ao procurar `1528721`;
113
- - `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
114
- o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
115
- com `opacity: 0`;
116
- - `name: ""` com `index` não negativo para controles sem nome. O resultado
117
- inclui um aviso porque a posição pode mudar entre execuções. O índice é
118
- zero-based para o mesmo papel e inclui nomes vazios ou compostos só por
119
- espaços/glyphs de uso privado, como ícones Font Awesome; controles
120
- desabilitados não aparecem no diagnóstico, mas continuam contando para que o
121
- índice aponte ao controle correto;
122
- - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
123
- em `warnings`; não é permitido enviar JavaScript nem coordenadas;
124
- - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
125
- - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
126
- `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
127
- valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
128
- - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
129
- `text_hidden`). `wait_for_text` aceita `fail_on: {"role":"alert"}` para
130
- interromper a espera assim que um alerta visível aparecer e incluir seu texto
131
- no erro. Se o alerta contiver o texto esperado, a etapa passa; caso contrário,
132
- o alerta interrompe a espera. `network_idle` aceita `url_contains` para
133
- aguardar só as requisições correspondentes;
134
- - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
135
- `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
136
- envia a tecla ao elemento focado; com alvo, usa o localizador informado;
137
- - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
138
- pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
104
+ Cada plano pode usar:
105
+
106
+ - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
107
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
108
+ `text`, `test_id` ou `selector`;
109
+ - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
110
+ `within: {"row_containing":"..."}` para limitar por trecho e
111
+ `within: {"row_containing_exact":"..."}` para exigir um elemento com o
112
+ texto exato na linha, sem casar com `15287210` ao procurar `1528721`;
113
+ - `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
114
+ o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
115
+ com `opacity: 0`;
116
+ - `name: ""` com `index` não negativo para controles sem nome. O resultado
117
+ inclui um aviso porque a posição pode mudar entre execuções. O índice é
118
+ zero-based para o mesmo papel e inclui nomes vazios ou compostos só por
119
+ espaços/glyphs de uso privado, como ícones Font Awesome; controles
120
+ desabilitados não aparecem no diagnóstico, mas continuam contando para que o
121
+ índice aponte ao controle correto;
122
+ - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
123
+ em `warnings`; não é permitido enviar JavaScript nem coordenadas;
124
+ - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
125
+ - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
126
+ `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
127
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
128
+ - `wait_for_text`, `wait_for_value`, `wait_for_enabled` e `wait_for_condition`
129
+ (`network_idle`, `hidden`, `text_hidden` ou `angular_idle`). `wait` recebe
130
+ `ms` para uma pausa curta e limitada. `angular_idle` aguarda requisições
131
+ `$http` e digest do AngularJS. `wait_for_text` aceita `fail_on: {"role":"alert"}` para
132
+ interromper a espera assim que um alerta visível aparecer e incluir seu texto
133
+ no erro. Se o alerta contiver o texto esperado, a etapa passa; caso contrário,
134
+ o alerta interrompe a espera. `network_idle` aceita `url_contains` para
135
+ aguardar só as requisições correspondentes;
136
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
137
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
138
+ envia a tecla ao elemento focado; com alvo, usa o localizador informado;
139
+ - `assert_text`, `assert_value`, `assert_visible`, `assert_hidden` e
140
+ `assert_enabled`; `assert_text`
141
+ pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
139
142
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
140
143
  dropzone;
141
144
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
142
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
143
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
144
- `Descurtir`.
145
-
146
- As proteções e evidências por etapa usam estes campos:
147
-
148
- - `confirm_dialog` recebe `expected_text` e `button`. O MCP exige um diálogo
149
- visível único e confere se ele contém o texto esperado antes de clicar; se o
150
- alerta mudou, a etapa falha sem clicar no botão. Reserve `click` comum para
151
- ações que não dependem do conteúdo de uma confirmação;
152
- - `mutating: true` marca etapas que gravam dados ou disparam efeitos externos.
153
- Com `options.dry_run: true`, o fluxo para imediatamente antes da primeira
154
- etapa marcada e retorna `dry_run_stopped_before_step` e `mutating_steps`.
155
- Marque toda ação que grava ou envia algo, mesmo quando não for um botão
156
- chamado Salvar;
157
- - `duration_ms` aparece em cada etapa concluída ou falha. `mutating_steps`
158
- lista as etapas marcadas e informa quais foram executadas;
159
- - `screenshot: true` salva uma captura depois da etapa e inclui seu caminho na
160
- evidência da etapa;
161
- - `options.report_path` grava um resumo `.md` ou JUnit `.xml`. O caminho deve
162
- ser absoluto e estar dentro de `JEV_BROWSER_ARTIFACT_DIR` (ou do diretório de
163
- artefatos configurado). O relatório resume versão/status, duração, alvo e
164
- `resolved_target`, asserções de rede, falhas de rede e caminhos das capturas.
165
-
166
- `run_browser_flow` também aceita `params` como mapa de texto, números e
167
- booleanos. Use `{pedido}` em `flow`, `expected_outcome` e nos campos textuais do
168
- plano para reutilizar um valor sem editar o roteiro em vários lugares. A ação
169
- `extract` lê `text` (padrão), `value` ou `attribute` de um elemento e salva o
170
- resultado na variável indicada por `as`; etapas seguintes podem usar
171
- `{documento}`. O valor extraído é tratado como sensível e fica oculto no
172
- resultado por padrão; use `sensitive: false` só quando for apropriado exibi-lo.
173
- `resolved_target.match_strategy` informa quando um rótulo foi
174
- associado por proximidade (`label-proximity`) em vez de um `label[for]` direto.
175
-
176
- A ação `assert_network` verifica respostas observadas depois da etapa anterior,
177
- incluindo respostas 2xx ou erros esperados como 404. Exemplo:
178
-
179
- ```json
180
- {
181
- "action": "assert_network",
182
- "url_contains": "/documentoFinanceiro/atualizar",
183
- "method": "PUT",
184
- "status": 404,
185
- "message_contains": "Boleto não encontrado"
186
- }
187
- ```
188
-
189
- Essa asserção aparece na evidência como `response_status`, separado do campo
190
- `status` da etapa (`passed` ou `failed`). `message_contains` lê somente resposta
191
- da mesma origem e respeita o limite configurado para captura de corpos.
192
-
193
- Exemplo de parâmetro e extração: passe `params: {"pedido":"1528721"}`, filtre
194
- com `within: {"row_containing_exact":"{pedido}"}`, e use uma etapa
195
- `{"action":"extract","role":"cell","name":"{pedido}","within":{"row_containing_exact":"{pedido}"},"as":"documento"}`.
196
- A etapa seguinte pode localizar o mesmo documento com `name: "{documento}"`.
197
-
198
- Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
199
- localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
200
- aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
201
- `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
202
- esperar que ela termine.
203
-
204
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
205
- container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
206
- ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
207
- um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
208
- controle próximo ao texto visível do rótulo.
145
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
146
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
147
+ `Descurtir`.
148
+
149
+ As proteções e evidências por etapa usam estes campos:
150
+
151
+ - `confirm_dialog` recebe `expected_text` e `button`. O MCP exige um diálogo
152
+ visível único e confere se ele contém o texto esperado antes de clicar; se o
153
+ alerta mudou, a etapa falha sem clicar no botão. Reserve `click` comum para
154
+ ações que não dependem do conteúdo de uma confirmação;
155
+ - `mutating: true` marca etapas que gravam dados ou disparam efeitos externos.
156
+ Com `options.dry_run: true`, o fluxo para imediatamente antes da primeira
157
+ etapa marcada e retorna `dry_run_stopped_before_step` e `mutating_steps`.
158
+ Marque toda ação que grava ou envia algo, mesmo quando não for um botão
159
+ chamado Salvar;
160
+ - `duration_ms` aparece em cada etapa concluída ou falha. `mutating_steps`
161
+ lista as etapas marcadas e informa quais foram executadas;
162
+ - `screenshot: true` salva uma captura depois da etapa e inclui seu caminho na
163
+ evidência da etapa;
164
+ - `options.report_path` grava um resumo `.md` ou JUnit `.xml`. O caminho deve
165
+ ser absoluto e estar dentro de `JEV_BROWSER_ARTIFACT_DIR` (ou do diretório de
166
+ artefatos configurado). O relatório resume versão/status, duração, alvo e
167
+ `resolved_target`, asserções de rede, falhas de rede e caminhos das capturas.
168
+
169
+ `run_browser_flow` também aceita `params` como mapa de texto, números e
170
+ booleanos. Use `{pedido}` em `flow`, `expected_outcome` e nos campos textuais do
171
+ plano para reutilizar um valor sem editar o roteiro em vários lugares. A ação
172
+ `extract` lê `text` (padrão), `value` ou `attribute` de um elemento e salva o
173
+ resultado na variável indicada por `as`; etapas seguintes podem usar
174
+ `{documento}`. O valor extraído é tratado como sensível e fica oculto no
175
+ resultado por padrão; use `sensitive: false` só quando for apropriado exibi-lo.
176
+ `resolved_target.match_strategy` informa quando um rótulo foi
177
+ associado por proximidade (`label-proximity`) em vez de um `label[for]` direto.
178
+
179
+ A ação `assert_network` verifica respostas observadas depois da etapa anterior,
180
+ incluindo respostas 2xx ou erros esperados como 404. Exemplo:
181
+
182
+ ```json
183
+ {
184
+ "action": "assert_network",
185
+ "url_contains": "/documentoFinanceiro/atualizar",
186
+ "method": "PUT",
187
+ "status": 404,
188
+ "message_contains": "Boleto não encontrado"
189
+ }
190
+ ```
191
+
192
+ Essa asserção aparece na evidência como `response_status`, separado do campo
193
+ `status` da etapa (`passed` ou `failed`). `message_contains` lê somente resposta
194
+ da mesma origem e respeita o limite configurado para captura de corpos.
195
+
196
+ Exemplo de parâmetro e extração: passe `params: {"pedido":"1528721"}`, filtre
197
+ com `within: {"row_containing_exact":"{pedido}"}`, e use uma etapa
198
+ `{"action":"extract","role":"cell","name":"{pedido}","within":{"row_containing_exact":"{pedido}"},"as":"documento"}`.
199
+ A etapa seguinte pode localizar o mesmo documento com `name: "{documento}"`.
200
+
201
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
202
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
203
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
204
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
205
+ esperar que ela termine.
206
+
207
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
208
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
209
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
210
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
211
+ controle próximo ao texto visível do rótulo.
209
212
 
210
213
  ```json
211
214
  {
@@ -217,51 +220,52 @@ controle próximo ao texto visível do rótulo.
217
220
  ```
218
221
 
219
222
  ```json
220
- {"action":"click","role":"button","name":"Add to cart","index":0}
221
- ```
222
-
223
- Exemplos para controles legados sem nome acessível:
224
-
225
- ```json
226
- {"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
227
- {"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
228
- {"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
229
- {"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
230
- {"action":"click","role":"button","name":"","index":0}
231
- {"action":"click","selector":"#save-document"}
232
- ```
233
-
234
- O reconhecimento retorna `unnamed_controls_initial` e
235
- `unnamed_controls_final`, cada um com papel, índice Playwright por papel, rótulo
236
- mais próximo e um trecho HTML sanitizado dos controles visíveis e habilitados
237
- sem nome. Nomes vazios ou compostos apenas por espaços e glyphs da área Unicode
238
- de uso privado (como ícones Font Awesome) entram nessa lista e podem ser
239
- selecionados com `name: ""` e o mesmo índice. `unnamed_controls` continua
240
- disponível como alias da lista final. O placeholder conta como nome acessível.
241
- O snapshot também resume campos de formulário com `id`, `name`, valor, estado
242
- desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
243
- sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
244
- é `false` por padrão; defina `true` somente quando precisar inspecionar campos
245
- ocultos também.
246
-
247
- Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
248
- localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
249
- `textbox`, `searchbox` ou `combobox`.
250
-
251
- Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
252
- Valores dentro de campos não contam como resultado visível. `stop_on_expected:
253
- true` habilita parada antecipada quando o texto esperado aparece fora dos
254
- campos; mantenha `false` para fluxos com várias etapas.
255
-
256
- Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
257
- de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
258
- e erro.
223
+ {"action":"click","role":"button","name":"Add to cart","index":0}
224
+ ```
225
+
226
+ Exemplos para controles legados sem nome acessível:
227
+
228
+ ```json
229
+ {"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
230
+ {"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
231
+ {"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
232
+ {"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
233
+ {"action":"click","role":"button","name":"","index":0}
234
+ {"action":"click","selector":"#save-document"}
235
+ ```
236
+
237
+ O reconhecimento retorna `unnamed_controls_initial` e
238
+ `unnamed_controls_final`, cada um com papel, índice Playwright por papel, rótulo
239
+ mais próximo e um trecho HTML sanitizado dos controles visíveis e habilitados
240
+ sem nome. Nomes vazios ou compostos apenas por espaços e glyphs da área Unicode
241
+ de uso privado (como ícones Font Awesome) entram nessa lista e podem ser
242
+ selecionados com `name: ""` e o mesmo índice. `unnamed_controls` continua
243
+ disponível como alias da lista final. O placeholder conta como nome acessível.
244
+ O snapshot também resume campos de formulário com `id`, `name`, valor, estado
245
+ desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
246
+ sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
247
+ é `false` por padrão; defina `true` somente quando precisar inspecionar campos
248
+ ocultos também.
249
+
250
+ Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
251
+ localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
252
+ `textbox`, `searchbox` ou `combobox`.
253
+
254
+ Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
255
+ Valores dentro de campos não contam como resultado visível. `stop_on_expected:
256
+ true` habilita parada antecipada quando o texto esperado aparece fora dos
257
+ campos; mantenha `false` para fluxos com várias etapas.
258
+
259
+ Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
260
+ de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
261
+ e erro.
259
262
 
260
263
  ### Captura de downloads
261
264
 
262
265
  Marque o clique que deve iniciar um download com `expect_download: true`. O
263
- Playwright começa a aguardar o evento antes do clique; após a transferência
264
- terminar, o MCP verifica o tamanho, sanitiza o nome sugerido e copia o arquivo
266
+ Playwright começa a aguardar o evento antes do clique; isso também captura
267
+ downloads gerados por `URL.createObjectURL` (por exemplo, PDFs Blob). Após a
268
+ transferência terminar, o MCP verifica o tamanho, sanitiza o nome sugerido e copia o arquivo
265
269
  para `JEV_BROWSER_ARTIFACT_DIR` (ou para o diretório de artefatos configurado).
266
270
  O resultado inclui a lista `downloaded_files`, com nome, caminho local e bytes;
267
271
  cada passo também contém o arquivo capturado. Os limites contam arquivos e bytes
@@ -292,13 +296,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
292
296
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
293
297
  com revisão manual e testes com usuários assistivos.
294
298
 
295
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
296
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
297
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
298
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
299
- próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
300
- localizadores explícitos de último recurso e geram aviso. O plano não aceita
301
- JavaScript enviado pelo harness nem coordenadas.
299
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
300
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
301
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
302
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
303
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
304
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
305
+ JavaScript enviado pelo harness nem coordenadas.
302
306
 
303
307
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
304
308
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -381,9 +385,9 @@ do pacote Node ficam no bloco opcional `jev_browser_mcp`, que não altera o
381
385
  contrato lido pelo servidor Python. Preserve a estrutura completa exigida pelos
382
386
  validadores.
383
387
 
384
- `browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
388
+ `browser.mode` aceita `harness` ou `computer`; o padrão é `computer`:
385
389
 
386
- - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
390
+ - `harness` usa Chrome headless e contexto isolado, adequado a execuções do
387
391
  harness e CI; o estado de autenticação é descartado ao final da chamada.
388
392
  - `computer` abre o Chrome ou Edge instalado em modo visível e usa o diretório
389
393
  persistente `browser.computer_user_data_dir`, separado por navegador. Não
@@ -392,23 +396,23 @@ validadores.
392
396
 
393
397
  `browser.max_flow_steps` limita a soma de passos declarados entre os planos e
394
398
  `browser.max_text_entry_chars` limita cada valor digitado. O resultado contém
395
- `status`, o plano escolhido, as ações executadas, a última captura acessível e
396
- se o critério esperado apareceu. Quando existem asserções explícitas, `status`
397
- também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
398
- esse resultado e `expected_outcome_visible` continua descrevendo somente o
399
- texto global. `incomplete` significa que nenhum critério foi comprovado;
400
- confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
401
- espera da SPA; `warnings` registra capturas vazias durante transições; e
402
- `failed_step` identifica índice, ação, localizador, timeout e erro resumido
403
- quando uma etapa falha. Cada etapa executada também registra a composição do
404
- localizador usado e, quando disponível, `resolved_target` com tag, `id`, papel,
405
- nome acessível, `title` casado e `href` sanitizado do elemento resolvido.
406
- Etapas `type` só incluem o valor final do campo quando `sensitive: false`.
407
-
408
- Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
409
- origem são capturadas mesmo quando usam transferência chunked e não enviam
410
- `Content-Length`. Corpos acima do limite, com formato inválido ou que não
411
- podem ser lidos com segurança são omitidos e explicados em `warnings`.
399
+ `status`, o plano escolhido, as ações executadas, a última captura acessível e
400
+ se o critério esperado apareceu. Quando existem asserções explícitas, `status`
401
+ também pode ser `passed` com todas elas satisfeitas; `assertions_passed` registra
402
+ esse resultado e `expected_outcome_visible` continua descrevendo somente o
403
+ texto global. `incomplete` significa que nenhum critério foi comprovado;
404
+ confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
405
+ espera da SPA; `warnings` registra capturas vazias durante transições; e
406
+ `failed_step` identifica índice, ação, localizador, timeout e erro resumido
407
+ quando uma etapa falha. Cada etapa executada também registra a composição do
408
+ localizador usado e, quando disponível, `resolved_target` com tag, `id`, papel,
409
+ nome acessível, `title` casado e `href` sanitizado do elemento resolvido.
410
+ Etapas `type` só incluem o valor final do campo quando `sensitive: false`.
411
+
412
+ Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
413
+ origem são capturadas mesmo quando usam transferência chunked e não enviam
414
+ `Content-Length`. Corpos acima do limite, com formato inválido ou que não
415
+ podem ser lidos com segurança são omitidos e explicados em `warnings`.
412
416
 
413
417
  `jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
414
418
  seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
@@ -424,21 +428,26 @@ Os limites de download ficam no mesmo bloco: `max_download_files`,
424
428
  limita quantas descrições de violações axe entram no resultado; a contagem total
425
429
  continua informada mesmo quando a lista é truncada.
426
430
 
427
- O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
428
- `block_trackers`, `capture_console_errors`, `capture_network_errors`,
429
- `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
430
- `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
431
- `trace_on_failure`, `snapshot_include_hidden`, `stop_on_expected`, `dry_run` e
432
- `report_path`. Sem override,
433
- os padrões são lidos de `jev_browser_mcp` em
434
- `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
435
- captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
436
- de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
437
- acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
438
- acessível estável. `ready_text` pode identificar o conteúdo que marca a
439
- prontidão. `reuse_page: true` pula a navegação somente quando a página e
440
- `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
441
- `dialog`.
431
+ O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
432
+ `block_trackers`, `capture_console_errors`, `capture_network_errors`,
433
+ `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
434
+ `ready_stable_ms`, `ready_text`, `continue_from_current_page`, `reuse_page`, `screenshot_on_failure`,
435
+ `trace_on_failure`, `snapshot_include_hidden`, `stop_on_expected`, `dry_run` e
436
+ `report_path`. Sem override,
437
+ os padrões são lidos de `jev_browser_mcp` em
438
+ `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
439
+ captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
440
+ de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
441
+ acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
442
+ acessível estável na navegação inicial. Depois, a continuidade fica ligada por
443
+ padrão: `continue_from_current_page: true` mantém a página e seu estado entre
444
+ chamadas na mesma origem, não repete `page.goto` e consulta um snapshot atual
445
+ sem esperar novamente por `load`/`networkidle`. As etapas continuam aguardando
446
+ seus próprios alvos e condições. `reuse_page` segue como alias legado; defina
447
+ `continue_from_current_page: false` para iniciar cada chamada em `initial_url`.
448
+ Se a página atual e `initial_url` tiverem origens diferentes, o MCP navega para
449
+ `initial_url`. `snapshot_scope` aceita `body`, `main` ou `dialog`; se `main` não
450
+ existir, o snapshot usa `body`.
442
451
 
443
452
  `block_trackers: true` bloqueia os domínios e tipos de recurso listados na
444
453
  configuração (analytics, Hotjar, fontes externas e mídia). Isso pode alterar o
@@ -446,32 +455,34 @@ layout ou o comportamento do site, então a opção é desligada por padrão.
446
455
 
447
456
  Com `capture_console_errors` e `capture_network_errors`, o retorno traz
448
457
  `console_errors` e `network_failures`, limitados em quantidade e tamanho.
449
- Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
450
- fragmentos, valores de formulário e nomes de arquivo são removidos ou
451
- sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
452
- 4xx/5xx da mesma origem, limita o corpo e inclui apenas o campo textual
453
- `message`, também sanitizado. Em falhas, `screenshot_on_failure` salva
454
- screenshot local e retorna
458
+ Respostas HTTP 4xx/5xx e requisições que falham são listadas; query strings,
459
+ fragmentos, valores de formulário e nomes de arquivo são removidos ou
460
+ sanitizados. `capture_network_error_bodies: true` lê somente respostas JSON
461
+ 4xx/5xx da mesma origem, limita o corpo e inclui apenas o campo textual
462
+ `message`, também sanitizado. Em falhas, `screenshot_on_failure` salva
463
+ screenshot local e retorna
455
464
  `screenshot_path`. `trace_on_failure: true` também grava um `.zip` compatível
456
465
  com o Trace Viewer do Playwright e retorna `trace_path`. O diretório padrão é
457
466
  `~/.cache/orquestrador/jev-browser-artifacts`; `JEV_BROWSER_ARTIFACT_DIR` pode
458
467
  substituí-lo por uma pasta absoluta fora do pacote. Screenshots e traces podem
459
468
  conter dados visíveis da aplicação: mantenha o diretório local protegido e
460
- compartilhe os arquivos somente se o teste permitir.
461
-
462
- Screenshots por etapa usam `screenshot: true` no próprio passo; o MCP os grava
463
- depois que a ação termina. `options.report_path` pode apontar para `.md` ou
464
- JUnit `.xml` dentro da raiz de artefatos. O relatório inclui a versão, tempos,
465
- localizadores resolvidos, respostas verificadas por `assert_network`, falhas de
466
- rede e caminhos dos screenshots, para anexar a um PR ou card.
467
-
468
- Se o Chrome/Edge não iniciar porque o perfil persistente já está aberto, o erro
469
- identifica o PID que o mantém ocupado quando o sistema consegue associar o
470
- perfil ao processo. Em Windows, o MCP consulta a linha de comando dos processos
471
- Chrome/Edge; em outros sistemas, usa o `SingletonLock` do Chromium. Configure
472
- `JEV_BROWSER_PROFILE` com outro diretório absoluto para usar uma sessão isolada.
473
- Resultados MCP incluem `server_version`; erros também começam com a versão do
474
- servidor para facilitar a comparação entre instalações.
469
+ compartilhe os arquivos somente se o teste permitir.
470
+
471
+ Screenshots por etapa usam `screenshot: true` no próprio passo; o MCP os grava
472
+ depois que a ação termina. `options.report_path` pode apontar para `.md` ou
473
+ JUnit `.xml` dentro da raiz de artefatos. O relatório inclui a versão, tempos,
474
+ localizadores resolvidos, respostas verificadas por `assert_network`, falhas de
475
+ rede e caminhos dos screenshots, para anexar a um PR ou card.
476
+
477
+ Se o Chrome/Edge não iniciar porque o perfil persistente já está aberto, o erro
478
+ identifica o PID que o mantém ocupado quando o sistema consegue associar o
479
+ perfil ao processo. Em Windows, o MCP consulta a linha de comando dos processos
480
+ Chrome/Edge; em outros sistemas, usa o `SingletonLock` do Chromium. Configure
481
+ `JEV_BROWSER_PROFILE` com outro diretório absoluto para usar uma sessão isolada.
482
+ Resultados MCP incluem `server_version`; erros também começam com a versão do
483
+ servidor para facilitar a comparação entre instalações. A ferramenta
484
+ `browser_health` informa se a sessão está ativa e tenta reconectar um browser
485
+ que encerrou desde a chamada anterior.
475
486
 
476
487
  `harness_browser` e `computer_browser` aceitam `chrome` ou `msedge`.
477
488
  `computer_user_data_dir` deve ficar fora do repositório e conter `{browser}`;