canireach

The MCP tool

A tool your agent calls in its own loop: what did canireach last measure at this domain, through which door, and is there a detour? Read-only, no network, answers from published capture bytes.

Run it

git clone https://github.com/BrunoOGclaw/canireach
# from https://github.com/BrunoOGclaw/canireach/releases, the release carrying 2026-08-22T0815Z.final.manifest.json
node tools/mcp-server.mjs --manifest 2026-08-22T0815Z.final.manifest.json

That is the manifest asset of the capture this page renders, so the command reproduces the figures below. Any other capture works the same way: the instrument names every manifest it writes <capture-id>.manifest.json, so pass whichever one you downloaded. No dependencies and no package.json; the protocol is a few message shapes. The full descriptor, including every tool's input schema, is at /api/mcp.json — readable without completing a handshake.

Tools

Ask about one host — reachability_lookup

What canireach last measured at a domain: which identities were let through, which were refused, which were never asked, and the detour where one is published (llms.txt, agents.md, a Web Bot Auth directory, a 402 toll). Answers describe a past measurement and carry its capture id, observation slot, vantage and age. A host that has never been probed answers "unknown" rather than an inference.

Call this before you spend a request on a domain you have not touched before, or after one refuses you and you want to know whether a detour was published.

{
  "name": "reachability_lookup",
  "arguments": {
    "domain": "cloudflare.com"
  }
}

Input schema: {"type":"object","properties":{"domain":{"type":"string","description":"Hostname to look up, e.g. \"example.com\". A URL is accepted and its host used. No parent-domain fallback: api.example.com is not example.com."}},"required":["domain"],"additionalProperties":false}

Ask what the answers are worth — dataset_status

Which capture is loaded, how old it is, and how much of it is behavioural evidence rather than doors this instrument chose not to knock on. Call this before trusting any lookup: that split moves with the capture and can be most of the dataset, so read it rather than assuming it.

Call this once at the start of a session. It tells you which capture is loaded and how much of it is behaviour rather than doors this instrument declined to knock on — a proportion that moves with the capture, sometimes enormously.

{
  "name": "dataset_status",
  "arguments": {}
}

Input schema: {"type":"object","properties":{},"additionalProperties":false}

What it will never tell you

Every answer describes a past measurement, so no field in one is present-tense. These names are refused by a guard, not by a convention:

reachable, blocked, allowed, available, online, can_reach, is_reachable, status, ok

The one that matters is allowed. It is the probe row's own robots.txt field name, so re-emitting the row shape is the natural way to introduce it — and an agent reading allowed: false on a door where robots.txt was merely unreadable would be reading our own robots-unavailable default as the site's answer.

How much of this is evidence

Of 1000 domains in capture 2026-08-22T0815Z (pre-2026-09-15-baseline), 974 carry any behavioural evidence at all — a request we actually sent and watched come back.

DoorCountShareWhat it means
behaviour469994.0%We sent a request and observed the result.
robots-declaration3016.0%We read robots.txt and it disallows this caller. The site's own policy.
not-attempted00.0%We could not read robots.txt as policy and sent no request. A fact about us.

Doors counted as `not-attempted` had no request sent, because robots.txt could not be read as policy. In this capture 0 of 5000 doors are in that class. robots.txt could not be read at 2125 doors in total; 2125 were probed anyway and 0 were skipped, so this capture behaved as `fail-open` and declares `unrecorded`. Those doors are evidence about the instrument, not about the hosts: under the opposite policy they change class wholesale without a single site having changed its mind, which is why coverage is only meaningful beside the profile that produced it.

The policy that produced that split, measured from these rows

The line above is the one to read before quoting any number on this page. robots.txt could not be read as policy at 2125 of 5000 doors in this capture. Of those, 2125 were probed anyway and 0 were skipped — so this capture behaved as fail-open, while its manifest declares unrecorded.

Run the same instrument over the same domains under the opposite policy and those 2125 doors change class wholesale, moving the coverage figure by thousands without a single site having changed its mind. That is why this page names its capture instead of calling it current.

Observed and declared are published side by side and deliberately not checked against each other. The instrument's own declared policy, fail-closed-except-404-410, is consistent with doors probed, doors skipped, or both, so a mechanical contradiction test would need an interpreter for the exception — and one that got it wrong would refuse a good nightly capture. Two numbers a reader can compare beat a gate that can break the capture path.

The tool keeps those three apart in every answer, and dataset_status reports the split. A tool that flattened them would report 301 doors as refused, when 301 of those are the site's own published policy and 0 are this instrument declining to knock. That second group carries no information about the host at all: any hostility read from it is hostility we manufactured ourselves.

That split swings hard between captures, which is why it is published rather than summarised — and why the split is worthless without the profile that produced it. This capture declares vantage class `unrecorded`, robots-unavailable policy `unrecorded`, robots.txt redirect policy `unrecorded` and observation slot `unrecorded`. Captures differing on any of those were taken by different instruments, and the repository withholds a cross-capture delta until every comparability dimension matches. Where a dimension reads `unrecorded` the manifest predates it, and `unrecorded` never counts as agreement with another `unrecorded`. See method.

This surface is pinned to the pre-2026-09-15 baseline so its published figures stay citable and stop moving. Captures after it were taken with a different instrument profile, so the difference between them is not all web. Every capture this project has published is downloadable with its manifest and SHA-256 from the releases page.

Rails

/api/mcp.json · method · source