# Reticle (npm · @reticlehq/server)

Verify a running web app from the inside over MCP: look, act, observe, assert. No screenshots.

- Trust score: 74/100 (medium)
- Change this week: 0
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-10-25

## Components

- npm · `@reticlehq/server`: 74/100 (this document), [markdown](https://verifymcp.io/servers/reticlehq-reticle/reticlehq-server.md), [page](https://verifymcp.io/servers/reticlehq-reticle/reticlehq-server)

## Channel facts

- Registry: `npm`
- Package: `@reticlehq/server`
- Version: `3.8.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-10-25.

- **Supply Chain Security**: 81/100
  - No malware found by supply-chain analysis.
  - CVE check failed: a known high-severity CVE affects zod 3.25.76, a direct dependency. A fixed version is available.
  - No install/post-install scripts declared.
  - 31 of 103 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 87/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to reticlehq/reticle).
  - License check failed: the license (FSL-1.1-ALv2) isn't a recognized OSI-approved license.
  - Actively maintained (last published 0 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 51/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 4686 tokens (~468/item across 10 items; 10 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 37/100
  - Stability observed for 11 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 10 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 11 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the Reticle MCP server?

Reticle runs locally as an npm package, launched with npx -y @reticlehq/server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add reticlehq-reticle -- npx -y @reticlehq/server
```

### Cursor

```json
{
  "mcpServers": {
    "reticlehq-reticle": {
      "command": "npx",
      "args": [
        "-y",
        "@reticlehq/server"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "reticlehq-reticle": {
      "command": "npx",
      "args": [
        "-y",
        "@reticlehq/server"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add reticlehq-reticle -- npx -y @reticlehq/server
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "reticlehq-reticle": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@reticlehq/server"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add reticlehq-reticle --command npx --arg -y --arg @reticlehq/server
```

### Hermes

```yaml
mcp_servers:
  reticlehq-reticle:
    command: "npx"
    args: ["-y", "@reticlehq/server"]
```

### Netclaw

```json
{
  "McpServers": {
    "reticlehq-reticle": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "@reticlehq/server"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add reticlehq-reticle -t stdio -c npx -a -y @reticlehq/server
```

### Other

```json
{
  "mcpServers": {
    "reticlehq-reticle": {
      "command": "npx",
      "args": [
        "-y",
        "@reticlehq/server"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-25 (score 74, +1)

- [security regression] Tool safety: pass → unverified
- [security regression] Stability: 0.33 → unverified
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional improvement] Tool coverage: 94% → 100%
- [functional] Package version: 3.7.0 → 3.8.0

### 2026-10-24 (score 73, −5)

- [security regression] CVE-2023-54404 affects this package: high
- [security regression] Known CVEs: pass → fail

### 2026-10-23 (score 78, +1)

No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-22 (score 77, +3)

- [functional improvement] Stability: unverified → 0.27

### 2026-10-14 (score 74, +27)

- [security improvement] Injection markers: unverified → pass
- [security] First check of Judged manipulation: pass
- [security] Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window).
- [functional improvement] Tool coverage: unverified → 100
- [functional improvement] MCP protocol: unverified → pass
- [functional] First check of Schema quality: fail
- [functional] First check of Destructive annotations: pass
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 94
- [functional] First check of Schema quality: good

### 2026-10-13 (score 47)

First indexed and scored.

## MCP tools (10)

### `reticle_navigate` (~169 tokens)

Navigate the connected browser tab to a URL, or reload it in place with { reload: true } (add { hard: true } to bypass the cache). e.g. {"url":"/settings"}

Input parameters:

- `hard` (boolean): With reload:true, bypass the browser cache (Cmd+Shift+R).
- `reload` (boolean): Reload the current page instead of navigating (replaces the former standalone refresh tool).
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `timeout_ms` (integer): How long to wait for the page to come back (the SDK reconnecting at the new URL, or under the same id on a reload) before answering confirmed:false.
- `url` (string): The URL to navigate to.

### `reticle_act_and_wait` (~619 tokens)

Act on a ref, then wait for a predicate to hold — one hop for the act->observe->assert loop. e.g. {"ref":"e42","action":"click","until":{"kind":"signal","name":"todos:loaded"}}

Input parameters:

- `action` (string, required): Action to perform.
- `args` (object): Action-specific arguments: { value } for fill/select, { text } for type/press (the key NAME, e.g. Escape or Tab), { modifiers: ["Meta","Shift"] } for a press s…
- `detail` (string): "compact" keeps only the deciding fields.
- `durable` (boolean): After a yes, reload and require the element/text/state part of `until` to hold again.
- `intent` (string): What this change is meant to make true — as a durable statement ABOUT THE PRODUCT, or the id of an intent you already declared.
- `predicate` (object): Predicate object: { kind, ...fields }. kind is one of element | text | net | route | console | animation | signal | state | settled | compare | allOf | anyOf | not. Bug-catching options: net.count (e…
- `ref` (string): Element ref (e.g. 'e42') from reticle_look { action: "page" }/reticle_look { action: "find" } — stable until the element leaves the DOM, so no re-snapshot between actions.
- `refuseWhenThrottled` (boolean): Throw if the tab is throttled.
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `target` (object): Find the element and act on it in ONE call, instead of a reticle_look { action: "find" } round trip first: { testid } | { text } | { role, name } | { label }.
- `timeout_ms` (integer): Maximum wait time in milliseconds.
- `until` (object): Predicate object: { kind, ...fields }. kind is one of element | text | net | route | console | animation | signal | state | settled | compare | allOf | anyOf | not.

### `reticle_session` (~511 tokens)

By action: "list" (the default) shows connected tabs; "yield" is MANDATORY before you stop; "tune" hides or moves the HUD; "feedback" reports a problem. e.g. {"action":"yield","mode":"waiting"}

Input parameters:

- `action` (string): Which operation to run.
- `all` (boolean): Include already-resolved marks in the listing (default: pending only).
- `claim` (string): What YOU claim this session showed.
- `contact` (string): An email address for a reply from the maintainers.
- `currentApproach` (string): How you work around it TODAY.
- `disconnect` (boolean): Also detach this page for good (needs sessionId).
- `hud` (string): Hide, show or remove the HUD, or move it to a corner.
- `idleEndMs` (integer): Idle window in milliseconds after which the panel shows WAITING (your turn).
- `impact` (string): What measurably improves — fewer tool calls, fewer retries, a verdict that stops being ambiguous, a flow you currently cannot verify at all.
- `kind` (string): bug = a Reticle tool returned a wrong or broken result; gap = Reticle could not observe something you needed at all; ambiguity = the verification ran but you c…
- `level` (string): Display severity.
- `mode` (string): "waiting" = turn done, will resume; "ask" = blocked, need the human to answer.
- `model` (string): The model you are running (e.g. "claude-opus-4", "gpt-5").
- `need` (string): The GOAL behind a request, not the request itself.
- `note` (string): For mode:"ask", the question to show the human on the panel.
- `rating` (integer): How well it worked, 1-5, with an `experience`.
- `resolve` (string): A mark id (e.g. "m1") to retire after you have fixed it.
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `summary` (string): One sentence: what this session proved.
- `text` (string): Short sentence describing your next action, shown on the presenter HUD for the developer watching.
- `trace` (string): The literal tool calls and responses that led here, so the failure can be reproduced without guessing.

### `reticle_verify` (~579 tokens)

The Reticle Harness is { action: "explore" }: when the user asks for the Harness, or asks Reticle to drive and verify the app for you, call it and do not drive… e.g. {"action":"change","files":["src/App.tsx"]}

Input parameters:

- `action` (string, required): Which operation to run.
- `app` (boolean): Also fold into the app-wide ledger; returns `app.levels`.
- `apply` (boolean): Write the rebind.
- `confirmDangerous` (boolean): Set true to allow destructive controls during this run of the suite only.
- `driveId` (string): The drive id an explore call answered with.
- `exhaustive` (boolean): Walk every state it can tell apart, drive each write's failure path, fold into the coverage ledger.
- `expect` (object): Predicate it must end in (route, net, state), asserted after.
- `files` (array): Changed file paths, repo-relative (e.g. ["src/App.tsx"]).
- `flow` (string): Alias for `flowName`.
- `flowName` (string): Flow file name (without .json), from reticle_verify { action: "flows" }, which names every saved flow.
- `labels` (array): Verify flows with ANY of these labels.
- `maxSteps` (integer): Maximum number of controls to click.
- `names` (array): Flow names to verify.
- `parallel` (integer): Replay this many affected flows at once (needs the browser pool).
- `persona` (string): The journey in plain words; "quoted text" must show at the end.
- `planId` (string): Run a plan saved on the dashboard, as it stands.
- `runId` (string): The run id an explore call answered with; pass it to poll that run.
- `say` (string): With runId: a note to the running Harness.
- `scope` (string): CSS selector or element ref to restrict crawling to a subtree.
- `secrets` (object): Redacted fields' values, this call only, never kept: { "auth-password": "…" }
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `settleMs` (integer): Milliseconds to wait after each click for the app to react.
- `since` (string): Git ref to diff against (e.g. "HEAD~1", "main").
- `skipWrites` (boolean): Certify without changing data: hold back every flow with a step that sends a write request (POST, PUT, PATCH, DELETE), and name them in `skippedWrites`.
- `stop` (boolean): With runId: stop that Harness run.
- `wait` (number): Seconds; default 50.

### `reticle_look` (~600 tokens)

Read the page, by action: "page" is the semantic snapshot of what is rendered, "find" resolves a locator (testid/role/text/component) to refs you can act on, "… e.g. {"action":"find","by":"testid","value":"submit"}

Input parameters:

- `action` (string): Which operation to run.
- `alt` (string): Predicate spelling of by/value.
- `attrs` (array): Attribute NAMES to return per match, e.g. ['href'] for links, ['src'] for images.
- `audit` (boolean): Also measure the page for what a person would see broken: text cut off with no ellipsis, controls drawn over each other, text under WCAG contrast.
- `by` (string): Query strategy.
- `count_only` (boolean): Return just { count } (no element descriptors) — use when you only need "how many match?" and not their refs.
- `depth` (integer): Collapse anything deeper than N levels to a size marker — avoids huge outputs for large stores.
- `diff` (boolean): Return only what changed since your last snapshot of the same scope/mode (mode:delta|unchanged).
- `ids` (boolean): Add [testid=…] to each control that carries one: a stable identity for a harness mapping the app.
- `label` (string): Predicate spelling of by/value.
- `limit` (integer): Cap descriptors to the first N.
- `mode` (string): full = all elements; interactive = only clickable/focusable elements; status = only route + title.
- `name` (string): Accessible name filter — narrows results when `by` is role and the page has many elements of that role.
- `path` (string): Dot-path into the store (e.g. 'captionCache.v3').
- `placeholder` (string): Predicate spelling of by/value.
- `ref` (string): Element ref (e.g. 'e42') from reticle_look { action: "page" }/reticle_look { action: "find" } — stable until the element leaves the DOM, so no re-snapshot between actions.
- `role` (string): Predicate spelling of by/value.
- `scope` (string): CSS selector or element ref to restrict the snapshot to a subtree.
- `self` (boolean): Return the `scope` element ITSELF instead of searching inside it.
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `store` (string): Registered store name (e.g. 'workspace').
- `testid` (string): Predicate spelling of by/value.
- `text` (string): Predicate spelling of by/value.
- `value` (string): Query value for the selected strategy (e.g. by=role value=button, or by=testid value=submit-btn).

### `reticle_observe` (~333 tokens)

What the app DID, by action: "events" is the reaction window since a cursor, "network" the requests it made, "console" what it logged. e.g. {"action":"events"}

Input parameters:

- `action` (string): Which operation to run.
- `actionId` (string): Keep only events attributed to this action — answers "what did action N cause".
- `assets` (boolean): List the dev server's own successful asset GETs (modules, styles, maps, Vite plumbing).
- `bodies` (boolean): Body detail.
- `filters` (array): Event type allowlist — the cheapest way to shrink a large timeline.
- `level` (string): Log level filter.
- `limit`: Cap descriptors to the first N.
- `max_events` (integer): Cap the timeline to the most recent N events.
- `method` (string): HTTP method filter: GET | POST | PUT | DELETE | PATCH etc.
- `ok` (boolean): Outcome filter: false keeps only calls that FAILED, true only those that succeeded.
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `since` (integer): Cursor (a number) from a prior act or observe result.
- `status` (integer): HTTP status code filter (e.g. 200, 404, 500).
- `until`: Upper cursor bound.
- `urlContains` (string): Substring that the request URL must contain.
- `window_ms` (integer): Time window to look back, in ms (must be > 0).

### `reticle_assert` (~266 tokens)

Prove a consequence, by action: "now" evaluates a predicate against the window that already exists, "wait" waits for one to become true within a budget. e.g. {"action":"now"}

Input parameters:

- `action` (string): Which operation to run.
- `detail` (string): "compact" keeps only the deciding fields.
- `intent` (string): What this change is meant to make true — as a durable statement ABOUT THE PRODUCT, or the id of an intent you already declared.
- `predicate` (object): Predicate object: { kind, ...fields }. kind is one of element | text | net | route | console | animation | signal | state | settled | compare | allOf | anyOf | not.
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `since` (integer): Cursor (a number) from a prior act or observe result.
- `timeout_ms` (integer): If > 0, wait up to this many milliseconds before failing.
- `until` (object): Predicate object: { kind, ...fields }. kind is one of element | text | net | route | console | animation | signal | state | settled | compare | allOf | anyOf | not.

### `reticle_act` (~376 tokens)

Act WITHOUT checking the result — if the action is supposed to cause something, use reticle_act_and_wait { until } instead and get the verdict in the same call. e.g. {"ref":"e42","action":"fill","args":{"value":"hello"}}

Input parameters:

- `action` (string): Action to perform.
- `args` (object): Action-specific arguments: { value } for fill/select, { text } for type/press (the key NAME, e.g. Escape or Tab), { modifiers: ["Meta","Shift"] } for a press s…
- `burst` (number): ms gap between dispatches, to provoke an ordering race (try 50).
- `detail` (string): "compact" keeps only the deciding fields.
- `onDeviation` (string): What to do when a step's `expect` does not hold.
- `ref` (string): Element ref (e.g. 'e42') from reticle_look { action: "page" }/reticle_look { action: "find" } — stable until the element leaves the DOM, so no re-snapshot between actions.
- `refuseWhenThrottled` (boolean): Throw instead of silently sending synthetic events when the tab is throttled/backgrounded.
- `sessionId` (string): Target a specific tab. Omit unless you mean one — see instructions.
- `steps` (array): Ordered list of { ref | target, action, args?, expect? } objects.
- `target` (object): Find the element and act on it in ONE call, instead of a reticle_look { action: "find" } round trip first: { testid } | { text } | { role, name } | { label }.
- `timeout_ms` (integer): Per-step timeout in milliseconds.

### `reticle_tools` (~211 tokens)

Discover Reticle tools on demand. Call with no arguments to list every tool (name + one-line summary); call with names:["reticle_screenshot", …] to load full descriptions and parameters for specific tools. Then invoke them with reticle_run. This avoids paying for every tool definition on every turn. To make a verification REUSABLE (record once, replay free forever), the flow workflow lives here: reticle_record{action:"start"} → act → reticle_record{action:"stop"} → reticle_flow_save → reticle_verify{action:"flows"} (and reticle_verify { action: "heal" } on drift). Load those names when you want to save or re-run a flow.

Input parameters:

- `action` (string): "list": the catalogue, same as no arguments.
- `name` (string): One tool name: the same as names:[name].
- `names` (array): Tool names to load full params for. Omit to list all tools with summaries.

### `reticle_run` (~108 tokens)

Invoke any Reticle tool by name (discover names/params first with reticle_tools). On an unknown tool or bad arguments it returns the available names or the tool's params, so you can correct and retry.

Input parameters:

- `args` (object): Arguments object for that tool.
- `sessionId` (string): Target tab for the invoked tool. Forwarded to it — an explicit args.sessionId wins.
- `tool` (string, required): Tool name to invoke, e.g. reticle_clock.

## Diagnostics

Captured diagnostic sections: Provenance, Vulnerabilities, Dependencies. The full working is on the page: https://verifymcp.io/servers/reticlehq-reticle/reticlehq-server#diagnostics

## Score history

- 2026-10-25: 74
- 2026-10-24: 73
- 2026-10-23: 78
- 2026-10-22: 77
- 2026-10-21: 74
- 2026-10-20: 74
- 2026-10-19: 74
- 2026-10-18: 74
- 2026-10-17: 74
- 2026-10-16: 74
- 2026-10-15: 74
- 2026-10-14: 74
- 2026-10-13: 47

## Common questions

### What is the Reticle MCP server?

Reticle is an MCP server listed in the public MCP registry as io.github.reticlehq/reticle. Verify a running web app from the inside over MCP: look, act, observe, assert. No screenshots. This page covers its npm package (@reticlehq/server).

### Is the Reticle MCP server safe to use?

Reticle scores 74 out of 100 on VerifyMCP. We recorded 1 known advisory against it as of 25 October 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Reticle MCP server expose?

Reticle exposes 10 tools: reticle_navigate, reticle_act_and_wait, reticle_session, reticle_verify, reticle_look, and 5 more. Their descriptions and schemas cost roughly 3,772 tokens of context every time the server is loaded.

### Is the Reticle MCP server still maintained?

Reticle is still listed as active in the MCP registry. We last reached this channel on 25 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the Reticle MCP server under?

Reticle declares the FSL-1.1-ALv2 licence, which is not on the OSI-approved list. Read the terms before using it at work, and note this covers the source only, not the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/@reticlehq/server
- Socket report: https://socket.dev/npm/package/@reticlehq/server
- Repository: https://github.com/reticlehq/reticle
- Website: https://www.reticle.sh/
- Changelog RSS feed: https://verifymcp.io/servers/reticlehq-reticle/reticlehq-server.xml
- Changelog JSON feed: https://verifymcp.io/servers/reticlehq-reticle/reticlehq-server.json
- HTML version of this page: https://verifymcp.io/servers/reticlehq-reticle/reticlehq-server
