npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sitelensapi/mcp

v0.1.27

Published

SiteLens MCP + CLI: real-browser verification and page intelligence for developers and AI agents—Local Chromium, flows, registry sync, optional Cloud/API; no Docker required

Downloads

3,653

Readme

SiteLens

SiteLens is real-browser verification and page intelligence for developers and AI agents.

Run structured QA and agent verification flows from .sitelens/flows, capture screenshots and artifacts, sync prompts and templates from the registry, and optionally use Page Intelligence and Cloud/API runs. Use SiteLens Local on your machine via this MCP package, Desktop, or QA Studio as needed.

This package (@sitelensapi/mcp) is the portable npm distribution: an MCP server for Cursor and other MCP hosts, plus a CLI for setup, registry sync, and diagnostics. Local runs use bundled Chromium on your machine—no Docker required.

Links: sitelensapi.com · MCP docs · QA Studio · Dashboard / MCP setup · npm @sitelensapi/mcp


Install

# One-shot bootstrap (recommended first run)
npx --yes @sitelensapi/mcp sitelens-mcp setup

# Or install globally
npm install -g @sitelensapi/mcp

Requires Node.js 20+.


Quick start

1. Wire Cursor (local QA — no API key)

Add to ~/.cursor/mcp.json or your project .cursor/mcp.json:

{
  "mcpServers": {
    "sitelens": {
      "command": "npx",
      "args": ["-y", "@sitelensapi/mcp"],
      "env": {
        "SITELENS_MODE": "local",
        "SITELENS_DEFAULT_URL": "http://127.0.0.1:3000"
      }
    }
  }
}

For local/dev HTTPS targets with self-signed or private CA certificates (e.g. https://app.local), also allow the host and bypass Playwright TLS checks:

{
  "mcpServers": {
    "sitelens": {
      "command": "npx",
      "args": ["-y", "@sitelensapi/mcp"],
      "env": {
        "SITELENS_LOCAL_ALLOWED_HOSTS": "app.local",
        "SITELENS_LOCAL_IGNORE_HTTPS_ERRORS": "true"
      }
    }
  }
}

Restart Cursor after changing MCP env. Your normal browser may trust the cert; SiteLens local QA uses Playwright, which needs this flag for local/dev targets only.

Optional: on corporate machines where Chrome or Edge already trusts local certs, you may use the system browser instead of bundled Chromium:

{
  "mcpServers": {
    "sitelens": {
      "command": "npx",
      "args": ["-y", "@sitelensapi/mcp"],
      "env": {
        "SITELENS_LOCAL_ALLOWED_HOSTS": "app.local",
        "SITELENS_LOCAL_IGNORE_HTTPS_ERRORS": "true",
        "SITELENS_BROWSER_CHANNEL": "chrome"
      }
    }
  }
}

SITELENS_BROWSER_CHANNEL accepts chrome, msedge, or chromium (bundled default). When unset, SiteLens uses bundled Chromium. If you explicitly set chrome or msedge and that browser is missing, SiteLens reports a clear error — it does not silently fall back.

Restart Cursor, then ask: "Use SiteLens setup."

That runs the sitelens_setup MCP tool (bundled Chromium, writable dirs, API key presence only — never the key value).

2. Run local QA on your dev server

Ask Cursor:

"Run SiteLens local QA on http://localhost:3000 (desktop + mobile)."

That invokes sitelens_qa_run (alias sitelens_run_local_qa). Local QA does not require a SiteLens account or API key.

3. Check readiness from the terminal

npx --yes @sitelensapi/mcp sitelens-mcp -- --self-test
npx --yes @sitelensapi/mcp sitelens doctor
npx --yes @sitelensapi/mcp sitelens doctor --cursor

4. Scaffold and run a project flow from the terminal

Create a starter flow JSON in your project (edit steps and URL afterward):

npx --yes @sitelensapi/mcp sitelens flow init homepage-smoke
# or: npx --yes @sitelensapi/mcp sitelens flow init --flow-id homepage-smoke --template smoke

Then run it:

npx --yes @sitelensapi/mcp sitelens flow run \
  --flow-id homepage-smoke \
  --url http://127.0.0.1:3000/

Same engine as MCP sitelens_run_local_flow — useful for CI and shell scripts without Cursor.


Current status

Verified against package implementation and tests (May 2026). See MCP docs — project flows for flow schema and step reference.

Supported now

| Capability | How to use | |------------|------------| | Ad-hoc local QA | MCP sitelens_qa_run / sitelens_run_local_qa (≤ 8 steps, no API key) | | Project flows | JSON in .sitelens/flows/*.json + CLI sitelens flow run or MCP sitelens_run_local_flow (≤ 200 steps) | | Flow discovery | sitelens doctor, --self-test, MCP sitelens_setup list flows dir | | Local run artifacts | summary.json, report.md, screenshots/ under $TMPDIR/sitelens-mcp-local-qa | | Local run history / compare | MCP sitelens_list_local_runs, sitelens_compare_local_runs | | Saved auth profiles | ~/.sitelens/ + sitelens_auth_* tools | | Local MCP resources | sitelens-local://runs/{localRunId}/… | | CLI bootstrap / diagnostics | sitelens-mcp setup, --self-test, sitelens doctor | | CLI flow scaffold | sitelens flow init --flow-id <id> [--template smoke] | | CLI project flow runner | sitelens flow run --flow-id <id> --url <url> | | Scenario Runner | JSON in .sitelens/scenarios/*.json + CLI sitelens run scenario or MCP sitelens_run_local_scenario (chained flows, shared session) | | Remote content registry | sitelens registry sync — prompts, example flows, QA presets, scenario templates (optional) from sitelensapi.com/registry (no npm bump) | | Cloud QA (optional) | SITELENS_API_KEY + sitelens_run_qa, sitelens_run_flow (cloud UUID flows) |

Consumer-repo verification: release smoke (pnpm run pack:smoke) installs a publish-shaped tarball in a temp project with .sitelens/flows/smoke-flow.json, runs --self-test and sitelens doctor, and confirms flow discovery. Unit tests cover flow load, MCP registration, and GET /flows/local.

Experimental

| Capability | Notes | |------------|-------| | Strict pixel screenshot diff | MCP sitelens_compare_local_runs with includeScreenshotDiff: true — RGBA equality, not perceptual | | Local flow templates in ad-hoc QA | template presets on sitelens_qa_run (homepage-qa, basic-smoke, etc.) |

Internal only (not npm consumer surface)

| Capability | Notes | |------------|-------| | HTTP runtime sidecar | start:http-runtimeGET /flows/local, POST /flows/local/run, POST /runs/local for SiteLens Desktop | | Desktop capture packs | Desktop runs project flows via HTTP when a capture step references a flowId — not the primary npm onboarding path | | SITELENS_MCP_LOCAL_RUN_PLACEHOLDER | Dev/test flag — skips browser execution |

Planned / roadmap

| Capability | Notes | |------------|-------| | sitelens_local_doctor MCP tool | Targeted local connectivity diagnostics (hostname, allowlist, HTTPS ignore, browser channel, DNS/navigation) | | Desktop “Run flow” UI | Desktop Project flows page runs .sitelens/flows from the app | | QA Studio ↔ .sitelens/flows sync | Studio stores cloud UUID flows; repo JSON is separate | | Cloud sync of local artifacts | Local bundles stay on disk (supportsCloudUpload: false) | | Desktop visual compare viewer | MCP compare works; Desktop UI roadmap | | Advanced cloud history in Desktop | In progress |


Project flows

Project flows are JSON files stored in .sitelens/flows/*.json in your project — not hand-written browser test files (*.spec.ts), not QA Studio cloud records, and not files inside the npm package install path.

Intended convention

your-app-repo/
  .sitelens/
    flows/
      homepage-smoke.json      ← flowId "homepage-smoke"
      login-check.json         ← flowId "login-check"
    scenarios/
      login-then-smoke-scenario.json   ← scenarioId (see Scenario Runner)

Auth and browser profiles (when using profile or authProfile) are stored under ~/.sitelens/ on your machine — not in the repo:

~/.sitelens/
  auth/          ← Playwright storage-state JSON per profile name
  profiles/      ← persistent browser profile dirs (cookies, localStorage)

| Directory | Purpose | |-----------|---------| | .sitelens/flows/ | Single QA flows — one page or workflow step sequence each | | .sitelens/scenarios/ | Chained orchestration — runs multiple flows in order with one shared browser session | | ~/.sitelens/auth/ | Saved login state (storage-state auth mode) | | ~/.sitelens/profiles/ | Persistent browser profiles (persistent-profile auth mode; default for scenarios) |

| Rule | Detail | |------|--------| | Location | <workspace>/.sitelens/flows/{flowId}.json | | flowId | Lowercase slug: [a-z0-9][a-z0-9-]{0,63} (must match "id" inside the file) | | Workspace | Resolved from SITELENS_WORKSPACE_DIRCURSOR_PROJECT_DIRVSCODE_CWDprocess.cwd() | | Schema | version: 1, required id, name, url, steps[] — validated by @sitelensapi/qa-smoke | | Steps | Same vocabulary as SiteLens cloud saved flows (click, assert*, network waits, expectEither, etc.) | | Step limits | File-backed: up to 200 steps. Ad-hoc sitelens_qa_run: 8 steps max |

Commit .sitelens/flows/ to git in your app repo so agents and CI can run the same smoke paths.

Starter flows (flow init)

Scaffold a valid flow file without hand-writing the full schema (via the sitelens bin from @sitelensapi/mcp):

npx --yes @sitelensapi/mcp sitelens flow init --flow-id homepage-smoke
npx --yes @sitelensapi/mcp sitelens flow init homepage-smoke --template smoke
npx --yes @sitelensapi/mcp sitelens flow init --flow-id screenshot-pack --template screenshots

After npm install -g @sitelensapi/mcp, you can use sitelens flow init … directly.

| Template | What you get | |----------|----------------| | smoke (default) | readySelector: body, document screenshot, minimal assertSelector, final-state screenshot step | | screenshot | Explicit waitForSelector on body, assertions, final-state screenshot step, exportArtifacts | | text-check | assertText placeholder plus final-state screenshot step — edit the expected string after init | | login | Login form fill, before-submit / after-submit / after-login screenshot checkpoints | | form-submit | Generic form fill/submit with before-submit / after-submit / final-state checkpoints |

Default URL in generated files is http://localhost:3000/ — change it in JSON or override at run time with --url. Existing files are not overwritten unless you pass --force.

Example flow file

{
  "version": 1,
  "id": "homepage-smoke",
  "name": "Homepage Smoke",
  "url": "http://127.0.0.1:3000/",
  "viewports": ["desktop", "mobile"],
  "screenshot": true,
  "readySelector": "body",
  "steps": [
    { "type": "assertSelector", "selector": "body", "state": "visible" },
    { "type": "assertText", "text": "Welcome" },
    { "type": "screenshot", "label": "final-state" }
  ]
}

Use screenshot steps for labeled checkpoints during a flow (saved under the run artifact screenshots/ directory and returned in actionLog[].screenshot):

{ "type": "screenshot", "label": "after-login" }

Common labels for investigations: before-submit, after-submit, after-login, final-state.

Legacy flow JSON may also use { "action": "screenshot", "label": "after-login" } — it normalizes to the same step.

Scaffold flows with checkpoints:

sitelens flow init login-smoke --template login
sitelens flow init checkout --template form-submit
sitelens flow init homepage-smoke --template smoke

Agent guidance: evidence collection

When debugging UI, auth, or workflow issues with MCP or CLI:

  1. Call sitelens_status to confirm workspace and flow discovery.
  2. Run flows/scenarios with exportArtifacts: true (default for repo flows).
  3. Add { "type": "screenshot", "label": "…" } steps at key moments — before/after submit, after login, final state.
  4. Read summary.actionLog[].screenshot.path and summary.screenshotPaths in the tool response; open PNGs under {artifactDir}/screenshots/.
  5. For ad-hoc checks (≤8 steps), pass screenshot steps in sitelens_qa_run actions / scenario arrays.

Cursor prompt example: "Run sitelens_run_local_flow for auth-login-setup with export artifacts enabled. List every labeled screenshot path from actionLog."

Step reference: Project flows & local templates.

selectOption (native <select>)

Use selectOption when working with native HTML <select> dropdowns — especially when options are visually hidden or hard to click in headless mode. Playwright selects through the native element directly.

{
  "type": "selectOption",
  "selector": "select[name='status']",
  "value": "active"
}

Provide exactly one of value, label, or index. selector is required. Custom JavaScript dropdowns should still use click / press steps.

Tier 1 interactions

Target with exactly one of selector, testId, label, or role+name:

  • check / uncheck — checkbox state via locator.check() / uncheck()
  • setChecked{ "checked": true \| false } via locator.setChecked()
  • clear — clear text inputs via locator.clear() (file inputs blocked)
  • hover — reveal menus/tooltips via locator.hover()
  • doubleClicklocator.dblclick() with the same allowSubmit guard as click
{ "type": "hover", "selector": "[data-testid='account-menu']" }
{ "type": "setChecked", "testId": "terms", "checked": true }

Tier 2 interactions

  • uploadFilelocator.setInputFiles() on native input[type=file]; requires files (one or more paths)
  • dragTolocator.dragTo() with source and target endpoint objects (each uses one target ref style)
  • focus / blurlocator.focus(); blur focuses first then locator.blur()
  • scrollIntoViewlocator.scrollIntoViewIfNeeded()
{ "type": "uploadFile", "label": "Attach CSV", "files": ["/tmp/report.csv"] }
{
  "type": "dragTo",
  "source": { "testId": "draggable-item" },
  "target": { "testId": "drop-zone" }
}

Browser storage

Safe localStorage / sessionStorage manipulation for authenticated or spoofed workflows — no arbitrary JavaScript. Mutations apply to the active page (no reload). Run results include actionLog[].storage with storage, operation, keysAffected, and pageUrl for each mutation step.

| Step | Behavior | |------|----------| | storage.set | Set a string value (setItem) | | storage.remove | Remove one key or many keys | | storage.clear | Clear all items in local or session storage | | storage.assert | Assert key exists / exists: false or exact value |

{ "type": "storage.remove", "storage": "session", "key": "environmentConfig" }
{ "type": "storage.set", "storage": "local", "key": "featureFlag", "value": "enabled" }
{ "type": "storage.assert", "storage": "session", "key": "environmentConfig", "exists": false }

Example smoke flow: .sitelens/flows/storage-smoke.json.

Project flows vs QA Studio vs cloud flows

These are three different storage/run paths that share step types:

| | Project flows (this package) | QA Studio / API | |--|---------------------------|-----------------| | Storage | .sitelens/flows/my-smoke.json in your repo | Postgres via sitelens-api | | ID | String slug (my-smoke) | UUID | | Run tool | CLI sitelens flow run or MCP sitelens_run_local_flow | MCP sitelens_run_flow or Studio UI | | API key | Not required | Required | | Browser | Your machine (bundled Chromium) | SiteLens cloud hosts | | History | Local disk (sitelens_list_local_runs) | Cloud (sitelens_list_runs) |

QA Studio does not read or write .sitelens/flows/*.json today. Export/import between Studio and repo JSON is not implemented.

Run a project flow (CLI or MCP)

Project flows can run from the terminal or Cursor MCP — same load → execute path (loadLocalFlowDocumentlocalFlowToToolInputexecuteLocalRunQa).

CLI (shell / CI)

npx --yes @sitelensapi/mcp sitelens flow run --flow-id homepage-smoke --url http://127.0.0.1:3000/
npx --yes @sitelensapi/mcp sitelens flow run --flow-id login-flow --url http://localhost:3000 --viewport desktop --json
  • --flow-id.sitelens/flows/{flowId}.json in your workspace.
  • --url is required (overrides or supplements the file’s url).
  • Optional: --viewport, --output, --json, --auth-profile, --auth-mode, --browser.
  • Prerequisites: dev server on url, sitelens-mcp setup completed, cwd (or SITELENS_WORKSPACE_DIR) pointing at the repo with .sitelens/flows/.

MCP (Cursor / IDE agents)

Tool: sitelens_run_local_flow (registered when local tools are enabled — always, including SITELENS_MODE=local)

{
  "flowId": "homepage-smoke",
  "url": "http://127.0.0.1:3000/"
}
  • Same flags as CLI where applicable: authProfile, authMode, viewports, browser, exportArtifacts.
  • Cursor prompt: "Run sitelens_run_local_flow with flowId auth-login-setup and url http://127.0.0.1:3000/login — list labeled screenshot paths from actionLog (before-submit, after-login, final-state)."

Flow discovery (CLI — list only)

These commands list flows; they do not run them:

npx --yes @sitelensapi/mcp sitelens doctor
npx --yes @sitelensapi/mcp sitelens-mcp -- --self-test

Both report the resolved workspace, flows directory, and discovered flow ids when present.

To run a flow from the terminal, use npx --yes @sitelensapi/mcp sitelens flow run (see above).

Screenshot & artifact output

When exportArtifacts is true (default for flow runs):

$SITELENS_LOCAL_ARTIFACT_DIR/runs/<localRunId>/
  summary.json                 # status, paths, localRunId, screenshotPaths, actionLog
  report.md                    # human-readable report
  raw.json                     # per-viewport capture (redacted)
  screenshot-inventory.json    # PNG metadata (size, WxH)
  screenshots/                 # PNG files — end-of-run and labeled checkpoint steps

Labeled checkpoint steps ({ "type": "screenshot", "label": "after-login" }) save {label}-{viewport}-step{N}.png during the flow. Each successful step adds actionLog[].screenshot with path, url, and label.

  • Default base: $TMPDIR/sitelens-mcp-local-qa (override with SITELENS_LOCAL_ARTIFACT_DIR).
  • Tool response includes summary.artifactDir, summary.reportPath, and sitelens-local:// resource URIs.
  • Not uploaded to SiteLens cloud. Optional pixel diff only via sitelens_compare_local_runs.

SiteLens Desktop (architecture note)

Desktop bundles the MCP HTTP runtime (start:http-runtime) as a sidecar. That runtime exposes:

  • GET /flows/local — catalog .sitelens/flows/*.json
  • POST /flows/local/run — execute a flow (used by Desktop capture packs)

Desktop Project flows lists .sitelens/flows/*.json and runs them in-app. When Desktop detects supportsRepoLocalScenarios in MCP capabilities, it can surface Run Scenario using localScenarioRunner metadata (path pattern, param syntax, CLI command). npm consumers can use CLI or Cursor MCP without Desktop.


Scenario Runner

Flows and scenarios solve different problems:

| | Flow | Scenario | |--|------|----------| | What it is | A single QA flow targeting one page or workflow step sequence | Setup and orchestration of one or more flows using a shared browser session/profile | | Storage | .sitelens/flows/{flowId}.json | .sitelens/scenarios/{scenarioId}.json | | Browser session | New session per run | One session for all chained flows (cookies, localStorage, sessionStorage carry over) | | Run | sitelens flow run / sitelens_run_local_flow | sitelens run scenario / sitelens_run_local_scenario | | Params | Override url at run time | {{paramName}} interpolation + scenario/runtime params |

Supported use cases

  • Login flows — authenticate once, then run smoke tests in the same session
  • Session initialization — establish browser state before downstream flows
  • Role elevation — dev or staging session setup that grants elevated permissions for admin flows
  • Feature flag activation — toggle flags in an admin flow, verify in the app flow
  • Test data selection — pick a record or fixture, then run workflow verification
  • Environment setup — configure staging/local context before smoke validation
  • Multi-step application workflows — paths spanning several pages with shared state
  • Admin workflow verification — validate admin panels and privileged actions after setup
  • End-to-end smoke validation — chained setup + assertion flows in one run

Scenarios stay inside the SiteLens flow step vocabulary (click, assert*, network waits, etc.) — they chain existing flow JSON files; they are not arbitrary Playwright scripts.

Example scenario JSON

{
  "version": 1,
  "id": "role-elevation-scenario",
  "name": "Role Elevation Scenario",
  "profile": "qa-user",
  "params": {
    "baseUrl": "http://localhost:3000",
    "userId": "12345"
  },
  "flows": [
    { "flow": "session-setup" },
    { "flow": "admin-workflow-smoke" }
  ]
}

Each flows[] entry references a flow id (.sitelens/flows/{id}.json) or a path to a flow file. Optional with overrides flow fields or supplies param values for that step.

Parameter interpolation

Use {{paramName}} placeholders in flow URL fields and string step fields (selectors, assert text, fill values, etc.).

Per-flow URL override with interpolation:

{
  "flow": "session-setup",
  "with": {
    "url": "{{baseUrl}}/dev/elevate-session?user={{userId}}"
  }
}

Example flow with interpolated fields:

{
  "id": "session-setup",
  "name": "Session Setup",
  "url": "{{baseUrl}}/dev/elevate-session?user={{userId}}",
  "steps": [
    { "type": "waitForSelector", "selector": "[data-testid='session-updated']" },
    { "type": "assertText", "text": "session updated" },
    { "type": "assertUrlContains", "text": "/dev/elevate-session" }
  ]
}

Precedence (later values win):

  1. scenario.params — defaults in the scenario file
  2. Runtime params — CLI --param key=value or MCP params object
  3. Per-flow with — overrides and extra values for that flow entry

Validation (before browser launch):

  • Missing {{param}} placeholders → clear error listing required param names
  • Interpolated flow JSON → validated against the same schema as .sitelens/flows (invalid URLs or steps fail before execution)

Run a scenario (CLI)

npx --yes @sitelensapi/mcp sitelens run scenario role-elevation-scenario \
  --profile qa-user \
  --param baseUrl=http://localhost:3000 \
  --param userId=12345

| Flag | Description | |------|-------------| | --profile <name> | Auth profile for persistent browser session (overrides scenario.profile) | | --param key=value | Runtime param (repeatable); merges over scenario.params | | --viewport desktop\|mobile | Repeat for both viewports | | --output <dir> | Artifact base directory (SITELENS_LOCAL_ARTIFACT_DIR) | | --json | Machine-readable combined scenario result | | --auth-mode | none | storage-state | persistent-profile (default for scenarios: persistent-profile) | | --browser | chromium | chrome | msedge | firefox | webkit | | --no-screenshot | Disable screenshots for all flows in the scenario | | --no-artifacts | Disable artifact bundle export |

Help: sitelens run scenario --help

Each flow in the scenario gets its own artifact folder under the configured artifact base; the combined JSON output lists per-flow statuses, errors, labeled screenshot paths (actionLog[].screenshot), and artifactDir values.

Run a scenario (MCP)

Tool: sitelens_run_local_scenario

Input schema:

| Field | Type | Required | Description | |-------|------|----------|-------------| | scenarioId | string | yes | Scenario id (.sitelens/scenarios/{id}.json) or path to scenario JSON | | params | object (string values) | no | Runtime params merged over scenario.params | | profile | string | no | Auth profile override | | authMode | enum | no | none | storage-state | persistent-profile | | viewports | string[] | no | desktop, mobile | | browser | enum | no | Browser channel | | screenshot | boolean | no | Enable/disable screenshots | | exportArtifacts | boolean | no | Enable/disable artifact bundles |

Example request:

{
  "scenarioId": "role-elevation-scenario",
  "profile": "qa-user",
  "params": {
    "baseUrl": "http://localhost:3000",
    "userId": "12345"
  }
}

Example response (summary fields):

{
  "scenarioId": "role-elevation-scenario",
  "scenarioName": "Role Elevation Scenario",
  "status": "passed",
  "profile": "qa-user",
  "sharedSession": true,
  "startedAt": "2026-06-01T12:00:00.000Z",
  "finishedAt": "2026-06-01T12:01:30.000Z",
  "flowResults": [
    {
      "flowRef": "session-setup",
      "flowId": "session-setup",
      "flowName": "Session Setup",
      "index": 0,
      "status": "passed",
      "testedUrl": "http://localhost:3000/dev/elevate-session?user=12345",
      "localRunId": "local_abc123",
      "artifactDir": "/tmp/sitelens-mcp-local-qa/runs/local_abc123",
      "screenshotPaths": ["/tmp/.../screenshots/local-qa-....png"],
      "reportPath": "/tmp/.../report.md"
    },
    {
      "flowRef": "admin-workflow-smoke",
      "flowId": "admin-workflow-smoke",
      "flowName": "Admin Workflow Smoke Test",
      "index": 1,
      "status": "passed",
      "testedUrl": "http://localhost:3000/admin/dashboard",
      "localRunId": "local_def456",
      "screenshotPaths": [],
      "artifactDir": "/tmp/sitelens-mcp-local-qa/runs/local_def456"
    }
  ],
  "infrastructure": "local",
  "billingNotice": "Local SiteLens MCP runs are free."
}

If a flow fails, flowResults includes error on the failed entry and later flows are skipped. CLI human output and JSON include workspace paths, auth diagnostics (profile name, auth paths, whether saved state exists), and full artifact paths (artifactDir, summary.json, screenshots).

Working across multiple repositories

Each git repo can have its own SiteLens workspace. Flows and scenarios are repo-local; auth profiles are machine-local under ~/.sitelens/.

Recommended repo layout:

your-app-repo/
  .sitelens/
    flows/           ← flow JSON files
    scenarios/       ← scenario JSON files
    config.json      ← optional: browser channel, default profile name

Run artifacts (screenshots, summary.json, report.md) are written under the configured artifact base — default $TMPDIR/sitelens-mcp-local-qa/runs/<localRunId>/, or set SITELENS_LOCAL_ARTIFACT_DIR / CLI --output.

Workspace resolution order (first match wins):

  1. SITELENS_WORKSPACE_DIR — explicit override (best for CI or monorepo subprojects)
  2. CURSOR_PROJECT_DIR — Cursor’s open project root
  3. VSCODE_CWD — VS Code / integrated terminal cwd hint
  4. process.cwd() — shell working directory when you run the CLI

Per-run workspaceDir is not a CLI flag today; use SITELENS_WORKSPACE_DIR or cd into the repo. Scenario paths can also be passed as explicit file paths (relative to workspace or absolute).

There is no automatic walk for a nearest ancestor .sitelens/ directory. If you run from a subdirectory, set SITELENS_WORKSPACE_DIR to the repo root or pass a path to the scenario file.

Use distinct profile names per app (--profile my-app-qa) so cookies from one repo do not leak into another when reusing ~/.sitelens/profiles/.

Interactive login and saved profiles

Scenarios default to persistent-profile auth — one Chromium user-data directory per profile name under ~/.sitelens/profiles/<name>/.

| Step | Command / tool | |------|----------------| | Interactive login | sitelens auth start --profile qa-user → log in → sitelens auth save | | Check saved state | sitelens auth status --profile qa-user or MCP sitelens_auth_status | | Run with profile | sitelens run scenario … --profile qa-user |

At scenario start, CLI and MCP results include auth diagnostics (no secrets):

  • Profile name and resolved paths (~/.sitelens/auth/<profile>.json, ~/.sitelens/profiles/<profile>/)
  • Whether each path exists on disk before the run
  • Auth mode (persistent-profile, storage-state, none)
  • Whether a shared session is reused across chained flows

For login flows inside a scenario, prefer DOM and URL assertions over a single network URL check — see Troubleshooting login redirects.

Running scenarios

| Surface | Command / tool | |---------|----------------| | CLI | sitelens run scenario <scenario-id> [--profile …] [--param key=value …] | | MCP | sitelens_run_local_scenario with scenarioId, optional profile, params | | Help | sitelens run scenario --help |

Use --json for CI: combined status, per-flow artifactDir, summary.json paths, and auth block. Exit code 1 when scenario status is failed.

List scenario ids: ls .sitelens/scenarios/ or copy examples from docs/examples/scenarios/.

Troubleshooting login redirects

If a flow lands on /login instead of the expected page:

  1. Read auth diagnostics in the scenario result — confirm profile name, paths, and found vs missing.
  2. Run sitelens auth status --profile <name> — re-save if storage state or profile dir is empty.
  3. Inspect the failed flow artifact — open summary.json and screenshots under the printed artifactDir.
  4. Harden login flows — combine multiple success signals instead of relying on one API response URL:
{
  "type": "expectEither",
  "label": "login success",
  "oneOf": [
    { "type": "assertSelector", "selector": "[data-testid='user-menu']", "state": "visible" },
    { "type": "assertText", "text": "Welcome" },
    { "type": "assertUrlContains", "text": "/dashboard" }
  ]
}

After submit, use assertNotExists on the login form to catch silent failures. Avoid only waitForResponse on a login API path — pair it with assertText, waitForSelector, or assertUrlContains.

Scenario runs surface login-related interpretationNotes from the underlying QA runner when a redirect is detected.

Capabilities (Desktop discovery)

When the MCP HTTP runtime is enabled, GET /capabilities includes:

| Field | Meaning | |-------|---------| | supportsRepoLocalScenarios | true when sitelens_run_local_scenario is registered | | supportsScenarioParamInterpolation | true{{paramName}} supported in flows | | localScenarioRunner | { tool, scenarioPathPattern, paramSyntax, cliCommand } for Desktop UI |

Desktop should call /capabilities (or read MCP tool list) and, when supportsRepoLocalScenarios is true, offer Run Scenario with runtime param inputs matching localScenarioRunner.paramSyntax ({{paramName}}).

Complete examples

Copyable bundles live in docs/examples/:

  1. Login → smoke testlogin-then-smoke-scenario.json + auth-login-setup, homepage-smoke flows
  2. Session setup → admin smokerole-elevation-scenario.json + session-setup, admin-workflow-smoke flows
  3. Multi-flow workflow verificationworkflow-verification-scenario.json — test data selection → feature toggle → admin panel verify

See docs/scenario-runner-release-notes.md for release notes and a pre-release verification checklist.

Migrating from helper scripts

Shell wrappers that call multiple flow runs in sequence:

./run-workflow.sh userId=12345
./run-smoke.sh userId=12345

become one scenario file plus a single command:

sitelens run scenario role-elevation-scenario \
  --param userId=12345

Scenarios replace custom orchestration scripts in many cases while keeping flows as reusable, reviewable JSON. You still author flows for individual pages; scenarios wire them together with shared session and params.


SiteLens ecosystem

| Surface | What it is | Local flows? | |---------|------------|--------------| | @sitelensapi/mcp (this package) | MCP server + CLI for Cursor/IDEs and shell/CI | Yes.sitelens/flows + CLI + MCP tools | | SiteLens API | Hosted cloud QA, run history, artifacts | Cloud UUID flows via sitelens_run_flow | | QA Studio | Visual flow builder (web) | Cloud-stored flows — not the same as .sitelens/flows JSON | | SiteLens Desktop | Native app + local engine | Project flows page — list and run .sitelens/flows/*.json | | Dashboard / MCP onboarding | API keys, setup copy-paste | — |

Website: https://www.sitelensapi.com
MCP docs: https://www.sitelensapi.com/mcp/docs
npm: @sitelensapi/mcp · @sitelensapi/qa-smoke (shared step schema; usually a dependency)

Setup guides


CLI commands

| Command | Purpose | |---------|---------| | sitelens-mcp | Start stdio MCP server (normal Cursor wiring) | | sitelens-mcp setup | Install bundled Chromium + verify dirs | | sitelens-mcp -- --self-test | Readiness probe (workspace, flows dir, browser) | | sitelens doctor | Portable diagnostics (lists .sitelens/flows ids) | | sitelens doctor --cursor | Cursor-focused hints + example mcp.json | | sitelens flow init | Scaffold .sitelens/flows/{flowId}.json (--flow-id or positional id; --template) | | sitelens flow run | Run .sitelens/flows/{flowId}.json (--flow-id, --url) | | sitelens run scenario | Run .sitelens/scenarios/{scenarioId}.json (chained flows, shared session) |

Example:

npx --yes @sitelensapi/mcp sitelens flow run \
  --flow-id homepage-smoke \
  --url https://example.com

npx --yes @sitelensapi/mcp sitelens run scenario login-then-smoke-scenario \
  --profile qa-user \
  --param baseUrl=http://localhost:3000

Cursor wiring: use npx -y @sitelensapi/mcp as the command — do not pass setup, doctor, flow run, or --self-test as MCP server args.

SiteLens Desktop uses a separate HTTP runtime process (start:http-runtime) — do not set SITELENS_MCP_HTTP=1 in Cursor unless you intentionally want a loopback health server.


MCP tools

Local (registered when SITELENS_MODE=local or always without cloud key)

| Tool | Description | |------|-------------| | sitelens_setup | First-run bootstrap | | sitelens_billing_status | Local-free vs cloud-paid boundary | | sitelens_auth_start / _save / _status / _clear | Login-once auth under ~/.sitelens/ | | sitelens_qa_run | Ad-hoc local QA (preferred name) | | sitelens_run_local_qa | Same as sitelens_qa_run (legacy alias) | | sitelens_run_local_flow | Run .sitelens/flows/{flowId}.json | | sitelens_run_local_scenario | Run .sitelens/scenarios/{scenarioId}.json (chained flows, shared session, {{param}} interpolation) | | sitelens_list_local_runs | Scan local artifact dirs | | sitelens_compare_local_runs | Diff two local run bundles |

Cloud (requires SITELENS_API_KEY + SITELENS_MODE=all or cloud)

| Tool | HTTP | |------|------| | sitelens_analyze_page | POST /analyze/page | | sitelens_run_qa | POST /analyze/qa | | sitelens_list_runs | GET /qa/runs | | sitelens_get_run | GET /qa/runs/:runId | | sitelens_run_flow | POST /qa/flows/:flowId/run |

Cloud run resources: sitelens://runs/{runId} (Markdown digest via MCP resources/read).


Cursor MCP config (cloud + local)

When you need cloud tools, add your API key:

{
  "mcpServers": {
    "sitelens": {
      "command": "npx",
      "args": ["--yes", "@sitelensapi/mcp", "sitelens-mcp"],
      "env": {
        "SITELENS_API_BASE_URL": "https://api.sitelensapi.com",
        "SITELENS_API_KEY": "sitelens_sk_…",
        "SITELENS_MODE": "all"
      }
    }
  }
}

Local-only tools work without an API key — omit the key or use SITELENS_MODE=local.

Page Intelligence: Use MCP tool sitelens_analyze_page (cloud API) to plan flows from page structure. See Page Intelligence overview and monorepo doc docs/sitelens-mcp-page-intelligence.md for the analyze → flow → verify workflow.


Environment variables

| Variable | Description | |----------|-------------| | SITELENS_MODE | local (default for Cursor) · all · cloud | | SITELENS_API_KEY | Required for cloud tools only | | SITELENS_API_BASE_URL | API origin (default http://127.0.0.1:3000; production https://api.sitelensapi.com) | | SITELENS_WORKSPACE_DIR | Override workspace root for .sitelens/flows and .sitelens/scenarios (see Working across multiple repositories) | | SITELENS_LOCAL_ARTIFACT_DIR | Base for runs/<localRunId>/ bundles | | SITELENS_LOCAL_BROWSER_CHANNEL | Omit → bundled Chromium; or chrome / msedge / firefox / webkit | | SITELENS_BROWSER_CHANNEL | Optional local MCP alias when SITELENS_LOCAL_BROWSER_CHANNEL unset — chrome, msedge, or chromium (bundled default). Explicit chrome/msedge never silently falls back to bundled Chromium | | SITELENS_LOCAL_BROWSER_ARGS | Advanced/dev-only: comma-separated Chromium launch flags (e.g. --ignore-certificate-errors) for local MCP runs | | SITELENS_LOCAL_ALLOWED_HOSTS | Extra hostnames for local QA (staging domains) | | SITELENS_LOCAL_IGNORE_HTTPS_ERRORS | Local/dev only: true, 1, or yes — Playwright ignores HTTPS certificate errors (self-signed / private CA) | | SITELENS_DEFAULT_URL | Default target for cloud sitelens_run_qa |

Never commit real API keys.


Example Cursor prompts

  • "Use SiteLens setup."
  • "Run SiteLens local QA on http://localhost:3000."
  • "Run sitelens_run_local_flow with flowId homepage-smoke and url http://127.0.0.1:3000/."
  • "Run sitelens_run_local_scenario for login-then-smoke-scenario with baseUrl http://127.0.0.1:3000/."
  • "List my last 10 SiteLens local QA runs."
  • "Compare these two local runs and include screenshot diff."
  • "Open the SiteLens local report resource for the last run."

With cloud API key configured:

  • "Use sitelens_analyze_page on https://www.sitelensapi.com/ and list primaryActions and workflowStages."
  • "Use SiteLens to QA https://staging.example.com and call out blockers."
  • "List my latest SiteLens QA runs."
  • "Run saved flow <cloud-flow-uuid> against https://staging.example.com."

Remote registry (prompts, flows, templates)

Ship updated Cursor prompts, example flows, and local QA template presets without publishing a new @sitelensapi/mcp version.

npx --yes @sitelensapi/mcp sitelens registry sync
npx --yes @sitelensapi/mcp sitelens registry list --type prompts
npx --yes @sitelensapi/mcp sitelens registry show prompts teach-cursor
npx --yes @sitelensapi/mcp sitelens registry materialize flow homepage-smoke

Cache: ~/.sitelens/registry/ (override with SITELENS_REGISTRY_DIR). Catalog URL: SITELENS_REGISTRY_URL (default https://www.sitelensapi.com/registry/v1/).

Operators publish catalog JSON to https://www.sitelensapi.com/registry/v1/ (manifest + prompts/, flows/, scenarios/, qa-templates/). Scenario templates use the same flow-entry shape as local scenarios; remote sync is optional — local .sitelens/scenarios/ works without registry sync.


Monorepo development

cd packages/sitelens-mcp
pnpm install
pnpm run build
pnpm run setup
pnpm run doctor
pnpm run start        # stdio MCP server
pnpm run test
pnpm run pack:smoke   # release tarball smoke

Rebuild after src/ changes — MCP clients run compiled dist/.


Requirements & privacy

  • Node.js 20+
  • Local QA: bundled browser runtime (via sitelens-mcp setup); no Docker
  • macOS: approve Cursor + browser automation in Privacy & Security when prompted
  • Local artifacts stay on disk — not uploaded to SiteLens cloud by default
  • SITELENS_API_KEY is required only for cloud HTTP tools and sitelens://runs/… resources

Troubleshooting: browser runtime (last resort)

Normal path: sitelens-mcp setup (or sitelens doctor) — installs dirs, probes the bundled Chromium, and reports what failed.

Only if setup cannot finish (offline CDN, strict proxies, corrupted cache) and you are developing this package from a git checkout:

cd packages/sitelens-mcp && pnpm exec playwright install chromium

Then rerun sitelens-mcp setup. Do not use the command above for routine installs — it bypasses SiteLens setup checks.


License

See repository root for license terms.