addrbookFor publishers
← The evidence ledger

Evidence row 516207

Observed , by probe.mcp/1.

Kind
mcp.tools
About
endpoint 60f785a7-b56c-4d7f-84d7-6a89f2204e19
Recorded
Previous row
None: the first of its kind about this subject
Body SHA-256
5809da7bc4b07e582e92438e855b296b4fcbcdef5e7607d13ead6ad6c5f4e223
Leaf
0x789d58ee25bc86f8024328f3bab9ef7e043d8cf6bd4161f2f207a1ada6104bf8

What was observed

{
  "count": 5,
  "tools": [
    {
      "description": "Check whether search engines and AI assistants can crawl, read and quote this site. Use when the person asks about SEO basics, robots.txt, sitemaps, llms.txt, or whether Google, ChatGPT, Claude or Perplexity can see their site. Input: a bare domain like example.com. Returns a Discoverability score 0-100 broken into crawl access (25: robots.txt, plus what the edge actually serves to Googlebot, Bingbot, OAI-SearchBot, PerplexityBot, ClaudeBot and GPTBot), site plumbing (20: HTTPS, one canonical host, sitemap, real 404s), page metadata (20), structured data (20) and answer-engine readiness (15: llms.txt, a definitional opening, question-form headings). Every finding carries the exact file, tag or record to publish. It makes roughly 15 fetches over a few seconds - robots.txt, the sitemap, the root page, up to four pages listed in the sitemap, llms.txt, the preview image, one deliberately missing URL to see how 404s are handled, and the root page once as each of the six crawlers. It identifies itself as AstraVerifyBot, except on those six checks, where the point is to send the crawler's own user-agent. It fetches nothing off that domain and crawls no further. Cached 15 minutes. It changes nothing on the site. This is a separate scan from check_email_security and does not include it. It scores crawl access across all six crawlers at once; for the exact response a single named crawler receives - status, redirect chain, headers, the text it would index - use fetch_as_crawler.",
      "inputSchema": {
        "properties": {
          "domain": {
            "description": "The domain to check, as the person gave it (no scheme, no path). Reserved names such as example.com are refused.",
            "maxLength": 253,
            "minLength": 3,
            "type": "string"
          },
          "refresh": {
            "default": false,
            "description": "Force a fresh scan instead of the cached result (rate limited)",
            "type": "boolean"
          }
        },
        "required": [
          "domain"
        ],
        "type": "object"
      },
      "name": "check_discoverability"
    },
    {
      "description": "Check whether anyone can send email as this domain, and whether its own mail reaches the inbox. Use when the person asks about email security, spoofing or phishing risk, SPF, DKIM or DMARC setup, or why their mail goes to spam. Input: a bare domain like example.com - no scheme, no path. Given a URL or an email address, extract the domain and say what you extracted. Subdomains score in their own right: mail from the apex is not evidence about mail.example.com. Returns an Email Security score 0-100 broken into MX (25), SPF (25), DKIM (20) and DMARC (30), the status of each published record, the mail provider identified from MX, and the exact DNS record to publish for every finding. DNS-only, so it answers in about a second; cached 15 minutes, and refresh is for when DNS has just changed. One caveat to pass on rather than hide: DKIM selectors cannot be enumerated from DNS. They are found by probing the selectors known for the mail provider plus a list of a few hundred common names. A provider that issues random selectors - Amazon SES and Postmark among them - can only be confirmed from a live email, so report DKIM as not found by probing, never as proof the domain does not sign.",
      "inputSchema": {
        "properties": {
          "domain": {
            "description": "The domain to check, as the person gave it (no scheme, no path). Reserved names such as example.com are refused.",
            "maxLength": 253,
            "minLength": 3,
            "type": "string"
          },
          "refresh": {
            "default": false,
            "description": "Force a fresh scan instead of the cached result (rate limited)",
            "type": "boolean"
          }
        },
        "required": [
          "domain"
        ],
        "type": "object"
      },
      "name": "check_email_security"
    },
    {
      "description": "Show exactly what one named crawler receives from the domain's root page. Use when the person asks \"what does Google see?\" or \"can ChatGPT read my site?\", and whenever check_discoverability reports a crawl-access problem. check_discoverability scores crawl access across all six crawlers; this returns the one raw response behind that score, which is what explains such a result rather than restating it. robots.txt can read perfectly while a CDN or firewall returns 403 to one crawler and 200 to another, and only a real fetch shows that. Inputs: domain (bare, like example.com) and agent, exactly one of googlebot, bingbot, oai-searchbot, perplexitybot, claudebot, gptbot. Call it once per crawler to compare them. Returns the HTTP status, the full redirect chain, response headers, content type, the text that crawler would index, and flags for an outright block or a bot-challenge page - which is how cloaking becomes visible. One live fetch of the root page, nothing else, and it changes nothing.",
      "inputSchema": {
        "properties": {
          "agent": {
            "enum": [
              "googlebot",
              "bingbot",
              "oai-searchbot",
              "perplexitybot",
              "claudebot",
              "gptbot"
            ],
            "type": "string"
          },
          "domain": {
            "description": "The domain to check, as the person gave it (no scheme, no path). Reserved names such as example.com are refused.",
            "maxLength": 253,
            "minLength": 3,
            "type": "string"
          }
        },
        "required": [
          "domain",
          "agent"
        ],
        "type": "object"
      },
      "name": "fetch_as_crawler"
    },
    {
      "description": "Both AstraVerify scores for a domain, plus a shareable report link. Reach for this first on any broad question - \"is my domain set up right?\", \"check my domain\", \"what should I fix first?\" - and use the single-subject tools only once the person has narrowed it to email or to the website. Input: a bare domain like example.com. Returns the Email Security score, the Discoverability score, every open fix ranked critical then important then informational, and report_url. Work down that order. Some findings are marked as needing no action - a weak key the provider generates and the owner cannot replace, for instance - so do not present those as work. Unlike the other tools here, this one creates something: report_url is a snapshot of these findings saved to a new unlisted page at astraverify.com/r/..., and that page is what the person can send to whoever administers the domain. It opens later without rescanning, after the scan itself has aged out. Running the tool again on an unchanged scan returns the same page rather than a second one. Nothing is written anywhere the person owns. Set include_history to answer \"has this improved?\" or \"did my fix land?\": it adds the first and latest reading of each score, the move between them, and only the dates the score actually changed. A domain we have not watched before says so rather than reporting a flat line.",
      "inputSchema": {
        "properties": {
          "domain": {
            "description": "The domain to check, as the person gave it (no scheme, no path). Reserved names such as example.com are refused.",
            "maxLength": 253,
            "minLength": 3,
            "type": "string"
          },
          "include_history": {
            "description": "Also return how these scores have moved over time, and when",
            "type": "boolean"
          },
          "refresh": {
            "default": false,
            "description": "Force a fresh scan instead of the cached result (rate limited)",
            "type": "boolean"
          }
        },
        "required": [
          "domain"
        ],
        "type": "object"
      },
      "name": "get_report"
    },
    {
      "description": "Re-check a single discoverability component after the person has fixed it. Use only once check_discoverability has reported that component failing and the person says the fix is done - never speculatively. Without a previous scan to compare against it returns NOT_READY. Inputs: domain (bare, like example.com) and component, one of crawl, plumbing, metadata, structured, answer - the identifier from the earlier scan's findings. Returns that component re-measured and the updated Discoverability score, so you can tell the person plainly whether the change worked. Always a live re-fetch, never served from cache, which is exactly why it beats a second check_discoverability straight after an edit. It draws on the discoverability fresh-scan budget for that domain (30 an hour, counted across all callers), so use a full check_discoverability instead when several areas changed. It only re-reads public pages; it changes nothing on the site.",
      "inputSchema": {
        "properties": {
          "component": {
            "enum": [
              "crawl",
              "plumbing",
              "metadata",
              "structured",
              "answer"
            ],
            "type": "string"
          },
          "domain": {
            "description": "The domain to check, as the person gave it (no scheme, no path). Reserved names such as example.com are refused.",
            "maxLength": 253,
            "minLength": 3,
            "type": "string"
          }
        },
        "required": [
          "domain",
          "component"
        ],
        "type": "object"
      },
      "name": "verify_fix"
    }
  ]
}

What the leaf hashes

{"body":"5809da7bc4b07e582e92438e855b296b4fcbcdef5e7607d13ead6ad6c5f4e223","id":516207,"kind":"mcp.tools","method":"probe.mcp/1","observed_us":1793120495195791,"prev":null,"subject":"60f785a7-b56c-4d7f-84d7-6a89f2204e19","subject_kind":"endpoint"}

Proof

Fold these into the leaf in order, hashing each sorted pair with keccak256, to reach the root of (273461 rows).

  1. 0x789d18342744b2b297352d7d9afbd2384ef00658b70a09c2d372446c69abd9c3
  2. 0x09e52be3ddd7aaf54f2e5380d3baef505ce9957316c0fc918e82faef58f6ad57
  3. 0x263356780cfeec70585fa22f1e7e884274ea3292c75f610184490aa770a09caf
  4. 0x00abf31d128a3668e7a5cae8146e7d8b25a181b9ee239f9f924e17c6f0665a5d
  5. 0xaa6a1184deecec44714e948cda08294db723098f4a55d43968e0ffbda0042e26
  6. 0x0e926632b52b1fc072b22d1f9358f94544d5a7e0e7429fb77d9df421e2a85474
  7. 0x6cbff641f3b8cd8443036468d3d3de84516373afe3af761f9160094f807adb44
  8. 0x4b26eeef3fc589da6bf9ae41115a92b3d5af44217610f83cc9c9d42e1822b0f2
  9. 0x186892b9e45df4ac43e9600c0cabc28d3ca8f86e168330f03388db77b836bb0c
  10. 0xc93ff62c98f70c7f45a1e129c112326b4251aee97fcb847be8902e7ce832840d
  11. 0xa1e6e989ecb6e1c43313ac525ace9dc4656b12fbac67512d19580139784350ab
  12. 0x30b0c1fa0ae50435d58b5b7f993dde40a8bcc3f5956d7e3d31946f1a957684b4
  13. 0x8f2d125f5fe55a24b5da16577766eeaa13f24a272bb4c1c016f423ae917da681
  14. 0x9848c068b1371232529d2b5738fdc45b854c57da041b69ea7c9e112b14e2d9d1
  15. 0x275720ecabb68df33eee92ae4fd70572a8d952d6c61c061c2869cfc3217aa5c5
  16. 0x23cf9bb4337ee8be7fcae368fd69d24c62c11fb45882127b4cd919bb96a19996
  17. 0x0e01aa9525097570a6edaf32bfc959de57bf5c24317cf10c0716affea85ca60d
  18. 0xa20d48798a34aba12eb9c7297722982d910f06c148f5e27ac59307422964a585
  19. 0x9fc354c0ea3efc3f1b6548bb77ea902a50f2c9647647ea61592efce2bd795699
Day root
0xdd77e5e99da32c3f154180d63e3c3e6fe11e896a2c6896412ef6b5c4bcf7e795
Chained
0x23bb4dfd09f55c15ac3962f53578e02c6114d5bfd9bb451cf8794fb6e2817ef4
Published
On Arc Testnet, block 69414147: 0xb2ebd83aafeb765a0ce66e76aefb133ed06606c98038fd56191e2bcd1dcb77b4

How to check it · This row as JSON