{
 "serverInfo": {
  "name": "crawlcheck",
  "version": "1",
  "title": "CrawlCheck"
 },
 "description": "Measures what AI crawlers and answer engines actually receive from a domain. Tools: scan_domain, verify_crawler_log, corpus_state, resolve_robots, draft_llms, fix_robots, fix_entitymap, video_check, video_channel, video_site, registry_lookup, crawler_path, public_counts, telemetry.",
 "transport": {
  "type": "streamable-http",
  "url": "https://crawlcheck.io/mcp"
 },
 "capabilities": {
  "tools": {
   "listChanged": false
  }
 },
 "tools": [
  {
   "name": "scan_domain",
   "description": "Scan a public domain as several crawler identities in the same second and return the graded record: grade, AI-visibility score, per-section scores, findings with evidence, and whether the origin refused the scanner. One scan takes 5-15 seconds."
  },
  {
   "name": "verify_crawler_log",
   "description": "Given raw web-server access-log lines, decide for each line that names a crawler (GPTBot, ClaudeBot, Googlebot, PerplexityBot...) whether the source IP falls inside that operator's published ranges. Returns verified, spoofed, or unverifiable when the operator publishes no ranges."
  },
  {
   "name": "corpus_state",
   "description": "Coverage of CrawlCheck's public dataset: how many distinct domains have been measured and how they split by platform, rendering, size, language and kind, with the strata that are still under-sampled."
  },
  {
   "name": "resolve_robots",
   "description": "Resolve every named answer engine, search index and training crawler against a domain's robots.txt the way a crawler does: most-specific group only, longest match, allow wins a tie. Shows when a Disallow under * does not apply to an agent with its own group."
  },
  {
   "name": "draft_llms",
   "description": "Draft an llms.txt from the domain's own homepage and up to 25 declared pages, using their titles and descriptions. A draft for the owner to cut down, not a publication."
  },
  {
   "name": "fix_robots",
   "description": "The domain's served robots.txt, corrected: * group rules copied into named groups that lacked them (shadowing), a Sitemap line added when missing, a minimal replacement when the served file was HTML. Every change is listed at the top; nothing else is touched."
  },
  {
   "name": "fix_entitymap",
   "description": "A starter entitymap.json built from the domain's latest scan record: name, phone, coordinates and declared service areas as entities with SERVES relations. Fields the page never stated are marked TODO, never guessed. Needs a prior scan."
  },
  {
   "name": "video_check",
   "description": "One YouTube video against the video anchor model: metadata, chapters, captions and storyboard where observed, twelve checks each naming what it reads."
  },
  {
   "name": "video_channel",
   "description": "Every upload on a YouTube channel, read 50 at a time, sorted by views. The upload list is free; the per-check tally needs a Watch licence and is not offered here."
  },
  {
   "name": "video_site",
   "description": "The site half of video: homepage plus up to 60 sitemap pages read for YouTube embeds, facades and page-builder widgets, VideoObject nodes and their required properties, and - with a handle - how many of the channel's videos the site carries."
  },
  {
   "name": "registry_lookup",
   "description": "Whether a domain is in CrawlCheck's registry and what it serves: llms.txt, agents.md, a media kit at /.well-known/media-kit.json, a reciprocity-tested entity graph, an AI access policy that names crawlers, and agent-callable surfaces. With no domain, returns the shelf counts across every measured site. A row exists because a fetch produced it; nothing here is self-reported and no payment moves a shelf."
  },
  {
   "name": "crawler_path",
   "description": "Where each crawler's path into a domain dies, as an observed data flow: edge decision, robots.txt as a file, robots.txt rules, then the page, JSON-LD, sitemap, llms.txt and entitymap.json it reached. Give agent (e.g. ClaudeBot, GPTBot, googlebot) for one identity's path and a one-line answer; omit it for every identity plus the stores and breaks. Uses the latest record on file, or scans first when there is none (fresh=true forces a scan). The answer-engine output is drawn but never measured."
  },
  {
   "name": "public_counts",
   "description": "The figures CrawlCheck quotes about itself, read from the source: sites_measured, domains_in_corpus, crawler_visits (a rolling window), sections, sections_scored, findings_published, guides_published, with an at timestamp."
  },
  {
   "name": "telemetry",
   "description": "Verified-crawler traffic observed at crawlcheck.io itself: which named agents arrived, how many claims were confirmed against operator ranges, how many were forged."
  }
 ],
 "documentation": "https://crawlcheck.io/docs/api",
 "openapi": "https://crawlcheck.io/openapi.json",
 "terms": "https://crawlcheck.io/policy"
}