Navigation
Getting Started
Guides
Integrations
Guides
Create a Monitor
How to create HTTP, browser, and MCP monitors using the Web UI, CLI, or natural language.
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:
- Navigate to the dashboard and click Create Monitor.
- Select the monitor type (HTTP, Browser, or MCP).
- For HTTP monitors, fill in the URL, method, headers, authentication, and assertions.
- For browser monitors, choose URL mode (just a URL) or Scripted mode and write a Playwright TypeScript script in the built-in editor.
- For MCP monitors, enter the endpoint and optionally list expected tools and test calls.
- Choose check locations and frequency.
- 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: 14Agent personas
To check that the same URL responds to AI crawlers and agents, add an agentPersonas block to an HTTP monitor. Each run can repeat the request as the selected personas and report any that are blocked, challenged, or served different content.
agentPersonas:
personas:
- claude-user
- chatgpt-user
every: 6See Monitor AI Agent Access for verdicts, sampling, cost and alerting.
Agent readiness
To monitor what AI agents look for on the site itself (robots.txt rules, llms.txt, a Markdown version of the page, discovery files), add an agentReadiness block to an HTTP monitor.
agentReadiness:
every: 12
require:
- llms_txtSee Check Agent Readiness for the probes, the score and alerting.
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
| Type | Fields | Description |
|---|---|---|
status_code | operator (equals, not_equals, less_than, greater_than), value | Assert on HTTP status code. Operator defaults to equals. |
response_time | max | Fail if response takes longer than max milliseconds. |
body_contains | value | Fail if response body does not contain the string. |
body_matches | pattern | Fail if response body does not match the regex pattern. |
body_json_path | path, operator (equals, not_equals, contains, exists), value | Assert on a JSONPath expression. Operator defaults to equals. |
header_value | header, operator (equals, contains, exists), value | Assert on a response header. Operator defaults to equals. |
ssl_expiry | daysBeforeExpiry | Fail if SSL certificate expires within the given number of days. Defaults to 14. |
openapi_conformance | specId, 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: falseThe script file (./monitors/checkout.ts) can take either of two forms:
- A script body. Write the body of your check directly, referencing
page(aPage) andcontext(aBrowserContext) as if they were already in scope. The Yorker runner wraps the script in an async function and injects both. Do not add otherimportorrequirestatements; a script body has no module scope. - A standard
@playwright/testspec. A file that importstestandexpectfrom@playwright/testand wraps the journey intest("name", async ({ page }) => { ... })runs as it is, so an existing end-to-end test can double as a monitor.
In both forms, 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)
| Field | Default | Description |
|---|---|---|
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"). |
screenshotMode | every_step | When to capture screenshots: every_step, failure_only, or disabled. |
videoEnabled | false | Whether to record video of the browser session. |
timeoutMs | 30000 | Maximum 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 executes the full JSON-RPC session lifecycle the way a real MCP client does:
- Sends
initializeand asserts the response carriesprotocolVersionandcapabilities, capturing anyMcp-Session-Idfor the rest of the session. - Sends the
notifications/initializednotification. - Calls
tools/listand verifies every tool inexpectedToolsis present (if configured). - Runs each
testCallsentry: invokes the tool and checks the result containsexpectedOutputContains(if provided). - Optionally detects drift: fingerprints each tool's input schema, description and annotations and the server's reported identity, and reports what changed since the previous run, including annotation hints that became less safe.
- Optionally checks that the server rejects an
initializerequest sent with no credentials.
A server that returns HTTP 200 but cannot complete the handshake fails the check with the phase that broke, not a generic error. Yorker speaks the Streamable HTTP transport; if the server responds with HTML or a non-JSON content type, the result says the Streamable HTTP transport may not be supported.
monitors:
- name: Docs MCP Server
type: mcp
endpoint: https://mcp.example.com/mcp
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: trueMCP configuration options
| Field | Default | Description |
|---|---|---|
endpoint | (required) | Streamable HTTP endpoint URL of the MCP server. |
timeoutMs | 30000 | Request 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. |
detectSchemaDrift | true | Track tool changes (added, removed, input schema, description, annotations, less-safe hints) and server identity changes between runs. |
rejectUnauthenticated | false | Requires auth. Also send initialize with no credentials and fail unless the server answers 401 or 403. |
Note: MCP monitors cannot be executed locally with
yorker test; deploy them and watch results viayorker results tailor 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_stepGroups 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/ordersThe 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 1mList monitors
yorker monitors list
yorker monitors list --type http --status enabledView 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" --yesSee 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://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://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.