@diegosouzacdv/jev-browser-mcp 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -69,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
69
69
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
70
70
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
71
71
  raiz local configurada e reações idempotentes a um comentário único. Também
72
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
- JavaScript enviado pelo harness, seletores livres nem coordenadas. Ele usa a
74
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
74
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
75
+ são o último recurso e geram um aviso no resultado. Ele usa a
76
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
75
77
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
76
78
  `stderr` para não misturar com JSON-RPC.
77
79
 
@@ -87,29 +89,50 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
87
89
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
88
90
  resultado esperado na tela.
89
91
 
90
- Cada plano pode usar:
91
-
92
- - `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
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;
93
106
  - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
94
107
  - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
95
108
  `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
96
- valor apareça nas evidências;
109
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
97
110
  - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
98
- `text_hidden`);
99
- - `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
100
- `Enter`, `Escape` ou `Tab`;
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;
101
116
  - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
102
117
  pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
103
118
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
104
119
  dropzone;
105
120
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
106
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
107
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
108
- `Descurtir`.
109
-
110
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
111
- container acessível único, como uma linha ou card. `index` escolhe uma ocorrência
112
- zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
122
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
123
+ `Descurtir`.
124
+
125
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
126
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
127
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
128
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
129
+ esperar que ela termine.
130
+
131
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
132
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
133
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
134
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
135
+ controle próximo ao texto visível do rótulo.
113
136
 
114
137
  ```json
115
138
  {
@@ -121,8 +144,40 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
144
  ```
122
145
 
123
146
  ```json
124
- {"action":"click","role":"button","name":"Add to cart","index":0}
125
- ```
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.
126
181
 
127
182
  ### Captura de downloads
128
183
 
@@ -159,12 +214,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
159
214
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
160
215
  com revisão manual e testes com usuários assistivos.
161
216
 
162
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
163
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
164
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
165
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
166
- próximos quando o snapshot os encontrar. O plano não aceita JavaScript enviado
167
- pelo harness, coordenadas ou seletores livres.
217
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
218
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
219
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
220
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
221
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
222
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
223
+ JavaScript enviado pelo harness nem coordenadas.
168
224
 
169
225
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
170
226
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -285,11 +341,13 @@ continua informada mesmo quando a lista é truncada.
285
341
  O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
286
342
  `block_trackers`, `capture_console_errors`, `capture_network_errors`,
287
343
  `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
288
- `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure` e
289
- `trace_on_failure`. Sem override, os padrões são lidos de `jev_browser_mcp` em
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
290
347
  `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
291
348
  captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
292
- de recursos ficam desligados. O browser espera a SPA renderizar uma captura
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
293
351
  acessível estável. `ready_text` pode identificar o conteúdo que marca a
294
352
  prontidão. `reuse_page: true` pula a navegação somente quando a página e
295
353
  `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
@@ -32,6 +32,9 @@
32
32
  "max_step_timeout_seconds": 60,
33
33
  "key_delay_ms_default": 30,
34
34
  "reuse_page_default": false,
35
+ "stop_on_expected_default": false,
36
+ "snapshot_include_hidden_default": false,
37
+ "visibility_poll_interval_ms_default": 50,
35
38
  "capture_network_error_bodies_default": false,
36
39
  "max_network_error_body_bytes": 65536,
37
40
  "max_network_error_message_chars": 300,
@@ -69,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
69
69
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
70
70
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
71
71
  raiz local configurada e reações idempotentes a um comentário único. Também
72
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
- JavaScript enviado pelo harness, seletores livres nem coordenadas. Ele usa a
74
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
74
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
75
+ são o último recurso e geram um aviso no resultado. Ele usa a
76
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
75
77
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
76
78
  `stderr` para não misturar com JSON-RPC.
77
79
 
@@ -87,29 +89,50 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
87
89
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
88
90
  resultado esperado na tela.
89
91
 
90
- Cada plano pode usar:
91
-
92
- - `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
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;
93
106
  - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
94
107
  - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
95
108
  `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
96
- valor apareça nas evidências;
109
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
97
110
  - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
98
- `text_hidden`);
99
- - `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
100
- `Enter`, `Escape` ou `Tab`;
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;
101
116
  - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
102
117
  pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
103
118
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
104
119
  dropzone;
105
120
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
106
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
107
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
108
- `Descurtir`.
109
-
110
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
111
- container acessível único, como uma linha ou card. `index` escolhe uma ocorrência
112
- zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
122
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
123
+ `Descurtir`.
124
+
125
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
126
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
127
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
128
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
129
+ esperar que ela termine.
130
+
131
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
132
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
133
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
134
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
135
+ controle próximo ao texto visível do rótulo.
113
136
 
114
137
  ```json
115
138
  {
@@ -121,8 +144,40 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
144
  ```
122
145
 
123
146
  ```json
124
- {"action":"click","role":"button","name":"Add to cart","index":0}
125
- ```
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.
126
181
 
127
182
  ### Captura de downloads
128
183
 
@@ -159,12 +214,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
159
214
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
160
215
  com revisão manual e testes com usuários assistivos.
161
216
 
162
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
163
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
164
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
165
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
166
- próximos quando o snapshot os encontrar. O plano não aceita JavaScript enviado
167
- pelo harness, coordenadas ou seletores livres.
217
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
218
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
219
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
220
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
221
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
222
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
223
+ JavaScript enviado pelo harness nem coordenadas.
168
224
 
169
225
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
170
226
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -285,11 +341,13 @@ continua informada mesmo quando a lista é truncada.
285
341
  O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
286
342
  `block_trackers`, `capture_console_errors`, `capture_network_errors`,
287
343
  `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
288
- `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure` e
289
- `trace_on_failure`. Sem override, os padrões são lidos de `jev_browser_mcp` em
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
290
347
  `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
291
348
  captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
292
- de recursos ficam desligados. O browser espera a SPA renderizar uma captura
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
293
351
  acessível estável. `ready_text` pode identificar o conteúdo que marca a
294
352
  prontidão. `reuse_page: true` pula a navegação somente quando a página e
295
353
  `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
@@ -27,6 +27,9 @@ const CONFIG_KEYS = {
27
27
  "max_step_timeout_seconds",
28
28
  "key_delay_ms_default",
29
29
  "reuse_page_default",
30
+ "stop_on_expected_default",
31
+ "snapshot_include_hidden_default",
32
+ "visibility_poll_interval_ms_default",
30
33
  "capture_network_error_bodies_default",
31
34
  "max_network_error_body_bytes",
32
35
  "max_network_error_message_chars",
@@ -264,6 +267,7 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
264
267
  postStepReadyTimeoutMs: postStepReadyTimeoutSeconds * 1000,
265
268
  maxStepTimeoutSeconds: positiveNumber(browserOptions.max_step_timeout_seconds, "jev_browser_mcp.browser.max_step_timeout_seconds"),
266
269
  keyDelayMs: positiveNumber(browserOptions.key_delay_ms_default, "jev_browser_mcp.browser.key_delay_ms_default", true),
270
+ visibilityPollMs: positiveNumber(browserOptions.visibility_poll_interval_ms_default, "jev_browser_mcp.browser.visibility_poll_interval_ms_default", true),
267
271
  maxNetworkErrorBodyBytes: positiveNumber(browserOptions.max_network_error_body_bytes, "jev_browser_mcp.browser.max_network_error_body_bytes", true),
268
272
  maxNetworkErrorMessageChars: positiveNumber(browserOptions.max_network_error_message_chars, "jev_browser_mcp.browser.max_network_error_message_chars", true),
269
273
  maxUploadFiles: positiveNumber(browserOptions.max_upload_files, "jev_browser_mcp.browser.max_upload_files", true),
@@ -287,6 +291,8 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
287
291
  blockTrackers: booleanValue(browserOptions.block_trackers_default, "jev_browser_mcp.browser.block_trackers_default"),
288
292
  readyNetworkIdle: booleanValue(browserOptions.ready_network_idle_default, "jev_browser_mcp.browser.ready_network_idle_default"),
289
293
  reusePage: booleanValue(browserOptions.reuse_page_default, "jev_browser_mcp.browser.reuse_page_default"),
294
+ stopOnExpected: booleanValue(browserOptions.stop_on_expected_default, "jev_browser_mcp.browser.stop_on_expected_default"),
295
+ snapshotIncludeHidden: booleanValue(browserOptions.snapshot_include_hidden_default, "jev_browser_mcp.browser.snapshot_include_hidden_default"),
290
296
  readyTimeoutSeconds: readyTimeoutSecondsDefault,
291
297
  readyStableMs: readyStableMsDefault,
292
298
  snapshotScope,