Skip to main content
Glama
SEOMonster

SEOMonster

by avansaber

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 asseo-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.

Local evidence workbench

SEOmonster Workbench is a separately installed local companion for preserving source evidence, inspecting recommendation calculations, drafting action plans and comparing later observations. Its CLI stores project records in SQLite and supports portable exports, backup/restore and deterministic replay. The optional MCP interface exposes 17 tools for one configured project. Plans and recorded approvals remain separate from execution; the workbench has no external executor.

Start with the offline fixture workflow. The CLI needs no provider credentials or paid data. SDK 2 capture requires SEOmonster 0.10.0 or later, the first engine release on MCP SDK 2. The Workbench itself installs from source; it is not published on PyPI.

Related MCP server: gsc-mcp

Quickstart

TIP

Fastest path: theone-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

Provider requests and local records

Selected tools contact Google Search Console, Indexing, GA4 Data/Admin, Google Ads, PageSpeed Insights, CrUX, Cloudflare or IndexNow. Optional research uses DataForSEO, Open PageRank, Perplexity, OpenAI, Anthropic or Gemini. Technical checks fetch the requested websites and related robots, sitemap, redirect or verification URLs. Providers receive the arguments and credentials needed for the selected request; optional paid calls can incur provider charges. These calls do not add maintainer telemetry.

SerpBase is an optional paid SERP source. Set SEO_MCP_SERP_PROVIDER=serpbase and SERPBASE_API_KEY, or use [serp] provider and [serpbase] api_key in the config file. A key alone does not select it. Set SEO_MCP_SERP_PROVIDER=dataforseo to select DataForSEO explicitly; it is also the default when no provider is selected. Each process allows one SerpBase request before restart; this is not a shared or durable budget. The provider receives the query, language, country and device and may retain query logs. Its privacy policy does not offer customer-configurable zero retention, a per-request logging opt-out or self-service query-log deletion. Review its current terms, privacy policy and credit pricing before use. SerpBase supports desktop and other locales; this integration currently requests US English and the mobile layout. The provider client connects directly and does not use environment proxies. Check provider terms before storing or exporting its results as Workbench evidence. The Google AI Overview leg requires one prompt and one sample; SERP adjacency requires one seed. The default AI sample count exceeds this limit, so specify one sample for the SerpBase leg. Missing provider modules are unavailable. Responses without the documented query and page metadata, or with a mismatched query, are rejected even if the provider reports a charge.

Website checks accept publicly routable targets only. Private, loopback and local staging targets are refused, including redirects and linked pages. Networks that require the well-known NAT64 prefix 64:ff9b::/96 are not supported by these checks. Website fetches use direct connections and refuse HTTP, HTTPS, all-protocol or SOCKS proxies reported by Python's standard proxy discovery. Proxy auto-configuration and other system policies may not be detected. A configured proxy is refused even when a bypass list includes the target. SEO analysis results can include complete supplied or discovered page URLs, including paths and query strings. Avoid secrets in URLs shared with these tools.

The engine does not keep a query/result history. The separately installed local Workbench stores user-owned evidence and decision records in SQLite and creates exports only when requested. Your MCP host controls its own transcripts and logs. See Privacy for destinations and persistence scopes.

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)

Structured data + cross-site + on-page (7) - no new credentials (the v0.9 SERP auto-fetch is optional).

  • inspect_schema(url) - extract every JSON-LD block from a page; report the schema.org @type counts and a sample entity per type.

  • validate_schema(url, types?) - verdict each JSON-LD entity against the Google Rich Results required-field set. Covers Article, NewsArticle, BlogPosting, Product, FAQPage, BreadcrumbList, Organization, LocalBusiness, Event, Review, Recipe. Per-entity verdict plus missing_required and missing_recommended lists.

  • hreflang_consistency_check(urls) - cross-page hreflang audit on a user-supplied URL set. Flags missing reciprocity, broken hreflang targets, duplicate hreflang on one page, missing self-link, missing x-default when there are 3+ language variants.

  • internal_link_graph(start_url, max_depth=2, max_pages=50) - small BFS crawl within the same host. Per-page in-degree + out-degree, orphan pages, broken internal links, depth distribution. Hard caps (max_depth <= 4, max_pages <= 200) so a misuse never melts the host.

  • lighthouse_budget(url, budget) - wraps psi_analyze and verdicts the results against a budget dict, e.g. {performance: 80, LCP_ms: 2500, CLS: 0.1}. Per-metric pass/fail and an overall verdict. Useful as a CI / pre-deploy gate inside an LLM session. Reuses PSI_API_KEY.

  • internal_link_recommend(start_url, site_url?, days?, position_min?, position_max?, relevance_floor?, limit?)

    • recommends specific source->target internal links from high-in-degree pages to GSC striking-distance pages (default position 8-20 with real impressions), with anchor text. Ranks sources by lexical relevance + internal authority, skips pages that already link the target, balances anchor text, and never suggests nofollow. Built on internal_link_graph + GSC. Free. (v0.9.0)

  • onpage_serp_gap(target_url, query?, competitor_urls?, max_competitors?) - the headings, entities, and schema the top SERP results have that a target page lacks, turned into on-page actions. FREE with caller-supplied competitor_urls; optional DataForSEO SERP auto-fetch by query, which also returns winnability signals (serp_composition AI-Overview / UGC zero-click risk) and, with Open PageRank, competitor domain authority. Surfaces information gain, not just parity. Boilerplate/nav headings are filtered out (pattern-class chrome filter). (v0.9.0; F6 fix v0.9.1, F1 generalized v0.9.2)

Every tool's tools/list entry carries the MCP standard annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) so MCP hosts can decide what to auto-approve and what to confirm.

Workflow prompts

The server publishes thirteen named MCP prompts (via prompts/list / prompts/get) that chain the granular tools into common SEO workflows. Hosts that surface prompts (Claude Desktop's slash menu, Cursor's command palette, Cline's prompt picker) advertise them automatically.

Prompt

Arguments

Chains

post_deploy_verify

urls, zone?, skip_psi?

cf_purge_cache -> gsc_request_indexing -> indexnow_bulk_submit -> psi_analyze

weekly_review

days?, site_url?

gsc_compare_periods (gainers + losers via sort_dir) -> gsc_query_opportunities -> gsc_query_gaps -> ga4_organic_search_overview

content_audit

site_url?, days?, top_n_queries?

gsc_top_queries -> per-query gsc_top_pages_by_query -> cannibalization recommendation

migration_check

urls, site_url?

gsc_batch_inspect_urls -> gsc_list_sitemaps -> canonical-agreement table -> remediation list

technical_seo_audit

url

inspect_meta -> check_canonical -> redirect_chain_audit -> mixed_content_check -> robots_txt_validate -> sitemap_health -> severity-ranked triage list

structured_data_audit

urls

per-URL inspect_schema -> validate_schema -> (if 2+ URLs) hreflang_consistency_check -> per-URL + cross-URL report

pre_deploy_check

urls

robots_txt_validate -> per-URL inspect_meta -> check_canonical -> validate_schema -> redirect_chain_audit -> mixed_content_check -> deploy-gate verdict (block on critical issues, approve otherwise)

content_brief (v0.7.1)

topic, target_query, site_url?

gsc_top_pages_by_query -> inspect_meta / inspect_schema on top rankers -> brief with required sections + validation rules

content_outline (v0.7.1)

brief

outline with rules: >=5 H2, >=70% target-query coverage, H1 has the primary keyword

content_article (v0.7.1)

outline, brief

article with rules: word count within +/-15%, per-section minimum, internal links, inline JSON-LD hint, no em-dashes

content_workflow (v0.7.1)

site_url?, days?

content_opportunities -> brief -> outline -> article -> pre_deploy_check -> gsc_request_indexing + indexnow_submit -> scheduled content_performance

content_performance (v0.7.1)

url, target_queries?, site_url?

gsc_compare_periods + gsc_search_analytics before / after the publish window

seo_setup_audit (v0.7.1)

site_url?, property_id?

ga4_setup_audit -> cf_settings_audit -> psi_opportunities -> robots_txt_validate -> consolidated stack-config report

Why prompts and not megatools: composability. A failed step inside a megatool poisons the megatool's envelope and the host loses the ability to retry just the failing leg. Prompts hand the host a recipe; each step's envelope arrives intact at the LLM.

Install

SEOMonster ships two install paths, both fully local:

  • .mcpb bundle for Claude Desktop. One-click install, GUI form for credentials, secret-typed inputs stored in the OS keychain. Recommended for most users.

  • uvx for Cursor, Cline, Codex, and Claude Desktop power users who prefer to hand-edit MCP config files.

Both paths run the same Python package (seo_mcp) and expose the same 70 tools. The difference is only how the host launches the server and how it collects credentials.

Three short steps. The OAuth consent is run once from a terminal (the GUI flow inside Claude Desktop's MCP subprocess times out before a real user can finish; see Why pre-flight auth? below).

1. Install the bundle. Download the versioned .mcpb asset from GitHub releases (or, when listed, from the Claude Directory) and double-click it. Claude Desktop verifies the bundle, runs uv to materialize the Python environment, and shows a configuration form:

Field

Type

Required

Notes

Google OAuth Client Secrets

file picker

yes

Desktop-app client-secrets JSON from Google Cloud Console.

Google OAuth Token Cache Path

string

yes

Defaults to ~/.config/seo-monster/token.json. Written on consent.

GSC Default Property

string

no

e.g. sc-domain:example.com or https://www.example.com/.

GA4 Default Property ID

string

no

properties/123456789 or bare 123456789.

PageSpeed Insights API Key

string, secret

no

Stored in the OS keychain. Strongly recommended (why?).

Cloudflare API Token

string, secret

no

Stored in the OS keychain. Required only for the Cloudflare tools.

Cloudflare Default Zone

string

no

e.g. example.com.

IndexNow Key

string, secret

no

Required only for IndexNow tools. Any 8-128 hex string you generate.

IndexNow Key File URL

string

no

Override the default verification location (https://<host>/<key>.txt).

Fill the fields, click Save, then toggle the extension on. Quit Claude Desktop completely (⌘Q on macOS) and reopen.

2. Run the one-time OAuth consent from a terminal. Before using any Google-backed tool, run:

uvx seo-monster auth

A browser opens. Approve the requested scopes. The command writes token.json to the path you configured (default ~/.config/seo-monster/token.json) with 0600 permissions, then exits. This step is the recommended pattern; it sidesteps the timeout that Claude Desktop imposes on every tool call.

3. Start a new chat in Claude Desktop and use the tools. Click the 🔧 tools icon in the input box; you should see 70 SEOMonster tools. Try system_status first to verify everything is configured.

Why pre-flight auth?

The OAuth installed-app flow opens a local browser and waits for the user to finish the consent screen. Inside Claude Desktop, MCP servers are launched as subprocesses whose tool calls have a ~30-60 second timeout. Real users do not complete browser consent that fast, so the originating call times out, and since every Google tool retries the flow until a token exists, every call times out in turn. Running uvx seo-monster auth once from a terminal puts the token on disk; from that point on, Claude Desktop's MCP server just reads the cached token and silently refreshes it as needed.

uvx for Cursor, Cline, Codex (and Claude Desktop power users)

uvx runs the published PyPI package seo-monster in an ephemeral environment. Add the snippet for your host below, using the absolute path to uvx (find it with which uvx; GUI hosts do not read your shell profile).

Cursor (~/.cursor/mcp.json or project .cursor/mcp.json)

{
  "mcpServers": {
    "seomonster": {
      "command": "/Users/me/.local/bin/uvx",
      "args": ["seo-monster"],
      "env": {
        "SEO_MCP_GOOGLE_OAUTH_CLIENT": "/Users/me/.config/seo-monster/client_secret.json",
        "SEO_MCP_GOOGLE_TOKEN": "/Users/me/.config/seo-monster/token.json",
        "SEO_MCP_GA4_PROPERTY_ID": "properties/123456789",
        "PSI_API_KEY": "AIza...",
        "CF_API_TOKEN": "..."
      }
    }
  }
}

Cline (cline_mcp_settings.json)

{
  "mcpServers": {
    "seomonster": {
      "command": "/Users/me/.local/bin/uvx",
      "args": ["seo-monster"],
      "env": {
        "SEO_MCP_GOOGLE_OAUTH_CLIENT": "/Users/me/.config/seo-monster/client_secret.json",
        "SEO_MCP_GOOGLE_TOKEN": "/Users/me/.config/seo-monster/token.json"
      },
      "alwaysAllow": ["system_status", "gsc_search_analytics", "ga4_run_report", "psi_analyze"]
    }
  }
}

alwaysAllow lists read tools so Cline does not prompt on each call. Leave the cache-purge tools off so they always prompt.

Codex (~/.codex/config.toml)

[mcp_servers.seomonster]
command = "/Users/me/.local/bin/uvx"
args = ["seo-monster"]

[mcp_servers.seomonster.env]
SEO_MCP_GOOGLE_OAUTH_CLIENT = "/Users/me/.config/seo-monster/client_secret.json"
SEO_MCP_GOOGLE_TOKEN = "/Users/me/.config/seo-monster/token.json"
SEO_MCP_GA4_PROPERTY_ID = "properties/123456789"

Claude Desktop, direct uvx (advanced)

If you prefer to hand-edit claude_desktop_config.json instead of using the .mcpb bundle, the same snippet shape as Cursor above works.

Auth

The four services authenticate independently. Configure only the ones you use; a tool for an unconfigured service returns a clear AUTH_MISSING error rather than failing the server.

Run seo-monster setup once from a terminal. It interactively collects your Cloudflare token, PageSpeed Insights key, IndexNow key, and the default GSC and GA4 properties, validates what it can against the live APIs, and writes them to ~/.config/seo-mcp/config.toml with 0600 permissions. Your MCP host config then needs no secrets in it:

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

Two things setup does not do, by design:

  • Google OAuth still uses the separate one-time browser step. After setup, run seo-monster auth to complete Google consent (see the next section).

  • It never overrides environment variables. Anything set in your host's env block still wins over the config file, so CI and Docker keep using env vars.

setup is re-runnable: existing values are shown as defaults and kept when you leave a field blank. The sections below document the per-service env vars, which are what setup writes for you and what CI pipelines can set directly.

This is the lower-friction path: no Cloud service account, no per-property email grants.

  1. In the Google Cloud Console, create (or pick) a project and enable the APIs you will use:

    • Search Console API

    • Indexing API (for gsc_request_indexing)

    • Google Analytics Data API (for the GA4 tools)

    • PageSpeed Insights API (only if you want a PSI key; see below)

  2. Create an OAuth client of type Desktop app and download the client-secrets JSON.

  3. Point the server at it and at a writable token path:

    • SEO_MCP_GOOGLE_OAUTH_CLIENT = path to the client-secrets JSON

    • SEO_MCP_GOOGLE_TOKEN = a writable path where the token will be cached

  4. One-time: run uvx seo-monster auth from a terminal. A browser opens; approve the scopes. The command writes token.json (0600) and exits.

  5. Subsequent runs (server-side) refresh the token silently. The server never opens a browser; if the cached token is missing, tools return AUTH_MISSING pointing back at the auth command.

The signed-in Google account must have access to the Search Console properties and GA4 properties you query.

Token-cache hardening. The cached token is refresh-capable and equivalent to a long-lived credential for the requested scopes. The server writes it with 0600 and its parent directory with 0700. Keep SEO_MCP_GOOGLE_TOKEN under a directory you control (e.g. ~/.config/seo-monster/) and do not put it on a shared filesystem.

Google - service account (advanced, headless)

For fully headless or server deployments where a browser is not available:

  1. Create a service account and download its JSON key.

  2. Set SEO_MCP_GOOGLE_CREDENTIALS (or the standard GOOGLE_APPLICATION_CREDENTIALS) to the key path.

  3. Grant the service-account email access on each property:

    • Search Console: add it as a user on the property.

    • GA4: add it as a Viewer on the property.

If both OAuth and a service account are configured, OAuth is used.

Coverage note. The OAuth installed-app path is exercised in our validation pass and in production-style smoke tests. The service-account path is documented but not independently validated against a live Cloud project. If you hit issues on the SA path, please open an issue.

Scopes (minimal vs full)

The default consent requests the scopes needed for every tool, including the two writes:

Capability

Scope

GSC read

webmasters (covers readonly)

GSC sitemap submit

webmasters

GSC indexing request

indexing

GA4 reporting

analytics.readonly

If you only want reads, you can consent to a narrower set (webmasters.readonly + analytics.readonly) and simply not call gsc_submit_sitemap / gsc_request_indexing; calling a write tool without its scope returns SCOPE_INSUFFICIENT with remediation, never a crash.

PageSpeed Insights

PSI works without a key in principle, but in practice the anonymous quota is shared across every caller without a key and is frequently exhausted: a single psi_analyze call against the anonymous endpoint often returns RATE_LIMITED. Treat the anonymous mode as a fallback, not the steady state.

To get reliable PSI access:

  1. In Cloud Console, enable the PageSpeed Insights API.

  2. Create an API key (Credentials > Create credentials > API key). It takes a minute. The key is free.

  3. Set PSI_API_KEY (or use the field in the .mcpb configuration form).

The PSI API only accepts the key as a URL query parameter (not a header), so treat PSI keys as low-sensitivity. Scope the key to the PageSpeed Insights API only and attach no other GCP roles.

Cloudflare

Create an API token at dash.cloudflare.com/profile/api-tokens and set CF_API_TOKEN (and optionally CF_ZONE for a default zone). Grant only the permissions you need:

Permission

Needed for

Zone: Zone:Read

cf_list_zones, cf_zone_info

Zone: DNS:Read

cf_list_dns

Account: Account Analytics:Read

cf_web_analytics

Zone: Cache Purge:Purge

cf_purge_cache, cf_purge_cache_all (only if you enable destructive mode)

Zone: Single Redirect:Edit

cf_create_redirect, cf_delete_redirect (only if you enable destructive mode); cf_list_redirects reads with it

Zone: Zone Settings:Edit

cf_settings_update (only if you enable destructive mode); cf_settings_audit only needs Zone Settings Read

Account: Account Rulesets:Edit + Account Filter Lists:Edit

cf_bulk_redirect_upsert (only if you enable destructive mode)

IndexNow

IndexNow notifies Bing, Yandex, Naver, Seznam, and Yep when a URL is created or updated. Google does not participate, so the IndexNow tools complement rather than replace gsc_request_indexing.

One-time setup

  1. Generate a key. Any 8-128 character string of letters, digits, or hyphens (a-z, A-Z, 0-9, -) per the IndexNow spec. Common patterns: a 32-char lowercase hex string (e.g. python -c "import secrets; print(secrets.token_hex(16))") or any random alphanumeric of similar length. Treat it like an API key; do not commit it.

  2. Configure SEOMonster by setting SEO_MCP_INDEXNOW_KEY to that string (or use the .mcpb configuration form; the field is marked sensitive and lands in the OS keychain).

  3. Host the verification file at https://<your-host>/<key>.txt. The file body MUST be exactly the key string with no trailing newline, no BOM, no extra whitespace, no HTML wrapper. The Content-Type should be text/plain. Confirm with curl -i https://<your-host>/<key>.txt before moving on; the response body must be byte-identical to the key.

  4. (Optional) Set SEO_MCP_INDEXNOW_KEY_LOCATION if the verification file lives at a non-standard URL (some CDNs rewrite /key.txt paths). The default location is https://<host>/<key>.txt derived from the URLs you submit, so you usually do not need this.

Same-host constraint

Every URL submitted in one indexnow_submit or indexnow_bulk_submit call must share the same host as the verification file. Mixed-host batches are rejected by IndexNow with HTTP 422; indexnow_bulk_submit enforces this client-side and returns INVALID_INPUT before any network call when it detects mixed hosts.

If you have multiple hosts, host a verification file per host and either make separate calls per host or override SEO_MCP_INDEXNOW_KEY_LOCATION per call (the tool does not currently expose per-call override; set distinct env values per session).

Common errors

Symptom

Likely cause

AUTH_INVALID from indexnow_submit

Engines could not fetch https://<host>/<key>.txt. Confirm the file returns HTTP 200 with the exact key as the body

INVALID_INPUT from indexnow_bulk_submit mentioning mixed hosts

URL list spans multiple hosts; split into per-host batches

RATE_LIMITED

Hit IndexNow's per-host rate cap. Wait before retrying

Verify your setup

After configuring, call system_status to see what is detected. Call it with {"probe": true} to make one cheap live request per configured service and confirm the credentials actually work (GSC lists properties, GA4 runs a 1-row report against the default property, Cloudflare lists one zone, PSI pings the endpoint). With probe off (the default) it does a config-only check and makes no network calls.

Destructive mode

Cache purges affect every visitor, so they are off by default. Set SEO_MCP_ALLOW_DESTRUCTIVE=true to enable cf_purge_cache and cf_purge_cache_all. While off, those tools return DESTRUCTIVE_DISABLED and make no network call.

cf_purge_cache_all (purge the whole zone) carries an extra safeguard: it requires a confirm argument equal to the resolved zone hostname. A missing or mismatched confirm returns CONFIRM_REQUIRED and issues no purge.

The two GSC writes (gsc_submit_sitemap, gsc_request_indexing) are not gated; they are routine, low-blast-radius SEO tasks.

Configuration

Resolution is environment-first, with a TOML file fallback. Environment always wins. The config file is normally written for you by seo-monster setup (with 0600 permissions); you can also write it by hand or set the env vars below.

Env var

Service

Purpose

SEO_MCP_GOOGLE_OAUTH_CLIENT

Google

OAuth client-secrets JSON path (recommended).

SEO_MCP_GOOGLE_TOKEN

Google

Writable cached-token path (OAuth).

SEO_MCP_GOOGLE_CREDENTIALS

Google

Service-account key path (alternative).

GOOGLE_APPLICATION_CREDENTIALS

Google

Standard service-account fallback.

SEO_MCP_GSC_DEFAULT_SITE

GSC

Default property, e.g. sc-domain:example.com.

SEO_MCP_GA4_PROPERTY_ID

GA4

Default property, e.g. properties/123456789.

SEO_MCP_DATA_STATE

GSC

all (default) or final.

PSI_API_KEY

PSI

PageSpeed Insights API key (optional).

CF_API_TOKEN

CF

Cloudflare API token.

CF_ZONE

CF

Default zone hostname.

SEO_MCP_INDEXNOW_KEY

IndexNow

Shared key for the IndexNow tools (sensitive).

SEO_MCP_INDEXNOW_KEY_LOCATION

IndexNow

Override default key-file URL (optional).

SEO_MCP_ALLOW_DESTRUCTIVE

all

true enables cache-purge tools. Default off.

SEO_MCP_CONFIG

all

Path to the TOML config file.

DATAFORSEO_LOGIN / DATAFORSEO_PASSWORD

DataForSEO

Optional (v0.9): SERP/PAA, keyword volume/difficulty/intent, competitor gap, Google AIO.

SEO_MCP_SERP_PROVIDER and SERPBASE_API_KEY

SerpBase

Optional paid SERP source when explicitly selected as serpbase.

OPENPAGERANK_API_KEY

Open PageRank

Optional (v0.9): free competitor domain authority.

PERPLEXITY_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY

AI engines

Optional (v0.9): engines for ai_citation_track (any subset).

GOOGLE_ADS_DEVELOPER_TOKEN / GOOGLE_ADS_CUSTOMER_ID

Google Ads

Optional (v0.9): volume alt to DataForSEO (needs adwords-scope consent).

Config file fallback at ~/.config/seo-mcp/config.toml (or SEO_MCP_CONFIG):

[google]
oauth_client = "/Users/me/.config/seo-mcp/client_secret.json"
token        = "/Users/me/.config/seo-mcp/token.json"
# credentials = "/Users/me/.config/seo-mcp/sa.json"   # service-account alternative

[gsc]
default_site = "sc-domain:example.com"
data_state   = "all"

[ga4]
property_id  = "properties/123456789"

[psi]
api_key = "AIza..."

[cloudflare]
api_token = "..."
zone      = "example.com"

[server]
allow_destructive = false

# Optional v0.9 providers (discovery + AI/GEO). The free GSC/GA4/HTTP core
# works without any of these; each tool degrades gracefully when unset.
[dataforseo]
# login    = "..."
# password = "..."

[openpagerank]
# api_key = "..."

[ai_engines]
# perplexity = "..."
# openai     = "..."
# anthropic  = "..."
# gemini     = "..."

[google_ads]
# developer_token = "..."   # volume alt to DataForSEO; needs adwords-scope OAuth
# customer_id     = "..."

Result envelope

Every tool returns the same shape. On success:

{ "ok": true, "data": { /* tool-specific */ }, "error": null }

On failure:

{
  "ok": false,
  "data": null,
  "error": {
    "code": "AUTH_MISSING",
    "service": "gsc",
    "message": "No Google credentials found for Search Console.",
    "remediation": "Configure OAuth ... or a service-account key. See README > Auth.",
    "docs_url": "https://www.avansaber.com/seomonster/docs/#auth",
    "details": null
  }
}

Error codes:

Code

Meaning

AUTH_MISSING

No credential configured for the service.

AUTH_INVALID

Credential present but rejected (401/403, bad key, expired).

SCOPE_INSUFFICIENT

Token lacks the scope this tool needs.

DESTRUCTIVE_DISABLED

A cache-purge tool was called with destructive mode off.

CONFIRM_REQUIRED

cf_purge_cache_all called without a matching confirm.

NOT_FOUND

Site / property / zone / record not found or not visible.

INVALID_INPUT

Argument failed validation (bad date, missing required arg).

RATE_LIMITED

Upstream 429.

SERVICE_DISABLED

A Google Cloud API is not enabled; details has the activation URL.

UPSTREAM_ERROR

Any other non-2xx from an upstream API.

Development

git clone https://github.com/avansaber/seo-monster
cd seo-monster
uv sync --locked --extra dev
uv run --no-sync pytest                 # offline test suite
uv run --no-sync seo-monster            # run the server over stdio
uv run --no-sync seo-monster auth       # one-time OAuth consent

The package exposes two console-script aliases: seo-monster (canonical, matches the PyPI distribution) and seo-mcp (a v0.1.x dev alias kept for back-compat). Both invoke the same entry point. As of v0.2.0, invoking the server via seo-mcp emits a one-line stderr deprecation notice; nothing on stdout, so the MCP protocol channel is unaffected. Production configs should use seo-monster; the alias will be removed in a future major release.

Tests are fully offline: they mock at the client layer, so no network and no credentials are needed to run them.

SDK 2 source builds. This checkout requires Python 3.11 or later and MCP Python SDK 2.3 or later within major version 2. The MCP handshake reports the engine package version; the protocol server name remains seo-mcp. After updating a source installation, sync its dependencies and restart the MCP host. Published packages and existing installations retain the version they installed until upgraded.

Changelog

Release-by-release notes, including the validation checks each version's external testing pass should cover, live in CHANGELOG.md.

Privacy

SEOMonster runs entirely on your machine and talks only to the upstream APIs you configure. The maintainers do not see any of your data, credentials, queries, or tool calls. See PRIVACY.md for the full statement.

License

MIT. See LICENSE.

Available Tools

70 tools
ai_citation_readinessA
Read-onlyIdempotent

Score whether a page is structured to be extracted and cited by LLM answer engines (ChatGPT, Perplexity, Claude, Google AI Overviews). Leads with a render-blindness check (AI crawlers 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. Reports schema.org / FAQ as informational only -- the 2026 evidence does NOT support them as AI-citation drivers, so they are not scored. Read-only HTTP GET; does not guarantee a citation.

Inputs: url (required).

ai_citation_trackA
Read-only

Track brand mention + citation share-of-voice across AI answer engines (Perplexity/OpenAI/Anthropic/Gemini via their APIs, Google AI Overviews via DataForSEO) for a managed prompt set, vs competitors. Samples each prompt N times (default 7) and reports visibility with a 95% confidence interval, share-of-voice, and run-to-run volatility -- NOT an 'AI rank' (single runs are statistically meaningless). Honest bound: developer-API output differs from the logged-in consumer UI, and AIO has no API. Paid + non-deterministic; results are directional and dated, not guaranteed.

Inputs: brand (required), prompts (required), engines, samples, +2 more.

ai_referral_overviewA
Read-onlyIdempotent

First-party view of AI traffic: (1) referral sessions from AI apps (ChatGPT, Perplexity, Gemini, Copilot, Claude, ...) via GA4, detected by both the native ai-assistant channel and a source-host regex; and (2) AI-crawler coverage -- whether robots.txt lets GPTBot, ClaudeBot, PerplexityBot, etc. reach the site. Needs a GA4 property (for referral) and/or a site_url (for crawl coverage). Honest bound: AI referrals undercount badly (~70% land as Direct), and AI-Overview clicks count as Organic, not here.

Inputs: days, site_url, property_id.

cf_bulk_redirect_upsertA
DestructiveIdempotent

Create or append many redirects at once via an account-level Bulk Redirect List (for site migrations). Gated: requires SEO_MCP_ALLOW_DESTRUCTIVE=true AND a confirm value equal to list_name. Validates every item locally first and rejects the whole batch on any bad item (never half-applies); supports dry_run. Items are added asynchronously by Cloudflare.

Inputs: items (required), list_name (required), confirm, dry_run, +1 more.

cf_create_redirectA
DestructiveIdempotent

Create one single (dynamic) redirect at the Cloudflare edge (e.g. a 301 for a renamed/migrated URL). Gated: requires SEO_MCP_ALLOW_DESTRUCTIVE=true. Validates the target is reachable (no redirecting to a dead URL), refuses loops and duplicates, and supports dry_run to preview the rule first.

Inputs: source (required), target (required), zone, dry_run, +3 more.

cf_delete_redirectA
DestructiveIdempotent

Delete one single (dynamic) redirect rule by its id (the rollback path for cf_create_redirect). Gated: requires SEO_MCP_ALLOW_DESTRUCTIVE=true. Get the rule id from cf_list_redirects.

Inputs: rule_id (required), zone.

cf_list_dnsA
Read-onlyIdempotent

List DNS records for a zone (read-only). Useful for verifying the canonical host, CNAME flattening, and TXT verification records during SEO migrations.

Inputs: type, zone.

cf_list_redirectsA
Read-onlyIdempotent

List a zone's single (dynamic) redirect rules (source, target, status code, rule id) plus the account's Bulk Redirect lists (read-only). Call this before cf_create_redirect / cf_delete_redirect / cf_bulk_redirect_upsert so writes never clobber existing rules. Pairs with redirect_chain_audit and the migration_check prompt.

Inputs: zone.

cf_list_zonesA
Read-onlyIdempotent

List the Cloudflare zones the API token can see, with status, plan, and id.

Inputs: no named parameters.

cf_managed_robotsA
DestructiveIdempotent

Get / configure / disable Cloudflare's managed robots.txt and Content-Signals policy on a zone (rides on the Bot Management config). action='get' reads the current state (read-only, un-gated). action='configure' enables/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 managed robots.txt and the Content-Signals policy back off. NOTE: managed robots.txt and the Content-Signals policy are MUTUALLY EXCLUSIVE in Cloudflare - 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. Writes are gated (SEO_MCP_ALLOW_DESTRUCTIVE) and need confirm=; supports dry_run. Always returns a caveat distinguishing the stated-preference signals from the levers that actually enforce at the edge.

Inputs: action (required), zone, confirm, dry_run, +5 more.

cf_purge_cacheA
DestructiveIdempotent

Purge specific URLs from the Cloudflare cache so crawlers refetch updated content. Gated: requires SEO_MCP_ALLOW_DESTRUCTIVE=true.

Inputs: urls (required), zone.

cf_purge_cache_allA
DestructiveIdempotent

Purge the entire Cloudflare cache for a zone (affects all visitors). Gated: requires SEO_MCP_ALLOW_DESTRUCTIVE=true AND a confirm value equal to the resolved zone hostname, so a full purge cannot fire ambiguously.

Inputs: confirm (required), zone.

cf_settings_auditA
Read-onlyIdempotent

Audit a Cloudflare zone's settings for SEO and crawl/index safety (read-only): SSL/TLS mode, Always Use HTTPS, HSTS, Automatic HTTPS Rewrites, Brotli, and browser cache TTL. Findings are severity-graded with the reason and a benign exception each. Cloudflare cannot see the origin, so the SSL and Always-HTTPS checks are phrased as 'verify,' not 'fail,' and HSTS is never hard-failed (premature HSTS is dangerous and hard to undo). Answers 'are my edge settings silently sabotaging crawl/index?' It grades the edge layer only, not origin behavior.

Inputs: zone.

cf_settings_updateA
DestructiveIdempotent

Write the SEO/crawl/security Cloudflare zone settings that cf_settings_audit grades, to close the audit -> remediate loop. Gated: requires SEO_MCP_ALLOW_DESTRUCTIVE=true. Changing ssl_mode, or any HSTS change that raises protection, additionally requires confirm= (HSTS also requires acknowledge_hsts_risk=true). Validates locally first and supports dry_run (before/after preview). Needs the Zone Settings:Edit token scope (the audit only needs Read).

Inputs: settings (required), zone, confirm, dry_run, +1 more.

cf_web_analyticsA
Read-onlyIdempotent

Read-only Cloudflare Web Analytics (edge RUM). With no argument, lists the account's Web Analytics sites; with host_or_tag, returns one site's detail. Edge-measured traffic complements GA4 (it sees visits GA4's JS tag may miss). Create/delete are intentionally not exposed.

Inputs: host_or_tag.

cf_zone_infoA
Read-onlyIdempotent

Zone overview for a hostname: status, plan, paused, name servers, created/modified.

Inputs: zone.

check_canonicalA
Read-onlyIdempotent

Fetch a URL and analyse its canonical link tag: report whether it is self-referential, cross-host, protocol-mismatched, or trailing-slash drift; flag missing canonical, and follow one canonical hop to confirm it itself returns 2xx.

Inputs: url (required).

content_brief_dataA
Read-onlyIdempotent

Gather the hard evidence for a content brief: fetch the competitor pages and return their heading union, median word count (a FLOOR, not a target), schema types, and entity coverage, plus the 2026 GEO writing directives and validation rules. Pass competitor_urls (e.g. the top SERP results) for a true brief; with none it falls back to your own ranking pages via GSC (refresh-vs-new, NOT the full SERP). The host writes the brief prose from this; SEOMonster supplies rules + evidence. Read-only; no ranking guarantee. Backs the content_brief prompt.

Inputs: target_query (required), days, topic, site_url, +1 more.

content_opportunitiesA
Read-onlyIdempotent

Rank data-grounded content/blog topics from your own Search Console data. Fuses CTR-vs-expected gap, striking-distance position, demand volume, and momentum into a transparent opportunity score, flags cannibalization, and reports the click upside plus the score's components. Read-only. It prioritizes demand you already have; it does not do cold-start keyword research (that needs existing impressions) and does not write the content or guarantee a ranking.

Inputs: days, count, site_url, impressions_min.

crux_historyA
Read-onlyIdempotent

Return the last 25 weekly collection periods of Core Web Vitals at p75 (LCP, INP, CLS, etc.) for a URL or origin via the Chrome UX Report History API. Complements psi_analyze with the trend axis.

Inputs: url, origin, metrics, form_factor.

crux_snapshotA
Read-onlyIdempotent

Return the CURRENT (latest 28-day) p75 Core Web Vitals snapshot (LCP, INP, CLS, FCP, TTFB) for a URL or origin via the Chrome UX Report queryRecord API, with each metric's GOOD/NEEDS_IMPROVEMENT/POOR category and an overall verdict. Use crux_history for the 25-week trend. Small pages/origins legitimately have no field data; that returns no_data.

Inputs: url, origin, form_factor.

ga4_landing_page_conversionsA
Read-onlyIdempotent

Landing pages with their conversions / key events over the last N days, broken down by channel group and sorted by conversions descending. Filtered to organic search by default (the SEO view) so you see which entry pages actually drive organic outcomes. Convenience wrapper over ga4_run_report.

Inputs: days, limit, property_id, organic_only.

ga4_organic_search_overviewA
Read-onlyIdempotent

Organic-search health over the last N days: window totals (sessions, engaged sessions, engagement rate, average session duration, conversions) plus a day-by-day trend of the same metrics. Two GA4 reports under the hood.

Inputs: days, property_id.

ga4_run_reportA
Read-onlyIdempotent

Run a GA4 report (Analytics Data API runReport) with arbitrary dimensions, metrics, a date range, an optional dimension filter, and ordering. The workhorse GA4 tool. Dates accept ISO (YYYY-MM-DD) or GA4 relatives like '28daysAgo' and 'today'.

Inputs: days, limit, metrics, end_date, +6 more.

ga4_setup_auditA
Read-onlyIdempotent

Audit a GA4 property's configuration for SEO-measurement readiness (read-only): is a web data stream present, are key events / conversions defined, is data retention long enough for year-over-year analysis, are content-group custom dimensions set, and (via v1alpha) is enhanced measurement on and what the Google Signals state is. Findings are severity-graded with the reason and the benign exception for each. Answers 'can this property actually measure my organic outcomes?' It checks hygiene, not whether your events are the right business events.

Inputs: property_id.

ga4_top_landing_pagesA
Read-onlyIdempotent

Top landing pages by sessions over the last N days, with engagement rate and conversions. Filtered to organic search by default (the SEO view). Convenience wrapper over ga4_run_report.

Inputs: days, limit, property_id, organic_only.

ga4_traffic_by_channelA
Read-onlyIdempotent

Sessions, engaged sessions, and conversions broken down by default channel group over the last N days. Separates organic from paid / referral / direct at a glance. Convenience wrapper over ga4_run_report.

Inputs: days, limit, property_id.

gsc_batch_inspect_urlsA
Read-onlyIdempotent

Inspect several URLs in one call (capped at 25). Returns a result per URL plus a list of per-URL failures. Rate-limit and transient errors are reported per URL without failing the whole batch.

Inputs: urls (required), site_url.

gsc_compare_periodsA
Read-onlyIdempotent

Compare two equal-length time windows (current vs prior) and return per-key deltas in clicks, impressions, CTR, and position, plus keys present in only one window. v0.2.0: optional sort_by / sort_dir / min_delta_* filters and an anomalies_only z-score gate so the same tool covers 'biggest gainers', 'biggest losers', 'meaningful movers', and 'statistical outliers' without needing separate tools. When anomalies_only=true, the response's filters_applied.sigma_used field reports the population-stdev (sigma) actually computed from the matched rows' sort_by metric distribution; the effective z-score cutoff applied is sigma_threshold * sigma_used.

Inputs: top, days, limit, sort_by, +11 more.

gsc_coverage_auditA
Read-onlyIdempotent

Heuristic coverage audit. The GSC Index Coverage report is NOT exposed in the public API, so this tool takes a user-supplied URL list (typically pulled from a sitemap) and bulk-inspects each, then rolls up the verdicts (PASS / PARTIAL / FAIL plus coverage_state frequencies). Honest substitute for the Coverage UI; the AI host can use the rollup to decide which URLs to deep-inspect.

Inputs: urls (required), site_url.

gsc_decaying_pagesA
Read-onlyIdempotent

Pages whose impressions fell most over the last N days vs the prior N days. Equivalent to gsc_compare_periods with dimensions=["page"], sort_by="delta_impressions", sort_dir="asc". Use this for lifecycle triage (find pages to invest in or rescue).

Inputs: days, limit, site_url.

gsc_inspect_urlA
Read-onlyIdempotent

Inspect a single URL via the URL Inspection API: index verdict, coverage state, crawl info, canonicals, and mobile/rich-results summaries when present.

Inputs: url (required), site_url.

gsc_keyword_expandA
Read-onlyIdempotent

Ground LLM-brainstormed keyword candidates against your own Search Console data to find net-new terms you have no current footprint on. YOU (the host) supply candidates -- brainstorm them from the site's winning queries first (call gsc_top_queries). For each candidate this returns a footprint verdict (covered / thin / none) and a confidence band from sibling-strength (does it share tokens with queries that already win impressions). 'none' means no VISIBLE footprint, not no demand (GSC hides ~75% of impressions); net-new terms are scored hypotheses, not facts. Read-only.

Inputs: candidates (required), days, site_url, impressions_min.

gsc_list_propertiesA
Read-onlyIdempotent

List every Search Console property the configured credentials can see, with each property's permission level. Use this to discover valid site_url values.

Inputs: no named parameters.

gsc_list_sitemapsA
Read-onlyIdempotent

List the sitemaps Google knows about for a property, with submission and indexing status.

Inputs: site_url.

gsc_new_queriesA
Read-onlyIdempotent

Queries that have impressions in the current window but had no impressions in the prior comparison window. Useful for spotting emerging topics or pages that just started ranking.

Inputs: days, limit, site_url, prior_days, +1 more.

gsc_portfolio_summaryA
Read-onlyIdempotent

Multi-property fleet view. Lists every property the credentials can see and returns a one-row summary per property (total clicks, impressions, average CTR, average position) for the last N days. The single fastest answer to 'how is the portfolio doing?' across agency or multi-brand setups. Honors the v0.2.0 alias convention (days) and applies the configured data_state.

Inputs: days, exclude, include.

gsc_query_gapsA
Read-onlyIdempotent

Queries that drive impressions but very few clicks. These are content opportunity signals: a page is being shown for the query, the click experience is not landing. Returns rows sorted by impressions desc.

Inputs: days, limit, site_url, clicks_max, +1 more.

gsc_query_opportunitiesA
Read-onlyIdempotent

Queries already ranking in the top N positions but with below-target CTR. These are title and meta-description optimization candidates. Returns rows sorted by impressions desc (the bigger the impression volume, the more clicks a CTR lift unlocks).

Inputs: days, limit, ctr_max, site_url, +2 more.

gsc_request_indexingA
Idempotent

Ask Google to (re)crawl one or more URLs via the Indexing API (URL_UPDATED). Requires the indexing scope. Available by default. Accepts a single url (string) or urls (array up to 100). A scope or disabled-API error stops the batch and is returned with remediation; per-URL errors are collected. notify_time: null on success is normal upstream behavior, not a failure.

Inputs: url, urls, site_url.

gsc_search_analyticsA
Read-onlyIdempotent

Query Search Console search analytics (clicks, impressions, CTR, position) for a property, with dimensions, a date range, optional dimension filters, and data_state. The workhorse GSC tool.

Inputs: days, limit, filters, end_date, +7 more.

gsc_submit_sitemapA
Idempotent

Submit a sitemap to Search Console. Requires the writable webmasters scope. Available by default (a routine SEO task; not gated). Accepts either sitemap_url (preferred, friendly name) or feedpath (the raw API field name; kept for back-compat).

Inputs: feedpath, site_url, sitemap_url, skip_preflight.

gsc_top_pagesA
Read-onlyIdempotent

Convenience wrapper: top pages for a property over the last N days by clicks. Equivalent to gsc_search_analytics with dimensions=["page"]. Uses the configured data_state (default 'all'; 'final' lags 2-3 days behind the dashboard).

Inputs: days, limit, site_url.

gsc_top_pages_by_queryA
Read-onlyIdempotent

Which pages rank for a specific query. The classic cannibalization audit input: if multiple pages rank for the same query, you typically want to consolidate or differentiate them. Filters search_analytics by an exact query match and returns rows by page dimension.

Inputs: query (required), days, limit, site_url.

gsc_top_queriesA
Read-onlyIdempotent

Convenience wrapper: top queries for a property over the last N days by clicks. Equivalent to gsc_search_analytics with dimensions=["query"]. Uses the configured data_state (default 'all'; 'final' lags 2-3 days behind the dashboard).

Inputs: days, limit, site_url.

hreflang_consistency_checkA
Read-onlyIdempotent

Validate hreflang link tags across a set of URLs. Checks: missing reciprocity, broken target URLs, duplicate hreflang on one page, missing self-link, missing x-default when there are 3+ language variants. Returns per-URL findings and a global findings list.

Inputs: urls (required).

indexnow_bulk_submitA
Idempotent

Submit multiple URLs to IndexNow in one batched request. All URLs must share the same host (IndexNow rejects mixed-host batches with HTTP 422). Cap: 10000 URLs per call (IndexNow's documented limit).

Inputs: urls (required), skip_preflight.

indexnow_submitA
Idempotent

Submit a single URL to IndexNow (Bing + Yandex + Naver + Seznam + Yep). Complements gsc_request_indexing for the non-Google engines. Requires SEO_MCP_INDEXNOW_KEY plus a key-verification file at https:///.txt.

Inputs: url (required), skip_preflight.

inspect_metaA
Read-onlyIdempotent

Fetch a single URL and return its on-page SEO surface: title, meta description, meta robots, canonical, Open Graph + Twitter Card tags, hreflang list, and the H1 count. Read-only HTTP GET.

Inputs: url (required).

inspect_schemaA
Read-onlyIdempotent

Extract every JSON-LD block from a page and report the schema.org @type counts plus a sample entity per type. Discovery tool: tells you what structured data exists. Pair with validate_schema to check required-field compliance.

Inputs: url (required).

keyword_universeA
Read-onlyIdempotent

External keyword data (optional, paid). Its core value is the COMPETITOR keyword GAP: keywords competitors rank for that you don't (DataForSEO Domain Intersection; no Google equivalent). Optionally returns search volume/difficulty/intent for a keyword list via a provider chain (DataForSEO, else Google Ads volume-only). Requires DataForSEO and/or Google Ads to be configured. External volume is a degraded directional signal in 2026 -- never let a low/missing volume drop a high-intent term.

Inputs: limit, keywords, competitors, target_domain.

lighthouse_budgetA
Read-onlyIdempotent

Run PageSpeed Insights on a URL and verdict the results against a performance budget. Valid budget keys: higher-is-better Lighthouse scores on a 0-100 scale ('performance', 'accessibility', 'best-practices', 'seo'); lower-is-better latency in milliseconds ('LCP_ms', 'FCP_ms', 'TBT_ms', 'TTI_ms', 'speed_index_ms'); lower-is-better unitless shift score ('CLS'). Unknown keys are surfaced as a non-fatal finding with a 'did you mean' hint; the metric is NOT silently ignored. Returns per-metric verdict and an overall pass/fail. Useful as a CI / pre-deploy gate.

Inputs: url (required), budget (required), strategy.

mixed_content_checkA
Read-onlyIdempotent

Fetch an HTTPS page and report any sub-resource references that use plain http:// (img/script/iframe/form action/anchor href). Mixed content blocks browsers from running scripts and triggers warnings on user-facing pages. No-op for http:// pages (returns 'not_https').

Inputs: url (required).

onpage_serp_gapA
Read-onlyIdempotent

Find the headings, entities and schema the top SERP results have that a target page lacks, and turn them into on-page actions. Pass competitor_urls (free), or a query with DataForSEO configured to auto-fetch the SERP. When the SERP is auto-fetched, also returns winnability signals (AI-Overview presence, UGC/forum dominance = zero-click risk) and, with Open PageRank, competitor domain authority. Surfaces information-gain (add something novel), not just parity. Read-only; does not guarantee a ranking.

Inputs: target_url (required), query, competitor_urls, max_competitors.

psi_analyzeA
Read-onlyIdempotent

Run PageSpeed Insights on a URL and return Lighthouse category scores, lab Core Web Vitals (synthetic), and field Core Web Vitals (real-user CrUX) when available. Defaults to the mobile strategy (Google ranks on mobile).

Inputs: url (required), strategy, categories.

psi_opportunitiesA
Read-onlyIdempotent

Run PageSpeed Insights and return the actionable Lighthouse opportunity audits (estimated load-time savings) plus the Lighthouse SEO-category audits graded by severity (critical/high/medium/low). Lab data only; does not use field/CrUX data (use crux_snapshot / crux_history for real-user metrics). Defaults to the mobile strategy.

Inputs: url (required), strategy.

rank_change_attributionA
Read-onlyIdempotent

Estimate whether an on-site change moved a page's clicks, using difference-in-differences against a control group of untouched pages (never a naked before/after). Returns an estimated lift with a 95% confidence interval and a three-state verdict (likely_positive / likely_negative / inconclusive), plus a confounders block (algo-update proximity, GSC data-regime breaks, control quality, sample sizes). Clicks-based (position/CTR were corrupted by the 2025 GSC bugs). Observational, not proof of causation -- a server-side split test is the only true causal test.

Inputs: change_date (required), url, urls, query, +5 more.

redirect_chain_auditA
Read-onlyIdempotent

Walk the redirect chain for a URL without auto-following 3xx. Returns every hop (status, location, elapsed_ms) and flags issues: chain longer than 1, mixed-protocol hops (https -> http), loops, or non-2xx terminus. Cap defaults to 10 hops.

Inputs: url (required), max_redirects.

robots_ai_postureA
Read-onlyIdempotent

Recommend a Content-Signals posture (search / ai-input / ai-train) from a business goal and emit a ready-to-apply artifact: the Content-Signal directive line plus a full suggested robots.txt. Read-only, offline, deterministic - no network, no writes. Always returns the trade-off alternatives and the mandatory caveat that Content-Signal is honored only by adopting crawlers, is ignored by Googlebot, and is not a ranking factor.

Inputs: goal, sitemap_url.

robots_txt_validateA
Read-onlyIdempotent

Fetch /robots.txt for a site, parse user-agent groups + Allow/Disallow + Crawl-delay + Sitemap, and return the structured ruleset. Optionally probe a list of (user_agent, url) pairs and return per-probe allow/deny verdicts using RFC 9309 longest-match.

Inputs: site_url (required), probes.

serp_adjacency_expandA
Read-onlyIdempotent

Expand seed terms into adjacent terms from SERP signals. FREE core: Google Autocomplete (no key). Optional PAA + related-searches via DataForSEO if configured. Pass your winning queries as seeds (seed from gsc_top_queries). Returns per-seed suggestions plus the aggregated net-new terms (suggestions you didn't seed). Degrades gracefully: autocomplete-only without a DataForSEO key. Read-only. Note: the autocomplete endpoint is undocumented and may change.

Inputs: seeds (required), include_paa.

sitemap_healthA
Read-onlyIdempotent

Sample N URLs from a sitemap (or one level deep in a sitemap index) and HEAD-check each. Aggregates a status-code histogram and lists the first few non-2xx URLs so you can triage broken entries fast.

Inputs: sitemap_url (required), sample_size.

sitemap_validateA
Read-onlyIdempotent

Fetch a sitemap or sitemap-index URL, validate its XML structure, count entries, and flag oversize (>50,000 URLs or >50 MiB), missing , and entries whose host does not match the sitemap host. Handles .gz transparently.

Inputs: sitemap_url (required).

system_statusA
Read-onlyIdempotent

Report which SEO services are configured and reachable, the Google auth method and scopes, whether destructive mode is enabled, and the full catalog of available tools grouped by service. Call this first if unsure what is set up. Pass probe=true to confirm credentials work via one cheap live call per configured service (default false: config-only).

Inputs: probe.

topic_cluster_mapA
Read-onlyIdempotent

Map a content cluster from your own Search Console data and surface missing subtopics. Define the cluster by cluster_path (a URL path prefix) or pillar_url. For each query the cluster's pages show for, classifies it into defend / optimize / create / monitor by demand and best position, flags cannibalization, and lists the create-quadrant queries (high demand, weak position) as missing-subtopic candidates for you to group into named subtopics. Free, GSC-only. 'create' = no VISIBLE strong coverage (GSC hides ~47% of queries); no external volume.

Inputs: days, limit, site_url, pillar_url, +2 more.

validate_schemaA
Read-onlyIdempotent

Validate every JSON-LD block on a page against the Google Rich Results required-field set. Per-entity verdict (pass/fail) and a list of missing required + recommended fields. Covers Article, NewsArticle, BlogPosting, Product, FAQPage, BreadcrumbList, Organization, LocalBusiness, Event, Review, Recipe.

Inputs: url (required), types.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 70 tools

    Disambiguation4/5

    Each tool targets a specific SEO function, and the descriptions clearly differentiate them. However, with 70 tools, some overlap exists between convenience wrappers and their generic counterparts (e.g., gsc_top_queries vs gsc_search_analytics), which could cause minor confusion for an agent.

    Naming Consistency4/5

    Tool names follow a consistent pattern: lowercase with underscores, mostly using a service prefix (gsc_, ga4_, cf_, etc.) or descriptive compound names for standalone tools. The naming is predictable and readable, though a few tools lack a clear prefix.

    Tool Count3/5

    70 tools is high for a single server, but the broad SEO domain justifies the count through coverage of multiple services and specialized utilities. The number may be overwhelming for agents, but the tools are well-organized.

    Completeness4/5

    The tool surface covers major SEO areas: Search Console, Analytics, Cloudflare, PageSpeed, Core Web Vitals, redirects, robots, sitemaps, schema, internal links, content opportunities, and keyword research. Minor gaps include lack of Google Search Console sitemap deletion or GA4 property management, but these are outside typical scope.

    Maintenance

    ActivityMaintained
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      B
      maintenance
      SEO audit and Google Search Console MCP server with 23 tools. Search analytics, URL inspection, Indexing API, Core Web Vitals (CrUX), striking distance keywords, keyword cannibalization detection, branded query analysis, and automated site audits.
      43
      3
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      MCP server for Google Search Console, URL Inspection & Indexing API — search analytics, sitemap management, and batch indexing
      13
      149 npm
      8
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      OAuth-protected Google Search Console MCP for analytics, URL inspection, sitemap management, indexing requests, and SEO diagnostics. Open-source Cloudflare Workers implementation with 17 tools.
      17
      389 npm
      8
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables SEO audits, keyword research, rank tracking, and Core Web Vitals reporting through an MCP interface using only free services.
      15 npm
      Apache 2.0