Guides

Create a Monitor

How to create HTTP, browser, and MCP monitors using the Web UI, CLI, or natural language.

Create a Monitor

Yorker supports three monitor types:

  • HTTP — sends an HTTP request and asserts on the response (status code, body, headers, timing, SSL expiry, OpenAPI conformance).
  • Browser — runs a real Chromium session, either against a URL (automatic Core Web Vitals + screenshots) or scripted with Playwright TypeScript.
  • MCP — exercises a Model Context Protocol server over Streamable HTTP, validates the advertised tool list, and (optionally) calls tools with expected output.

There are three ways to create monitors: the Web UI, the CLI (monitoring as code), and natural-language generation.

Web UI

To create a monitor through the dashboard:

  1. Navigate to the dashboard and click Create Monitor.
  2. Select the monitor type (HTTP, Browser, or MCP).
  3. For HTTP monitors, fill in the URL, method, headers, authentication, and assertions.
  4. For browser monitors, choose URL mode (just a URL) or Scripted mode and write a Playwright TypeScript script in the built-in editor.
  5. For MCP monitors, enter the endpoint and optionally list expected tools and test calls.
  6. Choose check locations and frequency.
  7. Click Create.

CLI / Monitoring as Code

To manage monitors as code, define them in yorker.config.yaml and deploy with yorker deploy.

HTTP monitor

project: my-app
monitors:
  - name: API Health
    type: http
    url: https://api.example.com/health
    method: GET
    frequency: 1m
    locations:
      - loc_us_east
      - loc_eu_central
    timeoutMs: 10000
    followRedirects: true
    headers:
      Accept: application/json
    labels:
      - env:production
      - service:api
    assertions:
      - type: status_code
        operator: equals
        value: 200
      - type: response_time
        max: 2000
      - type: body_contains
        value: '"status":"ok"'
      - type: body_json_path
        path: $.version
        operator: exists
      - type: header_value
        header: content-type
        operator: contains
        value: application/json
      - type: ssl_expiry
        daysBeforeExpiry: 14

HTTP authentication

Three auth types are supported. Add an auth block to any HTTP monitor:

# Basic auth
auth:
  type: basic
  username: "{{secrets.API_USER}}"
  password: "{{secrets.API_PASS}}"

# Bearer token
auth:
  type: bearer
  token: "{{secrets.AUTH_TOKEN}}"

# API key header (defaults to X-API-Key)
auth:
  type: api-key
  header: X-API-Key
  value: "{{secrets.API_KEY}}"

Assertion types

TypeFieldsDescription
status_codeoperator (equals, not_equals, less_than, greater_than), valueAssert on HTTP status code. Operator defaults to equals.
response_timemaxFail if response takes longer than max milliseconds.
body_containsvalueFail if response body does not contain the string.
body_matchespatternFail if response body does not match the regex pattern.
body_json_pathpath, operator (equals, not_equals, contains, exists), valueAssert on a JSONPath expression. Operator defaults to equals.
header_valueheader, operator (equals, contains, exists), valueAssert on a response header. Operator defaults to equals.
ssl_expirydaysBeforeExpiryFail if SSL certificate expires within the given number of days. Defaults to 14.
openapi_conformancespecId, operationPath (optional), validateHeaders (optional)Validate the response against an OpenAPI spec registered in Yorker. See Assertions.

See the Assertions reference for full details.

Browser monitor — URL mode

The simplest browser monitor: Yorker navigates to the URL, captures Core Web Vitals, takes screenshots, and runs assertions. No script to write.

URL-mode browser monitors are currently created via the Web UI or the REST API. yorker deploy is scripted-only for browser monitors — create URL-mode monitors from the dashboard, or via POST /api/checks with browserConfig.browserMode: "url". See the REST API reference.

Browser monitor — scripted mode

Scripted browser monitors run full Playwright TypeScript scripts. Reference the script file from your config:

monitors:
  - name: Checkout Flow
    type: browser
    script: ./monitors/checkout.ts
    frequency: 5m
    locations:
      - loc_us_east
    viewport:
      width: 1280
      height: 720
    screenshotMode: every_step
    videoEnabled: false

The script file (./monitors/checkout.ts) is a Playwright script body, not a full test file. The Yorker runner wraps your script in an async function and injects page and context (both standard Playwright objects) for you to use. That means:

  • Do not write import { test } from "@playwright/test" or any other import/require statements — the script has no module scope.
  • Do not wrap the code in test(...) or describe(...) — Yorker doesn't run the Playwright test runner.
  • Do write the body of your check directly, referencing page (a Page) and context (a BrowserContext) as if they were already in scope.
  • Do use // @step: Name comments to mark steps. Yorker captures a screenshot at each step (when screenshotMode: every_step) and surfaces step timing in the filmstrip view.
// @step: Go to shop
await page.goto("https://shop.example.com");

// @step: Add to cart
await page.click("text=Add to Cart");

// @step: Checkout
await page.click("text=Checkout");
await page.waitForSelector(".order-confirmation");

Browser configuration options (scripted mode, YAML)

FieldDefaultDescription
script(required)Path to the Playwright TypeScript script file, relative to the config file.
viewport{ width: 1280, height: 720 }Browser viewport dimensions.
device(none)Playwright device name for emulation (e.g., "iPhone 14").
screenshotModeevery_stepWhen to capture screenshots: every_step, failure_only, or disabled.
videoEnabledfalseWhether to record video of the browser session.
timeoutMs30000Maximum script execution time (5000-120000 ms).

MCP monitor

MCP monitors check the health of a Model Context Protocol server over Streamable HTTP. On each run, Yorker:

  1. Connects to the endpoint and calls tools/list.
  2. Verifies every tool in expectedTools is present (if configured).
  3. Runs each testCalls entry: invokes the tool and checks the result contains expectedOutputContains (if provided).
  4. Optionally detects schema drift — tools that appeared, disappeared, or changed signatures since the last successful run.
monitors:
  - name: Docs MCP Server
    type: mcp
    endpoint: https://mcp.example.com/sse
    frequency: 5m
    timeoutMs: 30000
    locations:
      - loc_us_east
    auth:
      type: bearer
      token: "{{secrets.MCP_TOKEN}}"
    expectedTools:
      - search_docs
      - fetch_page
    testCalls:
      - toolName: search_docs
        arguments:
          query: "pricing"
        expectedOutputContains: "Plans"
    detectSchemaDrift: true

MCP configuration options

FieldDefaultDescription
endpoint(required)Streamable HTTP endpoint URL of the MCP server.
timeoutMs30000Request timeout (5000-120000 ms).
auth(none)Same auth block shape as HTTP monitors (basic, bearer, api-key).
expectedTools(none)Array of tool names that MUST be present. Missing tools fail the check.
testCalls(none)Array of tool invocations to run. Each entry has toolName, optional arguments (plain object), and optional expectedOutputContains.
detectSchemaDrifttrueEmit schema-drift events when the tool list or tool signatures change.

Note: MCP monitors cannot be executed locally with yorker test — deploy them and watch results via yorker results tail or the dashboard.

Labels

Attach labels to any monitor. Labels serve two purposes: filtering and grouping in the dashboard, and emission as OTel resource attributes so you can slice telemetry by label in your observability backend.

monitors:
  - name: Payments API
    type: http
    url: https://api.example.com/payments
    labels:
      - env:production      # key:value label
      - service:payments
      - critical            # boolean label (becomes yorker.label.critical="true")

Labels follow the convention [a-zA-Z0-9][a-zA-Z0-9_.:-]*, max 128 characters. Plain labels (no colon) emit as yorker.label.<name>="true". Key-value labels emit as yorker.label.<key>="<value>".

Omitting the labels field leaves labels unmanaged by config — the CLI preserves whatever labels exist on the remote. Setting labels: [] explicitly clears all labels.

Defaults and groups

To avoid repeating configuration across monitors, use defaults and groups.

Defaults apply to all monitors unless overridden:

defaults:
  frequency: 5m
  locations:
    - loc_us_east
    - loc_eu_central
  http:
    timeoutMs: 15000
    followRedirects: true
    assertions:
      - type: status_code
        value: 200
  browser:
    viewport:
      width: 1280
      height: 720
    screenshotMode: every_step

Groups apply shared settings to a subset of monitors:

groups:
  - name: API Endpoints
    frequency: 1m
    locations:
      - loc_us_east
      - loc_us_west
      - loc_eu_central
    monitors:
      - name: Users API
        type: http
        url: https://api.example.com/users
      - name: Orders API
        type: http
        url: https://api.example.com/orders

The cascade order is: defaults -> group -> monitor. Each level overrides the previous.

Per-monitor assertions replace defaults entirely (they do not merge). To clear inherited assertions, set assertions: [] on the monitor.

Frequency format

Frequencies use a shorthand: 30s (seconds), 5m (minutes), 1h (hours). Valid range: 10 seconds to 24 hours.

CLI imperative commands

For quick one-off monitors, use the monitors commands instead of a config file:

Create a monitor

yorker monitors create --name "API Health" --type http --url https://api.example.com/health --frequency 1m

List monitors

yorker monitors list
yorker monitors list --type http --status enabled

View monitor details

yorker monitors get "API Health"

Edit, pause, and resume

yorker monitors edit "API Health" --frequency 30s --add-location loc_eu_central
yorker monitors pause "API Health"
yorker monitors resume "API Health"

Delete a monitor

yorker monitors delete "Old Endpoint" --yes

See the CLI reference for the full list of monitor commands and flags.

Natural language

To create a monitor using natural language, use either the Web UI or the API.

Web UI: Click Describe in plain English on the create monitor page and type a description like "Monitor our checkout flow every 2 minutes from US and EU, alert if it takes longer than 3 seconds." Yorker generates a Playwright script you can edit before saving.

API: Send a POST request to /api/checks/generate with a description. The endpoint returns a generated Playwright script you can review, optionally refine, and save as a browser monitor:

curl -X POST https://app.yorkermonitoring.com/api/checks/generate \
  -H "Authorization: Bearer $YORKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Navigate to https://shop.example.com, add the first product to cart, and verify the cart shows it.",
    "targetUrl": "https://shop.example.com"
  }'

You can also pass previousScript and refinement to iteratively improve an existing script. See the REST API reference.

Generate HTTP checks from an OpenAPI spec

/api/checks/generate also accepts a spec field. Pass an existing spec ID, an OpenAPI URL Yorker should fetch, or the name of a spec already on your team — Yorker creates one HTTP check per operation, skips operations that already have a check, and returns the full list. This is the API equivalent of the spec import flow:

curl -X POST https://app.yorkermonitoring.com/api/checks/generate \
  -H "Authorization: Bearer $YORKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "spec": { "source": "url", "specUrl": "https://api.example.com/openapi.json" },
    "locations": ["us-east", "eu-west"],
    "frequencySeconds": 300
  }'

The spec field is a discriminated union: pass {"source": "id", "specId": "spec_..."} to use an existing spec, {"source": "url", "specUrl": "https://..."} to fetch and (if needed) import a new one, or {"source": "name", "specName": "..."} to look up by name. If the spec yields more than 50 new operations the first call returns 409 with requiresConfirmation: true — re-submit with "confirm": true to proceed. See the Generate Checks From OpenAPI Spec reference for the full request/response shape and error codes.