Skip to main content
Glama

ShipCheck v0

Independent preview-URL QA for coding agents. An agent POSTs a public https preview URL plus a goal/charter (human-equivalent QA) or click:/fill:/see: stories. We walk the product in Playwright, screenshot, write a findings brief, and return a pass/fail evidence pack. Homepage expect-only is needs_review (smoke only — no interaction), not a pass.

The same model that wrote the UI is a bad judge of the UI. That is the product.

Playwright MCP is free; this is not a hosted browser. It is an independent check with a human on fail. Screenshot APIs give pixels. ShipCheck answers "did story 3 actually work?"

Run

cd /workspace/shipcheck
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/playwright install chromium
.venv/bin/python -m shipcheck serve --host 0.0.0.0 --port 8788

The venv already exists on this box. Default: the API process also drains the disk queue (inline worker). To split:

SHIPCHECK_INLINE_WORKER=0 .venv/bin/python -m shipcheck serve --port 8788
.venv/bin/python -m shipcheck worker
.venv/bin/python -m shipcheck run-job sc_xxxxxxxxxxxx

Health: GET http://127.0.0.1:8788/health

Public (localhost.run, this box, Wed Aug 19 2026 ET): https://91526eb1894540.lhr.life Same process serves GET / (landing), REST, and POST /mcp. Preferred URL in PUBLIC_URL.txt (backup Cloudflare quick tunnel, often blocked on consumer ISPs: https://realtor-all-enclosed-altered.trycloudflare.com). localhost.run dies if the ssh reverse tunnel stops; keep ssh -R 80:localhost:8788 nokey@localhost.run running.

Jobs live at /workspace/shipcheck/queue/{job_id}.json. Reports and screenshots at /workspace/shipcheck/reports/.

Related MCP server: Prufa

Example request / response

Charter (preferred): a goal, not a click script. If stories is omitted, the explorer synthesizes the walk.

curl -sS -X POST https://91526eb1894540.lhr.life/qa_preview \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com/",
    "goal": "Walk booking and check a Sat-Sat week uses the weekly rate",
    "viewport": "desktop"
  }'

Or pass explicit stories. If both stories and goal are set, we run the stories and the judge still uses the goal.

curl -sS -X POST https://91526eb1894540.lhr.life/qa_preview \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com/",
    "stories": [
      {
        "id": "checkout",
        "steps": [
          "click:text=Book now",
          "fill:#email|guest@example.com",
          "see:Order total"
        ],
        "expect": "Order total"
      }
    ],
    "viewport": "desktop"
  }'

Response:

{
  "job_id": "sc_ab12cd34ef56",
  "status": "queued",
  "price_usd": 6,
  "billed": false,
  "message": "queued. poll GET /qa_status/{job_id}; fetch GET /qa_get_report/{job_id} when status is pass or needs_review."
}
curl -sS https://91526eb1894540.lhr.life/qa_status/sc_ab12cd34ef56
curl -sS https://91526eb1894540.lhr.life/qa_get_report/sc_ab12cd34ef56

Terminal statuses: pass (heuristics green and stories executed click:/fill: — not homepage smoke, not a high-severity finding) or needs_review (heuristic failures, smoke-only, or any high-severity finding). Every finished job writes human_note (verdict, what was clicked, what failed, smoke checks) and report.findings[] {severity, title, detail} when steps or expects miss. A later human can still overwrite the note via POST /qa_note/{job_id} or MCP qa_note. error is our infrastructure (timeout, crash, unsafe URL) and is not billed.

Optional headers for later billing: Authorization: Bearer <key> or X-Api-Key. v0 accepts missing keys and does not debit.

Pass a goal/charter (max 500 chars) or story steps. Charter explorer v0: visible Book/Buy/Checkout/Cart/Setup/Rent/Continue/Add, then cart/setup/review if the goal needs dates/week/cart; Sat-Sat ISO dates when the goal asks for a week; no payment fill, no Send/Pay/Place order. An unfinished date/week/price charter is needs_review (charter incomplete), not pass. Story steps: click:css=.buy, click:text=Sign in, fill:#email|user@example.com, wait:1000, see:Order total. click: prefers a visible match (hidden mobile-nav CTAs lose to the hero/sticky button). Analytics/gtag/collect 429s are recorded but do not fail the job.

Homepage expect-only (steps: ["open homepage"], expect: "Welcome") is not a pass — the report will say smoke only — no interaction.

See examples/sample_report.json for the evidence-pack shape.

Security

https only. Localhost, RFC1918, link-local, CGNAT, metadata IPs (169.254.169.254), file://, embedded credentials, and redirect-to-private are rejected. Every Playwright request is re-checked. 20s navigation timeout, 4 minute job cap. Details in PRODUCT.md.

SSRF tests (no live target required):

cd /workspace/shipcheck
python -m pytest tests/test_ssrf.py tests/test_api.py tests/test_runner.py -q

Cursor mcp.json

Streamable-HTTP MCP is served at POST /mcp (same process as REST). Tools: qa_preview, qa_status, qa_get_report, qa_note. Add this to .cursor/mcp.json or ~/.cursor/mcp.json (omit type; Cursor treats a url as streamable HTTP):

{
  "mcpServers": {
    "shipcheck": {
      "url": "https://91526eb1894540.lhr.life/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

v0 accepts a missing key and does not debit. Same file lives at examples/mcp.json. Server must be running (python -m shipcheck serve --host 127.0.0.1 --port 8788). Public URL is a localhost.run ssh reverse tunnel in front of that process (Cloudflare quick tunnel kept as backup).

Landing page: GET / (HTML in shipcheck/landing.html). Public preview rate limit: 20 qa_preview jobs/day/IP (loopback unlimited). SHIPCHECK_PREVIEW_LIMIT_PER_IP overrides; 0 disables.

Pricing

Intent, not charged yet: $6 desktop / $10 both-viewports (or 5–8 stories) per run. Prepaid Polar credits later. Hook: shipcheck/billing.py.

Next steps

  1. Polar credit packs + license key as Authorization: Bearer; debit on success only.

  2. Slack/Telegram ping when status is needs_review; human writes human_note (REST POST /qa_note/{job_id} and MCP qa_note already accept the note).

  3. List on PulseMCP / Glama / official MCP registry (discovery, not a marketplace).

  4. Public sample report + a 30-line llms.txt.

Do not add a dashboard, GitHub App, or crypto rail.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wtaylorwilson/shipcheck-preview-qa'

If you have feedback or need assistance with the MCP directory API, please join our Discord server