seo-monster

MCP serverSearch

SEO MCP over Search Console, GA4, PageSpeed Insights, Cloudflare, IndexNow, CrUX, technical-SEO.

Unavailable. This server has no hosted endpoint yet, so ahel can't serve it.

Connect ahel once, and every AI you use reads what you have installed.

From the project's README

As published by avansaber/seo-monster in README.md.


You don't open a new tool — you just ask, in plain English, inside Claude (or Cursor / Cline / Codex):

You   "What should I write about next?"

🦖 SEOMonster   Pulls your Search Console and surfaces three topics you're almost ranking for — positions 8–20 with real demand — ranked by opportunity. Say the word and it drafts the brief.

You ask …… SEOMonster does
"What should I write about next?"Surfaces near-ranking topics from your own Search Console demand
"Is this page ready to publish?"Runs the technical-SEO + structured-data checks before you ship
"Get this indexed."Nudges Google (Indexing API) and Bing / Yandex (IndexNow)
"Did my change actually move rankings?"Before/after attribution vs a matched control group — with a confidence interval, not a guess
"Is ChatGPT recommending us, or our competitors?"Tracks your brand's share of voice across the AI answer engines

70 tools across Search Console, GA4, PageSpeed, Cloudflare, AI-citation tracking, keyword discovery, and technical SEO — every one returning the same JSON result envelope, every one driven by your own credentials. No new dashboard to learn; you chat with the assistant you already use.

[!NOTE] Published on PyPI as seo-monster (so the command is uvx seo-monster). The import package is seo_mcp; seo-mcp is a dev/local alias. The package ships zero secrets — every credential is resolved at runtime from your own environment or config file.

  • Your data, your machine. User-credential-driven; nothing is sent to any third party.
  • Read-first, safe by default. Reads always work; the two routine writes (sitemap submit, indexing request) are on by default; the Cloudflare write tools (cache purge, redirects, settings, managed robots.txt) are gated behind SEO_MCP_ALLOW_DESTRUCTIVE, and the riskier ones also need a per-call confirm token.
  • Lean. Standard library + the mcp SDK + the Google client libraries; PageSpeed and Cloudflare ride on urllib, no extra HTTP dependency.

Quickstart

[!TIP] Fastest path: the one-click install buttons above. Or add it to any MCP client by hand:

{
  "mcpServers": {
    "seomonster": { "command": "uvx", "args": ["seo-monster"] }
  }
}

Run the one-time Google sign-in once — uvx --from seo-monster seo-monster auth — then ask your assistant to call system_status to confirm what's connected. Full per-client setup and credentials are in Install and Auth.

How it works

flowchart LR
  U["You — plain English"] --> H["Claude · Cursor · Cline · Codex"]
  H -- "MCP · stdio" --> S["SEOMonster<br/>70 tools"]
  S --> GSC["Search Console · GA4"]
  S --> PSI["PageSpeed · CrUX"]
  S --> CF["Cloudflare · IndexNow"]
  S --> AI["AI engines · SERP<br/>(optional)"]
  S -. "your creds · your machine" .-> U

SEOMonster is a stdio MCP server: your AI host launches it, it calls Google / Cloudflare / the AI engines with your credentials, and returns a consistent JSON envelope the assistant reads back to you in plain language.

Requirements

For the .mcpb bundle path (Claude Desktop): just Claude Desktop on macOS or Windows. The bundle declares Python 3.11+ as a runtime; Claude Desktop materializes the environment for you. No prior uv install needed.

For the uvx path (Cursor, Cline, Codex, advanced Claude Desktop): Python 3.11 or newer plus uv (which provides uvx). Find the absolute path to uvx with which uvx; GUI hosts do not read your shell profile, so MCP configs need the full path.

Tools

70 tools, grouped by service. All return the same result envelope (see Result envelope). Call system_status first if unsure what is configured. The server also publishes thirteen named workflow prompts.

Cross-service

  • system_status - which services are configured/reachable, the Google auth method and scopes, whether destructive mode is on, the full tool catalog, and the list of registered prompts.

Google Search Console (18)

Workhorses

  • gsc_list_properties - properties the credentials can see, with permission level and a derived writable flag (true for siteOwner / siteFullUser).
  • gsc_search_analytics - the workhorse: clicks/impressions/CTR/position by dimensions, date range, filters, and data_state.
  • gsc_top_queries / gsc_top_pages - convenience top-N wrappers.
  • gsc_compare_periods - current vs prior window with per-key deltas. v0.2.0 added sort_by, sort_dir, min_delta_clicks / _impressions / _position, anomalies_only + sigma_threshold, and top for one-call movers / losers / outliers reporting.
  • gsc_inspect_url - URL Inspection (index verdict, coverage, canonicals).
  • gsc_batch_inspect_urls - inspect up to 25 URLs, per-URL failures collected.
  • gsc_list_sitemaps - registered sitemaps and their status.
  • gsc_submit_sitemap - submit a sitemap (write, un-gated; needs the writable scope). Accepts either sitemap_url (friendly) or feedpath (raw API field).
  • gsc_request_indexing - request (re)crawl via the Indexing API (write, un-gated). Accepts singular url or urls.

Query intelligence (v0.2.0)

  • gsc_query_opportunities - queries already ranking top N with below-target CTR. Title and meta optimization candidates.
  • gsc_query_gaps - queries that draw impressions but barely any clicks. Content opportunity signal.
  • gsc_new_queries - queries appearing in the current window with no prior impressions. Emerging topics.
  • gsc_top_pages_by_query - which pages rank for a specific query. The cannibalization audit input.

Multi-property + lifecycle (v0.5.0)

  • gsc_portfolio_summary(days, include?, exclude?) - multi-property fleet view. Per-property one-row summary (clicks, impressions, CTR, position) for the last N days, plus a portfolio-level rollup. Honors optional include / exclude filters. The single fastest answer to "how is the whole portfolio doing?" across agency or multi-brand setups.
  • gsc_trending_pages(days, limit) - pages whose impressions grew most over the last N days vs the prior N days. Wrapper on gsc_compare_periods with dimensions=["page"], sort_by="delta_impressions", sort_dir="desc".
  • gsc_decaying_pages(days, limit) - same wrapper, ascending sort. Pages to rescue.
  • gsc_coverage_audit(urls, site_url?) - heuristic coverage audit. The GSC Index Coverage report is not exposed in the API; this tool takes a user- supplied URL list (typically pulled from a sitemap) and bulk-inspects each, then rolls up verdicts (PASS / PARTIAL / FAIL) and coverage_state frequencies.

Content intelligence (4)

  • content_opportunities(site_url?, days?, count?, impressions_min?) - ranks data-grounded content topics from your own Search Console data: fuses CTR-vs-expected gap (curve self-calibrated from your own per-position CTR), striking-distance position, demand, and momentum into a transparent opportunity score; flags cannibalization. If a GA4 property is configured, it also weights each topic by the organic conversions its top page already drives (up to +50%), so topics that convert rank higher; filters_applied.ga4_value_status reports whether that ran and why (applied / no_ga4_property / ga4_unreachable / no_conversions). Prioritizes demand you already have; does not do cold-start keyword research or write the content. Pairs with the content workflow prompts below. (GA4 weighting v0.7.3) v0.9.0 adds an additive per-candidate winnability block (banded: striking-distance + topical- proximity, GSC-personalization tier; existing fields unchanged).
  • content_brief_data(target_query, competitor_urls?, topic?, site_url?, days?) - data-wired backing for a content brief: fetches the competitor pages (or your own GSC-ranking pages as a fallback) and returns the heading union, median word-count floor, schema types, and entity coverage, plus the 2026 GEO writing directives and validation rules. The host writes the prose; SEOMonster brings rules + evidence. Backs the content_brief prompt. (v0.9.0)
  • topic_cluster_map(cluster_path | pillar_url, site_url?, days?, impressions_min?)
    • maps a content cluster from your own GSC data and surfaces missing subtopics. Classifies each cluster query into defend / optimize / create / monitor by demand and best position; the create quadrant is your missing-subtopic list. Flags cannibalization. GSC-only; honest about the ~47% query anonymization. (v0.9.0)
  • rank_change_attribution(url | urls, change_date, query?, site_url?, pre_days?, post_days?, gap_days?, control_scope?)
    • estimates whether an on-site change moved a page's clicks via difference-in-differences against a matched control group (never a naked before/after). Returns an estimated lift with a 95% CI, a three-state verdict (likely_positive / likely_negative / inconclusive), and a confounders block that auto-detects the 2025 GSC data-regime breaks (impression bug, num=100) and downgrades position reliability. Observational, not causal -- a server-side split test is the only true causal test. GSC-only. (v0.9.0)

AI / GEO citation (3, v0.9.0) - whether the AI answer surfaces reach and cite you.

  • ai_citation_readiness(url) - is a page structured to be extracted/cited by LLM answer engines? Leads with a render-blindness check (GPTBot / ClaudeBot / PerplexityBot fetch but do not run JS, so a client-rendered SPA is invisible to them), then scores evidence-backed signals (statistics, quotations, cited sources, no keyword-stuffing). schema.org / FAQ / llms.txt are reported as informational only -- the 2026 evidence does not support them as AI-citation drivers, so they are not scored. Free, HTTP-only.
  • ai_referral_overview(property_id?, site_url?, days?) - first-party AI traffic: GA4 referral sessions from AI apps (the native ai-assistant channel plus a configurable source-host regex) and AI-crawler robots coverage (GPTBot, ClaudeBot, PerplexityBot, ...). Surfaces the ~70% dark-traffic undercount and keeps AI-Overview clicks (counted as Organic) separate. Free.
  • ai_citation_track(prompts, brand, brand_domains?, competitors?, engines?, samples?)
    • sampled brand mention + citation share-of-voice across AI engines (Perplexity / OpenAI / Anthropic / Gemini APIs + Google AI Overviews via DataForSEO) for a managed prompt set, vs competitors. N samples/prompt (default
    1. with a 95% CI, share-of-voice, and run-to-run volatility -- NOT an "AI rank" (single runs are statistically meaningless). Discloses that developer-API output differs from the logged-in consumer UI and that AIO has no API. Paid + non-deterministic. Needs at least one engine key and/or DataForSEO.

Keyword discovery (3, v0.9.0) - find terms you don't already rank for.

  • gsc_keyword_expand(candidates, site_url?, days?, impressions_min?) - you (the host) brainstorm candidate terms from your winning queries; this grounds each against your own Search Console data (footprint covered / thin / none) with a sibling-strength confidence band. "none" = no VISIBLE footprint (GSC hides ~75% of impressions), so net-new terms are scored hypotheses. Free.
  • serp_adjacency_expand(seeds, include_paa?) - expand seed terms into adjacent terms. FREE core: Google Autocomplete (no key). Optional People-Also-Ask + related searches via DataForSEO. Returns per-seed suggestions plus the aggregated net-new terms; degrades gracefully without a key.
  • keyword_universe(target_domain?, competitors?, keywords?, limit?) - optional, paid. Core value: the competitor keyword GAP (DataForSEO Domain Intersection; no Google equivalent). Optional search volume / difficulty / intent via a provider chain (DataForSEO, else Google Ads volume-only). External volume is a degraded directional signal -- a tiebreaker, never a gate.

Google Analytics 4 (7)

  • ga4_run_report - the workhorse: arbitrary dimensions/metrics/date range, optional dimension filter and ordering.
  • ga4_top_landing_pages - top landing pages, organic-only by default.
  • ga4_traffic_by_channel - sessions/engagement/conversions by channel group.
  • ga4_organic_search_overview - organic totals plus a day-by-day trend.
  • ga4_setup_audit(property_id?) - read-only SEO-measurement-readiness audit: web data stream, key events, data retention, content-group dimensions, and (v0.7.4) enhanced measurement, internal site search, and Google Signals. Severity-graded with a benign exception per finding. Uses the GA4 Admin API over REST (analytics.readonly; no extra dependency). (v0.7.0)
  • ga4_site_search(days?, limit?) - internal site-search query report (a direct content-gap signal); honest envelope when no real search terms. (v0.7.1)
  • ga4_landing_page_conversions(days?, organic_only?, limit?) - organic landing pages ranked by conversions. (v0.7.1)

PageSpeed Insights (2)

  • psi_analyze - Lighthouse scores, lab Core Web Vitals, and field (CrUX) Core Web Vitals for a URL. Defaults to the mobile strategy. Field data carries a field_data_note: Google is deprecating PSI field data, so use crux_snapshot / crux_history for durable field metrics.
  • psi_opportunities(url, strategy?) - the actionable Lighthouse "opportunity" audits (with estimated savings) plus the SEO-category audits, severity-graded. Lab data only. An on-page-basics checklist, not a ranking predictor. (v0.7.1)

Cloudflare (13)

  • cf_list_zones - zones the token can see.
  • cf_zone_info - status, plan, name servers for a zone.
  • cf_list_dns - DNS records (read-only); useful for verifying canonical host and TXT verification records during migrations.
  • cf_web_analytics - read-only edge Web Analytics (RUM), to compare against GA4. Cloudflare returns host: null for some sites; pass the site_tag to look those up explicitly.
  • cf_purge_cache - purge specific URLs (gated).
  • cf_purge_cache_all - purge an entire zone (gated + confirm token).
  • cf_settings_audit(zone?) - read-only audit of SEO-relevant Cloudflare zone settings (SSL mode, Always-Use-HTTPS, HSTS, Automatic HTTPS Rewrites, Brotli, cache TTL). Severity-graded with a "verify, not fail" discipline because CF cannot see the origin; HSTS is never a hard failure. Needs Zone Settings Read on the token. Each finding carries a machine-readable fix hint (the exact cf_settings_update setting + recommended value) to chain audit -> fix. (v0.7.1)
  • cf_settings_update(settings, zone?, confirm?, acknowledge_hsts_risk?, dry_run?)
    • write the SEO/crawl/security settings the audit grades (SSL mode, Always-Use- HTTPS, Automatic HTTPS Rewrites, Brotli, browser cache TTL, HSTS), closing the audit -> remediate loop. Gated. ssl_mode or any HSTS-raise needs confirm=<zone> (HSTS-raise also needs acknowledge_hsts_risk=true); validates locally, supports dry_run, and re-runs the audit so you see the finding clear. Needs Zone Settings:Edit (vs the audit's Read). (v0.7.10)
  • cf_list_redirects(zone?) - list a zone's single (dynamic) redirect rules plus the account's Bulk Redirect lists (read-only). Call before any redirect write so nothing is clobbered. (v0.7.8; bulk lists added v0.7.9)
  • cf_create_redirect(source, target, status_code?, ...) - create one edge redirect (e.g. a 301 for a renamed URL). Gated. Pre-flights the target (no redirecting to a dead URL), refuses loops/duplicates, supports dry_run. (v0.7.8)
  • cf_delete_redirect(rule_id, zone?) - remove a single-redirect rule by id (rollback for cf_create_redirect). Gated. (v0.7.8)
  • cf_bulk_redirect_upsert(items, list_name, confirm, ...) - create/append many redirects at once via an account-level Bulk Redirect List (for migrations). Gated + a confirm token equal to list_name. Validates every item locally first and rejects the whole batch on any bad item (never half-applies); supports dry_run. (v0.7.9)
  • cf_managed_robots(action, zone?, ...) - get / configure / disable Cloudflare's managed robots.txt and Content-Signals policy (these ride on the zone's Bot Management config). action="get" reads the current state (read-only, un-gated). action="configure" sets the managed robots.txt (managed_robots), the Content-Signals variant (cf_robots_variant: off / policy_only), and the AI-bot blocking levers (ai_bots_protection, content_bots_protection, crawler_protection). action="disable" turns the managed robots.txt and the policy back off. Managed robots.txt and the Content-Signals policy are mutually exclusive in Cloudflare, so the valid combinations are managed_robots=true + cf_robots_variant="off" (managed robots.txt) OR managed_robots=false + cf_robots_variant="policy_only" (the policy); the tool rejects the invalid combo locally with INVALID_INPUT. A custom Content-Signal line (e.g. from robots_ai_posture) is not a managed option - put that in your origin robots.txt. Writes are gated, need confirm=<zone>, and support dry_run; reads are safe (GET -> overlay -> PUT, so nothing else in the config is clobbered). Every response carries a caveat separating the stated-preference signals (Content-Signals, honored only by adopting crawlers and ignored by Googlebot) from the levers that actually enforce at the edge. Needs Bot Management:Edit for writes (Read for get). (v0.8.2)

IndexNow (2, v0.2.0)

  • indexnow_submit(url) - submit a single URL to Bing, Yandex, Naver, Seznam, Yep. Complements (does not replace) gsc_request_indexing, which only talks to Google. Requires SEO_MCP_INDEXNOW_KEY plus a verification file at https://<your-host>/<key>.txt (see IndexNow setup for the full key + file format + same-host rules).
  • indexnow_bulk_submit(urls) - up to 10,000 URLs sharing one host in a single POST. Mixed-host batches are rejected client-side with INVALID_INPUT before any network call. The SEO_MCP_INDEXNOW_KEY_LOCATION env var overrides the default verification-file URL when your CDN rewrites /key.txt paths.

Technical SEO (8, v0.3.0) - no credentials needed; built-in HTTP client.

  • inspect_meta(url) - on-page surface in one call: title, meta description, meta robots, canonical, Open Graph + Twitter Card tags, hreflang, H1 count.
  • check_canonical(url) - canonical-link audit: self-referential / cross-host / protocol-mismatched / trailing-slash drift / canonical target reachable.
  • mixed_content_check(url) - parses an HTTPS page and flags any http:// references (img / script / iframe / form action / srcset). No-op for http://.
  • redirect_chain_audit(url, max_redirects=10) - walks the chain hop by hop. Flags long chains, protocol downgrades, loops, non-2xx terminus.
  • robots_txt_validate(site_url, probes?) - parses robots.txt (per-group rules + sitemaps + Content-Signals), optionally verdicts (user_agent, url) probes using RFC 9309 longest-match (matches what Google + Bing actually do, not stdlib's first-match). Also detects a stale edge-cached robots.txt (cache-bust comparison; re-parses from the fresh content) and a Cloudflare Managed robots.txt / Content-Signals policy overriding your origin - catching false-clean robots on migrated/CF-fronted sites. (v0.8.0)
  • sitemap_validate(sitemap_url) - validates a sitemap or sitemap-index XML, counts entries, flags oversize + cross-host + missing lastmod. .gz transparent.
  • sitemap_health(sitemap_url, sample_size=25) - sample-HEAD audit. Status histogram + first non-2xx examples.
  • robots_ai_posture(goal?, sitemap_url?) - deterministic, offline advisor for the Content-Signals levers (search / ai-input / ai-train). Takes a business goal (content_authority default / maximize_visibility / protect_ip), recommends a posture with a plain-language rationale, lays out the trade-off alternatives, and emits a ready-to-apply artifact: the Content-Signal: directive line plus a full suggested robots.txt. No network, no writes. Every response carries the mandatory caveat that Content-Signal is honored only by adopting crawlers, is ignored by Googlebot, and is not a ranking factor. (v0.8.1)

Chrome UX Report (2)

  • crux_history(url? | origin?, form_factor?, metrics?) - 25 weeks of p75 Core Web Vitals via the CrUX History API. Reuses PSI_API_KEY; works anonymously at a tighter rate limit when no key is configured.
  • crux_snapshot(url? | origin?, form_factor?) - the current p75 Core Web Vitals (point-in-time, vs the history). Each metric reports a category (GOOD / NEEDS_IMPROVEMENT / POOR); the rolled-up rating is overall_category. Time metrics use p75_ms; the unitless CLS uses p75. Small origins return a no_data envelope. (v0.7.1)

Shortened here. Read the whole README on GitHub.

Signals

GitHub stars
157
Forks
60
Last commit
Sep 2026
Advanced
Delivery
seo-monster MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
Catalog kind
mcp-server
Gateway key
io-github-avansaber-seo-monster
Source
github.com/avansaber/seo-monster