Vedha
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Vedha
Is Playwright alone enough for agentic testing?

Run this demo in about 3 seconds: npx tsx examples/demo/run.ts
Not when your agent trusts the screen. Your agent clicks "Save", the page says "Saved", and it reports success. But the server returned an error, or stored nothing. Vedha catches that. It runs on Playwright and checks that each action really happened before it reports a pass. It is built for AI agents driving a browser and for people writing tests.
~3x fewer missed bugs | when an AI agent tests: 9 seeded defects missed vs 26 for Playwright MCP (held-out sets 2-4) |
60 vs 0 | broken features caught with everyday text/URL checks (140 seeded defects, scripted) |
30% fewer tokens | for the agent on healthy tasks (set 4; 12-46% across sets) |
0 false passes | in a 1,120-trial audit, with every seeded defect caught (210/210) |
Within 5% | of hand-written Playwright's speed on healthy flows (median 1.05x): the checks cost almost nothing |
npx -y @vedhajs/mcp --allow-domain localhost # MCP server for your agent
npm install -D @vedhajs/cli # or the CLI / SDK for your tests
npm install -D @vedhajs/playwright-test # guard an existing Playwright suite: change one importHead to head: AI agent testing a web app
Same model, same tasks, written before any run on them. Playwright MCP reports success whenever the page looks right; Vedha also checks what the server did.
Held-out set 4 (pilot 8) | Playwright MCP | Vedha MCP |
Broken features caught (seeded defects) | 10 / 18 | 16 / 18 |
Healthy tasks completed | 18 / 18 | 17 / 18 |
Median tokens, healthy tasks | 76,018 | 52,990 (-30%) |
Median tokens, defect tasks | 210,000 | 139,029 (-34%) |
Median wall time, healthy tasks | 169 s | 176 s (+4%) |
The lead held on every held-out set: 10 vs 4 of 14 (set 2), 15 vs 10 of 18 (set 3) and 16 vs 10 of 18 (set 4), or 41 vs 24 caught overall.
Fine print: LLM results are from one free model (minimax/minimax-m3.1-flash) at 3 trials per cell. When an expert writes every check by hand, Vedha and Playwright tie; Vedha's lead is with typical checks and with AI agents. All numbers come from raw data in benchmarks/results/, and the known misses are listed under Measured results.
Why use Vedha instead of Playwright alone
Playwright (expert use) | Vedha | |
Server rejected the write, but the page still says "Saved" | passes unless you wrote a network assertion | fails the step: page-health and write checks run on every mutating step |
Same test with typical (text/URL-only) checks, 140 seeded defects | 0 / 140 caught | 60 / 140 caught (every rejected-write defect) |
REST write silently dropped (200, nothing stored) | 0 / 10 | 10 / 10 via automatic read-back |
MCP origin allowlist under redirects and WebSockets (5 hostile cases) | redirect and WebSocket escapes 3 / 3 each | 0 / 15 escapes |
Outcome unknown after a click (timeout, flaky network) | nothing tracks it; re-running the step or test can submit the order twice | never re-issues: reconciles with a read-only probe or reports |
Result after a fallback was needed | no per-step fallback; a test that passes on retry is marked |
|
Output for an agent | full accessibility snapshot after each action (Playwright MCP) | bounded observations and deltas (12-46% fewer tokens on healthy held-out tasks, pilots 6-8) |
Speed on healthy flows | baseline | median 1.05x expert Playwright (6 scenarios, r11) |
Everything declared by an expert | ties: 200/200 healthy, 138-140/140 defects | ties |
Vedha does not replace Playwright, it builds on it. It reuses Playwright's auto-waiting and actionability, and can wrap an existing page in a Playwright test (see Migrating a Playwright test).
Related MCP server: periscope-mcp
Core ideas
Verified semantic actions. An action is
verifiedonly when framework-run, deterministic postconditions pass (URL, element state/value/text, network response and JSON fields, read-only API probes). No postcondition ⇒unverified, never silently "passed".Bounded recovery that keeps the evidence. Alternate locators, known-interstitial dismissal and a single safe retry are tried in a fixed ladder; every attempt is a
RecoveryRecordcontaining the original failure. A run that needed recovery reportspassed_with_recovery.Uncertainty is a first-class result. For
mutatingactions with an unobserved outcome the framework does not re-issue the action: it reconciles via a read-only probe, or reportsoutcome_unknown.Bounded observations.
controls(interactive elements only),outline(ARIA tree, refs from Playwright), region/detail on demand, deltas between observations. Page-derived text is flaggeduntrusted.Explore → promote → replay. An actor (scripted, rule-based, or your LLM adapter) explores through the same verified runner; the result becomes a reviewable
TestProposaland a plain@playwright/testspec, which can be replay-checked.Failure bundles. Goal, steps, verdicts, recovery records, network summary, redacted trace;
replayre-drives the steps and reports divergences (and states what cannot be replayed).Agents can make mistakes without breaking the run. Failures come back with a hint (
fillon a dropdown: "use select"); the explore loop continues, but a repeat guard refuses to run the same mutating action again while its earlier outcome is unresolved, and an independent check (confirms) can clear an unknown outcome.Server errors cannot hide behind an optimistic page. A page-health check fails a mutating step if a request returned 5xx, a write was rejected, or the page threw, even when the declared checks passed.
Real-app reach. Beyond click/fill/select/check/press: hover, double click, uncheck, upload (fail-closed
uploadRoots), scroll, drag, wait, back, reload, tab switching, iframe targets, dialog policy.Usable from any MCP client.
@vedhajs/mcpexposes the same engine as a stdio MCP server.No LLM required. The core has no model dependency; LLM actors implement a small
Actorinterface outside the core.
It is not a Playwright wrapper that forwards commands: it uses Playwright as a replaceable browser substrate (BrowserAdapter) and owns the action/verification/recovery/promotion/bundle layers. It does not replace Playwright Test, and it reuses Playwright's actionability and auto-waiting (the strongest part of Playwright, per research/playwright-execution-model.md).
Status: v0.1 research MVP. Every number here comes from raw
trials.jsonlfiles inbenchmarks/results/, and each held-out set was written before any run on it. Vedha ties expert Playwright when the author declares every check. It leads when checks are typical or missing, and when an LLM agent does the testing. The LLM results come from one free model (minimax/minimax-m3.1-flash) at 3 trials per cell. Known misses are listed under Measured results.
Quick start
Install from npm (Node 20 or later):
npm install -D @vedhajs/cli # the `vedha` command
npx playwright install chromium # browser for Playwright, if you don't have it yet
npx vedha doctor # checks Node and the Playwright browserPackage | What it is |
| |
MCP server ( | |
SDK: run checked steps on a Playwright page | |
One-line guard for existing | |
Engine (installed with the others) |
Agent skill (Claude Code, Codex, Cursor and other agents that read SKILL.md): npx skills add HMAKT99/VEDHA installs vedha-verified-browser-testing, which teaches the agent to declare checks, mark writes and never repeat an unknown outcome.
From source instead: nvm use 22 && pnpm install && npx playwright install chromium && pnpm build, then use node packages/cli/dist/bin.js wherever this README says npx vedha.
Deterministic spec (no LLM)
order.json:
{
"goal": "place an order",
"steps": [
{
"id": "open",
"intent": "open the form",
"op": "goto",
"value": "/",
"postconditions": [{ "type": "state", "target": { "label": "Name" }, "state": "visible" }]
},
{
"id": "name",
"intent": "enter name",
"op": "fill",
"target": { "label": "Name" },
"value": "Ada",
"postconditions": [{ "type": "value", "target": { "label": "Name" }, "equals": "Ada" }]
},
{
"id": "submit",
"intent": "place the order",
"op": "click",
"target": { "role": "button", "name": "Place order" },
"altTargets": [{ "testId": "place-order" }],
"dismiss": [{ "role": "button", "name": "Accept" }],
"mutating": true,
"postconditions": [
{ "type": "text", "target": { "role": "status" }, "contains": "Order placed" },
{
"type": "network",
"method": "POST",
"urlPattern": "/api/orders",
"status": "2xx",
"json": { "path": "qty", "equals": 3 }
}
],
"reconcile": { "type": "api", "get": "/api/orders", "matchesAny": { "name": "Ada" } }
}
]
}npx vedha run order.json --base-url http://localhost:3000 --out ./failure-bundle
# exit 0 passed | 1 failed | 2 blocked | 4 outcome_unknown | 5 unverified ; JSON report on stdout
npx vedha replay ./failure-bundle --base-url http://localhost:3000SDK
npm install -D @vedhajs/adapter-playwright playwright
import { openSession } from "@vedhajs/adapter-playwright";
const session = await openSession({ allowedDomains: ["localhost"] });
const report = await session.run(steps); // ActionSpec[]
console.log(
report.verdict,
report.steps.map((s) => [s.actionId, s.status, s.recovered]),
);
await session.close();Wrap an existing Playwright page: sessionFromPage(page, policy).
Agent-driven exploration → regression test
npx vedha explore goal.json --start-url http://localhost:3000/ \
--promote order.spec.ts --check http://localhost:3000 # generates the spec and replay-checks itThe shipped RuleActor is a heuristic form-filler used for tests and benchmarks. To use an LLM, implement Actor.decide({goal, observation, history, step}) and return an ActionSpec or done; the framework enforces policy, verification and budgets regardless of what the actor proposes. No provider is bundled and nothing is sent anywhere by default.
Use it from an MCP client
Claude Code:
claude mcp add vedha -- npx -y @vedhajs/mcp --allow-domain localhost --out ./vedha-outAny client that takes an mcpServers config (Claude Desktop, Cursor, VS Code and others):
{
"mcpServers": {
"vedha": {
"command": "npx",
"args": ["-y", "@vedhajs/mcp", "--allow-domain", "localhost", "--out", "./vedha-out"]
}
}
}Run npx playwright install chromium once first if Playwright's browser is not installed. npx -y @vedhajs/mcp --help lists the options (browser, headed, uploads, secrets to redact, step cap).
Tools: vedha_act (one action with the checks you declare in expect), vedha_observe, vedha_probe (GET a same-origin JSON path without moving the page), vedha_report, vedha_promote (verified steps to a Playwright spec), vedha_bundle, vedha_close. The server refuses to start without --allow-domain HOST or an explicit --allow-any-domain. Mark data-changing steps mutating: true; after an unknown outcome Vedha refuses to repeat them until a check confirms the effect (confirms: "<step id>").
Migrating a Playwright test
One line, no rewrite. Install @vedhajs/playwright-test and change the import in your existing tests:
// before
import { test, expect } from "@playwright/test";
// after
import { test, expect } from "@vedhajs/playwright-test";
Run this demo: npx tsx examples/guard-demo/run.ts
Your tests run exactly as before, with guard mode watching each one. A test whose own checks pass still fails if the app answered a request with a 5xx, or a write request (POST/PUT/PATCH/DELETE) failed outright: the page said "Saved", the server didn't. A 4xx answer to a write and an uncaught page error are added to the report as warnings, because validation tests and third-party scripts produce them on purpose. Requests to other sites (analytics, CDNs) are not watched. The findings are attached to the test as vedha-guard.json.
test.use({ vedhaGuard: "strict" }); // 4xx writes and page errors fail too
test.use({ vedhaGuard: { ignore: ["/api/flaky", /\/v2\//], hosts: ["api.other-domain.com"] } });
test.use({ vedhaGuard: false }); // off for these tests (for example a test that expects a 500)Checked steps. For steps that must hold, Vedha can also run the action itself and verify it:
// before
await page.getByRole("button", { name: "Save" }).click();
await expect(page.getByRole("status")).toHaveText("Saved");// after (wraps your existing page; the rest of the test is unchanged)
const af = await sessionFromPage(page);
const r = await af.step({
id: "save",
intent: "save the form",
op: "click",
target: { role: "button", name: "Save" },
altTargets: [{ testId: "save" }],
postconditions: [{ type: "text", target: { role: "status" }, equals: "Saved" }],
});
expect(r.status).toBe("verified"); // r.recoveries explains any recovery that was neededMore in design/migration-and-compatibility.md.
Measured results
Everything below is from raw trials.jsonl files under benchmarks/results/; protocols, limits and amendments are in benchmarks/preregistration.md and benchmarks/methodology.md. Scripted tracks use no model. "Expert" baselines (pw-strong, sel-strong) were given every technique the scenarios' declared checks allow, including state probes.
Track | What was run | Result |
Held-out widget families, full declarations | 17 scenarios x 7 drivers x 20 trials ( | Vedha, expert Playwright and expert Selenium tie: 200/200 healthy, 138-140/140 defects, 0 false passes. Weaker baselines detect 0/140. |
Held-out widget families, minimal declarations (text/url only) | same, 20 trials ( | Vedha detects 60/140 (every rejected-write defect); every Playwright and Selenium baseline 0/140; healthy 200/200 for Vedha and the expert baselines; false-pass 19-28% vs 36-58%. All frameworks miss silent drops (HTTP 200, nothing recorded) on these fixtures. |
Cross-implementation: 16 third-party TodoMVC implementations | 4 user-level scenarios, 3 trials ( | Vedha 189/192 (96-99%); expert Playwright 182, expert Selenium 183, |
Independent app with mutants (TodoMVC) | 10 scenarios, n=5, Vedha vs expert Playwright | both 50/50 after idle-aware classification (before it Vedha reported "uncertain" on client-only defects). n=20 and the other drivers still to run. |
Conventional-REST silent drop (S16, added after the feature: a positive control) | 10 trials | Vedha 10/10 detected via read-back inference; |
Generated regression test (B8) | explore -> promote, run on 3 healthy and 4 broken variants | promoted test: 9/9 healthy, 12/12 defects caught; recorder-style references 9/9 and 3/12 (constructed references, one app). |
Security red-team over MCP (B7) | 5 hostile cases, 3 trials, each MCP server configured as documented | Playwright MCP's origin allowlist let a GET redirect, a POST redirect and a WebSocket through 3/3 each; Vedha 0/15; both blocked subresources and redacted a secret. Consistent with Playwright MCP's own docs that origin filtering is not a security boundary. |
Scripted re-audit after every change (r11) | all 8 scripted sets, 5 trials (M2 at 20 per framework), Vedha | 1,120 trials: 0 false passes, 0 false fails. Every seeded defect detected (210/210); 25 honest fails, all on the dijon TodoMVC implementation. |
Overhead (B5) | 6 healthy scenarios, 12 trials, concurrency 1 ( | Median 1.05x expert Playwright (S01 1.04, S02 1.00, S03 1.05, S11 1.29, S12 1.05, S15 1.08). The <=15% target is met as a median; S11 (search, paginate, open) is above it. |
Time to verdict on a server error (S17) | POST /api/orders 500, page shows the error honestly; n=10 | Vedha 1.3 s median (was 9.4 s before fail-fast waiting); expert Playwright 0.28 s (its check awaits the response directly); expert Selenium 13.2 s. Vedha is slower than expert Playwright here. |
LLM, MCP vs MCP, held-out widget sets 2-4 (pilots 6-8, one free model, n=3 per cell) | Playwright MCP vs Vedha MCP, each set written before any LLM run on it | Defects caught: set 2 10 vs 4 /14, set 3 15 vs 10 /18, set 4 16 vs 10 /18. Healthy tasks completed: 17 vs 17, 16 vs 17, 17 vs 18 (Vedha first). Tokens on healthy tasks -46%, -12%, -30%. Vedha makes more tool calls (set 4 defects: 43 vs 23), and latency was not better (+4% on set 4). Remaining misses: W20 search-filter twin (3) and W26 carousel twin (2). Earlier pilots 4-5 (older builds) favoured Playwright MCP on completion; see each |
What this does not show: that Vedha beats expert Playwright or expert Selenium when the author declares everything (it ties); anything about models beyond one free model family; anything about real production apps; Chromium-only for Selenium. Several results are mechanism-specific by design (read-back needs a conventional REST convention; the page-health check needs a request that returned an error).
Reproduce a scripted track: pnpm bench -- --set held-out --trials 20 --concurrency 3 --run-id my-run (sets: seen, held-out, held-out-minimal, independent, multi; the last two need VEDHA_TODOMVC_DIR pointing at a clone of tastejs/todomvc checked out at ff43b02; Selenium drivers are opt-in via --drivers sel-trust,sel-strong). Merge valid parts of several runs with benchmarks/analysis/merge.ts.
Repository map
Path | What |
| Reverse-engineering of Playwright with REA, ecosystem study, evidence ledger, open questions |
| Gap matrix-driven architecture proposals, selected architecture, ADRs |
| Types/schemas, runner, verifiers, observation, policy, bundle, promotion, explorer |
| Playwright |
|
|
| Fixture app, scenarios, drivers, harness, analysis, methodology, raw results |
| Phase status, tests run, blockers, unverified assumptions |
Security
Page and repository content is treated as untrusted data; see SECURITY.md for the threat model and known limits (notably: Playwright route handlers do not see redirect hops - Vedha validates them itself; WebSockets are gated and service workers blocked in launched sessions; Chromium only was tested).
Contributing / License
See CONTRIBUTING.md. Licensed under Apache-2.0 (see LICENSE).
This server cannot be deployed
Maintenance
Related MCP Connectors
Browser-based QA for AI-built software. Test pages with real browsers via agents.
Test a web app in a real browser from plain English. Passed, failed or cannot verify, with evidence.
Website checker for AI coding agents. Measures your site in a real browser, with evidence.
Web scraping, browser automation, screenshots and AI data extraction for AI agents via MCP.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceA Playwright-based MCP server that exposes a live browser as a traceable, inspectable, debuggable and controllable execution environment for AI agents.5,660 npm57-
- AlicenseAqualityCmaintenanceWebsite testing MCP server built for AI agents: 63 Playwright tools with hard assertions, auto form-fill, persistent authenticated sessions, network mocking, and accessibility/SEO/GEO + Lighthouse audits.7410AGPL 3.0
- AlicenseAqualityDmaintenanceAn MCP server that provides an LLM with a real Chromium browser via Playwright, recording every action taken toward a stated goal and producing a structured trace so the run can be audited for goal achievement.544 npmMIT
- FlicenseNot gradedqualityBmaintenanceMCP server that lets agents drive a browser and record every action into a replayable trace, then replay it deterministically with network request assertions. It exposes tools for navigating, clicking, filling, and verifying requests.-