# Scout (oci · ghcr.io/klarlabs-studio/scout:1.15.3)

Browser automation MCP server with 84 tools. Pure CDP, DOM diffing, vision hybrid.

- Trust score: 42/100 (low)
- Change this week: −2
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- oci · `ghcr.io/klarlabs-studio/scout:1.15.3`: 42/100 (this document), [markdown](https://verifymcp.io/servers/klarlabs-studio-scout/ghcr-io-klarlabs-studio-scout-1-15-3.md), [page](https://verifymcp.io/servers/klarlabs-studio-scout/ghcr-io-klarlabs-studio-scout-1-15-3)

## Channel facts

- Registry: `oci`
- Package: `ghcr.io/klarlabs-studio/scout:1.15.3`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 0/100
  - Malware scan not yet available for this package.
  - CVE data not yet available for this package.
  - Install-script risk not yet assessed.
  - Dependency-health data not yet available.
- **Provenance & Transparency**: 45/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 7 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 75/100
  - AI-judged instruction clarity (good).
  - Tool/resource definitions use about 5808 tokens (~66/item across 88 items; 88 tools + 0 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 23/100
  - Stability observed for 7 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 98/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 94% of tool parameters carry a description.
  - Structured output schemas are declared (16% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### Claude

```bash
claude mcp add klarlabs-studio-scout -- docker run --rm -i ghcr.io/klarlabs-studio/scout:1.15.3
```

### Codex

```bash
codex mcp add klarlabs-studio-scout -- docker run --rm -i ghcr.io/klarlabs-studio/scout:1.15.3
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "klarlabs-studio-scout": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "ghcr.io/klarlabs-studio/scout:1.15.3"
      ],
      "enabled": true
    }
  }
}
```

### Hermes

```yaml
mcp_servers:
  klarlabs-studio-scout:
    command: "docker"
    args: ["run", "--rm", "-i", "ghcr.io/klarlabs-studio/scout:1.15.3"]
```

### Other

```json
{
  "mcpServers": {
    "klarlabs-studio-scout": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/klarlabs-studio/scout:1.15.3"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 42, +3)

- [functional improvement] Stability: unverified → 0.23
- [functional] MCP protocol: Implements a current MCP spec version (2026-07-28).

### 2026-08-01 (score 39, −5)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-27 (score 44, +33)

- [functional improvement] Tool coverage: unverified → 100
- [functional] First check of Tool coverage: 16
- [functional] First check of Schema quality: good
- [functional] First check of Schema quality: pass
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 94

### 2026-07-26 (score 11)

First indexed and scored.

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

## MCP tools (88)

### `accessibility_tree` (~32 tokens)

Get a compact accessibility tree showing all interactive elements.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `annotated_screenshot` (~136 tokens)

Label all interactive elements with numbers and return their selectors/info. By default returns only the element list (compact). Set include_image=true to also get the screenshot with labels drawn on it. NOTE: label numbers are per-call only — after any DOM mutation (re-render, modal open, route change), the same label may point to a different element. Pair click_label with the most recent annotated_screenshot in the same turn; for stable identity across mutations use the returned selector.

Input parameters:

- `include_image` (boolean): Include base64 image data in response. Default false to avoid large responses. Use screenshot tool separately if you need the image.

### `app_state` (~50 tokens)

Extract global app state (Redux, Next.js, Nuxt, Remix, SvelteKit, Gatsby, Astro, Alpine, HTMX).

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `aria_violations` (~67 tokens)

Minimal accessibility scan grouped by impact (critical/serious/moderate/minor). Covers image-alt, button-name, link-name, label, duplicate-id, html-has-lang, landmark-one-main. Zero dependency — for full WCAG coverage run axe-core in your test pipeline.

Output parameters:

- `count` (integer)
- `critical` (array)
- `minor` (array)
- `moderate` (array)
- `serious` (array)

### `assert_text_contains` (~114 tokens)

Check that the given text appears on the page in one round-trip. If selector is set, searches only that element's text; otherwise searches body innerText. Returns ok=true with a surrounding snippet on hit, ok=false with a short page-tail snippet on miss. Replaces extract+string-match for post-action verification.

Input parameters:

- `case_insensitive` (boolean): Fold case when comparing. Default false.
- `selector` (string): Optional CSS selector to scope the search.
- `text` (string, required): Text to search for.

### `auto_extract` (~46 tokens)

Auto-detect repeating patterns (product cards, search results, list items) and extract structured data. No selectors needed.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `back` (~31 tokens)

Navigate to the previous page in browser history (like clicking the browser Back button). Errors if there is no previous entry.

### `batch` (~88 tokens)

Execute multiple actions in a single call. Avoids repeated round-trips. Actions: click, type, fill_form_semantic, wait, scroll_to, click_label. Continues on error.

Input parameters:

- `actions` (array, required): Array of actions to execute. Each has action (click/type/fill_form_semantic/wait/scroll_to/click_label) plus selector/value/label/fields as needed.

### `check_readiness` (~58 tokens)

Check how ready the page is for interaction. Returns a 0-100 score, pending XHR count, skeleton/spinner presence, and suggestions for what to wait for.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `has_skeleton` (boolean)
- `has_spinner` (boolean)
- `pending_images` (integer)
- `pending_xhr` (integer)
- `score` (integer)
- `state` (string)
- `suggestions` (array)

### `click` (~50 tokens)

Click an element by CSS selector. Set wait=true for navigation clicks.

Input parameters:

- `selector` (string, required): CSS selector of element to click
- `wait` (boolean): If true wait for full page navigation after click

### `click_handle` (~107 tokens)

Click the element identified by a stable node_handle from a previous annotated_screenshot. Unlike click_label, the handle survives DOM mutations that would shuffle label numbers. Returns a stale_handle error when the element is no longer in the DOM — re-annotate and retry.

Input parameters:

- `handle` (string, required): Stable node handle from a previous annotated_screenshot call (the node_handle field). Survives DOM mutations that would shuffle label numbers; returns a stale_handle error if the element has since be…

### `click_label` (~38 tokens)

Click an element by its label number from annotated_screenshot.

Input parameters:

- `label` (string, required): Label number from annotated screenshot (e.g. 8)

### `click_text` (~103 tokens)

Click an element by its visible text. Resolution: aria-label exact match, then button/link text match, then closest interactive ancestor of a matching text node. Pass role="button"|"link" to disambiguate when text appears in both. Cheaper than annotated_screenshot for the common 'click that thing I can see' case.

Input parameters:

- `role` (string): Optional role filter: button or link.
- `text` (string, required): Visible text to match (exact

### `close_tab` (~49 tokens)

Close a named tab. Cannot close the currently active tab.

Input parameters:

- `name` (string): Tab name (for open_tab and switch_tab)
- `url` (string): URL to open in new tab

### `compare_tabs` (~51 tokens)

Compare content between two named tabs. Returns what's different, what's only in one tab.

Input parameters:

- `tab1` (string, required): Name of the first tab
- `tab2` (string, required): Name of the second tab

### `component_state` (~44 tokens)

Extract component state/props from any framework (React, Vue, Svelte, Angular, Alpine, Lit).

Input parameters:

- `selector` (string, required): CSS selector of the component root element

### `configure` (~179 tokens)

Change browser settings without restarting. Use headless=false to see the browser window. Set allow_private_ips=true for local-dev workflows (localhost, 127.0.0.1, private IPs). Pass fresh=true to force-kill the current page and start clean (use after observing session_dead in status).

Input parameters:

- `allow_private_ips` (boolean): Allow navigation to loopback (127.0.0.1
- `fresh` (boolean): Kill the current page and browser and start a fresh session even if headless/allow_private_ips didn't change. Use after observing session_dead=true in status or when accumulated SPA state needs to be…
- `headless` (boolean): Run browser in headless mode (no visible window). Omit to keep the current setting (default true); a missing value no longer silently switches to a visible window.

### `console_errors` (~64 tokens)

Get captured console.error / console.warn messages plus recent network 4xx/5xx failures. Auto-installs lightweight network observers, so failures recorded after the first call surface here without an explicit enable_network_capture.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `messages` (array)
- `network_failures` (array)

### `cookies_clear` (~104 tokens)

Clear cookies. With no name, drops all cookies via Network.clearBrowserCookies. With a name, deletes only that cookie (optionally scoped by domain/path). Use this when a backend has been restarted and the previous session token is invalid.

Input parameters:

- `domain` (string): Optional domain scope when deleting a single cookie.
- `name` (string): Cookie name to delete. Leave empty to clear all cookies.
- `path` (string): Optional path scope when deleting a single cookie.

### `cookies_list` (~51 tokens)

List all cookies for the active page (names + flags only — values are redacted). Useful for diagnosing stale-session issues after a backend restart.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `items` (array)
- `total` (integer)

### `cookies_set` (~83 tokens)

Set a cookie on the active page. Useful for restoring sessions or seeding state.

Input parameters:

- `domain` (string)
- `expires` (number)
- `http_only` (boolean)
- `name` (string)
- `path` (string)
- `same_site` (string)
- `secure` (boolean)
- `value` (string)

### `detect_auth_wall` (~46 tokens)

Check if the page is a login wall, paywall, or CAPTCHA. Returns type, confidence, and reason.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `detect_dialog` (~48 tokens)

Check if a modal, dialog, popup, or overlay is currently visible. Returns its title, text, buttons, and inputs.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `detect_frameworks` (~33 tokens)

Detect which frontend frameworks are active on the page.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `discover_form` (~38 tokens)

Discover form fields with their labels, types, and CSS selectors.

Input parameters:

- `selector` (string): CSS selector for specific form (empty = all forms)

Output parameters:

- `action` (string)
- `fields` (array)
- `form_selector` (string)
- `method` (string)

### `dismiss_cookies` (~55 tokens)

Auto-dismiss cookie consent banners. Tries common selectors and text patterns (Accept, Agree, Got it, OK). Returns whether a banner was found and dismissed.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `dispatch_event` (~139 tokens)

Dispatch a DOM event on an element. Useful for triggering SPA event handlers. Special cases: event_type='submit' on a <form> (or any element inside one) calls form.requestSubmit() — the only reliable way to fire Vue @submit.prevent / React onSubmit and run HTML5 validation. event_type='click' invokes el.click() so the default action runs (e.g. submitting the owning form when target is type=submit).

Input parameters:

- `detail` (object): Event detail/payload data
- `event_type` (string, required): DOM event type (e.g. click
- `selector` (string, required): CSS selector of the target element

### `double_click` (~42 tokens)

Double-click an element.

Input parameters:

- `selector` (string, required): CSS selector of element to click
- `wait` (boolean): If true wait for full page navigation after click

### `drag_drop` (~43 tokens)

Drag an element and drop it on another element.

Input parameters:

- `from` (string, required): CSS selector of element to drag
- `to` (string, required): CSS selector of drop target

### `enable_network_capture` (~40 tokens)

Start capturing network XHR/fetch responses. Patterns filter by URL substring.

Input parameters:

- `patterns` (array): URL substring patterns to capture (empty = all)

### `extract` (~28 tokens)

Extract text content from a single element.

Input parameters:

- `selector` (string, required): CSS selector to extract text from

### `extract_all` (~31 tokens)

Extract text from all elements matching a selector.

Input parameters:

- `selector` (string, required): CSS selector to extract all matching texts

### `extract_table` (~33 tokens)

Extract structured data from an HTML table (headers + rows).

Input parameters:

- `selector` (string, required): CSS selector for the table element

### `failed_requests` (~56 tokens)

Recent network requests with status >= 400 (4xx/5xx). URL + method + status + response body snippet. Use after a form submission that silently failed.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `items` (array)
- `total` (integer)

### `fill_form` (~28 tokens)

Fill multiple form fields at once.

Input parameters:

- `fields` (object, required): Field values keyed by CSS selector

### `fill_form_semantic` (~116 tokens)

Fill form fields by label or name. Strings fill text inputs; booleans toggle checkboxes; for radios pass the label/value as a string. Each result includes the value re-read after dispatching input/change events plus a warning when framework binding (Vue v-model / React onChange) didn't pick up the change.

Input parameters:

- `fields` (object, required): Field values keyed by human-readable field name. Strings fill text inputs/textareas/selects. Booleans toggle checkboxes (or pick a radio when paired with a string label).

### `find_by_coordinates` (~64 tokens)

Find the interactive element at given pixel coordinates. Returns the smallest element containing that point, with CSS selector and text. Use after hybrid_observe.

Input parameters:

- `x` (integer, required): X pixel coordinate in the viewport
- `y` (integer, required): Y pixel coordinate in the viewport

### `focus` (~32 tokens)

Set focus on an element, triggering :focus CSS state.

Input parameters:

- `selector` (string, required): CSS selector of element to focus

### `forward` (~31 tokens)

Navigate to the next page in browser history (like clicking the browser Forward button). Errors if there is no next entry.

### `has_element` (~29 tokens)

Check if an element exists on the page.

Input parameters:

- `selector` (string, required): CSS selector to check for

### `hover` (~39 tokens)

Hover over an element to trigger CSS :hover states, tooltips, and dropdown menus.

Input parameters:

- `selector` (string, required): CSS selector of element to hover over

### `hybrid_observe` (~74 tokens)

Vision+DOM hybrid mode: returns a clean screenshot (no labels) plus bounding boxes for all interactive elements. Use find_by_coordinates to select elements by pixel position. Set include_image=true to get the base64 screenshot.

Input parameters:

- `include_image` (boolean): Include base64 screenshot in response. Default false to keep responses compact.

### `install_submit_tracker` (~48 tokens)

Pre-install the submit tracker so the next submit event records defaultPrevented + XHR count. Call after navigate, before triggering a form submit, if you plan to read submit_outcome afterwards.

### `list_tabs` (~35 tokens)

List all open tabs with their names, URLs, and titles.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `items` (array)
- `total` (integer)

### `markdown` (~36 tokens)

Get a compact markdown representation of the page. Ideal for LLM processing.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `navigate` (~29 tokens)

Navigate to a URL. Returns page title and URL.

Input parameters:

- `url` (string, required): URL to navigate to

### `network_requests` (~106 tokens)

Get captured network requests/responses including request bodies (POST/PUT/PATCH) and response bodies (max 32KB each, truncated if larger). Includes recent buffered requests so you can inspect traffic even if capture was enabled late. If the list is empty and capture was never enabled, the response includes a hint pointing at enable_network_capture.

Input parameters:

- `max_recent` (integer): Maximum number of most recent requests to return (0 = all)
- `pattern` (string): URL substring filter

Output parameters:

- `capture_enabled` (boolean)
- `count` (integer)
- `hint` (string)
- `requests` (array)

### `network_summary` (~95 tokens)

Rolled-up view of captured network traffic. Returns total count, bucketed by status class (1xx/2xx/3xx/4xx/5xx/0), every request with status >= 400 inline, and the pending count. Single call replaces enable_network_capture → act → failed_requests for the common 'did this action succeed at the network layer' question.

Input parameters:

- `pattern` (string): Optional URL substring filter.

Output parameters:

- `by_status` (object)
- `capture_enabled` (boolean)
- `failures` (array)
- `hint` (string)
- `pending` (integer)
- `total` (integer)

### `observe` (~38 tokens)

Get a structured snapshot of the current page. Optionally pass url to navigate first.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `active_navigation` (array)
- `active_tab` (string)
- `active_tab_id` (string)
- `buttons` (array)
- `cookies` (object)
- `dialog_text` (string)
- `dialog_type` (string)
- `has_dialog` (boolean)
- `inputs` (array)
- `interactive_elements` (integer)
- `links` (array)
- `meta` (object)
- `text` (string)
- `title` (string)
- `url` (string)

### `observe_diff` (~31 tokens)

Return only page changes since the last observation.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `observe_scoped` (~135 tokens)

Observe a subset of the page. Limit by landmark roles (nav/main/footer/...) and/or cap text length and element counts. Use on listing pages where the unscoped observation eats more tokens than the task needs.

Input parameters:

- `buttons_limit` (integer): Cap on returned buttons (0 = session default).
- `inputs_limit` (integer): Cap on returned inputs (0 = session default).
- `limit_chars` (integer): Maximum length of the returned text blob.
- `links_limit` (integer): Cap on returned links (0 = session default).
- `sections` (array): Landmark roles to limit the observation to: nav

Output parameters:

- `active_navigation` (array)
- `active_tab` (string)
- `active_tab_id` (string)
- `buttons` (array)
- `cookies` (object)
- `dialog_text` (string)
- `dialog_type` (string)
- `has_dialog` (boolean)
- `inputs` (array)
- `interactive_elements` (integer)
- `links` (array)
- `meta` (object)
- `text` (string)
- `title` (string)
- `url` (string)

### `observe_with_budget` (~31 tokens)

Observe the page within a token budget.

Input parameters:

- `budget` (integer, required): Approximate token budget for the response

### `open_tab` (~55 tokens)

Open a new named browser tab and navigate to a URL. The new tab becomes active.

Input parameters:

- `name` (string): Tab name (for open_tab and switch_tab)
- `url` (string): URL to open in new tab

### `pdf` (~15 tokens)

Generate a PDF of the current page.

### `readable_text` (~35 tokens)

Extract just the main readable content, stripping navigation and boilerplate.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `reload` (~43 tokens)

Reload the current page. Set ignore_cache=true for a hard reload that bypasses the browser cache.

Input parameters:

- `ignore_cache` (boolean): Bypass the browser cache (hard reload).

### `replay_playbook` (~45 tokens)

Replay a saved playbook deterministically without LLM calls. Returns success/failure and any extracted data.

Input parameters:

- `path` (string, required): File path to the playbook JSON file

### `reset` (~24 tokens)

Force-reset the current browser session, clearing stuck state and creating a fresh page context.

### `right_click` (~46 tokens)

Right-click an element to trigger context menus.

Input parameters:

- `selector` (string, required): CSS selector of element to click
- `wait` (boolean): If true wait for full page navigation after click

### `save_playbook` (~38 tokens)

Save the last recorded playbook to a JSON file for deterministic replay.

Input parameters:

- `path` (string, required): File path to save the playbook JSON

### `screenshot` (~166 tokens)

Capture a screenshot. Defaults: JPEG quality 60, max_width 1024, 80KB cap (~20k tokens base64) so result fits MCP tool-result token limits. Pass quality / max_width to override; on overflow the image is progressively downscaled rather than failing. Returns base64 data URL.

Input parameters:

- `full_page` (boolean): Capture the entire scrollable page instead of just the viewport.
- `max_width` (integer): Maximum image width in pixels. Downscales proportionally. Good values: 800 or 1024.
- `quality` (integer): JPEG quality 1-100. Forces JPEG format. Lower = smaller file. Default auto-compresses to fit 200KB.
- `url` (string): Optional URL to navigate to before taking screenshot

### `scroll_and_collect` (~55 tokens)

Auto-scroll the page and collect items as they lazy-load. For infinite scroll pages.

Input parameters:

- `max_items` (integer): Maximum items to collect (default 100)
- `selector` (string, required): CSS selector for the repeating items

### `scroll_by` (~49 tokens)

Scroll the page by pixel offset. Positive y = scroll down.

Input parameters:

- `x` (integer): Horizontal scroll offset in pixels
- `y` (integer, required): Vertical scroll offset in pixels (positive=down)

### `scroll_to` (~31 tokens)

Scroll to bring an element into view.

Input parameters:

- `selector` (string, required): CSS selector of element to scroll into view

### `select_by_prompt` (~67 tokens)

Find an element using natural language (e.g. 'the login button', 'search input'). Returns the best match with confidence score and CSS selector.

Input parameters:

- `prompt` (string, required): Natural language description of the element to find (e.g. 'the login button' or 'search input')

### `select_option` (~48 tokens)

Select an option from a dropdown/select element by visible text or value.

Input parameters:

- `option` (string, required): Option text or value to select
- `selector` (string, required): CSS selector of the select element

### `session_history` (~45 tokens)

Get the last N actions performed in this session. Provides context about what has been done so far.

Input parameters:

- `count` (integer): Number of recent actions to return (default 5

### `set_viewport` (~205 tokens)

Resize the live page's viewport / emulate a device so width-based CSS @media breakpoints resolve against the given size (what responsive/mobile testing needs). Pass width+height in CSS pixels, optionally device_scale_factor and mobile; or a 'device' preset (iphone-se, iphone-14, pixel-7, ipad-mini, desktop). Applies immediately to the current page — no restart. The override persists across navigations until changed.

Input parameters:

- `device` (string): Optional preset that fills the other fields: iphone-se
- `device_scale_factor` (number): Device pixel ratio (e.g. 2 or 3 for retina/phones). Default 1.
- `height` (integer): Viewport height in CSS pixels. Required unless 'device' is given.
- `mobile` (boolean): Enable mobile emulation (touch + meta-viewport handling). Default false.
- `width` (integer): Viewport width in CSS pixels. Required unless 'device' is given.

### `start_recording` (~41 tokens)

Start recording browser actions into a replayable playbook. Call stop_recording when done.

Input parameters:

- `name` (string, required): Name for the playbook being recorded

### `start_screen_recording` (~175 tokens)

Start capturing the active page as a screencast video. Frames are streamed via CDP and (if ffmpeg is in PATH) encoded to webm/mp4 on stop. Otherwise raw JPEG frames + ffmpeg concat list are returned for offline encoding. Call stop_screen_recording to finish.

Input parameters:

- `format` (string): Output format: webm (default if ffmpeg present)
- `fps` (integer): Target frames per second 1-60 (default 30)
- `height` (integer): Capture height in CSS pixels (default 800)
- `output_dir` (string): Parent directory for output. Defaults to OS temp dir.
- `quality` (integer): JPEG frame quality 1-100 (default 80)
- `width` (integer): Capture width in CSS pixels (default 1280)

### `start_trace` (~42 tokens)

Start tracing all browser actions with before/after screenshots. Call stop_trace to export a zip file.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `status` (~26 tokens)

Get current browser/session health status including URL, pending requests, timeout streak, and last error.

### `stop_recording` (~41 tokens)

Stop recording and return the playbook. Save it with save_playbook for later replay.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `stop_screen_recording` (~41 tokens)

Stop the active screen recording. Returns a struct with the output file path (video or frames dir), format, encoder used, frame count, and duration.

### `stop_trace` (~40 tokens)

Stop tracing and export a zip file containing trace events, screenshots, and network requests.

Input parameters:

- `path` (string, required): File path to write the trace zip file

### `submit_form` (~157 tokens)

Submit a form using form.requestSubmit() — fires Vue @submit.prevent / React onSubmit / native @submit listeners and runs HTML5 validation. Pass the form selector or any selector inside it. If match_url is set, waits for an XHR/fetch whose URL contains that substring and returns its status code. Returns the request URL, method, status, and post-submit URL so a single tool call replaces click + sleep + check_readiness + network_requests.

Input parameters:

- `match_url` (string): Optional URL substring. When set
- `selector` (string, required): CSS selector of the <form> element or any element inside it.
- `timeout_ms` (integer): Hard cap to wait for response/navigation in ms. Default 8000.

### `submit_outcome` (~64 tokens)

Diagnose silent form-submit failures. Returns defaultPrevented for the latest submit, visible [role=alert] messages, aria-invalid field labels, dev-server error overlay text, XHR count since tracker install, and whether navigation committed. Auto-installs the tracker on first call.

Output parameters:

- `alerts_visible` (array)
- `aria_invalid_fields` (array)
- `current_url` (string)
- `default_prevented` (boolean)
- `framework_error_overlay` (string)
- `navigation_committed` (boolean)
- `submitted_form` (string)
- `tracker_installed` (boolean)
- `xhr_count` (integer)

### `suggest_selectors` (~47 tokens)

Find elements similar to a selector that failed. Returns up to 5 suggestions with selector, tag, text, and classes.

Input parameters:

- `selector` (string, required): The selector that failed to match

### `switch_tab` (~51 tokens)

Switch to a named tab. Use list_tabs to see available tabs.

Input parameters:

- `name` (string): Tab name (for open_tab and switch_tab)
- `url` (string): URL to open in new tab

### `switch_to_frame` (~47 tokens)

Switch execution context into an iframe. Subsequent actions operate inside the iframe until switch_to_main_frame is called.

Input parameters:

- `selector` (string, required): CSS selector of the iframe element to switch into

### `switch_to_main_frame` (~37 tokens)

Switch back to the main page frame after operating inside an iframe.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `type` (~44 tokens)

Type text into an input element. Clears existing value first.

Input parameters:

- `selector` (string, required): CSS selector of input element
- `text` (string, required): Text to type into the element

### `upload_file` (~46 tokens)

Upload a file to a file input element.

Input parameters:

- `file_path` (string, required): Local path to the file to upload
- `selector` (string, required): CSS selector of the file input element

### `wait_for` (~30 tokens)

Wait for an element to appear in the DOM.

Input parameters:

- `selector` (string, required): CSS selector to wait for

### `wait_for_navigation` (~144 tokens)

Wait for the page to navigate. mode: 'full' (real document load) | 'spa' (History API push/replace/popstate) | 'any' (default, first to fire). Use when an external action — a button outside scout's control, a JS-triggered route change — moves the page; click(wait=true) covers the case where scout is the one triggering.

Input parameters:

- `mode` (string): One of full|spa|any. full = real document load. spa = History API push/replace/popstate. any = first to fire. Default any.
- `timeout_ms` (integer): Maximum wait in milliseconds. Default 5000.

Output parameters:

- `elapsed_ms` (integer)
- `full_navigation` (boolean)
- `idle_after_change` (boolean)
- `mode` (string)
- `spa_navigation` (boolean)
- `timed_out` (boolean)
- `title` (string)
- `url` (string)
- `url_changed` (boolean)

### `wait_for_spa_idle` (~132 tokens)

Stronger SPA wait than wait_spa: blocks until document complete, framework hydration events fired (Astro 'astro:page-load' / 'astro:end', Vue/React mount markers populated), no pending XHR/fetch, no visible spinners/skeletons, and the DOM has been mutation-free for quiet_ms. Use after a click that triggers route change or hydration when check_readiness returns 100 too eagerly.

Input parameters:

- `quiet_ms` (integer): Required mutation-free quiet window in ms. Default 400.
- `timeout_ms` (integer): Hard cap in ms. Default 15000.

### `wait_spa` (~43 tokens)

Wait for SPA framework (React/Vue/Angular/Next.js/Svelte) to finish rendering.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

### `web_vitals` (~66 tokens)

Extract Core Web Vitals (LCP, CLS, INP) and performance timing (TTFB, First Paint, DOM Content Loaded). Each metric is rated good/needs-improvement/poor per Google thresholds.

Input parameters:

- `url` (string): Optional URL to navigate to before observing

Output parameters:

- `cls` (number)
- `cls_rating` (string)
- `dom_content_loaded_ms` (number)
- `first_paint_ms` (number)
- `inp_ms` (number)
- `inp_rating` (string)
- `lcp_ms` (number)
- `lcp_rating` (string)
- `overall_rating` (string)
- `ttfb_ms` (number)

## Diagnostics

Captured diagnostic sections: Provenance. The full working is on the page: https://verifymcp.io/servers/klarlabs-studio-scout/ghcr-io-klarlabs-studio-scout-1-15-3#diagnostics

## Score history

- 2026-08-03: 42
- 2026-08-02: 39
- 2026-08-01: 39
- 2026-07-31: 44
- 2026-07-29: 44
- 2026-07-28: 44
- 2026-07-27: 44
- 2026-07-26: 11

## Links

- Repository: https://github.com/klarlabs-studio/scout
- Changelog RSS feed: https://verifymcp.io/servers/klarlabs-studio-scout/ghcr-io-klarlabs-studio-scout-1-15-3/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/klarlabs-studio-scout/ghcr-io-klarlabs-studio-scout-1-15-3/changelog.json
- HTML version of this page: https://verifymcp.io/servers/klarlabs-studio-scout/ghcr-io-klarlabs-studio-scout-1-15-3
