{
  "markdown": "# prufa-mcp — the QA agent for your vibe-coded app\n\n<!-- mcp-name: io.github.prufa-dev/prufa-mcp -->\n\n**Vibe-coded apps ship faster than anyone can review them.** In June 2026 we\naudited [49 fresh Show HN launches](https://prufa.dev/blog/engineering/we-audited-49-show-hn-launches/) —\n**38 had a critical bug on day one**: a broken signup, a silent console error,\nanalytics that never fired, a consent banner that did nothing.\n\nPrufa is the agent that catches those before your users do. Point it at a URL\nand it audits the things humans skip when they're moving fast — broken flows,\nJS console errors, missing tracking, consent violations, security headers,\nmobile tap targets, accessibility — and hands back machine-verified findings,\ngraded A–F. This repo is the open-source MCP server that wires that audit\nstraight into your coding agent.\n\n## 30-second demo\n\n![Installing prufa-mcp and wiring it into Claude Code](https://raw.githubusercontent.com/prufa-dev/prufa-mcp/main/assets/demo.gif)\n\n## What an audit gives you\n\nAsk your agent to `audit https://yourapp.com` and `prufa_run_audit` returns one\nJSON report. Findings are grouped into graded sections, each finding carries a\nseverity, the **impact** (why it matters), and a **fix hint**. Real output,\ntrimmed:\n\n```jsonc\n{\n  \"url\": \"https://yourapp.com\",\n  \"headline\": \"2 warnings found\",\n  \"counts\": { \"critical\": 0, \"warning\": 2, \"info\": 5 },\n  \"sections\": [\n    { \"label\": \"Works\",     \"grade\": \"C\", \"counts\": { \"warning\": 2, \"info\": 1 } },\n    { \"label\": \"Fast\",      \"grade\": \"A\" },\n    { \"label\": \"Found\",     \"grade\": \"A\" },\n    { \"label\": \"Compliant\", \"grade\": \"A\" }\n  ],\n  \"check_results\": [\n    {\n      \"check_id\": \"ux\",\n      \"findings\": [{\n        \"severity\": \"warning\",\n        \"title\": \"2 javascript console error(s) during page load\",\n        \"impact\": \"Errors at load time often mean broken features visitors never report.\",\n        \"evidence\": { \"count\": 2, \"sample\": [\n          \"Access to XMLHttpRequest at 'https://api.fontshare.com/...' blocked by CORS policy\",\n          \"Failed to load resource: net::ERR_FAILED\"\n        ]}\n      }]\n    },\n    {\n      \"check_id\": \"mobile\",\n      \"findings\": [{\n        \"severity\": \"warning\",\n        \"title\": \"13 tap target(s) smaller than 24px\",\n        \"impact\": \"Fingers are not cursors — undersized buttons mean mis-taps on exactly the elements you want pressed.\",\n        \"fix_hint\": \"Give interactive elements at least 24x24px of hit area (WCAG 2.5.8).\"\n      }]\n    },\n    {\n      \"check_id\": \"security\",\n      \"findings\": [{\n        \"severity\": \"info\",\n        \"title\": \"no Content-Security-Policy header\",\n        \"impact\": \"Without a CSP, one injected script owns the page — and every third-party tag you load is trusted completely.\",\n        \"fix_hint\": \"Start with a report-only CSP and tighten from real violation reports.\"\n      }]\n    }\n  ],\n  \"report_url\": \"/r/G82RpzTi_zn-o71_XoMLCprP7uvCQP87\"\n}\n```\n\n`report_url` is a shareable HTML version of the same report. The full payload\nalso includes `tracking`, `consent`, `seo`/`aeo`, `a11y`, `forms`, and detected\nuser flows — see [the OSS surface](#what-you-get-the-oss-surface) below.\n\n## Install\n\nThe package is on [PyPI](https://pypi.org/project/prufa-mcp/). Install it\nglobally with `pipx` (recommended — isolated venv, exposes the `prufa-mcp`\nbinary on your PATH) or into a project venv with `pip`:\n\n```bash\n# Recommended — global install, isolated venv\npipx install prufa-mcp\n\n# Or, into your project venv\npip install prufa-mcp\n\n# Pin a specific version with ==, e.g. pipx install prufa-mcp==0.1.3\n\n# Verify the binary is on PATH\nwhich prufa-mcp\n# Should print something like: /Users/you/.local/bin/prufa-mcp\n```\n\nYou also need a free Prufa API key. **The first audit is free, no card required.**\n\n1. Sign in at [prufa.dev](https://prufa.dev) (Google OAuth)\n2. Create an API key from the dashboard\n\n## Wire into your agent\n\nThe MCP server runs as a stdio subprocess, spawned by your agent on first use.\nThe cleanest way to register it is `claude mcp add` (Claude Code's built-in\ncommand — it writes the config to `~/.claude.json` correctly, which the\n`~/.claude/mcp.json` path does NOT).\n\n### Claude Code (recommended path)\n\n```bash\n# Get the absolute path of the binary (use whatever `which prufa-mcp` returned)\nPRUFA_BIN=$(which prufa-mcp)\n\n# Add the MCP server. The token stays out of your shell history.\nread -s -p \"Prufa API token: \" PRUFA_TOKEN && echo\nclaude mcp add \\\n  --scope user \\\n  --env \"PRUFA_API_TOKEN=$PRUFA_TOKEN\" \\\n  prufa \\\n  -- \"$PRUFA_BIN\"\n```\n\nRestart Claude Code (config is read at startup), then verify:\n\n```\n/mcp\n```\n\nYou should see `prufa` listed as **Connected**, with `prufa_run_audit` and\n`prufa_get_report` as available tools.\n\n### Cursor / Cline / Continue (hand-edit `.mcp.json`)\n\nIn your project root or in `~/.config/Claude/` etc.:\n\n```json\n{\n  \"mcpServers\": {\n    \"prufa\": {\n      \"command\": \"/Users/you/.local/bin/prufa-mcp\",\n      \"env\": {\n        \"PRUFA_API_TOKEN\": \"your-prufa-api-key\"\n      }\n    }\n  }\n}\n```\n\nRestart the host app. The command path must be the absolute binary path\n(not `~`, not `$()`) — those don't expand in MCP config.\n\n> Prefer config files to env vars? Drop your token in\n> `~/.config/prufa/mcp.json` instead — see [ADVANCED.md](ADVANCED.md).\n\n## Use it\n\nIn your agent:\n\n```\n> audit https://my-vibe-coded-app.com and show me the criticals\n> run prufa on my staging deploy\n> fetch the report for the audit I just ran\n```\n\n`prufa_run_audit` with `wait=true` (the default) **blocks** until the audit\ncompletes and returns the JSON report directly — typically 25–60s for a public\npage. If you set `wait=false`, the call returns immediately with the queued\nstate plus a `share_token` you can poll with `prufa_get_report`.\n\n## What you get — the full agent surface\n\n`prufa-mcp` exposes **the whole product** over MCP (44 tools). Point your agent\nat Prufa and it can audit pages, drive multi-step flows, watch for regressions,\nrun chaos tests, run full-auto discovery, and manage the workspace + billing —\nno dashboard round-trip. Free/anonymous tools need no card; Pro tools return the\nAPI's `402` with a checkout link when you're not on a plan (the tool is visible,\nthe paywall is server-side).\n\n### Audit & reports\n| Tool | What it does |\n|---|---|\n| `prufa_run_audit(url, wait=true)` | One-shot public-page audit; blocks and returns findings JSON. |\n| `prufa_get_report(run_id?, share_token?)` | Fetch a report by UUID or `/r/` slug. |\n| `prufa_get_run(run_id)` | Poll a run's status. |\n| `prufa_list_runs(limit)` | Recent runs in the workspace. |\n| `prufa_get_finding(run_id, finding_key?)` | Persisted findings, machine-readable. |\n| `prufa_list_alerts()` | Alert ledger (newest first, incl. suppressions). |\n\n### Workspace, usage & conversion\n| Tool | What it does |\n|---|---|\n| `prufa_setup_workspace(owner_email, name?)` | Create a **free, no-card** `agent_temp` workspace (7-day trial) and return an API token **once**. If a token is already set, returns the real workspace + trial state. |\n| `prufa_get_workspace()` | Current workspace + inlined usage + a `trial` block. |\n| `prufa_get_usage()` | Usage object + `trial`/`upsell` blocks — call before metered actions. |\n| `prufa_workspace_settings(...)` | Usage webhook, auto-recharge, email/Slack switches. |\n| `prufa_set_notifications(cells)` | The 9-event × {email, slack} routing matrix. |\n\n### Billing (returns a URL for the human to open — never takes a card)\n| Tool | What it does |\n|---|---|\n| `prufa_upgrade_plan(tier)` | Stripe checkout URL for a paid plan (starter/pro/team). |\n| `prufa_buy_credits(credits)` | Stripe checkout URL for a one-time credit pack. |\n| `prufa_billing_portal()` | Stripe customer portal URL (card, invoices, cancel). |\n\n### Flows (describe a journey → reviewable spec → run)\n| Tool | What it does |\n|---|---|\n| `prufa_create_flow(url, test_case, name?)` | Compile a plain-text test case to a **draft** spec. |\n| `prufa_confirm_flow(flow_id, spec?)` | Approve a draft — only confirmed flows run. |\n| `prufa_run_flow(flow_id, credentials?)` | Execute a confirmed flow. |\n| `prufa_set_flow_credentials(flow_id, credentials)` | Store `{{VAR}}` values (write-only). |\n| `prufa_edit_flow(flow_id, spec)` | Edit the spec (returns it to draft). |\n| `prufa_get_flow` · `prufa_list_flows` · `prufa_delete_flow` | Read · list · remove. |\n\n### Monitors (watch a URL or flow on a schedule)\n| Tool | What it does |\n|---|---|\n| `prufa_start_monitor(url, cadence?, flow_id?)` | 1-click monitor; returns a deploy-hook secret **once**. |\n| `prufa_trigger_monitor(monitor_id)` | Run now (rate-capped). |\n| `prufa_pause_monitor` · `prufa_resume_monitor` · `prufa_get_monitor` · `prufa_list_monitors` · `prufa_delete_monitor` | Lifecycle. |\n| `prufa_rotate_monitor_webhook(monitor_id)` | Rotate the deploy-hook secret. |\n| `prufa_list_monitor_deliveries(monitor_id)` | Deploy-hook delivery log + CI snippets. |\n\n### Gremlin (chaos QA)\n| Tool | What it does |\n|---|---|\n| `prufa_run_gremlin(url, persona?, direction?, credentials?)` | Imitate a difficult user; detectors verify what breaks. Mutations dry-run unless authorized; payments never execute. |\n| `prufa_rerun_gremlin(run_id)` | Re-run a past gremlin with the same intent + saved login. |\n| `prufa_authorize_domain(host, allow_mutation?)` | Allow real (non-payment) writes on a host you own. |\n| `prufa_list_gremlin_domains()` | List mutation authorizations. |\n| `prufa_gremlin_saved_logins()` | Reuse a prior login (owning workspace only — sensitive). |\n| `prufa_promote_gremlin_path(share_token, path_index)` | Turn a reproduced bug path into a draft flow. |\n\n### Discovery (full-auto — crawl, infer flows, draft them)\n| Tool | What it does |\n|---|---|\n| `prufa_register_discovery_domain(domain)` | Register a domain, get the DNS TXT record to publish. |\n| `prufa_verify_discovery_domain(domain_id)` | Verify the DNS proof. |\n| `prufa_list_discovery_domains` · `prufa_revoke_discovery_domain` | Manage authorized domains. |\n| `prufa_run_discovery(url)` | Crawl a verified site and draft its meaningful flows. |\n| `prufa_get_discovery(discovery_id)` | Run status + the flows it surfaced. |\n\nPlus `prufa_health_check()` (probe the server/API).\n\n## The free trial, and when to upgrade\n\n`prufa_setup_workspace` mints a **free `agent_temp` workspace**: no card, a 7-day\ntrial, and an included credit budget. Monitors, discovery, and full-length\ngremlin runs work during the trial, then need a paid plan.\n\nThe MCP makes this legible to your agent: `prufa_get_usage`, `prufa_setup_workspace`,\nand every metered result carry a `trial` block (days + credits remaining) and,\nwhen you're low on credits or near the trial's end, an `upsell` block with a\n`message_for_human` your agent can relay plus the exact tool to call\n(`prufa_upgrade_plan` / `prufa_buy_credits`). When a Pro tool is called off-plan,\nthe `402` passes through with a `checkout_url` — no silent failures, no surprise\ncharges.\n\n## Examples\n\nThree runnable scripts in `examples/`:\n\n- `examples/nextjs-app/` — audit a deployed Next.js app\n- `examples/vite-spa/` — audit a Vite SPA (focuses on client-side routing audits)\n- `examples/stripe-checkout/` — audit a Stripe-checkout page (payment-flow verification)\n\nEach is a copy-pasteable demo:\n\n```bash\nexport PRUFA_API_TOKEN=...\npython examples/nextjs-app/audit.py https://your-nextjs-app.com\n```\n\n## GitHub Action\n\nFail a PR when Prufa finds a critical regression:\n\n```yaml\n# .github/workflows/prufa-scan.yml\nname: Prufa scan\non: [pull_request]\njobs:\n  audit:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v5\n        with:\n          python-version: \"3.11\"\n      - run: pip install prufa-mcp\n      - name: Run audit\n        env:\n          PRUFA_API_TOKEN: ${{ secrets.PRUFA_API_TOKEN }}\n        run: |\n          python -c \"\n          import asyncio, sys\n          from prufa_mcp.audit import run_audit\n          report = asyncio.run(run_audit(url='${{ secrets.STAGING_URL }}', wait=True))\n          print(report.get('headline', 'audit complete'))\n          criticals = report.get('counts', {}).get('critical', 0)\n          if criticals:\n              print(f'::error::Prufa found {criticals} critical finding(s)', file=sys.stderr)\n              sys.exit(1)\n          \"\n```\n\nSee `examples/prufa-scan.yml` for the full template.\n\n## License\n\nApache-2.0. See [LICENSE](LICENSE). Contributions welcome — see\n[CONTRIBUTING.md](CONTRIBUTING.md).\n</content>\n</invoke>\n",
  "bytes": 12500,
  "sha": "2c36028eb7496a958a67c7fd5c12f5ccf5a23846a36cb7991a0c92316f6c2078",
  "repo_slug": "prufa-dev/prufa-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_prufa_dev_prufa_mcp_326f978e/readme"
}