Skip to content
reflow

Your AI writes the PR.
Reflow proves it works.

Reflow is an MCP server your coding agent connects to. The agent drives a real cloud browser in plain language — exploring, reading, verifying — then freezes what worked into flows that run against every PR preview, with your own model key, posting the evidence where you merge.

Works with the agent you already use

Reflow is an MCP server. Add it to Claude Code, Cursor, Codex — anything that speaks MCP — and your agent can author flows, run them in real browsers, and bring back the evidence.

mcp.reflow.io

Connect the agent you already use

One click for the popular ones, one JSON block for everything else. No SDK, no test framework, nothing to learn up front — your agent reads the tools and knows what to do.

any other MCP client — raw configuration
{
  "mcpServers": {
    "reflow": {
      "type": "http",
      "url": "https://mcp.reflow.io/mcp"
    }
  }
}

No token to paste — the first connection opens browser sign-in (OAuth 2.1).

38 live tools, grouped by the job

The server teaches the full workflow through its hand-written tool descriptions. Here are the current capability groups and representative tools your agent can call.

Identity & guidance

Confirm the signed-in user, load the authoring guides, and report tool friction.

3 tools · get_me · get_context · give_feedback

Flows & DAGs

Create and version flows, inspect tags, follow dependencies, and reuse upstream output.

8 tools · list_flows · create_flow · get_flow_graph · get_flow_memory · save_flow_content

Runs & results

Run flows, tail step events, retrieve screenshots, and complete email-based journeys.

10 tools · create_run · tail_run · get_run_screenshot · get_mailbox · wait_for_message

Live browser sessions

Open a cloud browser, read its state, drive it with RFL, and capture the viewport.

9 tools · open_session · snapshot · act · screenshot · close_session

Harness & containers

Boot approved team images, run shell commands, stream output, and inspect containers.

8 tools · list_images · run_image · exec · tail_exec · get_container

Settings & keys

Provider keys and API tokens stay in the dashboard. MCP OAuth never asks for a token to paste.

dashboard boundary

A real browser, live in your agent's hands

Your agent doesn't just queue runs — it drives a live cloud browser through MCP. Plain language in; snapshots, screenshots, and what the page actually says back out. No selectors, no local Chrome, no playwright scripts to babysit. And because every command is a Reflow step, your agent can rewrite the session transcript into a permanent flow.

your agent, exploring the preview
⏺ reflow:open_session (target_url: pr-418 preview) → session_07
⏺ reflow:act ("add the first product to the cart") → ✓ cart badge: 1
⏺ reflow:act ("check out with the standard test card") → ✓ on /confirm
⏺ reflow:snapshot → "$24.00 — order #1042"
⏺ reflow:create_flow (transcript rewritten as named step fences) → checkout-happy-path
✓ verified by hand once — deterministic on every PR from now on

Steps in plain language, executed for real

“Fill out the signup form with realistic values” is a complete, runnable step — and so is “read the verification email and sign in with the magic link”: every run gets its own inbox. Reflow compiles steps to RFL once, then replays them deterministically — a real browser, realistic data, no model in the loop while they pass.

.reflow/flows/signup.md

# named step fences

step="fill out the signup form with realistic values"

step="submit the form"

step="read the verification email and sign in"

step="the welcome screen greets the user by name"

# frontmatter invariant

expect role=alert hidden

your-app.dev/signup — chromium · run_188

Full name

City

Email

Create account
run-188@inbox.reflow.io 0 messages

✓ “Welcome, Maya” — signed in, intent satisfied

Every pixel, diffed against main

Declared snapshot checkpoints compare against the approved baseline for the selected browser. Comparison is perceptual: SSIM weighted the way human eyes weigh difference, so anti-aliasing and sub-pixel shifts never cry wolf, while a moved button always does. Intentional changes arrive as a reviewable comparison — one click approves the new baseline.

run_204 · checkout-happy-path · desktop

✓ capture declared snapshot checkpoints

✓ diff against the baseline from main

◐ 2 regions changed — intentional?

✓ approved — baseline travels with the branch

Snapshots are captured when the page stops changing — adaptive stabilization, not fixed sleeps — and replays are deterministic: same viewport, compiled RFL. A diff means the UI changed, not that the test got flaky.

baseline · main 2 regions
+ promo banner · cart badge

capturing baseline…

Approve & commit delta

◐ visual differences detected

A moved button or a new banner is a warning you review, not a failure. Approve it and the baseline updates in the same PR — nothing to reconcile after merge.

✗ checkout did not succeed

Product breakage fails loud and blocks the merge. Visual review never buries a real failure — the two outcomes are never mixed.

Works on localhost

The same flows run against your dev server before a PR even exists. Point target_url at localhost and the MCP connection opens an ephemeral, run-scoped tunnel — the cloud browser reaches your machine, nothing is exposed beyond the run, and your agent verifies the change before you push it.

your agent, mid dev-loop
⏺ reflow:create_run (target_url: http://localhost:3000) → run_201
⏺ tunnel up: run-201.tunnel.reflow.io → localhost:3000 (closes with the run)
⏺ reflow:tail_run (run_201) → 4/4 steps ✓ · magic link handled · intent satisfied
✓ safe to push — opening the PR

Set up by your agent, not by you

Connect the MCP server and ask your agent to add Reflow. It discovers the tools, writes the flow, runs it against your preview, and reads the evidence.

your agent, setting reflow up
$ claude "add reflow to this repo and verify checkout still works"
reflow:list_flows — none found for this repo
Write(.reflow/config.yml) — flow globs, checks, DAG mode
Write(.reflow/flows/checkout-happy-path.md) — intent, 3 plain-language steps, 3 expectations
reflow:create_run (chromium · preview url) → run_142
reflow:tail_run (run_142) — watching steps land live
add-to-cart · shipping · pay · confirm
end-state validation — intent satisfied, 1 model call
check posted: reflow / checkout-happy-path — 31s, screenshots attached

It lives where your PRs live

Reflow posts into the pull request: a merge-blocking check per flow, the proposed fix as a reviewable diff, screenshot deltas against the main baseline — and one button that commits the accepted changes back to the branch.

what your PR sees — github.com/your-org/your-app/pull/142
Some checks were not successful — merge blocked
  • reflow / signup — 14s, intent satisfied
  • reflow / browse-and-search — significant visual differences detected, review below
  • reflow / checkout-happy-path — checkout did not succeed
r reflow bot commented 2 minutes ago · edited

browse-and-search

Layout changed against the main baseline: a promo banner was added and the cart badge moved. Every stated expectation still holds — this looks intentional. Approving commits the new baseline and the expectation update below.

baseline · main

this PR

delta · 2 regions

+ promo banner · cart badge
proposed change — .reflow/flows/browse-and-search.md
  ## Always true
  - the cart badge shows the running item count
- - the page shows no banners above the product grid
+ - a single promo banner may appear above the product grid
Approve & commit delta View side-by-side commits the new visual baseline + expectation edit to this branch

checkout-happy-path

Failed at “pay with the standard test card”: submitting payment returned 500 from /api/pay and no confirmation rendered. The expectation “the confirmation page shows an order number and the correct total” cannot be met. This looks like a product regression, not a flow problem — nothing to heal.

step 3/3 · pay with the standard test card
  POST /api/pay → 500 Internal Server Error
  page state: spinner persisted 30s, no confirmation, console: TypeError in pay.ts
  ✗ checkout did not succeed
View run · screenshots · trace · console

A flow is just markdown

Plain-language intent sits beside named ts step="…" fences. Their bodies can be deterministic RFL, Playwright TypeScript, or empty for an agent-driven step. The shipped parser runs those fences in document order.

.reflow/flows/checkout-happy-path.md
---
name: Checkout — happy path
url: /checkout
invariants:
  - 'expect page url~="/confirmation"'
budgets: { tokens: 50000 }
---

A signed-in user buys a single item.

```ts step="open checkout"
open /checkout
```

```ts step="complete checkout"
click role=button name="Checkout"
expect page url~="/confirmation"
```
  

How it works

  1. 01 — Flows live in your repo as markdown: intent, frontmatter, and named step fences containing RFL, Playwright TypeScript, or an empty agent-driven body.
  2. 02 — On every PR, Reflow runs each flow against your preview URL in a real browser. Your model key drives recovery; you pay your provider, not a token markup.
  3. 03 — Green check with screenshots; visual differences arrive as a reviewable comparison; real breakage fails loud with the exact state that went wrong. Git stays the source of truth.
}