Skip to main content
Glama
e2e-verifier

e2e-verifier

e2e-verifier

MCP server that reproduces and verifies website bug tickets in a real browser and hands back evidence: an annotated video, a Playwright trace, screenshots, logs and a verdict per acceptance criterion.

  • Input: a structured BugTicket (steps, expected behaviour, acceptance criteria) or a plain Scenario. The MCP client (for example Claude Code) turns free-text bug reports into tickets; the server itself never calls an LLM.

  • Execution: Playwright, Chromium headless by default, one isolated browser context per run.

  • Evidence: video.webm with a HUD overlay (step banner, red frame around the failing element), trace.zip for the Playwright trace viewer, per-step screenshots, console.jsonl, network.jsonl, chapters.vtt, report.md and result.json.

  • Modes: reproduce before a fix (a failing assertion means reproduced) and verify after it (all criteria met means fixed).

The full design is in spec.md.

Requirements

  • Python 3.12+ and uv

  • Chromium for Playwright (uv run playwright install chromium)

  • Optional: ffmpeg on the path for an additional mp4 export (E2E_FFMPEG_PATH)

Related MCP server: QualityMax QA MCP

Setup

uv sync
uv run playwright install chromium

Run the server

uv run e2e-verifier                 # stdio transport (default)
E2E_TRANSPORT=http uv run e2e-verifier   # Streamable HTTP on 127.0.0.1:8765

Claude Code configuration (.mcp.json in the project that contains the website under test):

{
  "mcpServers": {
    "e2e-verifier": {
      "command": "uv",
      "args": ["run", "e2e-verifier"],
      "env": {
        "E2E_ARTIFACT_DIR": "artifacts",
        "E2E_ALLOWED_HOSTS": "localhost,127.0.0.1"
      }
    }
  }
}

The paths are relative to the project root, which is the working directory Claude Code uses for a project-scoped .mcp.json. When the server is started from another directory, add "--directory", "<absolute path to end_to_end_testmcp>" after "run" and use an absolute E2E_ARTIFACT_DIR. The HTTP alternative is E2E_TRANSPORT=http uv run e2e-verifier and a client entry {"type": "http", "url": "http://127.0.0.1:8765/mcp"}.

Typical session

  1. probe_target("http://127.0.0.1:5173/") – is the site up?

  2. discover_elements(url, query="Save") – which targets exist? Returns suggested Targets.

  3. Build a BugTicket (prompt ticket_from_report), then validate_ticket.

  4. run_ticket(ticket, options={"mode": "reproduce"}) – attach video.webm to the ticket.

  5. After the fix: run_ticket(ticket, options={"mode": "verify"}).

Minimal ticket:

{
  "id": "WEB-142",
  "title": "Save button does nothing",
  "url": "http://127.0.0.1:5173/settings",
  "steps": [
    {"id": "s1", "action": "fill", "target": {"label": "Name"}, "value": "Anna"},
    {"id": "s2", "action": "click", "target": {"role": {"role": "button", "name": "Save"}}},
    {"id": "s3", "action": "expect_visible", "target": {"role": {"role": "status", "name": "Saved"}}},
    {"id": "s4", "action": "expect_request", "method": "POST", "url_pattern": "**/api/settings", "status": 200}
  ],
  "expected": "A toast 'Saved' appears and the settings are posted.",
  "actual": "Nothing happens.",
  "acceptance_criteria": [
    {"id": "AC1", "description": "Toast appears", "step_ids": ["s3"]},
    {"id": "AC2", "description": "Settings are posted", "step_ids": ["s4"]}
  ]
}

Interactive sessions: letting an agent operate the site

An agent that does not know the site yet can drive it step by step. Every session is recorded (video with HUD banners, trace, screenshots, logs), and every tool result comes with a screenshot the agent can look at.

session_open(url)                         -> session id, first navigation result, screenshot
session_inspect(session_id, query="Save") -> ARIA snapshot + candidate targets with suggested Target JSON
session_act(session_id, step)             -> step result + screenshot; step = any action/assertion,
                                             e.g. {"id":"s1","action":"click","target":{"test_id":"save"}}
session_annotate(session_id, message, target?, tone?) -> callout/frame drawn into the video + screenshot
session_screenshot(session_id, full_page?) -> screenshot
session_close(session_id, verdict?, summary?) -> RunResult with video.webm, trace.zip, report.md ...

Failed assertions do not end a session; they are marked with a red frame in the video and the agent can keep going. get_schema(kind="step") returns the schema of all step types. Sessions are closed automatically after E2E_SESSION_IDLE_TIMEOUT_S (default 600 s); at most E2E_MAX_SESSIONS (default 3) are open at once. The session id doubles as run id for get_artifact and the runs:// resources.

Tools

Tool

Purpose

session_open / session_act / session_inspect / session_annotate / session_screenshot / session_close / session_list

Interactive, recorded browser sessions (see above)

get_schema

JSON schema for ticket, scenario, run_options, run_result

validate_ticket

Semantic validation without a browser (host allowlist, criteria coverage, brittle selectors)

run_ticket / run_scenario

Execute in the browser, record artifacts, return RunResult with verdict

get_run / list_runs / delete_run

Manage stored runs

get_artifact

Fetch video, trace, report, screenshots, logs (inline up to E2E_MAX_INLINE_ARTIFACT_MB)

probe_target

Reachability, status, title, load time, console errors of a URL

discover_elements

ARIA snapshot plus candidate targets for a query, optional steps_before

server_info

Versions, configuration, run counts

Resources: schema://ticket, schema://scenario, schema://run-options, schema://run-result, runs://index, runs://{run_id}/{result,ticket,report,video,trace,console,network,chapters,har}, runs://{run_id}/screenshots/{index}.

Prompts: ticket_from_report, analyze_run, refine_target.

Configuration

All settings are environment variables with the prefix E2E_ (a .env file is read too).

Variable

Default

Meaning

E2E_ARTIFACT_DIR

artifacts

Root directory for runs

E2E_ALLOWED_HOSTS

localhost,127.0.0.1,[::1]

Hosts the browser may navigate to (*.example.test wildcards allowed)

E2E_ALLOW_ANY_HOST

false

Disable the allowlist

E2E_BROWSER

chromium

chromium, firefox, webkit

E2E_HEADLESS

true

Headed mode for local debugging

E2E_DEFAULT_STEP_TIMEOUT_MS

10000

Timeout per action/assertion

E2E_DEFAULT_RUN_TIMEOUT_S

120

Hard limit per run (capped by E2E_MAX_RUN_TIMEOUT_S, default 600)

E2E_MAX_PARALLEL_RUNS

1

Concurrent runs

E2E_MAX_RUNS_RETAINED

50

Retention by count

E2E_MAX_ARTIFACT_AGE_H

168

Retention by age

E2E_MAX_INLINE_ARTIFACT_MB

8

Larger artifacts are returned as a path

E2E_FIXTURE_DIR

unset

Root for upload_file paths and storage_state_path

E2E_FFMPEG_PATH

unset

Optional mp4 export

E2E_TRANSPORT

stdio

stdio or http

E2E_HTTP_HOST / E2E_HTTP_PORT

127.0.0.1 / 8765

HTTP transport bind address

E2E_HUD_LANGUAGE

en

en or de for fixed HUD texts

Artifacts

artifacts/runs/<run_id>/
  result.json  report.md  ticket.json  options.json
  video.webm   chapters.vtt   trace.zip
  console.jsonl  network.jsonl  [network.har]  [video.mp4]
  screenshots/001_passed.png ... 003_failed.png 003_failure_fullpage.png

Open a trace with:

uv run playwright show-trace artifacts/runs/<run_id>/trace.zip

Development

uv run ruff format .
uv run ruff check .
uv run mypy src tests
uv run pytest tests/unit
uv run pytest tests/integration/test_run_ticket_broken_button.py -x --timeout=120

Integration tests start a real Chromium against a fixture site under tests/fixtures/site; run them per file. The code base follows a no-comments, no-docstrings rule that is enforced by a unit test; tool descriptions live in decorator arguments and Field(description=...).

Available Tools

18 tools
delete_runA

Delete a finished run and all of its artifacts.

Inputs: run_id (required). Returns: run_id, deleted

discover_elementsB

Inspect a page: returns the ARIA snapshot and candidate targets matching a query, each with a suggested Target for tickets. steps_before can log in or navigate first.

Inputs: url (required), query, max_results, steps_before. Returns: url, query, final_url, candidates, +2 more

get_artifactB

Fetch one artifact of a run (video, trace, report, screenshot, logs). Small files are returned inline, large ones as a path.

Inputs: kind (required), run_id (required), index.

get_runB

Return the stored RunResult of a finished run.

Inputs: run_id (required). Returns: kind, mode, label, steps, +17 more

get_schemaB

Return the JSON schema for a BugTicket, Scenario, RunOptions or RunResult.

Inputs: kind (required). Returns: object

list_runsA

List finished runs, newest first, optionally filtered by ticket or outcome.

Inputs: limit, outcome, ticket_id. Returns: result

probe_targetA

Open a URL once and report status, title, load time and console errors.

Inputs: url (required). Returns: url, error, title, status, +5 more

run_scenarioC

Execute a Scenario (steps without bug semantics) and record artifacts.

Inputs: scenario (required), options. Returns: kind, mode, label, steps, +17 more

run_ticketA

Execute a BugTicket in a real browser. Records an annotated video, a Playwright trace, screenshots and logs, then returns the verdict per acceptance criterion. Use mode=reproduce before a fix and mode=verify after it.

Inputs: ticket (required), options. Returns: kind, mode, label, steps, +17 more

server_infoB

Versions, configuration and run counts of this server.

Inputs: no named parameters. Returns: headless, runs_stored, artifact_dir, allowed_hosts, +7 more

session_actA

Execute one step in an open session and return the step result plus a screenshot. A step is any action or assertion from the ticket schema, for example {"id": "s1", "action": "click", "target": {"role": {"role": "button", "name": "Save"}}} or {"id": "s2", "action": "expect_visible", "target": {"test_id": "toast"}}. Failed assertions do not end the session; they are marked in the video with a red frame. Call get_schema(kind="step") for all step types.

Inputs: step (required), session_id (required), include_screenshot.

session_annotateA

Draw an annotation into the recorded video: a callout with your message, optionally with a frame around a target element (tone info, success or failure). The annotation stays visible for hold_ms and is captured as a screenshot.

Inputs: message (required), session_id (required), tone, target, +1 more.

session_closeA

Close an open session, stop the recording and write video.webm, trace.zip, report.md, chapters.vtt and result.json. Optionally pass your own verdict (reproduced, not_reproduced, fixed, still_broken, passed, failed, inconclusive) and summary; otherwise they are derived from the executed assertions. Fetch artifacts with get_artifact using the session id as run_id.

Inputs: session_id (required), summary, verdict. Returns: kind, mode, label, steps, +17 more

session_inspectA

Inspect the current page of an open session without changing it: ARIA snapshot plus candidate targets matching a query, each with a suggested Target.

Inputs: session_id (required), query, max_results. Returns: url, query, final_url, candidates, +2 more

session_listA

List open interactive sessions.

Inputs: no named parameters. Returns: result

session_openA

Open an interactive, recorded browser session on a URL and return its id, the result of the first navigation and a screenshot. Everything that happens in the session is recorded as video, trace, screenshots and logs until session_close. Use session_act to drive the page step by step.

Inputs: url (required), options.

session_screenshotB

Take a screenshot of the current page of an open session (viewport or full page).

Inputs: session_id (required), full_page.

validate_ticketA

Validate a ticket without opening a browser; returns errors and warnings.

Inputs: ticket (required), options. Returns: ok, errors, warnings

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 18 tools

    Disambiguation4/5

    Tools are grouped into clear clusters: target probing, session control, schema/validation, ticket/scenario runs, and run artifacts. The only real ambiguity is discover_elements vs session_inspect, which perform nearly the same ARIA snapshot/target query and differ only by whether an interactive session is already open; probe_target and session_open also both open a URL but have different intent.

    Naming Consistency4/5

    Most tools follow clear snake_case verb_noun names (validate_ticket, run_ticket, list_runs, delete_run), and the session_* prefix makes that cluster immediately recognizable. It is not completely uniform because session tools invert the order (session_open instead of open_session) and server_info is a noun_noun outlier, but the pattern is still predictable.

    Tool Count4/5

    18 tools is on the heavier side, but each one maps to a distinct stage of the workflow: one-off probing, session lifecycle, ticket/scenario execution, and artifact retrieval. The count is slightly above the ideal range but feels justified by the domain rather than bloated.

    Completeness5/5

    The tool surface covers the full lifecycle: probe/open, inspect/discover targets, act/assert, annotate/screenshot, close session, run tickets/scenarios, fetch runs/artifacts, and delete. There are no obvious dead ends or missing operations for a bug-verification server.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI to perform real-browser QA testing on websites via Playwright, finding bugs, accessibility, SEO, and performance issues through natural language conversations.
      1
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables coding agents to independently verify web changes by scanning pages, inspecting UI structure, generating Playwright reproductions, and executing tests with structured QA evidence.
      4
      85 npm
      4
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables coding agents to verify application changes by running browser workflows, executing independent state assertions, and producing replayable evidence.
      3 npm
      MIT