Ask before you fetch. Skip domains that will refuse your crawler, and never route around an HTTP 402 paywall.
This is a client library, not an MCP server. It exports 18 functions (9 unique across TypeScript/Python) for web crawling with census preflight checks. Tool definitions are inferred from function signatures and JSDoc comments in source code, not from explicit MCP tool registration. Descriptions are present but generic (avg ~120 chars). Parameter schemas are partially documented in JSDoc but lack formal JSON Schema with type constraints. No input validation, error recovery guidance, or output schema documentation. The library itself is well-engineered (graceful degradation, batching, caching), but tool definitions for MCP consumption are incomplete.
Get the operator-facing view for an agent, including operator name and correction channel.
Get the operator-facing view for an agent, including operator name and correction channel.
Fetch the deny-list file for an agent. Returns a set of domains that block the specified agent.
Fetch the deny-list file, which is the cheap path for a fetcher. Returns a set of domains that block the specified agent.
Get deltas in the blocklist since a given timestamp, so nobody re-downloads the whole list.
Get deltas in the blocklist since a given timestamp, so nobody re-downloads the whole list.
Create a new bounded TTL cache instance for verdict caching.
No formal JSON Schema definitions for tool inputs. Parameter types are documented in JSDoc comments (e.g., 'domains: string|string[]') but not in machine-readable schema format. LLMs cannot validate or constrain inputs without explicit schema.
Output schemas not documented. Tools return complex objects (e.g., preflight returns array of verdict objects with domain, verdict, reason, robots, edge_refused, charges, measured_at, report fields) but no schema is provided to guide LLM response parsing or downstream tool chaining.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 41 | 2026-07-28+ | v2 |
Split a work queue before crawling it: one call per 1,000 domains, not one per host. The verdicts are written into the cache `polite_fetch` reads, so the documented pattern - partition a queue, then fetch what it says to fetch - costs one census call rather than two.
Split a work queue before crawling it: one call per 1,000 domains, not one per host. The verdicts are written into the cache `polite_fetch` reads, so the documented pattern - partition a queue, then fetch what it says to fetch - costs one census call rather than two.
A crawler-aware fetch. Consults the census, then either performs the fetch or returns a skip record explaining why it did not. The skip record is deliberately not an exception: skipping is the normal, correct outcome for a large share of the web, and a crawl loop should be able to count skips without a try/catch around every URL.
Consult the census, then fetch or skip. Skipping is the normal outcome for a large share of the web, so it is returned rather than raised: a crawl loop should be able to count skips without wrapping every URL in try/except.
Check a batch of domains for one agent. Domains are deduplicated and chunked to the anonymous limit unless a key raises it. Network failure is never fatal: an unreachable census returns `unknown` for everything, so a crawl degrades to its normal behaviour rather than stopping.
Check a batch of domains for one agent. An unreachable census yields `unknown` rather than raising: a crawl should degrade to its normal behaviour, not stop, because a third-party service is down.
Submit unmeasured domains to the census for measurement.
Submit unmeasured domains to the census for measurement.
Create a BlocklistSync instance that can refresh and apply deltas to a blocklist in place.
Normalise anything URL-ish to a bare hostname.
Normalise anything URL-ish to a bare hostname.
No error recovery guidance. Functions degrade gracefully (e.g., preflight returns 'unknown' verdict on network failure) but tool descriptions do not explain this behavior or guide LLM recovery. Agents cannot distinguish transient failures from actual blocks.
Duplicate tool definitions across TypeScript and Python (e.g., preflight, partition, blocklist appear twice with camelCase and snake_case variants). This creates ambiguity for LLM tool selection and violates single-responsibility principle.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Most tools are read-only (preflight, blocklist, agentProfile) but this is not declared. submitUnmeasured is destructive (writes to census) but lacks annotation. Agents cannot reason about side effects.