@diegosouzacdv/jev-browser-mcp 0.5.0 → 0.6.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 +301 -251
- package/config/ui-testing.json +28 -19
- package/docs/jev-browser-mcp.md +301 -251
- package/mcp_servers/jev-browser-npm/src/config.mjs +91 -55
- package/mcp_servers/jev-browser-npm/src/flow.mjs +2434 -1803
- package/mcp_servers/jev-browser-npm/src/jev-client.mjs +22 -9
- package/mcp_servers/jev-browser-npm/src/server.mjs +197 -113
- package/package.json +1 -1
|
@@ -16,23 +16,24 @@ const CONFIG_KEYS = {
|
|
|
16
16
|
"max_flow_steps",
|
|
17
17
|
"max_text_entry_chars",
|
|
18
18
|
],
|
|
19
|
-
nodeBrowser: [
|
|
20
|
-
"max_action_timeout_seconds",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
19
|
+
nodeBrowser: [
|
|
20
|
+
"max_action_timeout_seconds",
|
|
21
|
+
"mutation_confirmation_ttl_seconds",
|
|
22
|
+
"ready_timeout_seconds_default",
|
|
23
|
+
"max_ready_timeout_seconds",
|
|
24
|
+
"ready_network_idle_default",
|
|
25
|
+
"ready_stable_ms_default",
|
|
26
|
+
"max_ready_stable_ms",
|
|
27
|
+
"post_step_ready_timeout_seconds_default",
|
|
28
|
+
"max_step_timeout_seconds",
|
|
29
|
+
"key_delay_ms_default",
|
|
30
|
+
"reuse_page_default",
|
|
31
|
+
"stop_on_expected_default",
|
|
32
|
+
"snapshot_include_hidden_default",
|
|
33
|
+
"visibility_poll_interval_ms_default",
|
|
34
|
+
"capture_network_error_bodies_default",
|
|
35
|
+
"max_network_error_body_bytes",
|
|
36
|
+
"max_network_error_message_chars",
|
|
36
37
|
"max_upload_files",
|
|
37
38
|
"max_upload_path_chars",
|
|
38
39
|
"max_upload_file_bytes",
|
|
@@ -51,6 +52,14 @@ const CONFIG_KEYS = {
|
|
|
51
52
|
"capture_console_errors_default",
|
|
52
53
|
"capture_network_errors_default",
|
|
53
54
|
"block_trackers_default",
|
|
55
|
+
"block_fonts_default",
|
|
56
|
+
"local_only_default",
|
|
57
|
+
"auto_angular_idle_default",
|
|
58
|
+
"return_snapshot_default",
|
|
59
|
+
"busy_selectors_default",
|
|
60
|
+
"login_url_contains_default",
|
|
61
|
+
"login_text_default",
|
|
62
|
+
"max_busy_selectors",
|
|
54
63
|
"snapshot_scope_default",
|
|
55
64
|
"tracker_host_suffixes",
|
|
56
65
|
"blocked_resource_types",
|
|
@@ -221,7 +230,7 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
221
230
|
const uploadRoot = configuredUploadRoot
|
|
222
231
|
? configuredDirectory(configuredUploadRoot, `environment ${uploadRootEnv}`)
|
|
223
232
|
: null;
|
|
224
|
-
const snapshotScope = browserOptions.snapshot_scope_default;
|
|
233
|
+
const snapshotScope = browserOptions.snapshot_scope_default;
|
|
225
234
|
if (!new Set(["body", "main", "dialog"]).has(snapshotScope)) {
|
|
226
235
|
throw new JevBrowserError("config/ui-testing.json jev_browser_mcp.browser.snapshot_scope_default must be body, main, or dialog");
|
|
227
236
|
}
|
|
@@ -230,28 +239,46 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
230
239
|
"jev_browser_mcp.browser.tracker_host_suffixes",
|
|
231
240
|
(host) => /^[a-z0-9.-]+$/i.test(host) && !host.startsWith(".") && !host.endsWith("."),
|
|
232
241
|
);
|
|
233
|
-
const blockedResourceTypes = stringList(
|
|
242
|
+
const blockedResourceTypes = stringList(
|
|
234
243
|
browserOptions.blocked_resource_types,
|
|
235
244
|
"jev_browser_mcp.browser.blocked_resource_types",
|
|
236
245
|
(type) => new Set(["font", "media", "image"]).has(type),
|
|
237
|
-
);
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
throw new JevBrowserError("config/ui-testing.json
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
246
|
+
);
|
|
247
|
+
const busySelectorsDefault = stringList(
|
|
248
|
+
browserOptions.busy_selectors_default,
|
|
249
|
+
"jev_browser_mcp.browser.busy_selectors_default",
|
|
250
|
+
);
|
|
251
|
+
if (busySelectorsDefault.length > positiveNumber(browserOptions.max_busy_selectors, "jev_browser_mcp.browser.max_busy_selectors", true)) {
|
|
252
|
+
throw new JevBrowserError("config/ui-testing.json busy_selectors_default exceeds max_busy_selectors");
|
|
253
|
+
}
|
|
254
|
+
const loginUrlContainsDefault = stringList(
|
|
255
|
+
browserOptions.login_url_contains_default,
|
|
256
|
+
"jev_browser_mcp.browser.login_url_contains_default",
|
|
257
|
+
);
|
|
258
|
+
const loginTextDefault = stringList(
|
|
259
|
+
browserOptions.login_text_default,
|
|
260
|
+
"jev_browser_mcp.browser.login_text_default",
|
|
261
|
+
);
|
|
262
|
+
if (!new Set(["none", "diff", "full"]).has(browserOptions.return_snapshot_default)) {
|
|
263
|
+
throw new JevBrowserError("config/ui-testing.json return_snapshot_default must be none, diff, or full");
|
|
264
|
+
}
|
|
265
|
+
const maxReadyTimeoutSeconds = positiveNumber(browserOptions.max_ready_timeout_seconds, "jev_browser_mcp.browser.max_ready_timeout_seconds");
|
|
266
|
+
const readyTimeoutSecondsDefault = positiveNumber(browserOptions.ready_timeout_seconds_default, "jev_browser_mcp.browser.ready_timeout_seconds_default");
|
|
267
|
+
const maxReadyStableMs = positiveNumber(browserOptions.max_ready_stable_ms, "jev_browser_mcp.browser.max_ready_stable_ms", true);
|
|
268
|
+
const readyStableMsDefault = positiveNumber(browserOptions.ready_stable_ms_default, "jev_browser_mcp.browser.ready_stable_ms_default", true);
|
|
269
|
+
if (readyTimeoutSecondsDefault > maxReadyTimeoutSeconds) {
|
|
270
|
+
throw new JevBrowserError("config/ui-testing.json ready timeout default exceeds its configured maximum");
|
|
271
|
+
}
|
|
272
|
+
if (readyStableMsDefault > maxReadyStableMs) {
|
|
273
|
+
throw new JevBrowserError("config/ui-testing.json stable snapshot default exceeds its configured maximum");
|
|
274
|
+
}
|
|
275
|
+
const postStepReadyTimeoutSeconds = positiveNumber(
|
|
276
|
+
browserOptions.post_step_ready_timeout_seconds_default,
|
|
277
|
+
"jev_browser_mcp.browser.post_step_ready_timeout_seconds_default",
|
|
278
|
+
);
|
|
279
|
+
if (postStepReadyTimeoutSeconds > maxReadyTimeoutSeconds) {
|
|
280
|
+
throw new JevBrowserError("config/ui-testing.json post-step readiness timeout exceeds its configured maximum");
|
|
281
|
+
}
|
|
255
282
|
|
|
256
283
|
return Object.freeze({
|
|
257
284
|
env,
|
|
@@ -261,15 +288,16 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
261
288
|
profileDir: profileDirectory(profileTemplate, channel, env.JEV_BROWSER_PROFILE),
|
|
262
289
|
maxFlowSteps: positiveNumber(document.browser.max_flow_steps, "browser.max_flow_steps", true),
|
|
263
290
|
maxTextEntryChars: positiveNumber(document.browser.max_text_entry_chars, "browser.max_text_entry_chars", true),
|
|
264
|
-
actionTimeoutMs: positiveNumber(browserOptions.max_action_timeout_seconds, "jev_browser_mcp.browser.max_action_timeout_seconds") * 1000,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
291
|
+
actionTimeoutMs: positiveNumber(browserOptions.max_action_timeout_seconds, "jev_browser_mcp.browser.max_action_timeout_seconds") * 1000,
|
|
292
|
+
mutationConfirmationTtlMs: positiveNumber(browserOptions.mutation_confirmation_ttl_seconds, "jev_browser_mcp.browser.mutation_confirmation_ttl_seconds") * 1000,
|
|
293
|
+
maxReadyTimeoutSeconds,
|
|
294
|
+
maxReadyStableMs,
|
|
295
|
+
postStepReadyTimeoutMs: postStepReadyTimeoutSeconds * 1000,
|
|
296
|
+
maxStepTimeoutSeconds: positiveNumber(browserOptions.max_step_timeout_seconds, "jev_browser_mcp.browser.max_step_timeout_seconds"),
|
|
297
|
+
keyDelayMs: positiveNumber(browserOptions.key_delay_ms_default, "jev_browser_mcp.browser.key_delay_ms_default", true),
|
|
298
|
+
visibilityPollMs: positiveNumber(browserOptions.visibility_poll_interval_ms_default, "jev_browser_mcp.browser.visibility_poll_interval_ms_default", true),
|
|
299
|
+
maxNetworkErrorBodyBytes: positiveNumber(browserOptions.max_network_error_body_bytes, "jev_browser_mcp.browser.max_network_error_body_bytes", true),
|
|
300
|
+
maxNetworkErrorMessageChars: positiveNumber(browserOptions.max_network_error_message_chars, "jev_browser_mcp.browser.max_network_error_message_chars", true),
|
|
273
301
|
maxUploadFiles: positiveNumber(browserOptions.max_upload_files, "jev_browser_mcp.browser.max_upload_files", true),
|
|
274
302
|
maxUploadPathChars: positiveNumber(browserOptions.max_upload_path_chars, "jev_browser_mcp.browser.max_upload_path_chars", true),
|
|
275
303
|
maxUploadFileBytes: positiveNumber(browserOptions.max_upload_file_bytes, "jev_browser_mcp.browser.max_upload_file_bytes", true),
|
|
@@ -286,19 +314,27 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
|
|
|
286
314
|
screenshotOnFailure: booleanValue(browserOptions.screenshot_on_failure_default, "jev_browser_mcp.browser.screenshot_on_failure_default"),
|
|
287
315
|
traceOnFailure: booleanValue(browserOptions.trace_on_failure_default, "jev_browser_mcp.browser.trace_on_failure_default"),
|
|
288
316
|
captureConsoleErrors: booleanValue(browserOptions.capture_console_errors_default, "jev_browser_mcp.browser.capture_console_errors_default"),
|
|
289
|
-
captureNetworkErrors: booleanValue(browserOptions.capture_network_errors_default, "jev_browser_mcp.browser.capture_network_errors_default"),
|
|
290
|
-
captureNetworkErrorBodies: booleanValue(browserOptions.capture_network_error_bodies_default, "jev_browser_mcp.browser.capture_network_error_bodies_default"),
|
|
291
|
-
blockTrackers: booleanValue(browserOptions.block_trackers_default, "jev_browser_mcp.browser.block_trackers_default"),
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
317
|
+
captureNetworkErrors: booleanValue(browserOptions.capture_network_errors_default, "jev_browser_mcp.browser.capture_network_errors_default"),
|
|
318
|
+
captureNetworkErrorBodies: booleanValue(browserOptions.capture_network_error_bodies_default, "jev_browser_mcp.browser.capture_network_error_bodies_default"),
|
|
319
|
+
blockTrackers: booleanValue(browserOptions.block_trackers_default, "jev_browser_mcp.browser.block_trackers_default"),
|
|
320
|
+
blockFonts: booleanValue(browserOptions.block_fonts_default, "jev_browser_mcp.browser.block_fonts_default"),
|
|
321
|
+
localOnly: booleanValue(browserOptions.local_only_default, "jev_browser_mcp.browser.local_only_default"),
|
|
322
|
+
autoAngularIdle: booleanValue(browserOptions.auto_angular_idle_default, "jev_browser_mcp.browser.auto_angular_idle_default"),
|
|
323
|
+
returnSnapshot: browserOptions.return_snapshot_default,
|
|
324
|
+
readyNetworkIdle: booleanValue(browserOptions.ready_network_idle_default, "jev_browser_mcp.browser.ready_network_idle_default"),
|
|
325
|
+
reusePage: booleanValue(browserOptions.reuse_page_default, "jev_browser_mcp.browser.reuse_page_default"),
|
|
326
|
+
stopOnExpected: booleanValue(browserOptions.stop_on_expected_default, "jev_browser_mcp.browser.stop_on_expected_default"),
|
|
327
|
+
snapshotIncludeHidden: booleanValue(browserOptions.snapshot_include_hidden_default, "jev_browser_mcp.browser.snapshot_include_hidden_default"),
|
|
328
|
+
readyTimeoutSeconds: readyTimeoutSecondsDefault,
|
|
329
|
+
readyStableMs: readyStableMsDefault,
|
|
298
330
|
snapshotScope,
|
|
299
331
|
}),
|
|
300
332
|
trackerHostSuffixes: Object.freeze(trackerHostSuffixes),
|
|
301
333
|
blockedResourceTypes: Object.freeze(blockedResourceTypes),
|
|
334
|
+
busySelectorsDefault: Object.freeze(busySelectorsDefault),
|
|
335
|
+
loginUrlContainsDefault: Object.freeze(loginUrlContainsDefault),
|
|
336
|
+
loginTextDefault: Object.freeze(loginTextDefault),
|
|
337
|
+
maxBusySelectors: positiveNumber(browserOptions.max_busy_selectors, "jev_browser_mcp.browser.max_busy_selectors", true),
|
|
302
338
|
}),
|
|
303
339
|
jev: Object.freeze({
|
|
304
340
|
providerUrl,
|