Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

SEO & GEO

NPM · SEO-GEO-MCP-SERVER

Audit a page's SEO and its readiness for AI answer engines: meta, schema, robots, sitemaps, AI bots.

Available components

0 this week 93 Trust /100

Last scanned (12 hours ago)

Scores higher than 96% of npm servers

Category Marketing and SEO

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security98
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • 24 of 93 dependencies flagged as unhealthy (1 deprecated). View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to OrtaMarco/seo-geo-mcp-server). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 19 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability66
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 5645 tokens (~332/item across 17 items; 17 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
  • No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • We read all 17 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
  • An AI judge read all 18 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 1 Nov 26 +1
    • Stability: 0.97 → pass security
  • 31 Oct 26 −1
    • Stability: pass → 0.97 functional
  • 25 Oct 26 +1
    • Stability: 0.97 → pass security
  • 24 Oct 26 −1
    • Stability: pass → 0.97 functional
  • 20 Oct 26 0
    • Security disclosure: unverified → fail ▼ functional
  • 19 Oct 26 0
    • Security disclosure: fail → unverified ▼ functional
  • 18 Oct 26 +1
    • Stability: 0.97 → pass security
  • 17 Oct 26 +11
    • Known CVEs: unverified → pass ▲ security
    • Dependency health: unverified → 0.87 ▲ functional
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 5 Nov 2026 · Analysed npm/seo-geo-mcp-server@1.2.2

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem npm
Reason Verified
Discovered via Registry attestation endpoint
Source repo OrtaMarco/seo-geo-mcp-server
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/OrtaMarco/seo-geo-mcp-server/.github/workflows/publish.yml@refs/tags/v1.2.2
Rekor log index 3271041901
Predicate type SLSA build provenance https://slsa.dev/provenance/v1
Subject digest sha512:d4ffd1aeede96015b73969ae9f50d3541dc7a8d0f0a5f0c00b39bea81aabe85a6d1d49d228fc81b118aab924959b77eae6b1590ee9e233de9d4e77b7f

Background: How many MCP packages publish verified provenance →

Dependencies 93 packages
Packages resolved 93
Deprecated 1
Stale 24
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 17 exposed · ~5,257 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
ai_crawler_access ~592

Resolve every known AI/LLM crawler against a site's robots.txt and report which may fetch a given path. Covers OpenAI (GPTBot, OAI-SearchBot, ChatGPT-User, OAI-AdsBot), Anthropic (ClaudeBot, Claude-User, Claude-SearchBot), Google (Google-Extended, Googlebot, Google-CloudVertexBot), Perplexity, Apple, Meta, Amazon, Mistral, Common Crawl, ByteDance and others. Three things this gets right that a naive robots.txt reader does not: 1. **Training vs citation.** Blocking GPTBot stops training; blocking OAI-SearchBot stops you being *cited* in ChatGPT search. Most people want the first, not the second. Blocked citation-critical bots are called out separately. 2. **Which blocks are actually enforceable.** Perplexity-User, ChatGPT-User and meta-externalfetcher are documented by their own vendors as ignoring or possibly ignoring robots.txt. A "blocked" verdict for those is advisory, and is reported as such rather than as a clean block. 3. **Vendor quirks.** Apple documents that when robots.txt has no Applebot group but does have a Googlebot group, Applebot follows the Googlebot rules — so the effective verdict differs from the literal one. Each crawler also carries its provenance: whether the token comes from first-party vendor documentation or only from community aggregators. Vendors that publish no crawler token at all (xAI/Grok, Microsoft Copilot) are listed separately, because absence of a rule cannot be read as allowed or blocked. Args: - site (string): domain or any URL on it. - path (string): path to test (default '/'). - include_deprecated (boolean): include retired tokens (default false). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { crawlers[{token, vendor, purpose, allowed, via_wildcard, matched_rule, respects_robots_txt, compliance_note, provenance, quirk}], allowed_count, blocked_count, blocked_citation_critical[], unenforceable_blocks[], undocumented_vendors[], findings[] }. Example: "Can ChatGPT and…

NameTypeReqDescription
include_deprecatedboolean–Also resolve retired tokens (anthropic-ai, claude-web) for historical coverage.
pathstring–Path to test the rules against, e.g. '/blog/post'. Defaults to '/'.
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
sitestringyesDomain or any URL on it, e.g. 'example.com'.
NameTypeReqDescription
allowed_countnumberyes–
blocked_citation_criticalarrayyes–
blocked_countnumberyes–
crawlersarrayyes–
findingsarrayyes–
pathstringyes–
robots_foundbooleanyes–
undocumented_vendorsarrayyes–
unenforceable_blocksarrayyes–
urlstringyes–

No examples provided.

canonical_host_check ~261

Fetch all four host/scheme variants of a domain — http/https × apex/www — and confirm they converge on a single canonical URL. Divergence is the classic cause of a homepage competing with itself in the index. Also reports whether plain HTTP is upgraded to HTTPS, whether canonicalisation uses permanent (301/308) rather than temporary (302/307) redirects, and which variants do not serve content at all. Args: - site (string): a domain such as 'example.com' (www and scheme are ignored). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { domain, variants[{variant, reachable, status, final_url, hop_count, redirect_statuses[]}], canonical_url, converges, distinct_endpoints[], forces_https, score, grade, findings[] }. Example: "Do all versions of example.com redirect to one URL?" -> canonical_host_check(site="example.com").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
sitestringyesSite domain or any URL on it, e.g. 'example.com'. Only the origin is used.
NameTypeReqDescription
canonical_urlstring|nullyes–
convergesbooleanyes–
distinct_endpointsarrayyes–
domainstringyes–
findingsarrayyes–
forces_httpsbooleanyes–
gradestringyes–
scorenumberyes–
variantsarrayyes–

No examples provided.

content_analysis ~270

Measure the page's main content: word count, sentence and paragraph counts, Flesch reading ease with a plain-language reading level, estimated reading time, text-to-HTML ratio, thin-content detection, and the top non-stopword terms with their density (English and Spanish stopwords are both filtered). Content is read from the <main>/<article> landmark when present, so navigation and footer chrome do not inflate the counts. Args: - url (string): the page to check. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { word_count, sentence_count, paragraph_count, avg_words_per_sentence, reading_ease, reading_level, reading_time_minutes, thin_content, text_to_html_ratio, used_content_landmark, top_terms[{term, count, density}], score, grade, findings[] }. Example: "Is the content on https://example.com/post too thin?" -> content_analysis(url="https://example.com/post").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
avg_words_per_sentencenumberyes–
final_urlstringyes–
findingsarrayyes–
gradestringyes–
html_bytesnumberyes–
paragraph_countnumberyes–
reading_easenumberyes–
reading_levelstringyes–
reading_time_minutesnumberyes–
scorenumberyes–
sentence_countnumberyes–
text_to_html_rationumberyes–
thin_contentbooleanyes–
top_termsarrayyes–
urlstringyes–
used_content_landmarkbooleanyes–
word_countnumberyes–

No examples provided.

geo_audit ~369

Score how readily an AI answer engine (ChatGPT, Claude, Perplexity, Gemini, Copilot) can fetch, parse and cite this page. Weighted across: AI crawler access (25), server-rendered content (20), structured data (15), extractable structure (15), authorship & entity signals (10), freshness (8) and content depth (7). Two things this catches that a classic SEO tool does not: - Pages that rank fine in Google but are invisible to AI assistants, because most AI crawlers do not execute JavaScript and the content only appears after hydration. - robots.txt rules that block AI *search* crawlers (OAI-SearchBot, Claude-SearchBot, PerplexityBot) — the ones that build citation indexes — as opposed to the *training* crawlers people usually mean to block. Args: - url (string): the page to audit. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { geo{score, grade, signals[], top_recommendations[]}, rendering, crawler_access, llms_txt, robots }. Example: "Is https://example.com/guide ready to be cited by ChatGPT?" -> geo_audit(url="https://example.com/guide"). Note: llms.txt presence is reported but deliberately NOT scored — it is a community proposal with no committed vendor support, and Google has stated it does not use it.

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
crawler_access–yes–
geoobjectyes–
llms_txt–yes–
renderingobjectyes–
robots–yes–

No examples provided.

heading_structure ~228

Extract the full h1–h6 outline and evaluate it: how many h1s, whether levels are skipped (h2 followed by h4), empty heading tags, and how many headings are phrased as questions — the last being a strong signal for featured snippets and AI citations. Args: - url (string): the page to check. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { headings[{level, text, skips_level}], h1_count, h1_text[], level_skips, empty_headings, question_headings[], outline, score, grade, findings[] }. Example: "Show me the heading outline of https://example.com/guide" -> heading_structure(url="https://example.com/guide").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
empty_headingsnumberyes–
final_urlstringyes–
findingsarrayyes–
gradestringyes–
h1_countnumberyes–
h1_textarrayyes–
headingsarrayyes–
level_skipsnumberyes–
outlinestringyes–
question_headingsarrayyes–
scorenumberyes–
urlstringyes–

No examples provided.

hreflang_check ~322

Validate a page's `<link rel="alternate" hreflang>` annotations: language/region code validity (BCP-47), the required self-referencing entry, the x-default fallback, and duplicate codes. With check_reciprocity=true it fetches each alternate and confirms it links back to this page — non-reciprocal hreflang is silently ignored by Google, and it is impossible to detect from one page in isolation. Args: - url (string): the page to check. - check_reciprocity (boolean): verify alternates link back (default false). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { declared_lang, entries[{hreflang, href, valid_code, is_self, reciprocates}], has_x_default, self_referencing, duplicate_codes[], invalid_codes[], findings[] }. Example: "Is hreflang set up correctly on https://example.com/es/pagina?" -> hreflang_check(url="https://example.com/es/pagina", check_reciprocity=true).

NameTypeReqDescription
check_reciprocityboolean–Fetch each alternate to confirm it links back. Catches the most common hreflang bug.
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
declared_langstring|nullyes–
duplicate_codesarrayyes–
entriesarrayyes–
final_urlstringyes–
findingsarrayyes–
has_x_defaultbooleanyes–
invalid_codesarrayyes–
reciprocity_checkedbooleanyes–
self_referencingbooleanyes–
urlstringyes–

No examples provided.

image_seo_check ~242

Audit every <img> on the page: missing alt attributes (an accessibility failure and a lost image-search signal), decorative alt="" usage, missing width/height (which causes layout shift, a Core Web Vitals factor), lazy-loading adoption, and how many images use modern formats (WebP/AVIF) versus legacy JPEG/PNG. <picture> sources are counted as modern delivery. Args: - url (string): the page to check. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { total_images, missing_alt, decorative_alt, missing_dimensions, lazy_loaded, modern_format, legacy_format, images[], score, grade, findings[] }. Example: "Which images on https://example.com are missing alt text?" -> image_seo_check(url="https://example.com").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
decorative_altnumberyes–
final_urlstringyes–
findingsarrayyes–
gradestringyes–
imagesarrayyes–
lazy_loadednumberyes–
legacy_formatnumberyes–
missing_altnumberyes–
missing_dimensionsnumberyes–
modern_formatnumberyes–
scorenumberyes–
total_imagesnumberyes–
urlstringyes–

No examples provided.

link_audit ~333

Audit a page's outbound links: the internal/external split, rel attributes (nofollow, sponsored, ugc), links with no anchor text at all, generic anchor text ("click here", "leer más") that carries no topical signal, and the distribution of external domains. Optionally sample-verifies that links actually resolve, retrying with GET when a server rejects HEAD. Args: - url (string): the page to audit. - check_broken (boolean): verify links resolve (default false). - sample_size (number): how many links to verify (default 25). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { total_links, internal_links, external_links, nofollow_links, empty_anchor_text, generic_anchor_text[], external_domains[{domain, count}], checked_count, broken[], score, grade, findings[] }. Example: "Are there broken links on https://example.com/resources?" -> link_audit(url="https://example.com/resources", check_broken=true).

NameTypeReqDescription
check_brokenboolean–Sample links and verify they resolve. Adds up to sample_size requests (default 25), six at a time.
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
sample_sizeinteger–How many links to verify when check_broken is true.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
brokenarrayyes–
checked_countnumberyes–
empty_anchor_textnumberyes–
external_domainsarrayyes–
external_linksnumberyes–
final_urlstringyes–
findingsarrayyes–
generic_anchor_textarrayyes–
gradestringyes–
internal_linksnumberyes–
nofollow_linksnumberyes–
scorenumberyes–
sponsored_linksnumberyes–
total_linksnumberyes–
ugc_linksnumberyes–
urlstringyes–

No examples provided.

llms_txt_check ~373

Check whether a site publishes /llms.txt and validate it against the llmstxt.org proposal: a required H1 title, an optional blockquote summary, and H2-delimited lists of `- [name](url): notes` links. Also detects /llms-full.txt. **Important context this tool always reports:** llms.txt is a community proposal from September 2024, not an adopted standard. No major AI vendor has documented that its crawlers read llms.txt from third-party sites, and Google has publicly stated it does not support it. Publishing one is cheap and may help human readers and some documentation tooling, but it does not earn AI visibility on its own — robots.txt access, structured data and server-rendered content do. Note also that `llms-full.txt` is a de-facto convention popularised by docs tooling, not part of the proposal. Use this tool to answer "do they publish one, and is it well-formed?" — not as evidence that a site is or is not AI-optimised. Args: - site (string): domain or any URL on it. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { found, status, full_variant_found, bytes, title, has_summary_blockquote, sections[], link_count, spec_compliant, adoption_status, findings[] }. Example: "Does example.com publish an llms.txt?" -> llms_txt_check(site="example.com").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
sitestringyesSite domain or any URL on it, e.g. 'example.com'. Only the origin is used.
NameTypeReqDescription
adoption_statusstringyes–
bytesnumberyes–
findingsarrayyes–
foundbooleanyes–
full_variant_foundbooleanyes–
has_optional_sectionbooleanyes–
has_summary_blockquotebooleanyes–
link_countnumberyes–
sectionsarrayyes–
spec_compliantbooleanyes–
statusnumber|nullyes–
titlestring|nullyes–
urlstringyes–

No examples provided.

meta_tags_check ~230

Inspect a page's head tags: title, meta description, canonical, robots directives (meta AND the X-Robots-Tag header), html lang, charset, viewport and favicon. Flags length problems, missing or duplicated tags, and anything that makes the page non-indexable. Args: - url (string): the page to check. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { title, title_length, description, description_length, canonical, canonical_is_self, meta_robots, x_robots_tag, indexable, followable, lang, charset, viewport, score, grade, findings[] }. Example: "Are the meta tags on https://example.com correct?" -> meta_tags_check(url="https://example.com").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
canonicalstring|nullyes–
canonical_is_selfbooleanyes–
charsetstring|nullyes–
descriptionstring|nullyes–
description_lengthnumberyes–
faviconstring|nullyes–
final_urlstringyes–
findingsarrayyes–
followablebooleanyes–
gradestringyes–
indexablebooleanyes–
langstring|nullyes–
meta_robotsstring|nullyes–
robots_directivesarrayyes–
scorenumberyes–
titlestring|nullyes–
title_lengthnumberyes–
urlstringyes–
viewportstring|nullyes–
x_robots_tagstring|nullyes–

No examples provided.

redirect_trace ~221

Follow a URL's redirect chain hop by hop, reporting each status code and target. Flags long chains (which waste crawl budget), redirect loops, temporary 302/307 redirects where a permanent 301/308 belongs, and chains that do not end on HTTPS. Args: - url (string): the starting URL. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { final_url, final_status, hops[{url, status, location}], hop_count, https_upgrade, ends_https, has_loop, has_temporary_redirect, elapsed_ms, findings[] }. Example: "Where does http://example.com/old-page end up?" -> redirect_trace(url="http://example.com/old-page").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
elapsed_msnumberyes–
ends_httpsbooleanyes–
final_statusnumberyes–
final_urlstringyes–
findingsarrayyes–
has_loopbooleanyes–
has_temporary_redirectbooleanyes–
hop_countnumberyes–
hopsarrayyes–
https_upgradebooleanyes–
urlstringyes–

No examples provided.

render_check ~276

Determine whether a page's content exists in the server HTML, or only appears after JavaScript runs. This matters more for AI visibility than for classic SEO: Googlebot renders JavaScript, but GPTBot, ClaudeBot, PerplexityBot and CCBot largely do not. A client-rendered page can rank perfectly well in Google and still be completely invisible to every AI assistant — this tool is how you catch that. Detects unhydrated SPA shells (empty #root / #app / #__next containers), reports how many words survive without JS, and flags documents dominated by inline script bytes. Args: - url (string): the page to check. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { renders_without_js, server_text_words, script_bytes, html_bytes, spa_shell_detected, framework_hint, findings[] }. Example: "Can ChatGPT actually read https://example.com/app?" -> render_check(url="https://example.com/app").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
findingsarrayyes–
framework_hintstring|nullyes–
html_bytesnumberyes–
renders_without_jsbooleanyes–
script_bytesnumberyes–
server_text_wordsnumberyes–
spa_shell_detectedbooleanyes–

No examples provided.

robots_txt_check ~266

Fetch and parse a site's robots.txt per RFC 9309. Reports every user-agent group with its Allow/Disallow rules, the declared sitemaps, and any lines that could not be parsed. Flags the two failures that silently deindex a site: a wildcard `Disallow: /`, and a robots.txt that returns 5xx (which Google treats as "disallow everything"). Args: - site (string): domain or any URL on it, e.g. 'example.com'. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { found, status, group_count, sitemaps[], blocks_everything, groups[{agents[], rules[], crawl_delay}], parse_warnings[], findings[] }. Example: "What does example.com's robots.txt allow?" -> robots_txt_check(site="example.com"). For AI-crawler specifics use `ai_crawler_access` instead — it resolves each known AI bot against these rules.

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
sitestringyesSite domain or any URL on it, e.g. 'example.com'. Only the origin is used.
NameTypeReqDescription
blocks_everythingbooleanyes–
findingsarrayyes–
foundbooleanyes–
group_countnumberyes–
groupsarrayyes–
parse_warningsarrayyes–
sitemapsarrayyes–
statusnumber|nullyes–
urlstringyes–

No examples provided.

seo_audit ~382

Fetch a page once and audit it across seven weighted sections — meta tags & social preview, heading structure, content quality, structured data, image SEO, links and crawlability — returning a 0–100 score, an A–F grade and a prioritised fix list. This is the tool to start with for any "how is this page doing for SEO?" question; drill into the single-purpose tools afterwards for detail. Args: - url (string): the page to audit. - include_geo (boolean): also score AI answer-engine readiness (default false). - check_broken_links (boolean): sample-verify that links resolve (default false). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { score, grade, indexable, sections[{id, label, score, grade, weight, issues[]}], top_recommendations[], geo, findings[] }. Example: "Audit the SEO of https://example.com/pricing" -> seo_audit(url="https://example.com/pricing"). Note: a noindex page or a site-wide robots.txt block caps the score, because nothing else matters until that is fixed. Errors: returns an error if the URL is unreachable, non-HTML, or returns an HTTP error.

NameTypeReqDescription
check_broken_linksboolean–Sample up to 25 links and verify they resolve. Slower, but catches dead links.
include_geoboolean–Also score GEO (AI answer-engine) readiness. Adds ~2 requests.
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
fetch_msnumberyes–
final_urlstringyes–
findingsarrayyes–
geo–yes–
gradestringyes–
indexablebooleanyes–
redirect_hopsnumberyes–
scorenumberyes–
sectionsarrayyes–
statusnumberyes–
top_recommendationsarrayyes–
urlstringyes–

No examples provided.

sitemap_check ~343

Discover, fetch and validate an XML sitemap. Finds it via the robots.txt `Sitemap:` directive, then falls back to /sitemap.xml, /sitemap_index.xml and /sitemap-index.xml. Handles sitemap indexes (following children) and gzipped sitemaps. Validates: URL count against the 50,000 limit, uncompressed size against 50 MiB, <lastmod> presence and W3C-datetime validity, URLs pointing off-origin, http:// URLs, and duplicates. Args: - site (string): domain or any URL on it. - sitemap_url (string, optional): explicit sitemap URL. - follow_children (number): child sitemaps of an index to follow (default 3). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { found, type, url_count, child_sitemaps[], with_lastmod, invalid_lastmod[], newest_lastmod, off_origin_urls[], exceeds_url_limit, discovered_via, score, grade, findings[] }. Example: "Check the sitemap for example.com" -> sitemap_check(site="example.com").

NameTypeReqDescription
follow_childreninteger–How many child sitemaps of an index to follow (default 3).
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
sitestringyesDomain or any URL on it, e.g. 'example.com'.
sitemap_urlstring–Explicit sitemap URL. Omit to discover it via robots.txt, then the conventional paths.
NameTypeReqDescription
bytesnumberyes–
child_sitemapsarrayyes–
child_sitemaps_followednumberyes–
discovered_viastringyes–
duplicate_urlsarrayyes–
entriesarrayyes–
exceeds_size_limitbooleanyes–
exceeds_url_limitbooleanyes–
findingsarrayyes–
foundbooleanyes–
gradestringyes–
invalid_lastmodarrayyes–
newest_lastmodstring|nullyes–
non_https_urlsarrayyes–
off_origin_urlsarrayyes–
oldest_lastmodstring|nullyes–
scorenumberyes–
statusnumber|nullyes–
typestringyes–
urlstringyes–
url_countnumberyes–
with_lastmodnumberyes–

No examples provided.

social_preview_check ~268

Validate the tags that build link-preview cards on X, LinkedIn, Facebook, Slack, WhatsApp and Discord: og:title, og:description, og:image, og:url, og:type, og:site_name and the twitter:* family. Optionally verifies the preview image actually loads, and flags the classic bug of a relative og:image URL (social scrapers require absolute URLs). Args: - url (string): the page to check. - check_image (boolean): verify the og:image resolves (default true). - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { open_graph{}, twitter{}, og_image_url, og_image_reachable, og_image_status, score, grade, findings[] }. Example: "Why does my link preview look broken on LinkedIn?" -> social_preview_check(url="https://example.com/post").

NameTypeReqDescription
check_imageboolean–Issue a HEAD request to confirm the og:image actually loads.
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
final_urlstringyes–
findingsarrayyes–
gradestringyes–
og_image_content_typestring|nullyes–
og_image_reachableboolean|nullyes–
og_image_statusnumber|nullyes–
og_image_urlstring|nullyes–
open_graphobjectyes–
scorenumberyes–
twitterobjectyes–
urlstringyes–

No examples provided.

structured_data_check ~281

Extract and validate JSON-LD, microdata and RDFa. Reports every @type found, flags JSON-LD blocks that fail to parse (those are invisible to search engines), and checks recognised types against Google's rich-result requirements — required properties that are missing, plus recommended ones worth adding. Covers Article/BlogPosting/NewsArticle, Product, FAQPage, HowTo, Recipe, Event, Organization, LocalBusiness, Person, WebSite, BreadcrumbList, VideoObject, JobPosting, Course, Review and AggregateRating. Args: - url (string): the page to check. - response_format ('markdown' | 'json'): output format (default 'markdown'). Returns: { json_ld_blocks, microdata_items, parse_errors[], items[{type, properties[], missing_required[], missing_recommended[], valid}], types_found[], has_organization, has_breadcrumb, score, grade, findings[] }. Example: "Does https://example.com/product have valid Product schema?" -> structured_data_check(url="https://example.com/product").

NameTypeReqDescription
response_formatstring–Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
urlstringyesPage URL to analyse, e.g. 'https://example.com/blog/post'. The scheme defaults to https://.
NameTypeReqDescription
final_urlstringyes–
findingsarrayyes–
gradestringyes–
has_articlebooleanyes–
has_breadcrumbbooleanyes–
has_faqbooleanyes–
has_organizationbooleanyes–
has_personbooleanyes–
has_websitebooleanyes–
itemsarrayyes–
json_ld_blocksnumberyes–
microdata_itemsnumberyes–
parse_errorsarrayyes–
rdfa_itemsnumberyes–
scorenumberyes–
types_foundarrayyes–
urlstringyes–

No examples provided.

Install

How do I install the SEO & GEO MCP server?

SEO & GEO runs locally as an npm package, launched with npx -y seo-geo-mcp-server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · seo-geo-mcp-server

# add to Claude Code
claude mcp add ortamarco-seo-geo-mcp-server -- npx -y seo-geo-mcp-server
Common questions

What is the SEO & GEO MCP server?

SEO & GEO is an MCP server listed in the public MCP registry as io.github.OrtaMarco/seo-geo-mcp-server. Audit a page's SEO and its readiness for AI answer engines: meta, schema, robots, sitemaps, AI bots. This page covers its npm package (seo-geo-mcp-server).

Is the SEO & GEO MCP server safe to use?

SEO & GEO scores 93 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the SEO & GEO MCP server expose?

SEO & GEO exposes 17 tools: seo_audit, geo_audit, ai_crawler_access, llms_txt_check, render_check, and 12 more. Their descriptions and schemas cost roughly 5,257 tokens of context every time the server is loaded.

Is the SEO & GEO MCP server still maintained?

SEO & GEO is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the SEO & GEO MCP server under?

SEO & GEO declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.