← MCP Security Catalog

automatelab-ai-seo 1.0.0

npm · @automatelab/ai-seo-mcp · latest release

Scan failed
Security result
20
Observed tools
44
Version rating
100
Change risk

Independent inventory

Observed 2026-08-22T06:34:56.291Z using mcpSecurity-inventory. Protocol 2025-06-18.

ToolCategoryRisk
audit_canonicalAudit a page's canonical link integrity: presence, self-reference, cross-domain mismatches, trailing-slash hygiene, and og:url consistency. Read-only. One HTTP GET to fetch the HEAD section. Deterministic, rule-based; no LLM. When to use: a focused canonical-only audit (e.g. debugging a duplicate-content issue). For a full HEAD audit including OpenGraph, hreflang, noindex, title, use `check_technical`. For everything-on-a-page, use `audit_page`.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL whose canonical link tag and og:url consistency you want to audit. Must be a fully-qualified http(s) URL. The tool fetches the URL (following redirects) and inspects only the <head> section; the body is not parsed."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt before fetching. Set false only for auditing your own site where you've intentionally blocked crawlers."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "fetched_at": {
      "type": "string"
    },
    "canonical": {
      "type": [
        "string",
        "null"
      ]
    },
    "og_url": {
      "type": [
        "string",
        "null"
      ]
    },
    "self_referencing": {
      "type": "boolean",
      "description": "Whether the canonical points to the audited URL."
    },
    "cross_domain": {
      "type": "boolean",
      "description": "Whether the canonical points to a different domain."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "url",
    "fetched_at",
    "canonical",
    "og_url",
    "self_referencing",
    "cross_domain",
    "findings"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Audit canonical link integrity",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
audit_pageFull AI-SEO audit of a single URL: returns categorized findings (info/warning/error) with severity, fix instructions, and a 0-100 composite score plus per-dimension subscores. Read-only. Fetches the URL once and runs every sub-audit (schema, robots, technical, sitemap, AI-Overview eligibility) against the response. No writes, no third-party APIs, no auth required, no rate limits beyond polite per-host throttling. Deterministic, rule-based scoring; no LLM calls. Same URL + same input flags returns the same score. Supports `render: "static" | "headless"`. Default `static` (fast, raw HTML only). Use `headless` for React/Vue/Angular SPAs — adds 3-10s and requires the optional `playwright-core` peer dep plus a one-time `npx playwright install chromium`. When to use: the default entry point for `audit any page`. Use this instead of calling check_technical / audit_schema / check_robots / check_sitemap / score_ai_overview_eligibility individually unless you specifically need only one dimension - this tool composes all of them.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to audit. Must be a fully-qualified http(s) URL that returns HTTP 200 (redirects are followed). The tool fetches this URL once and runs every sub-audit (schema, robots, technical, sitemap, AI-Overview eligibility) against the response."
    },
    "include_raw_html": {
      "type": "boolean",
      "default": false,
      "description": "If true, return the full raw HTML in the response under `raw_html`. Default false. Set true only when you need to inspect markup that wasn't captured by the structured findings; the payload can be large."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), the tool checks robots.txt before fetching and skips disallowed paths, returning a robots_blocked finding instead. Set to false ONLY for auditing your own site where you've intentionally blocked crawlers and need the audit to bypass that block."
    },
    "generate_report": {
      "type": "boolean",
      "default": false,
      "description": "If true, return a standalone HTML scorecard in the `report_html` field. The HTML is self-contained (no external dependencies) and can be saved as a .html file or pasted to Gist/CodePen. Default false to keep audits cheap."
    },
    "render": {
      "type": "string",
      "enum": [
        "static",
        "headless"
      ],
      "default": "static",
      "description": "Rendering mode. `static` (default) fetches raw HTML via HTTP — fast (<1s) but misses JS-rendered content typical of SPAs (React/Vue/Angular landing pages). `headless` spins up Playwright Chromium, waits for networkidle, and audits the rendered DOM — adds 3-10s per audit and requires `playwright-core` installed plus a one-time `npx playwright install chromium`. Use `headless` when the static audit shows `content_quality: \"spa_empty\"` or you know the target is JS-rendered."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "The URL that was audited."
    },
    "fetched_at": {
      "type": "string",
      "description": "UTC ISO-8601 timestamp of the fetch."
    },
    "score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Composite 0-100 AI-citation score."
    },
    "grade": {
      "type": "string",
      "enum": [
        "A",
        "B",
        "C",
        "D",
        "F"
      ],
      "description": "Letter grade derived from the numeric score."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      },
      "description": "All findings emitted by the sub-audits, deduplicated."
    },
    "citation_verdict": {
      "type": "object",
      "properties": {
        "will_ai_cite": {
          "type": "string",
          "enum": [
            "unlikely",
            "marginal",
            "likely"
          ],
          "description": "Coarse verdict from the composite score."
        },
        "top_3_blockers": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "category": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "fix": {
                "type": "string"
              },
              "estimated_impact": {
                "type": "string",
                "enum": [
                  "high",
                  "medium",
                  "low"
                ]
              }
            },
            "required": [
              "category",
              "message",
              "fix"
            ],
            "additionalProperties": false
          },
          "description": "Top three highest-impact issues blocking AI citation."
        },
        "one_line_summary": {
          "type": "string",
          "description": "Single-sentence explanation suitable for headlines/dashboards."
        }
      },
      "required": [
        "will_ai_cite",
        "top_3_blockers",
        "one_line_summary"
      ],
      "additionalProperties": false,
      "description": "Prepended block summarizing whether AI assistants will cite this page and why."
    },
    "dimension_scores": {
      "type": "object",
      "properties": {
        "schema": {
          "type": "number"
        },
        "robots": {
          "type": "number"
        },
        "technical": {
          "type": "number"
        },
        "freshness": {
          "type": "number"
        },
        "structure": {
          "type": "number"
        },
        "authority": {
          "type": "number"
        },
        "entity_density": {
          "type": "number"
        },
        "sitemap": {
          "type": "number"
        },
        "citability": {
          "type": "number",
          "description": "Passage-level extractability: share of sections in the 134-167 word citable band."
        },
        "evidence": {
          "type": "number",
          "description": "Citations / statistics / quotations density (Princeton GEO weighting)."
        },
        "trust": {
          "type": "number",
          "description": "E-E-A-T trust signals: author, dates, contact/policy pages, HTTPS."
        }
      },
      "required": [
        "schema",
        "robots",
        "technical",
        "freshness",
        "structure",
        "authority",
        "entity_density",
        "sitemap",
        "citability",
        "evidence",
        "trust"
      ],
      "additionalProperties": false,
      "description": "Per-dimension 0-100 subscores. The composite score is a weighted blend of these."
    },
    "platform_readiness": {
      "type": "object",
      "properties": {
        "chatgpt": {
          "type": "object",
          "properties": {
            "score": {
              "type": "number"
            },
            "label": {
              "type": "string",
              "enum": [
                "ready",
                "partial",
                "weak"
              ]
            }
          },
          "required": [
            "score",
            "label"
          ],
          "additionalProperties": false
        },
        "perplexity": {
          "type": "object",
          "properties": {
            "score": {
              "type": "number"
            },
            "label": {
              "type": "string",
              "enum": [
                "ready",
                "partial",
                "weak"
              ]
            }
          },
          "required": [
            "score",
            "label"
          ],
          "additionalProperties": false
        },
        "google_ai_overview": {
          "type": "object",
          "properties": {
            "score": {
              "type": "number"
            },
            "label": {
              "type": "string",
              "enum": [
                "ready",
                "partial",
                "weak"
              ]
            }
          },
          "required": [
            "score",
            "label"
          ],
          "additionalProperties": false
        },
        "gemini": {
          "type": "object",
          "properties": {
            "score": {
              "type": "number"
            },
            "label": {
              "type": "string",
              "enum": [
                "ready",
                "partial",
                "weak"
              ]
            }
          },
          "required": [
            "score",
            "label"
          ],
          "additionalProperties": false
        }
      },
      "required": [
        "chatgpt",
        "perplexity",
        "google_ai_overview",
        "gemini"
      ],
      "additionalProperties": false,
      "description": "Per-engine readiness derived from the dimensions; engines reward different signals."
    },
    "score_caps": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Hard blockers that capped the composite score (e.g. noindex, AI bots blocked). Empty when none fired."
    },
    "content_quality": {
      "type": "string",
      "enum": [
        "static_html",
        "ssr_likely",
        "spa_empty"
      ],
      "description": "Classification of the fetched HTML's readiness. spa_empty means audit results are degraded."
    },
    "raw_html": {
      "type": "string",
      "description": "Full raw HTML response. Present only when include_raw_html=true."
    },
    "report_html": {
      "type": "string",
      "description": "Self-contained HTML scorecard. Present only when generate_report=true."
    }
  },
  "required": [
    "url",
    "fetched_at",
    "score",
    "grade",
    "findings",
    "citation_verdict",
    "dimension_scores",
    "platform_readiness",
    "score_caps",
    "content_quality"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Audit page (full)",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
audit_schemaValidate JSON-LD structured data against Schema.org rules and AI-citation best practices. Accepts either a URL (fetched) or a raw JSON string (parsed directly). Read-only when given `url` (one HTTP GET). Zero network when given `schema_json`. No writes. Deterministic, rule-based; no LLM. Validates required/recommended properties, @context correctness, sameAs links, and AI-search-friendly patterns. When to use: focused JSON-LD audits, or to validate a schema block you're about to ship. For a full page audit that includes schema + everything else, use `audit_page` instead. Either `url` or `schema_json` must be provided (not both). If both are provided, `schema_json` wins and no fetch happens.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to fetch and audit. Either this OR `schema_json` is required. Read-only HTTP GET."
    },
    "schema_json": {
      "type": "string",
      "description": "Raw JSON-LD as a string (the contents of a `<script type=\"application/ld+json\">` block). Use this to validate a schema block offline without fetching a URL. Either this OR `url` is required."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt before fetching `url`. Ignored when `schema_json` is used."
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "url",
        "inline"
      ],
      "description": "Where the JSON-LD came from."
    },
    "url": {
      "type": [
        "string",
        "null"
      ],
      "description": "Source URL (null when source=inline)."
    },
    "fetched_at": {
      "type": [
        "string",
        "null"
      ]
    },
    "found_types": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Schema.org @type values discovered across all JSON-LD blocks."
    },
    "ai_citation_readiness_score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "0-100 score for the JSON-LD's AI-citation readiness."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "source",
    "url",
    "fetched_at",
    "found_types",
    "ai_citation_readiness_score",
    "findings"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Audit JSON-LD schema",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
audit_siteSingle-call site sweep: runs audit_page (homepage), check_robots, check_sitemap, and audit_schema in parallel and returns an overall grade (A–F) plus top-5 highest-impact fixes. Read-only. Issues several HTTP GETs against the domain (homepage fetch, robots.txt, sitemap.xml, and up to 50 sitemap URL HEAD checks); no writes, no auth required, no rate limits beyond polite per-host throttling. The homepage GET is deduplicated across audit_page and audit_schema (~2 network fetches for 4 logical checks). Deterministic, rule-based scoring; no LLM calls. Same domain returns the same grade on repeated runs given unchanged content. Output: domain, homepage_url, fetched_at, overall_score (0–100), overall_grade, top_5_fixes (Finding[]), and a parts breakdown with individual audit_page, check_robots, check_sitemap, and audit_schema results — each may be a full result or { error: string } when that sub-audit fails. When to use: quick 'how does this site look overall?' — use when you want a single consolidated score and actionable fix list without calling 4 tools individually. Distinct from audit_sitemap (samples N pages from the sitemap, not just the homepage) and audit_page (single-URL deep dive with all findings, not just top-5).
Input schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 3,
      "description": "Hostname or origin to audit. Examples: `example.com`, `https://example.com`. The tool resolves the homepage and runs audit_page + check_robots + check_sitemap + audit_schema in parallel against it, then returns an overall grade plus top-5 fixes. Issues several HTTP GETs against the domain."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt before fetching the homepage. Set false ONLY to audit a site you own that has temporarily blocked crawlers."
    }
  },
  "required": [
    "domain"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string"
    },
    "homepage_url": {
      "type": "string"
    },
    "fetched_at": {
      "type": "string"
    },
    "overall_score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    },
    "overall_grade": {
      "type": "string",
      "enum": [
        "A",
        "B",
        "C",
        "D",
        "F"
      ],
      "description": "Letter grade derived from the numeric score."
    },
    "top_5_fixes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      },
      "description": "Up to five highest-impact findings across all sub-audits."
    },
    "parts": {
      "type": "object",
      "properties": {
        "audit_page": {
          "type": "object",
          "additionalProperties": {},
          "description": "Result of the homepage audit (or { error } on failure)."
        },
        "check_robots": {
          "type": "object",
          "additionalProperties": {}
        },
        "check_sitemap": {
          "type": "object",
          "additionalProperties": {}
        },
        "audit_schema": {
          "type": "object",
          "additionalProperties": {}
        }
      },
      "required": [
        "audit_page",
        "check_robots",
        "check_sitemap",
        "audit_schema"
      ],
      "additionalProperties": false,
      "description": "Raw sub-audit results, for callers who want to drill in."
    }
  },
  "required": [
    "domain",
    "homepage_url",
    "fetched_at",
    "overall_score",
    "overall_grade",
    "top_5_fixes",
    "parts"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Audit site (homepage + robots + sitemap + schema)",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
audit_sitemapSite-wide content audit: discovers the sitemap, samples N URLs by deterministic uniform stride, runs audit_page on each, and returns score distribution + worst pages + most-common findings. Read-only. One HTTP GET for sitemap discovery, optionally a few more for sitemap-index children, then `sample_size` × audit_page calls (each one HTTP GET + parsing). Polite throttling is enforced per host. Deterministic — same domain + same sample_size returns the same set of URLs (uniform-stride sampling). Per-page scoring is rule-based; no LLM. When to use: portfolio-level health check across a site ("how does our content score on average?"). Distinct from `audit_site` (homepage-only composite) and `check_sitemap` (validates sitemap.xml structure, not page content).
Input schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 3,
      "description": "Hostname or origin to audit. Examples: `example.com`, `https://example.com`. The tool discovers the sitemap, samples N URLs by uniform stride, and runs audit_page on each."
    },
    "sample_size": {
      "type": "integer",
      "minimum": 1,
      "maximum": 50,
      "default": 10,
      "description": "Number of URLs to sample from the sitemap. Default 10. Max 50 (sampling caps to avoid runaway audits — each sample is one full audit_page call, ~1-3s with polite throttling). Sampling is deterministic uniform-stride: if the sitemap has 1000 URLs and sample_size=10, every 100th URL is picked."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt for each sampled URL. Set false only for self-audits where you've intentionally blocked crawlers."
    },
    "concurrency": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5,
      "default": 2,
      "description": "Parallel audit_page calls. Default 2 (gentle). Max 5. The shared politeFetch host-delay is still enforced, so this is per-batch dispatch concurrency, not bypass."
    }
  },
  "required": [
    "domain"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "description": "The domain audited."
    },
    "sitemap_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "Resolved sitemap URL (null when discovery failed)."
    },
    "total_urls_in_sitemap": {
      "type": "number",
      "description": "Total URLs declared across the sitemap and any indexed children."
    },
    "urls_sampled": {
      "type": "number",
      "description": "Number of URLs picked via uniform-stride sampling."
    },
    "sampling": {
      "type": "string",
      "const": "uniform_stride",
      "description": "Sampling strategy. Deterministic uniform stride: every Nth URL is picked."
    },
    "audited": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "score": {
            "type": "number"
          },
          "grade": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D",
              "F"
            ],
            "description": "Letter grade derived from the numeric score."
          },
          "top_issue": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "score",
          "grade",
          "top_issue"
        ],
        "additionalProperties": false
      },
      "description": "Per-page audit results that completed successfully."
    },
    "failed": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "url",
          "error"
        ],
        "additionalProperties": false
      },
      "description": "URLs whose audit failed, with the error message."
    },
    "score_distribution": {
      "type": "object",
      "properties": {
        "avg": {
          "type": "number"
        },
        "median": {
          "type": "number"
        },
        "min": {
          "type": "number"
        },
        "max": {
          "type": "number"
        },
        "p25": {
          "type": "number"
        },
        "p75": {
          "type": "number"
        }
      },
      "required": [
        "avg",
        "median",
        "min",
        "max",
        "p25",
        "p75"
      ],
      "additionalProperties": false,
      "description": "Summary statistics across the audited sample."
    },
    "grade_distribution": {
      "type": "object",
      "properties": {
        "A": {
          "type": "number"
        },
        "B": {
          "type": "number"
        },
        "C": {
          "type": "number"
        },
        "D": {
          "type": "number"
        },
        "F": {
          "type": "number"
        }
      },
      "required": [
        "A",
        "B",
        "C",
        "D",
        "F"
      ],
      "additionalProperties": false,
      "description": "Count of pages per letter grade."
    },
    "worst_pages": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "score": {
            "type": "number"
          },
          "grade": {
            "$ref": "#/properties/audited/items/properties/grade"
          },
          "top_issue": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "score",
          "grade",
          "top_issue"
        ],
        "additionalProperties": false
      },
      "description": "Lowest-scoring pages from the sample, worst first."
    },
    "top_findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ]
          },
          "count": {
            "type": "number",
            "description": "How many pages in the sample had this finding."
          },
          "fix": {
            "type": "string"
          }
        },
        "required": [
          "message",
          "category",
          "severity",
          "count",
          "fix"
        ],
        "additionalProperties": false
      },
      "description": "Most-common findings across all sampled pages, sorted by occurrence count desc."
    },
    "fetched_at": {
      "type": "string",
      "description": "UTC ISO-8601 timestamp of the audit."
    }
  },
  "required": [
    "domain",
    "sitemap_url",
    "total_urls_in_sitemap",
    "urls_sampled",
    "sampling",
    "audited",
    "failed",
    "score_distribution",
    "grade_distribution",
    "worst_pages",
    "top_findings",
    "fetched_at"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Audit a site's content by sampling its sitemap",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
check_robotsFetch and parse a domain's robots.txt; report per-crawler allow/disallow posture for every known AI training crawler (GPTBot, CCBot, Anthropic-AI, Google-Extended, etc.), AI search crawlers (ChatGPT-User, PerplexityBot, OAI-SearchBot), and user-triggered fetchers. Read-only. One HTTP GET to /robots.txt. No auth, no rate limits applied. Deterministic, rule-based; no LLM. Returns structured findings with per-crawler status. When to use: figuring out which AI crawlers a site blocks vs allows. Combine with `check_sitemap` for a full pre-crawl audit. Distinct from `audit_page` which evaluates a single URL; this evaluates a whole-domain policy.
Input schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 3,
      "description": "Hostname or origin to inspect. Examples: `example.com`, `https://example.com`, `https://example.com/`. The tool fetches `https://<domain>/robots.txt` and reports per-crawler allow/disallow posture for all known AI training crawlers (GPTBot, CCBot, etc.), AI search crawlers (ChatGPT-User, PerplexityBot), and user-triggered fetchers. Read-only HTTP GET to /robots.txt only."
    }
  },
  "required": [
    "domain"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "robots_url": {
      "type": "string",
      "description": "The robots.txt URL that was fetched."
    },
    "fetched_at": {
      "type": "string",
      "description": "UTC ISO-8601 timestamp of the fetch."
    },
    "training_crawlers": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "allowed": {
            "type": "boolean",
            "description": "Whether this crawler is allowed to fetch the site root."
          },
          "match_source": {
            "type": "string",
            "description": "The robots.txt rule line that produced this verdict, if any."
          }
        },
        "required": [
          "allowed"
        ],
        "additionalProperties": false
      },
      "description": "Allow/disallow posture per known AI training crawler (GPTBot, ClaudeBot, CCBot, etc.)."
    },
    "search_crawlers": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/properties/training_crawlers/additionalProperties"
      },
      "description": "Allow/disallow posture per known AI search crawler (OAI-SearchBot, PerplexityBot, etc.)."
    },
    "user_triggered": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/properties/training_crawlers/additionalProperties"
      },
      "description": "Allow/disallow posture per user-triggered fetcher (ChatGPT-User, Claude-User, etc.)."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      },
      "description": "Per-crawler findings explaining why the posture matters."
    },
    "recommended_posture": {
      "type": "string",
      "enum": [
        "block_training_allow_search",
        "allow_all",
        "block_all",
        "custom"
      ],
      "description": "Suggested posture given the current rules."
    }
  },
  "required": [
    "robots_url",
    "fetched_at",
    "training_crawlers",
    "search_crawlers",
    "user_triggered",
    "findings",
    "recommended_posture"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Check robots.txt crawler posture",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
check_sitemapValidate a domain's XML sitemap: presence, accessibility, URL count, lastmod freshness, sitemap-index handling, and image/video sitemap extensions. Read-only. Issues N+1 HTTP GETs: one for robots.txt + sitemap, then up to `max_urls_to_check` HEADs against sampled URLs. Deterministic, rule-based; no LLM. When to use: site-wide indexing audits. Pair with `check_robots` for a full pre-crawl picture. For per-page checks, use `audit_page` or `check_technical` instead.
Input schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 3,
      "description": "Hostname or origin to inspect. Examples: `example.com`, `https://example.com`. The tool tries `/sitemap.xml` then the sitemap URL declared in robots.txt; follows sitemap index files one level deep. Read-only HTTP GETs against the domain only."
    },
    "max_urls_to_check": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "default": 100,
      "description": "Cap on how many URLs from the sitemap to sample for lastmod, image/video extension, and structural checks. Default 100. Increase up to 500 for large sites where you want a more representative sample; each extra URL is one HTTP HEAD."
    }
  },
  "required": [
    "domain"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "description": "The hostname the sitemap was checked for."
    },
    "fetched_at": {
      "type": "string",
      "description": "UTC ISO-8601 timestamp of the check."
    },
    "status": {
      "type": "string",
      "enum": [
        "found",
        "missing",
        "error"
      ],
      "description": "Outcome of the sitemap lookup."
    },
    "sitemap_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "Resolved sitemap URL (null when status != found)."
    },
    "total_urls": {
      "type": "number",
      "description": "Total URLs declared across the sitemap (and indexed children)."
    },
    "urls_with_lastmod": {
      "type": "number",
      "description": "Count of URLs that carry a lastmod attribute."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "domain",
    "fetched_at",
    "status",
    "sitemap_url",
    "total_urls",
    "urls_with_lastmod",
    "findings"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Check XML sitemap health",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
check_technicalAudit a page's HEAD section for technical signals relevant to AI crawlers: HTTPS, canonical, OpenGraph, Twitter Card, hreflang, noindex, and title-vs-H1 hygiene. Read-only. One HTTP GET, inspects HEAD only (body is not parsed). Deterministic, rule-based; no LLM. When to use: when you specifically need HEAD-tag audit findings. For the full page including schema and AI-Overview scoring, use `audit_page`. For canonical-only, use `audit_canonical`.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to audit. The tool fetches the URL once and inspects HEAD-section signals: HTTPS, canonical, OpenGraph, Twitter Card, hreflang, noindex, title length and overlap with H1. Body content is not parsed. Read-only HTTP GET."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt before fetching. Set false only for auditing your own site where you've intentionally blocked crawlers."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "fetched_at": {
      "type": "string"
    },
    "https": {
      "type": "boolean",
      "description": "Whether the URL is served over HTTPS after redirects."
    },
    "canonical": {
      "type": [
        "string",
        "null"
      ],
      "description": "Canonical link href, if present."
    },
    "og_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "OpenGraph og:url, if present."
    },
    "noindex": {
      "type": "boolean",
      "description": "Whether meta robots includes noindex."
    },
    "title": {
      "type": [
        "string",
        "null"
      ],
      "description": "Page title text."
    },
    "h1": {
      "type": [
        "string",
        "null"
      ],
      "description": "First H1 text."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "url",
    "fetched_at",
    "https",
    "canonical",
    "og_url",
    "noindex",
    "title",
    "h1",
    "findings"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Check technical HEAD signals",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
diff_pagesCompare two URLs for AI citation-worthiness and return a structured breakdown of which page is more likely to be cited and why. Typical use: your page (url_a) vs a competitor's page (url_b). Read-only. Runs audit_page on both URLs in parallel (2 HTTP fetches per URL), then diffs dimension_scores and findings. No new fetch logic beyond what audit_page already does. Deterministic, rule-based; no LLM calls. Same two URLs return the same comparison on repeated runs. When to use: competitive gap analysis - understand exactly which dimensions (schema, structure, robots, entity density, freshness, technical, authority, sitemap) put a competitor ahead, and get prioritized fix_recommendations_for_a to close the gap. For a single-URL audit, use audit_page. For overall scoring of one page, use score_citation_worthiness. Capped at 2 URLs per call. Heuristic verdict - does not claim to know what AI assistants actually cite; verdict matches audit_page's existing rubric.
Input schema
{
  "type": "object",
  "properties": {
    "url_a": {
      "type": "string",
      "format": "uri",
      "description": "First URL to compare - typically your own page. Must be a fully-qualified http(s) URL that returns HTTP 200 (redirects are followed)."
    },
    "url_b": {
      "type": "string",
      "format": "uri",
      "description": "Second URL to compare - typically a competitor's page. Must be a fully-qualified http(s) URL that returns HTTP 200 (redirects are followed)."
    },
    "query": {
      "type": "string",
      "description": "Optional target search query both pages are competing for (e.g. 'how to connect Zapier to Notion'). When provided, it is surfaced in fix_recommendations_for_a as context. Does not alter the scoring algorithm - scoring is based on audit_page's existing rubric."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt before fetching each URL. Set false only when auditing your own sites where you have intentionally blocked crawlers."
    }
  },
  "required": [
    "url_a",
    "url_b"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "url_a": {
      "type": "string"
    },
    "url_b": {
      "type": "string"
    },
    "query": {
      "type": [
        "string",
        "null"
      ]
    },
    "better_for_citation": {
      "type": "string",
      "enum": [
        "a",
        "b",
        "tie"
      ]
    },
    "scores": {
      "type": "object",
      "properties": {
        "a": {
          "type": "number"
        },
        "b": {
          "type": "number"
        }
      },
      "required": [
        "a",
        "b"
      ],
      "additionalProperties": false
    },
    "delta": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "a": {
            "type": "number"
          },
          "b": {
            "type": "number"
          },
          "advantage": {
            "type": "string",
            "enum": [
              "a",
              "b",
              "tie"
            ]
          }
        },
        "required": [
          "a",
          "b",
          "advantage"
        ],
        "additionalProperties": false
      }
    },
    "missing_in_a": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "missing_in_b": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "fix_recommendations_for_a": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "category": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "fix": {
            "type": "string"
          }
        },
        "required": [
          "category",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "url_a",
    "url_b",
    "query",
    "better_for_citation",
    "scores",
    "delta",
    "missing_in_a",
    "missing_in_b",
    "fix_recommendations_for_a"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Diff two pages for citation-worthiness",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
extract_entitiesExtract named entities, linked concepts, and sameAs graph nodes from a page's content and structured data. Combines body-text NER with JSON-LD `@type` / `sameAs` walking. Read-only when given `url` (one HTTP GET). Zero network when given `text`. Primary path: MCP sampling - the host LLM does the NER and returns typed entities with sameAs URIs. Fallback path: deterministic regex-based extractor when sampling is unavailable. The result includes `mode: "sampling" | "regex_fallback"` so callers can tell which path ran. When to use: building an entity map for schema generation, or auditing whether a page's entities match its target topic. To validate the JSON-LD itself, use `audit_schema`. Either `url` or `text` must be provided.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to fetch and analyze. Either this OR `text` is required."
    },
    "text": {
      "type": "string",
      "description": "Raw text/HTML to analyze directly. Either this OR `url` is required."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt when fetching `url`. Ignored when `text` is used."
    },
    "render": {
      "type": "string",
      "enum": [
        "static",
        "headless"
      ],
      "default": "static",
      "description": "Rendering mode for `url`. `static` (default) reads raw HTML. `headless` runs Playwright Chromium to capture JS-rendered content (adds 3-10s; requires `playwright-core` + `npx playwright install chromium`). Ignored when `text` is used."
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "url",
        "text"
      ]
    },
    "url": {
      "type": [
        "string",
        "null"
      ]
    },
    "entity_count": {
      "type": "number"
    },
    "entities": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "confidence": {
            "type": "number"
          },
          "same_as": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      }
    },
    "citation_density_score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    }
  },
  "required": [
    "source",
    "url",
    "entity_count",
    "entities",
    "citation_density_score"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Extract named entities and sameAs links",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": true
}
llms_txt_generateGenerate a spec-compliant llms.txt (and optionally llms-full.txt) for a domain by reading its sitemap, sampling up to `max_pages` pages, and synthesizing a grouped, sectioned summary. Read-only. Issues one HTTP GET for the sitemap then one per sampled page. Deterministic; no LLM. Output is the file content as a string - this tool does NOT write to disk or upload anywhere. The caller is responsible for hosting the resulting file at `https://<domain>/llms.txt`. When to use: bootstrapping llms.txt for a site you own. To check an existing llms.txt, use `llms_txt_validate` instead.
Input schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 3,
      "description": "Hostname or origin to generate llms.txt for. Examples: `example.com`, `https://example.com`. The tool reads the domain's sitemap, fetches up to `max_pages` of them, and synthesizes a spec-compliant llms.txt grouped by section. Issues N+1 HTTP GETs: one for the sitemap, then one per sampled page. Read-only."
    },
    "max_pages": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 30,
      "description": "How many pages to sample from the sitemap when building section groupings. Default 30. Each page is fetched (one HTTP GET per page) - keep this low for large sites or rate-limited hosts."
    },
    "include_full": {
      "type": "boolean",
      "default": false,
      "description": "If true, also generate llms-full.txt (the expanded variant containing full page text, not just URLs and titles). Default false. The llms-full.txt output can be large; only enable when you actually plan to host both files."
    },
    "site_name": {
      "type": "string",
      "description": "Override the site name used in the generated llms.txt header. If omitted, inferred from the homepage's <title> tag."
    },
    "site_description": {
      "type": "string",
      "description": "Override the site description used in the generated llms.txt header. If omitted, inferred from the homepage's meta description."
    }
  },
  "required": [
    "domain"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string"
    },
    "llms_txt": {
      "type": "string",
      "description": "The generated llms.txt file content. Caller is responsible for hosting it."
    },
    "llms_full_txt": {
      "type": [
        "string",
        "null"
      ],
      "description": "The generated llms-full.txt content. Null unless include_full=true."
    },
    "pages_indexed": {
      "type": "number",
      "description": "Number of pages successfully sampled from the sitemap."
    }
  },
  "required": [
    "domain",
    "llms_txt",
    "pages_indexed"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Generate llms.txt",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
llms_txt_validateValidate an existing llms.txt or llms-full.txt against the spec: structure, section ordering, link format, and (optionally) broken-link detection. Read-only. One HTTP GET when given `url`; zero network when given `content`. Optional link-check issues HEAD requests against each link if `check_links` is true. Deterministic; no LLM. When to use: auditing an llms.txt you already have. To generate one from scratch, use `llms_txt_generate`. Either `url` or `content` must be provided.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL of an existing llms.txt or llms-full.txt to validate (e.g. `https://example.com/llms.txt`). Either this OR `content` is required."
    },
    "content": {
      "type": "string",
      "description": "Raw llms.txt content as a string. Use this to validate a file offline without fetching. Either this OR `url` is required."
    },
    "check_links": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), HEAD each linked URL to detect broken links. Set false to skip link checks for faster, network-light validation of just the structural rules."
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "url",
        "content"
      ]
    },
    "url": {
      "type": [
        "string",
        "null"
      ]
    },
    "valid": {
      "type": "boolean",
      "description": "Whether the file passes structural and link rules."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "source",
    "url",
    "valid",
    "findings"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Validate llms.txt",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
pricing_generateGenerate a machine-readable /pricing.md for AI shopping/agent flows. Finds the site's pricing page (or uses `pricing_url`), extracts named tiers and price lines, and returns the file content as a string. Read-only. Issues a few HTTP GETs probing common pricing paths. Deterministic; no LLM. Does NOT write or upload — the caller hosts the file at `https://<domain>/pricing.md`. When to use: a SaaS/e-commerce site that wants agents to read pricing without parsing a JS-rendered table. Falls back to a fill-in template when no prices are detectable.
Input schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 3,
      "description": "Hostname or origin to generate pricing.md for, e.g. `example.com`. The tool finds the pricing page (or uses `pricing_url`), extracts tiers and prices, and returns a machine-readable pricing.md string. Read-only."
    },
    "pricing_url": {
      "type": "string",
      "format": "uri",
      "description": "Explicit pricing page URL. If omitted, the tool probes common paths (/pricing, /plans, /pricing/)."
    }
  },
  "required": [
    "domain"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string"
    },
    "pricing_md": {
      "type": "string",
      "description": "The generated pricing.md content. Caller hosts it at /pricing.md."
    },
    "source_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "The pricing page the content was derived from (null when none was found)."
    },
    "tiers_detected": {
      "type": "number",
      "description": "Number of pricing tiers extracted."
    },
    "validation_issues": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      },
      "description": "Issues encountered while deriving the file."
    },
    "suggested_path": {
      "type": "string",
      "const": "/pricing.md"
    }
  },
  "required": [
    "domain",
    "pricing_md",
    "source_url",
    "tiers_detected",
    "validation_issues",
    "suggested_path"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Generate pricing.md",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
report_saveRender an audit_page or audit_site result as a Markdown report and write it to a file under MCP_WORKSPACE_ROOT (defaults to cwd).
Input schema
{
  "type": "object",
  "properties": {
    "audit_result": {
      "description": "The return value of `audit_page` or `audit_site`. Pass the structured result verbatim - the tool detects which shape it is and renders the matching Markdown report."
    },
    "path": {
      "type": "string",
      "minLength": 1,
      "description": "Target file path. May be relative to MCP_WORKSPACE_ROOT (or cwd if unset). Paths that escape the workspace root are rejected."
    },
    "overwrite": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), overwrite an existing file. If false, the write fails when the target already exists."
    }
  },
  "required": [
    "path"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "saved_to": {
      "type": "string",
      "description": "Absolute path of the file that was written."
    },
    "bytes_written": {
      "type": "number"
    },
    "format": {
      "type": "string",
      "enum": [
        "audit_page",
        "audit_site"
      ],
      "description": "Which input shape the report was rendered for."
    }
  },
  "required": [
    "saved_to",
    "bytes_written",
    "format"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Save audit report to disk",
  "readOnlyHint": false,
  "destructiveHint": true,
  "idempotentHint": true,
  "openWorldHint": false
}
rewrite_aeoRewrite a content block for Answer Engine Optimization. Adds a BLUF opening, FAQ structure, schema additions, and concise question-shaped headings tuned for ChatGPT / Perplexity / Google AI Overviews. Read-only when given `url` (one HTTP GET). Zero network when given `text`. The tool does NOT write back to the URL - it only returns the rewritten content as a string. No side effects on the source. This tool delegates the actual rewrite to the calling LLM via MCP sampling - it does not call any external API itself. The MCP host's model produces the rewrite. Same input may produce different output across runs (model-dependent). When to use: optimizing content for direct-answer surfaces (definitions, how-tos, FAQs). For Generative Engine Optimization (entity-rich, comparison-ready synthesis), use `rewrite_geo` instead. Either `url` or `text` must be provided. `target_query` is required.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL whose content should be fetched and rewritten. Either this OR `text` is required."
    },
    "text": {
      "type": "string",
      "description": "Raw content (markdown or HTML) to rewrite directly. Either this OR `url` is required."
    },
    "target_query": {
      "type": "string",
      "description": "The user query the rewrite should answer (e.g. `what is RAG`, `how to deploy Ghost to Docker`). Required - drives heading shape and BLUF wording."
    },
    "format": {
      "type": "string",
      "enum": [
        "article",
        "faq",
        "howto",
        "comparison"
      ],
      "default": "article",
      "description": "Output shape. `article` for prose-with-headings. `faq` for Q&A list. `howto` for numbered-step procedural content with HowTo schema hints. `comparison` for X-vs-Y tables. Default `article`."
    },
    "max_words": {
      "type": "integer",
      "minimum": 100,
      "maximum": 5000,
      "default": 1500,
      "description": "Soft word budget for the rewrite. Default 1500. Range 100-5000. The rewrite tries to stay under this; very small budgets may force truncation."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt when fetching `url`. Ignored when `text` is used."
    }
  },
  "required": [
    "target_query"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "url",
        "text"
      ]
    },
    "url": {
      "type": [
        "string",
        "null"
      ]
    },
    "target_query": {
      "type": "string"
    },
    "format": {
      "type": "string",
      "description": "Output format (article, faq, howto, comparison)."
    },
    "rewritten": {
      "type": "string",
      "description": "The rewritten content. The caller decides where to publish it."
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Notes from the rewrite (e.g. truncations, format adjustments)."
    }
  },
  "required": [
    "source",
    "url",
    "target_query",
    "rewritten",
    "notes"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Rewrite for Answer Engine Optimization",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": true
}
rewrite_geoRewrite a content block for Generative Engine Optimization: entity-rich, comparison-ready, synthesis-friendly. Tuned for surfaces that summarize across sources (Perplexity, Google AI Mode, Claude search). Read-only on input. Does NOT write back to the source URL - returns the rewritten content as a string. This tool delegates the actual rewrite to the calling LLM via MCP sampling - it does not call any external API itself. The MCP host's model produces the rewrite. Output may vary across runs (model-dependent). When to use: optimizing for synthesis-style answers across multiple sources. For direct-answer (BLUF + FAQ) optimization on a single page, use `rewrite_aeo` instead. Either `url` or `text` must be provided. `target_query` is required.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL whose content should be fetched and rewritten. Either this OR `text` is required."
    },
    "text": {
      "type": "string",
      "description": "Raw content to rewrite directly. Either this OR `url` is required."
    },
    "target_query": {
      "type": "string",
      "description": "The user query the rewrite should answer. Required - drives entity selection and comparison framing."
    },
    "add_comparison_table": {
      "type": "boolean",
      "default": false,
      "description": "If true, inject an explicit X-vs-Y comparison table into the rewrite (useful for `X vs Y` queries). Default false."
    },
    "max_words": {
      "type": "integer",
      "minimum": 100,
      "maximum": 5000,
      "default": 1500,
      "description": "Soft word budget. Default 1500. Range 100-5000."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt when fetching `url`. Ignored when `text` is used."
    }
  },
  "required": [
    "target_query"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "url",
        "text"
      ]
    },
    "url": {
      "type": [
        "string",
        "null"
      ]
    },
    "target_query": {
      "type": "string"
    },
    "format": {
      "type": "string",
      "description": "Output format (article, faq, howto, comparison)."
    },
    "rewritten": {
      "type": "string",
      "description": "The rewritten content. The caller decides where to publish it."
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Notes from the rewrite (e.g. truncations, format adjustments)."
    }
  },
  "required": [
    "source",
    "url",
    "target_query",
    "rewritten",
    "notes"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Rewrite for Generative Engine Optimization",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": true
}
score_agentic_browsingScore a page against the four signals Google added to the Lighthouse "Agentic Browsing" category in May 2026: presence of an llms.txt, WebMCP integration, accessibility-tree integrity, and layout stability. Returns an overall 0-100 score, a letter grade, and a per-factor breakdown. Read-only. One HTTP GET for the page plus one for /llms.txt (skip with check_llms_txt=false). Pass `html` instead of `url` to score markup offline (llms.txt is then treated as absent). Deterministic, rule-based heuristics over the fetched HTML; no LLM and no headless render required. This approximates Lighthouse's runtime signals from static markup - it does not execute Lighthouse. When to use: checking whether a site is ready for AI agents / agentic browsers, or tracking the new Lighthouse Agentic Browsing category. For citation-eligibility of content, use `score_citation_worthiness`; for a full page audit, use `audit_page`.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to fetch and score. Either this OR `html` is required."
    },
    "html": {
      "type": "string",
      "description": "Raw HTML to score offline without fetching. Either this OR `url` is required. llms.txt is treated as absent in this mode."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt when fetching `url`. Ignored when `html` is used."
    },
    "render": {
      "type": "string",
      "enum": [
        "static",
        "headless"
      ],
      "default": "static",
      "description": "Rendering mode for `url`. `static` (default) reads raw HTML; `headless` runs Playwright Chromium (adds 3-10s; requires `playwright-core`). Ignored when `html` is used."
    },
    "check_llms_txt": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), probe /llms.txt for the host to score the llms.txt factor. Set false to skip that extra HTTP GET."
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": [
        "string",
        "null"
      ],
      "description": "The URL scored (null when scoring raw html)."
    },
    "fetched_at": {
      "type": "string",
      "description": "UTC ISO-8601 timestamp."
    },
    "score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Weighted 0-100 Agentic Browsing score (accessibility 40%, layout 35%, webmcp 15%, llms.txt 10%)."
    },
    "grade": {
      "type": "string",
      "enum": [
        "A",
        "B",
        "C",
        "D",
        "F"
      ],
      "description": "Letter grade derived from the numeric score."
    },
    "factors": {
      "type": "object",
      "properties": {
        "llms_txt": {
          "type": "object",
          "properties": {
            "score": {
              "type": "number",
              "minimum": 0,
              "maximum": 100,
              "description": "0-100 subscore for this signal."
            },
            "detail": {
              "type": "string",
              "description": "One-line description of what was measured."
            }
          },
          "required": [
            "score",
            "detail"
          ],
          "additionalProperties": false
        },
        "webmcp": {
          "$ref": "#/properties/factors/properties/llms_txt"
        },
        "accessibility_tree": {
          "$ref": "#/properties/factors/properties/llms_txt"
        },
        "layout_stability": {
          "$ref": "#/properties/factors/properties/llms_txt"
        }
      },
      "required": [
        "llms_txt",
        "webmcp",
        "accessibility_tree",
        "layout_stability"
      ],
      "additionalProperties": false,
      "description": "The four Lighthouse Agentic Browsing signals, scored 0-100 each."
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "severity": {
            "type": "string",
            "enum": [
              "critical",
              "warning",
              "info"
            ],
            "description": "Triage priority: critical blocks AI citation, warning hurts probability, info is nice-to-have."
          },
          "category": {
            "type": "string",
            "enum": [
              "schema",
              "robots",
              "technical",
              "freshness",
              "structure",
              "authority",
              "presence",
              "sitemap",
              "llms_txt",
              "citation",
              "evidence",
              "trust",
              "entity",
              "content"
            ],
            "description": "Finding category - which AI-SEO dimension it relates to."
          },
          "where": {
            "type": "string",
            "description": "Location of the issue (CSS selector, JSON-LD path, robots.txt line, or 'page-level')."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description of the issue."
          },
          "fix": {
            "type": "string",
            "description": "Concrete, copy-pasteable fix."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact on AI citation probability when resolved."
          },
          "failure_signal": {
            "type": "string",
            "description": "Falsifiability: the observable signal that would prove the fix did NOT work."
          },
          "leading_indicator": {
            "type": "string",
            "description": "Falsifiability: the leading indicator to monitor to confirm the fix is landing."
          }
        },
        "required": [
          "severity",
          "category",
          "where",
          "message",
          "fix"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "url",
    "fetched_at",
    "score",
    "grade",
    "factors",
    "findings"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Score Agentic Browsing readiness",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
score_ai_overview_eligibilityScore a page's probability of appearing in Google AI Overviews. Returns an overall 0-100 score plus six factor subscores: semantic completeness, structured data, E-E-A-T signals, entity density, freshness, and technical hygiene. Read-only. One HTTP GET. Deterministic, rule-based scoring derived from published 2025-2026 AI-Overview correlation studies. No LLM calls. Same URL returns the same score on repeated runs. When to use: AI-Overview-specific prioritization. For a multi-dimensional audit that includes this scoring plus everything else, use `audit_page`. For citation-worthiness of a specific text passage (rather than a URL ranking probability), use `score_citation_worthiness`.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to score. The tool fetches the URL once and runs deterministic, rule-based scoring across six factors (semantic completeness, structured data, E-E-A-T signals, entity density, freshness, technical hygiene) using published 2025-2026 correlation studies. No LLM calls. Read-only HTTP GET."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt before fetching. Set false only for auditing your own site where you've intentionally blocked crawlers."
    }
  },
  "required": [
    "url"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string"
    },
    "fetched_at": {
      "type": "string"
    },
    "overall_eligibility_score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    },
    "factors": {
      "type": "object",
      "properties": {
        "semantic_completeness": {
          "type": "number"
        },
        "structured_data": {
          "type": "number"
        },
        "eeat_signals": {
          "type": "number"
        },
        "entity_density": {
          "type": "number"
        },
        "freshness": {
          "type": "number"
        },
        "technical_hygiene": {
          "type": "number"
        }
      },
      "required": [
        "semantic_completeness",
        "structured_data",
        "eeat_signals",
        "entity_density",
        "freshness",
        "technical_hygiene"
      ],
      "additionalProperties": false,
      "description": "Per-factor 0-100 subscores."
    },
    "top_improvements": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "factor": {
            "type": "string"
          },
          "suggestion": {
            "type": "string"
          }
        },
        "required": [
          "factor",
          "suggestion"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "url",
    "fetched_at",
    "overall_eligibility_score",
    "factors",
    "top_improvements"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Score AI Overview eligibility",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
score_citation_worthinessScore how citable a page or text block is for AI engines (ChatGPT, Claude, Perplexity, Google AI Overviews). Evaluates BLUF (bottom-line-up-front) opening, FAQ patterns, statistic density, entity clarity, and answer-shape fit for the optional `target_query`. Also returns `extractability_score` plus per-section `chunk_analysis`: how cleanly an LLM can lift a self-contained answer from each heading-delimited section (length band, lead-sentence directness, anaphora, concrete anchors). This is the GEO mechanic - it pinpoints the exact sections to tighten, with `most_extractable` / `least_extractable` called out. Read-only when given `url` (one HTTP GET). Zero network when given `text`. No writes. Deterministic, rule-based; no LLM calls. Returns reproducible scores. When to use: pre-publish content QA, or to triage which existing pages are worth optimizing for AI citation first. Distinct from `score_ai_overview_eligibility` which scores Google-AI-Overview ranking probability for a URL; this scores the inherent citability of a text passage regardless of host. Either `url` or `text` must be provided.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to fetch and score. Either this OR `text` is required."
    },
    "text": {
      "type": "string",
      "description": "Raw text/markdown/HTML to score directly without fetching. Either this OR `url` is required."
    },
    "target_query": {
      "type": "string",
      "description": "Optional target search query the content is supposed to answer (e.g. `how to fix CORS errors in Next.js`). When provided, scoring weights answer-shape fit and query-term coverage. Omit if you want a query-agnostic citability score."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt when fetching `url`. Ignored when `text` is used."
    }
  },
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "source": {
      "type": "string",
      "enum": [
        "url",
        "text"
      ]
    },
    "url": {
      "type": [
        "string",
        "null"
      ]
    },
    "target_query": {
      "type": [
        "string",
        "null"
      ]
    },
    "overall_score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    },
    "engine_scores": {
      "type": "object",
      "properties": {
        "perplexity": {
          "type": "number"
        },
        "chatgpt": {
          "type": "number"
        },
        "google_ai_overviews": {
          "type": "number"
        },
        "claude": {
          "type": "number"
        }
      },
      "required": [
        "perplexity",
        "chatgpt",
        "google_ai_overviews",
        "claude"
      ],
      "additionalProperties": false
    },
    "signals": {
      "type": "object",
      "additionalProperties": {
        "type": "number"
      },
      "description": "Per-signal subscores (bluf, faq, stats, entities, etc.)."
    },
    "suggestions": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "extractability_score": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "Length-weighted mean of per-section extractability scores."
    },
    "chunk_analysis": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "heading": {
            "type": "string"
          },
          "level": {
            "type": "number"
          },
          "word_count": {
            "type": "number"
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "issues": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "heading",
          "level",
          "word_count",
          "score",
          "issues"
        ],
        "additionalProperties": false
      },
      "description": "Per-section extractability: how cleanly an LLM can lift a standalone answer from each chunk."
    },
    "most_extractable": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "heading": {
              "type": "string"
            },
            "score": {
              "type": "number"
            }
          },
          "required": [
            "heading",
            "score"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    },
    "least_extractable": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "heading": {
              "type": "string"
            },
            "score": {
              "type": "number"
            }
          },
          "required": [
            "heading",
            "score"
          ],
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "source",
    "url",
    "target_query",
    "overall_score",
    "engine_scores",
    "signals",
    "suggestions"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Score AI citation worthiness",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": true
}
score_test_citationSimulate `would an AI engine cite this page for this query?`. The host LLM role-plays the chosen engine (chatgpt / claude / perplexity / google_ai_overviews / any), reads the page content, and returns a cite/no-cite verdict with the verbatim excerpt it would surface plus ranked improvements. Read-only when given `url` (one HTTP GET). Zero network when given `text`. Primary path uses MCP sampling. If the host doesn't support sampling, falls back to a deterministic heuristic derived from `score_citation_worthiness` (overall_score + per-engine subscore must both clear thresholds). The result includes `mode: "sampling" | "static_heuristic"` so callers can tell which path ran. When to use: pre-publish gut-check for a specific query, or auditing whether existing content earns citation surface. Distinct from `score_citation_worthiness` (deterministic 0-100 score) and `audit_page` (whole-page rubric); this returns a binary cite/no-cite verdict tied to one query. Either `url` or `text` must be provided. `target_query` is required.
Input schema
{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "description": "Public URL to fetch and test. Either this OR `text` is required."
    },
    "text": {
      "type": "string",
      "description": "Raw text/HTML to test directly. Either this OR `url` is required."
    },
    "target_query": {
      "type": "string",
      "minLength": 3,
      "description": "The user query the engine is answering. Required. Example: `how to add JSON-LD to a Next.js app`."
    },
    "engine": {
      "type": "string",
      "enum": [
        "chatgpt",
        "claude",
        "perplexity",
        "google_ai_overviews",
        "any"
      ],
      "default": "any",
      "description": "Which engine to simulate. `any` (default) uses a generic AI-search persona. Specific engines tune the cite criteria (e.g. perplexity favors statistic-dense excerpts; google_ai_overviews favors schema + freshness)."
    },
    "respect_robots": {
      "type": "boolean",
      "default": true,
      "description": "If true (default), respect robots.txt when fetching `url`. Ignored when `text` is used."
    }
  },
  "required": [
    "target_query"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Output schema
{
  "type": "object",
  "properties": {
    "target_query": {
      "type": "string",
      "description": "The query the engine simulation answered."
    },
    "engine": {
      "type": "string",
      "enum": [
        "chatgpt",
        "claude",
        "perplexity",
        "google_ai_overviews",
        "any"
      ],
      "description": "Which engine persona produced the verdict."
    },
    "would_cite": {
      "type": "boolean",
      "description": "Binary verdict: would the simulated engine cite this page for the query?"
    },
    "confidence": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "description": "How likely a real engine is to surface this page (0-100)."
    },
    "citation_excerpt": {
      "type": [
        "string",
        "null"
      ],
      "description": "If would_cite=true, the 20-60 word verbatim excerpt the engine would surface; otherwise null."
    },
    "reasoning": {
      "type": "string",
      "description": "Plain-language explanation of the verdict."
    },
    "blocking_issues": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Concrete reasons the page is (or is not) citable. Empty if would_cite=true and excerpt is clearly attributable."
    },
    "improvements": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "change": {
            "type": "string",
            "description": "Specific edit the author should make."
          },
          "estimated_impact": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Estimated impact of this change on citation probability."
          }
        },
        "required": [
          "change",
          "estimated_impact"
        ],
        "additionalProperties": false
      },
      "description": "Ranked, specific edits to improve citation probability."
    },
    "mode": {
      "type": "string",
      "enum": [
        "sampling",
        "static_heuristic"
      ],
      "description": "Which code path produced the result: MCP sampling (host LLM) or deterministic heuristic fallback."
    }
  },
  "required": [
    "target_query",
    "engine",
    "would_cite",
    "confidence",
    "citation_excerpt",
    "reasoning",
    "blocking_issues",
    "improvements",
    "mode"
  ],
  "additionalProperties": false,
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Annotations
{
  "title": "Test whether an AI engine would cite this page",
  "readOnlyHint": true,
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": true
}

Resources 2

Resource templates 0

Prompts 5

Changes from previous version

Compared with initial baseline using full_baseline.

RiskChangeSubject
No material changes recorded.

Confirmed vulnerabilities

SeverityFindingAdvisory
No confirmed vulnerability is published for this version.

Provenance

Artifact SHA-256: 9c21f28b1308480b844786e2cf193f0e1b85dc3d7a71d896c8face338df67c2c

Scanner: mcp-proof-engine 0.1.0.

Let’s talk about MCP security.

Share your details and our security team will contact you.