addrbookFor publishers
← The evidence ledger

Evidence row 565689

Observed , by probe.mcp/1.

Kind
mcp.tools
About
endpoint 704378b9-dfb8-49e9-992b-056b97e0db5c
Recorded
Previous row
None: the first of its kind about this subject
Body SHA-256
1cad76609a973e2b76785d020726c0721784aceaefd37a5379099431e8007283
Leaf
0x054452c2f2e97984d2fa9fe0e7096eb9314bbb51e4cb208efdd7fd031ad6eb12

What was observed

{
  "count": 5,
  "tools": [
    {
      "description": "Audits ONE live page for AEO (Answer Engine Optimization), also called GEO (Generative Engine Optimization): whether ChatGPT, Claude, Perplexity, Google AI Overviews and Bing can reach it, read it and lift answers from it. Fetches the page the way those engines do — a plain HTTP GET as LektaBot, then a headless-Chromium render pass — and grades it A+ to F across four weighted layers: Access 25% (robots.txt permission for 38 published AI crawler tokens, counting vendor user agents and robots.txt control tokens alike: GPTBot, OAI-SearchBot, ClaudeBot, Claude-SearchBot, PerplexityBot, Googlebot, bingbot, CCBot and more), Indexability 25% (noindex / nosnippet / canonical controls, and how much main content survives with JavaScript off), Answerability 30% (concrete data density, external evidence, semantic section structure, hedging), Recency 20% (a machine-readable and visible last-updated date). Returns Markdown under fixed headings: \"## Verdict\" (grade, score, per-layer scores, and the URL actually measured after redirects), \"## Top issues\" (failing and warned checks ranked by points lost, tagged critical/serious/moderate/minor, with evidence), \"## Fixes\" (the full remediation text for each). Unmeasured layers cap the grade at B and say so. USE THIS for \"run an AEO audit\", \"run a GEO audit\", \"why is my page not cited in AI answers\", \"can ChatGPT / Claude / Perplexity fetch and read this page\", \"check my robots.txt for AI crawlers\" — and again after every deploy to re-measure. The grade measures eligibility preconditions (access, indexability, extractable answers, dates); it does not observe or predict whether any engine cites the page. DO NOT use it when code will parse the result (lekta_report is the same run as JSON), when an audit already exists and you only want the ranked work list (lekta_fix_plan, which never fetches), or to compare two runs (lekta_diff). It scores one page, not a site: no crawling, no sitemap expansion. COST AND BEHAVIOUR: read-only — the audited site is never modified. It READS AND GRADES robots.txt rather than obeying it as a fetch gate: the audit runs even where LektaBot is disallowed, and the report flags that. A blocking call — a live fetch plus a render pass, cut off at a 75 s hard limit. NOT idempotent: a URL not audited in the last 15 minutes starts a fresh run and spends one slot of the daily MCP quota (free plan default 10 fresh audits per UTC day across 1 hostname; every result prints the count used and the host slot in use), while a repeat inside that window replays the cached measurement for free. An unreachable, blocked or HTTP-error target still returns a report, graded U for \"unknown\" — never F. Only these return an error instead of a grade: a timeout or a server-side engine failure, an exhausted daily quota or host slot, 2 audits already in flight for this account, or the per-target ceiling of 1 audit per minute and 5 per hour.",
      "inputSchema": {
        "properties": {
          "url": {
            "description": "Required. The one absolute http(s) page URL to audit, e.g. \"https://example.com/pricing\". A bare host+path (\"example.com/pricing\") is accepted and upgraded to https; the #fragment is dropped and the hostname lower-cased, but the query string is kept and is part of the page identity (?variant=b is a distinct target). ONE page per call — not a domain, a sitemap or a list. Prefer a representative content page over the homepage: scoring is per-URL, not per-site. Redirects are followed and the verdict names the final measured URL, but the audit is STORED under the URL you pass here — give lekta_fix_plan and lekta_diff this same string, not the redirect destination.",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "name": "lekta_audit"
    },
    {
      "description": "Compares the two most recent scorable audits stored for ONE URL and reports the movement: score and grade before → after, which checks improved, which regressed, with both run timestamps. This is the progress meter of the fix loop. USE THIS to prove a deploy actually moved the number: lekta_audit → apply the fixes → deploy → lekta_audit again → lekta_diff. DO NOT use it to compare two different URLs or two pages of one site — it takes ONE url and compares that page against its own history — and do not call it when fewer than two scorable audits exist for that URL, which returns an error rather than a partial answer. For the ranked work list use lekta_fix_plan; for the current state of a page use lekta_audit. COST AND BEHAVIOUR: free and idempotent — reads storage only, no fetch, no quota; it never triggers an audit, so no diff exists until you have run lekta_audit twice yourself. Runs that could not be scored (grade U) and runs where a rule crashed server-side are excluded from the comparison entirely, so a failed re-audit is never reported as a regression — it simply is not there. When the engine version changed between the two runs the output says so, because part of the delta is then ours rather than yours.",
      "inputSchema": {
        "properties": {
          "url": {
            "description": "Required. An absolute http(s) URL with at least two stored scorable audits, e.g. \"https://example.com/pricing\". Same normalisation and the same keying rule as lekta_fix_plan: history is stored under the URL passed to lekta_audit, not the post-redirect final URL. One URL only — this compares a page with its own past, never with another page.",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "name": "lekta_diff"
    },
    {
      "description": "Turns the most recent STORED audit of a URL into an ordered remediation plan: every failing or warned check as a numbered step, biggest point recovery first, each with its severity, the points that fixing it is expected to regain, and the full fix text. Reads storage only and never fetches, so the plan is exactly as fresh as the last audit of that URL — and any audit of it counts, whether it was started over MCP or from the lekta.dev panel. USE THIS between lekta_audit and the code change, to decide what to fix and in what order, or to hand a developer or another agent a prioritised AEO/GEO work list. It keeps working when the daily fresh-audit quota is exhausted. DO NOT use it to measure or re-measure a page (lekta_audit does that), and do not call it for a URL that was never audited — it returns an error telling you to run lekta_audit first, not an empty plan. For what changed between two runs use lekta_diff; for the raw structured data use lekta_report. COST AND BEHAVIOUR: free and idempotent — no fetch, no quota, no rate limit; it never starts an audit under any circumstance, and repeat calls return the same plan until a newer audit lands. When the stored audit came from an older engine version the output says so and marks the point estimates unreliable. When it has no failing or warned checks, the tool reports that instead of inventing work.",
      "inputSchema": {
        "properties": {
          "url": {
            "description": "Required. An absolute http(s) URL that already has a stored audit, e.g. \"https://example.com/pricing\". Normalised like the lekta_audit url (https assumed when the scheme is missing, #fragment dropped, hostname lower-cased, query string significant). History is keyed on the URL that was PASSED to lekta_audit, never the final URL after a redirect — so if the audit reported a redirect, still pass the address you originally sent.",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "name": "lekta_fix_plan"
    },
    {
      "description": "Lists the sites saved on the authenticated Lekta account: URL, latest authoritative grade and score, when it was last audited, and the recheck interval where a schedule is on. This is account inventory, not a measurement. PARAMETERS: none — this tool takes no arguments; call it with an empty arguments object. USE THIS first in a session to see which URLs this account already tracks before picking one to pass to lekta_audit, lekta_fix_plan or lekta_diff, or to answer \"which of my pages has the worst grade\" and \"which pages are on a schedule\". DO NOT expect a fresh measurement (lekta_audit does that), sites belonging to other accounts, or arbitrary URLs — and do not expect to change anything here: sites are added and removed on the web panel at lekta.dev/en/panel, not over MCP. An account with no saved sites gets an explicit empty-list message, not an error. COST AND BEHAVIOUR: free and idempotent — no fetch to any site, no quota. Each grade shown is the last AUTHORITATIVE (scorable) run for that URL, the same definition the web panel and the badge use; when a newer attempt existed but could not be scored, that is stated on its own line, so the grade is neither hidden nor silently presented as current.",
      "inputSchema": {
        "properties": {},
        "type": "object"
      },
      "name": "lekta_my_sites"
    },
    {
      "description": "Runs the same page audit as lekta_audit and returns the whole report as one JSON document instead of Markdown — for programs, not people. Top-level fields: engineVersion, url (as requested), finalUrl, fetchedAt, durationMs, targetState, robotsDisallowsLektaBot, score (0-100, null when the target could not be measured), grade, coverage, coverageNote, appliedCaps, movers, warningCount, failCount, and fetchMeta (HTTP status, redirect chain, content type, bytes). layers[] carries each layer definition (name, weight) with its score, and layers[].checks[] every check with id, title, status (pass / fail / warn / info / not_applicable / unmeasured), severity, evidence values and full fix text. Scoring internals are stripped by design — rule source names, reference URLs and threshold rationale are absent; each check keeps only its dated evidence-class tag (SPEC, VENDOR, MEASUREMENT, PEER-REVIEWED or PROVISIONAL). USE THIS when code consumes the result, or when you need a field the Markdown verdict never prints: check ids, per-layer scores, raw evidence values, the redirect chain. DO NOT use it to show a person a verdict (lekta_audit is shorter and ranked by point impact), do not call it after lekta_audit for the same URL expecting new data (it is the same measurement in another shape), and do not reach for it to learn WHY a rule exists — that material is deliberately not in the payload. COST AND BEHAVIOUR: the same fetch, 15-minute cache, quota and limits as lekta_audit, with two differences — the JSON carries no quota line, so call lekta_audit when you need the count used, and nothing here is ranked: checks arrive in layer order, not by point impact.",
      "inputSchema": {
        "properties": {
          "url": {
            "description": "Required. One absolute http(s) page URL, e.g. \"https://example.com/pricing\". Handled exactly like the lekta_audit url: a missing scheme becomes https, the #fragment is dropped, the hostname is lower-cased, the query string is significant, and it is one page per call — no domain lists or sitemaps. A URL already audited within the last 15 minutes returns the cached run and spends no quota.",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "type": "object"
      },
      "name": "lekta_report"
    }
  ]
}

What the leaf hashes

{"body":"1cad76609a973e2b76785d020726c0721784aceaefd37a5379099431e8007283","id":565689,"kind":"mcp.tools","method":"probe.mcp/1","observed_us":1793138227338945,"prev":null,"subject":"704378b9-dfb8-49e9-992b-056b97e0db5c","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. 0x0544ace385912ff6d030b723acb8e627dd933564d38e62407eaf4a16de682348
  2. 0xf74c5b90c58ef0e057869529628c7cd7ec292bb297c0f2a20ad40df482061d44
  3. 0x28ccff3f99b958fb967fc590dc47c8bb977fe2cedd812e8d93d5cdde73048793
  4. 0xb12abb895e249627ec93f2dbb8e58918d43cee5e23bf3c0a3bcf1f4836f395cb
  5. 0x5e44377c155a2ac58f1ff864aae80aaa809fa442400ae906bb26f768cfcbd3b2
  6. 0xba57544ec3642d9ceb4369de45ab1830af7b694a45921d01fc3da96b28e8fbfd
  7. 0xfbd17a9173904b83aa1ea3f07e45c588933300ce678380f2fcc0227fdb3c6243
  8. 0x137d255152330e12cb128d264f3d43804c74eb05904512ec4137a77eecbc9883
  9. 0x765a5f71aab765ddbd857932211940014984602a81c6265f9cd52e5a94069201
  10. 0xa22400d0fd457dee119d6db1805b709d9d27c8f9e77b072a8b7bd0fdfe2ce3a4
  11. 0xe9db0158b4c259b87fc427fe2d76b9a481e59053039dd07a06261cfea061d5f8
  12. 0x6d7e35c9db9477d49c0dca0654b8a6378e19a394f96efba2061b6ef0ea5355fe
  13. 0x7e8c79bd0dee073006d03de64eaf1047d3bfd30041ac4fc765479ffd5a092e62
  14. 0x29e12cb67839430fa64ab8bd05d52bab606f2978d9e6d2fb094fece9438fd4de
  15. 0x2cf27e8a181d60d0dd27c186c2eddfcbb4e8fa71cf66feeb55a4d730e15ee8c4
  16. 0x518b93854db03dc9fc938883abf30da6eaae5ae0d4336903968fd32a7df8c71b
  17. 0x22c1fb9487ee0b9732fa017a0cc321eb27a60c08450d112f755089796e12cb1c
  18. 0xa20d48798a34aba12eb9c7297722982d910f06c148f5e27ac59307422964a585
  19. 0x9fc354c0ea3efc3f1b6548bb77ea902a50f2c9647647ea61592efce2bd795699
Day root
0xdd77e5e99da32c3f154180d63e3c3e6fe11e896a2c6896412ef6b5c4bcf7e795
Chained
0x23bb4dfd09f55c15ac3962f53578e02c6114d5bfd9bb451cf8794fb6e2817ef4
Published
On Arc Testnet, block 69414147: 0xb2ebd83aafeb765a0ce66e76aefb133ed06606c98038fd56191e2bcd1dcb77b4

How to check it · This row as JSON