e2e-verifier
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@e2e-verifier Reproduce ticket WEB-142 and verify the Save button fix."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 plainScenario. 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.webmwith a HUD overlay (step banner, red frame around the failing element),trace.zipfor the Playwright trace viewer, per-step screenshots,console.jsonl,network.jsonl,chapters.vtt,report.mdandresult.json.Modes:
reproducebefore a fix (a failing assertion means reproduced) andverifyafter 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:
ffmpegon the path for an additional mp4 export (E2E_FFMPEG_PATH)
Related MCP server: QualityMax QA MCP
Setup
uv sync
uv run playwright install chromiumRun the server
uv run e2e-verifier # stdio transport (default)
E2E_TRANSPORT=http uv run e2e-verifier # Streamable HTTP on 127.0.0.1:8765Claude 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
probe_target("http://127.0.0.1:5173/")– is the site up?discover_elements(url, query="Save")– which targets exist? Returns suggestedTargets.Build a
BugTicket(promptticket_from_report), thenvalidate_ticket.run_ticket(ticket, options={"mode": "reproduce"})– attachvideo.webmto the ticket.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 |
| Interactive, recorded browser sessions (see above) |
| JSON schema for |
| Semantic validation without a browser (host allowlist, criteria coverage, brittle selectors) |
| Execute in the browser, record artifacts, return |
| Manage stored runs |
| Fetch video, trace, report, screenshots, logs (inline up to |
| Reachability, status, title, load time, console errors of a URL |
| ARIA snapshot plus candidate targets for a query, optional |
| 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 |
|
| Root directory for runs |
|
| Hosts the browser may navigate to ( |
|
| Disable the allowlist |
|
|
|
|
| Headed mode for local debugging |
|
| Timeout per action/assertion |
|
| Hard limit per run (capped by |
|
| Concurrent runs |
|
| Retention by count |
|
| Retention by age |
|
| Larger artifacts are returned as a path |
| unset | Root for |
| unset | Optional mp4 export |
|
|
|
|
| HTTP transport bind address |
|
|
|
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.pngOpen a trace with:
uv run playwright show-trace artifacts/runs/<run_id>/trace.zipDevelopment
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=120Integration 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 toolsdelete_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
Scored across 18 tools
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.
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.
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.
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
Related MCP Connectors
Test a web app in a real browser from plain English. Passed, failed or cannot verify, with evidence.
Read-only web QA agent: scans a site in a real browser and returns evidence-backed findings
Run AI QA test runs on your web app and read the bugs they find, with steps to reproduce.
Browser-based QA for AI-built software. Test pages with real browsers via agents.
Related MCP Servers
AlicenseNot gradedqualityDmaintenanceEnables AI to perform real-browser QA testing on websites via Playwright, finding bugs, accessibility, SEO, and performance issues through natural language conversations.1MIT
QualityMax QA MCPofficial
AlicenseAqualityBmaintenanceEnables coding agents to independently verify web changes by scanning pages, inspecting UI structure, generating Playwright reproductions, and executing tests with structured QA evidence.485 npm4MIT- AlicenseNot gradedqualityBmaintenanceEnables coding agents to verify application changes by running browser workflows, executing independent state assertions, and producing replayable evidence.3 npmMIT
- AlicenseAqualityCmaintenanceTurn screen recordings into automated Playwright E2E reproduction tests, structured GitHub bug reports with clickable video timestamps, and SOP walkthroughs.621 npmMIT