navviBLOCK
Turn a browser task into a reusable scraper.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Navvi
Give it to your agent. Get a scraper you can run forever.
Install · Why Jev · How it works · For agents · Choosers
- Your agent asks in plain words.
navvi "extract the title, price and availability". - Navvi compiles a scraper, fast and accurately. Code finds the candidates on the
page; a model only picks among them. With Jev those picks are typed, cheap and several times faster than Haiku.
- Re-runs make zero LLM calls. The compiled scraper is a JSON file of selectors
and fingerprints. Run it in cron, in CI, on Apify.
- It heals itself when the site changes. A field that moved is found again and
the scraper is updated; a redesign is reported, never guessed.
Why use Jev
A scraper compiler makes a lot of small decisions: which element is the price, which control to click next, is the search done. Navvi never asks a model to write a selector or code; it enumerates the options and asks for a pick. That is exactly the shape Jev is built for
be29e766a000OBSERVED · 2026-10-10Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add navvi --env AI_GATEWAY_API_KEY=${AI_GATEWAY_API_KEY} --env TYPESAFE_API_KEY=${TYPESAFE_API_KEY} -- npx -y [email protected]{
"mcpServers": {
"navvi": {
"command": "npx",
"args": [
"-y",
"[email protected]"
],
"env": {
"AI_GATEWAY_API_KEY": "${AI_GATEWAY_API_KEY}",
"TYPESAFE_API_KEY": "${TYPESAFE_API_KEY}"
}
}
}
}Exposed tools (7)
7 read · 0 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
_9lives | read | 9lives |
name | read | description |
precio_oferta | read | Precio Oferta |
product_name | read | the product |
stock_total | read | units in stock |
tags | read | Tags associated with the quote |
title | read | token: unsafe |
Trust audit
BLOCKgrade D · trust 64/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | FAIL |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (8 observation(s))
- Network
- declared (6 observation(s))
- Shell
- declared (4 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (25)
new Function("window", SNAPSHOT_SOURCE)(sandbox);97.5% recall at 1% FPR and AUC 0.998 on Meta's private direct-jailbreak
trace.ts
id: "exfiltration",
expect(looksLikeCredential("use sk-ant-a1b2c3d4e5f6g7h8i9j0k1l2m3 for auth")).toBe("token-looking string");const SECRET = "hunter2-sealed-value";
detail-payload.json
payload-900201.json
payload-900202.json
payload-900203.json
payload-product.html
import { sanitizeText } from "../../src/guard/index.js";import { JEV_PRICE_PER_MILLION_INPUT_USD, TypeSafeEvaluationModel } from "../../src/chooser/jev.js";import { declares, declaredTypes } from "../../declared/json.js";import { normalize } from "../../util/text.js";import { normalize } from "../../util/text.js";expect(guard("http://169.254.169.254/latest/meta-data/")).toBe(false);it.each(["file:///etc/passwd", "http://169.254.169.254/", "http://localhost:9222/json", "javascript:alert(1)", "http://box.internal/", "http://10.0.0.5/", "http://[::1]/"])(
for (const ip of ["10.0.0.5", "172.16.0.1", "192.168.1.1", "169.254.169.254", "::1", "::ffff:10.0.0.5", "::ffff:a00:5", "fe80::1", "fd00::1"]) expect(isPrivateAddress(ip), ip).toBe(true);
const route = routes[new URL(req.url ?? "/", "http://127.0.0.1").pathname];
ok({ baseUrl: `http://127.0.0.1:${port}`, close: () => new Promise((r) => srv.close(() => r())) });expect(await main(["--mode", "record", "--fields", "a", "http://127.0.0.1:9/x"], io)).toBe(2);
const base = "http://127.0.0.1:8080/fixtures/python-jobs.html";
{ id: "k1", selector: "a.next", text: "Next", href: "http://127.0.0.1:8080/fixtures/python-jobs.html?page=2", count: 1 },zod, @types/node, tsx, typescript
Gates applied: instruction_override, no_behavioural_pass.
be29e766a000full audit observations/trust-audit/mcp-server/fellowship-dev__navvi.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-10 | be29e766a000 | BLOCK | D | 64 | first audit |
Questions
What is the navvi MCP server?
Turn a browser task into a reusable scraper.
What tools does navvi expose?
7 in total: 7 read-only, 0 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is navvi safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (64/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on.
What credentials does navvi need?
It reads AI_GATEWAY_API_KEY and TYPESAFE_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How current is this page?
The grade is for one exact copy of the source (be29e766a000), read on 2026-10-10. The repository is watched and re-audited when it changes.