Install
$ agentstack add skill-mexin-qa-agent-skill-qa-agent ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
QA Agent Skill
AI-driven browser testing via Chrome DevTools MCP. No selectors. No data-testid. No npm dependencies. No server to manage. The agent calls MCP tools directly.
Prerequisites
If this skill was installed as the qa-agent plugin, the Chrome DevTools MCP server is bundled — nothing to install.
If it was installed manually (copied into .claude/skills/ or ~/.claude/skills/), the Chrome DevTools MCP server must be available. Install it once with either:
/pluginin Claude Code → search forchrome-devtools-mcp→ install and enable, orclaude mcp add chrome-devtools -- npx chrome-devtools-mcp@latest
Depending on how the MCP server is installed, its tool names may carry a different prefix than the ones pre-approved in this skill's frontmatter — everything still works, Claude Code will just ask for permission on first use.
Report generation uses plain node — no other dependencies.
Three ways to trigger
1. Natural language → auto-generates spec + runs it > "Test that a user can log in and reach the dashboard"
2. Run an existing spec > "Run qa-specs/signup.yaml against http://localhost:3000"
3. Just create a spec (don't run yet) > "Create a spec for the signup flow"
Agent Protocol
Step 1 — Resolve the spec
If the user gave natural language, generate a YAML spec now and save it to the project's spec directory: use qa-specs/ at the project root, unless the project already has a directory of *.yaml QA specs — in that case follow the existing convention. Follow the spec format below. Be conservative with steps — prefer fewer, higher-level steps. Save to .qa-session/current-spec.yaml as well.
If the user gave a spec file path, read it directly.
Step 2 — Prepare the session
Create/clear the .qa-session/ directory:
rm -rf .qa-session && mkdir -p .qa-session
Select the browser page (use list_pages to find it, or navigate_page to open the baseUrl).
Step 3 — Execute each spec step
For every step in the spec, run this loop:
3a. Capture page state
Use take_snapshot — this returns an accessibility tree with UIDs directly in the response. Each interactive element has a UID like btn-3, input-5, link-12.
3b. Decide which action achieves the step goal
Read the snapshot response. Match the step's intent to an element by role + label, not by position. Never guess a UID — if nothing matches, re-snapshot or mark the step blocked.
3c. Execute the action
| Action | MCP Tool | Parameters | |------------|-------------------|--------------------------------| | Click | click | uid from snapshot | | Type/Fill | fill | uid + value | | Type text | type_text | text (into focused element) | | Navigate | navigate_page | url (full URL or path) | | Press key | press_key | key (e.g. "Enter", "Tab") | | Wait | wait_for | text or selector to await | | Fill form | fill_form | fields object |
When to use type_text vs fill:
- Use
fillfor standard text inputs and textareas (sets value directly). - Use
type_textfor OTP inputs, PIN fields, or any input wherefillfails or times out.
type_text simulates real keyboard events into the currently focused element. Common case: input-otp React components — always use type_text after clicking/focusing the input.
- If
fillfails on an input, retry withtype_textas a healing step before marking the step as failed.
3d. Check the result
The MCP tool response indicates success or error inline. No file reading needed. If the tool returns an error → go to Step 4 (Healing) before logging failure.
3e. Run the assertion (if the step has one)
Use take_snapshot to read current page state. The agent evaluates the assertion directly by inspecting the snapshot content. For URL or title checks, use evaluate_script with expression: "window.location.href" or expression: "document.title".
3f. Log the step outcome
Append to .qa-session/history.json:
{
"stepId": "login",
"status": "pass",
"action": "click",
"uid": "btn-3",
"label": "Login",
"durationMs": 340,
"healed": false,
"error": null
}
Step 4 — Healing (on failure only)
Read references/healing-protocol.md for the full decision tree. Short version:
- Re-snapshot → check if element exists with a different label → retry with new UID
- Check for overlay → if a modal/cookie banner is blocking, dismiss it → retry
- Check for native dialog → use
handle_dialogto accept/dismiss - Check console errors → use
list_console_messagesto detect app errors - On
screenshotOnFailure, usetake_screenshotand note the failure — the screenshot is available in the tool response for evidence (inline, not file-based) - Max 2 healing attempts per step. After that → mark
status: "fail".
Log all healing attempts in history with "healed": true or "healFailed": true.
Step 5 — Generate report
Run the bundled report script with plain node, referencing it via this skill's base directory (shown as "Base directory for this skill" when the skill loads):
node /scripts/report.mjs
Writes:
- Terminal summary (printed to stdout)
results/report.json— machine-readable full traceresults/report.html— open in browser
Spec Format
name: Checkout flow
baseUrl: http://localhost:3000
config:
healingEnabled: true # default: true
screenshotOnFailure: true # default: true
maxStepsPerAction: 15 # default: 15
steps:
- id: go-to-cart
action: Navigate to the cart page
assert: Cart page is visible with at least one item
- id: checkout
action: Click the proceed to checkout button
- id: fill-shipping
action: Fill in the shipping form
data: # injected into the action prompt
firstName: Test
lastName: User
email: test@example.com
zip: "10001"
- id: confirm
action: Submit the order
assert: Order confirmation is displayed with an order number
critical: true # failure here stops the entire suite
NL → Spec Generation Rules
When generating specs from natural language:
- One step = one meaningful user action (not one DOM interaction)
- Add
assertonly when there's a verifiable outcome (URL change, text appearing) - Keep IDs kebab-case and descriptive
- Mark steps
critical: trueonly for core happy-path assertions - Use
data:for any form inputs rather than hardcoding them in the action string - Save the generated spec to both
qa-specs/.yaml(or the project's existing spec directory) and.qa-session/current-spec.yaml
Reference files
references/healing-protocol.md— full healing decision tree with examplesexamples/login.yaml— a complete example spec
Session files (all in .qa-session/)
| File | Written by | Read by | |------|-----------|---------| | history.json | You (the agent) | report.mjs | | current-spec.yaml | You (the agent) | You (the agent) |
The .qa-session/ directory is ephemeral — cleared at the start of each run.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mexin
- Source: mexin/qa-agent-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.