chrome-devtools-mcp-ocarina

June 29, 2026 ยท View on GitHub

Synthetic health checks for a web page, written as YAML and run against a real headless Chrome through the MCP server, with no LLM. Load a page, fail on any console error or any failed request, assert the page rendered.

This drives Google's official chrome-devtools-mcp with Ocarina. A rondo is a declarative health spec you can commit and run in CI.

A health spec you can commit

The rondo reads a real headless Chrome through its own DevTools surface: the rendered page, the full console, every network request. It asserts on them directly. Load the page, fail on a console error, fail on a 4xx or 5xx, confirm the title rendered. The whole file is the spec, and the spec is the test. Point it at any URL with -e, drop it in CI, and keep it in the repo next to the thing it guards.

Prerequisites

  • Ocarina: go install github.com/msradam/ocarina@latest
  • Node.js (for npx). npx fetches the Chrome DevTools MCP server and a headless Chrome on first run.

Run

git clone https://github.com/msradam/chrome-devtools-mcp-ocarina
cd chrome-devtools-mcp-ocarina
ocarina play rondos/health-check.yaml

Point it at your own site with -e:

ocarina play rondos/health-check.yaml -e url=https://your-site.example

Or use the Makefile: make smoke, make health, make test.

What each rondo does

RondoWhat it checks
rondos/smoke.yamlChrome is reachable and loads a page.
rondos/health-check.yamlThe page loads, the console has no errors, no request returned 4xx or 5xx, and the page rendered its title.
rondos/multi-page.yamlOne reusable page check, run across three pages.
rondos/flow.yamlA navigation flow that captures diagnostics on failure and always dumps the console.

Reuse one check across pages (motifs)

A motif is a reusable, parameterized fragment. rondos/motifs/page-check.yaml loads a URL and asserts the rendered page contains some text. rondos/multi-page.yaml pulls it in once per page and passes the params with with::

rondo:
  - name: example.com
    motif: motifs/page-check.yaml
    with:
      url: "https://example.com"
      expect_text: "Example Domain"
  - name: example.org
    motif: motifs/page-check.yaml
    with:
      url: "https://example.org"
      expect_text: "Example Domain"
ocarina play rondos/multi-page.yaml

Error handling (block, rescue, always)

rondos/flow.yaml wraps a navigation flow in block, captures console and network diagnostics in rescue if a step fails, and always dumps the console as teardown:

ocarina play rondos/flow.yaml                                  # happy path
ocarina play rondos/flow.yaml -e url=https://httpstat.us/500   # rescue fires

The block stops at the first failed step, rescue runs only on failure, and always runs either way.

Make it fail

Point the check at a page that returns an error and watch it fail and exit non-zero:

ocarina play rondos/health-check.yaml -e url=https://httpstat.us/500

How it works

No model in the loop. Each step calls a Chrome DevTools tool (navigate_page, list_console_messages, list_network_requests, evaluate_script), and expect asserts on the result, including CEL rules like !output.contains('[404]'). See the Ocarina docs.

License

MIT.