Metadata-Version: 2.4
Name: fraser-gate
Version: 0.1.0
Summary: MCP server + CLI that lets an AI coding agent run FRASER's persona swarm against a build and gate the fix pass/fail
Project-URL: Homepage, https://fraser.lythe.ai
Author-email: Lythe <team@lythe.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: ai-agents,code-review,coding-agent,experience,fraser,mcp,merge-gate,model-context-protocol,qa,testing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.2.0
Description-Content-Type: text/markdown

# FRASER Experience Merge-Gate — for AI coding agents

Point FRASER's persona swarm at a build, get back grounded, machine-readable **experience** findings,
ship a fix, then re-run the **identical** cast to gate the fix `pass | fail`. FRASER is the loop's
**brain and eyes** — it finds where real users break and verifies the fix helped. It **never writes or
merges your code**; your agent does that.

Why this exists: a build can pass its own typecheck + unit tests and still have a user drop off. That
gap — **experience ≠ correctness** — is what the gate catches.

## The loop

```
your agent builds + deploys ─▶ fraser_start_review(target_url)   → {run_id, project_id, flow_id}
                                     │  (async, minutes — poll)
                              fraser_get_status(run_id) ─▶ complete
                              fraser_get_findings(run_id)
                                     │  → findings[] {finding_id, screenshot, reproduction, fix_hint} + fix_prompt
   your agent fixes + redeploys ◀────┘   (FRASER never touches code)
                                     ▼
                              fraser_validate_fix(project_id, flow_id, baseline_run_id, new_url)
                              fraser_get_validation(run_id, baseline_run_id)
                                     │  → {gate: pass|fail, per-finding {fixed|still_present|regressed}, new_findings}
                              gate=fail ⇒ don't merge · gate=pass ⇒ ship
```

## Setup (one paste)

Get an API token from the FRASER dashboard (**Settings → Connect MCP → Generate token**), then add to
your agent's `.mcp.json`:

```jsonc
{
  "mcpServers": {
    "fraser": {
      "command": "uvx",
      "args": ["--from", "fraser-gate", "fraser-gate-mcp"],
      "env": { "FRASER_API_KEY": "<your token>", "FRASER_API_URL": "https://fraser.lythe.ai" }
    }
  }
}
```

That's it. **localhost just works** — if you point a review at `http://localhost:3000`, the MCP opens
an ephemeral public tunnel automatically so the hosted engine can reach your machine; you set nothing up.

## Tools (6)

| Tool | Use |
|------|-----|
| `fraser_start_review(target_url, mode?, objective?, context?, num_testers?, auth_notes?)` | Start a review. Async — returns a `run_id`. |
| `fraser_get_status(run_id)` | Poll until terminal (`complete`/`failed`/`timed_out`). Runs take **minutes**. |
| `fraser_get_findings(run_id)` | Scrubbed findings + `fix_prompt`. You fix from these. |
| `fraser_validate_fix(project_id, flow_id, baseline_run_id, target_url)` | Re-run the identical cast on the fix. Async. |
| `fraser_get_validation(run_id, baseline_run_id)` | The `pass`/`fail` gate verdict. |
| `fraser_cancel(run_id)` | Stop a run. |

**It takes minutes.** FRASER generates personas from your app, then drives a real browser as each one.
Start the review, do other work, and poll `fraser_get_status` every few seconds.

**Knobs** (defaults are good): `mode` = `visual` (experience critique, default) or `battle` (defect
sweep); `num_testers` `0` = the grounded cast; `context` = one line on what the product is (anchors the
personas for a new/thin app); `auth_notes` = app login creds if it's behind your own login (secret).

## CLI (same loop, for CI without MCP)

```bash
export FRASER_API_KEY=<token> FRASER_API_URL=https://fraser.lythe.ai
fraser review https://myapp-pr42.vercel.app --wait          # prints findings JSON
fraser validate <project_id> <flow_id> <baseline_run_id> <new_url> --wait   # exits non-zero on a FAIL gate
```

Local dev of this package: `pip install -e .` then run `python mcp_server.py` (stdio) or `python cli.py`.
