Skip to main content
Glama
SEO Performance MCP

SEO Performance MCP

seo-performance-mcp

Know which blog posts to refresh, expand, merge, or kill - without guessing.

A MCP server that turns your scattered SEO and analytics data into one clear verdict per URL. Plug it into Claude, Cursor, or any MCP-aware client and ask: "Which three posts should I update this week?" - and get an answer backed by hard numbers.

What it does

seo-performance-mcp unifies post-publish signals from every channel you already pay for:

  • Google Search Console - clicks, impressions, CTR, position, top queries

  • Matomo or GA4 - visits, dwell time, bounce rate

  • Microsoft Clarity - scroll depth, rage clicks, dead clicks

  • AI citation tracking - which LLMs cite your URL today vs. last month

  • Sitemap / CMS - publish dates, tags, word counts (any platform via XML sitemap; optional Ghost integration for richer metadata)

It then runs a deterministic rule engine over those signals and emits a verdict per URL:

refresh / expand / merge / kill / double_down / hold

with reason codes, evidence, and a 0-1 confidence score. Reporting only - the server never mutates your posts.

Related MCP server: GSC SEO MCP

Why it matters

Most content teams have analytics in five tabs and a gut feeling. That's how good posts rot quietly, mediocre posts get over-promoted, and the obvious "rewrite this one" is invisible until traffic has already cratered.

This MCP closes the loop:

  • One question, one URL in, one verdict out.

  • Same logic across the whole cohort, so the ranking is comparable.

  • All decisions traceable to numeric thresholds you can pin in src/verdict/rules.ts.

  • AI clients (Claude, Cursor, MCP hosts) can drive the entire content audit in plain English.

Who it's for

  • Content marketers running a blog of 50+ posts and tired of guessing what to refresh.

  • SEO consultants doing audits who want a portable, deterministic scoring layer instead of bespoke spreadsheets.

  • AI-first content teams wiring up rewrite agents - this MCP is the upstream signal layer.

  • Indie publishers on Ghost, WordPress, Hugo, Astro, Next, Webflow, or any CMS that exposes a sitemap.

What you get

After one cohort run you have:

  • A ranked table of every post with a verdict and confidence score.

  • A markdown brief per "refresh" URL: numbers + top queries + suggested actions an editor (or a writing agent) can act on immediately.

  • A list of "quick wins": queries sitting at positions 5-15 with below-expected CTR - the fastest title-rewrite wins on the property.

  • A historical AI-citation diff: which LLMs cited you and stopped.

Install

npx -y @automatelab/seo-performance-mcp

In a Claude, Claude Code, or Cursor MCP config:

{
  "mcpServers": {
    "seo-performance": {
      "command": "npx",
      "args": ["-y", "@automatelab/seo-performance-mcp"],
      "env": {
        "POSTS_SITEMAP_URL": "https://example.com/sitemap.xml",
        "GSC_SERVICE_ACCOUNT_JSON": "<base64-encoded service-account JSON>",
        "GSC_SITE_URL": "sc-domain:example.com",
        "MATOMO_URL": "https://example.com/analytics",
        "MATOMO_TOKEN": "...",
        "MATOMO_SITE_ID": "1",
        "GA4_PROPERTY_ID": "123456789",
        "GA4_SERVICE_ACCOUNT_JSON": "<base64-encoded service-account JSON>",
        "CLARITY_PROJECT_ID": "...",
        "CLARITY_API_TOKEN": "...",
        "CITATION_INTELLIGENCE_URL": "https://citation.example.com"
      }
    }
  }
}

Every env var is optional. Adapters that lack their env config skip their slice of the snapshot; the server still boots. The verdict engine works on whatever slices are present.

Platform integration

Point it at any site, no CMS plugin required. The post-discovery layer resolves in priority order:

  1. POSTS_LIST - JSON array of {url, title?, published_at?, tags?, word_count?}. Use this when you already have a content index and want exact control.

  2. Ghost Admin API - if both GHOST_ADMIN_API_URL and GHOST_ADMIN_API_KEY are set, Ghost is used as a richer metadata source. Optional.

  3. HTML extraction - per-URL og:title, article:published_time, and JSON-LD datePublished are read live from the URL.

  4. XML sitemap - set POSTS_SITEMAP_URL to your sitemap (or sitemap index) and the server enumerates posts from <loc> + <lastmod>.

Most users only need POSTS_SITEMAP_URL. WordPress, Hugo, Astro, Next.js, Webflow, Framer, Wix, Squarespace, Notion-as-a-site, Substack-mirror sites all expose a sitemap by default.

To add a brand-new platform: nothing to build - just point POSTS_SITEMAP_URL at it.

Tools exposed

Tool

What it returns

posts_list

Posts with {url, title, age_days, tags} from sitemap, Ghost, or your POSTS_LIST.

posts_snapshot

Per-URL unified rollup for a 30/60/90-day window: GSC + Matomo + GA4 + Clarity + citations + meta.

posts_decay_curve

Weekly GSC clicks/impressions/position buckets + a decay/plateau/growth trend label.

posts_verdict

Verdict (refresh/expand/merge/kill/double_down/hold) + reason codes + 0-1 confidence.

posts_refresh_brief

Markdown brief for a human or downstream LLM editor: numbers, top queries, suggested actions.

cohort_report

Cohort verdict table sorted by priority + confidence. "Which three posts should I refresh this week?"

posts_cite_loss

LLM citations that dropped off for a given URL. Needs CITATION_INTELLIGENCE_URL.

gsc_quick_wins

(page, query) pairs at positions 5-15 with low CTR - fastest title-rewrite wins.

Use as a GitHub Action

Run any of the tools on a cron from CI and post the output to a GitHub Issue, Discussion, or PR. The action is published on the GitHub Marketplace.

- uses: AutomateLab-tech/seo-performance-mcp@v1
  with:
    tool: cohort_report
    format: markdown
    input: '{"window": 90, "min_age_days": 90, "limit": 20}'
    gsc-service-account-json: ${{ secrets.GSC_SERVICE_ACCOUNT_JSON }}
    gsc-site-url: ${{ secrets.GSC_SITE_URL }}
    posts-sitemap-url: ${{ secrets.POSTS_SITEMAP_URL }}

Outputs:

Output

Description

result

Tool output as a multi-line string (markdown or JSON, per format).

result-file

Path of the file the tool output was written to. Hand to peter-evans/create-issue-from-file etc.

rows

For cohort_report with format: json only: number of rows returned.

A complete weekly-audit workflow that opens a GitHub Issue with the cohort report is in examples/weekly-cohort-report.yml.

Use as a one-shot CLI

The package also ships a seo-perf-cli bin so you can run a single tool without an MCP client:

npx -p @automatelab/seo-performance-mcp seo-perf-cli cohort_report \
  --input '{"window": 90, "limit": 20}' \
  --format markdown

Same env vars as the MCP server. --format markdown is supported for cohort_report and posts_refresh_brief; other tools fall back to fenced JSON.

Companion skills + Cursor rule

Three thin routing files ship in the repo so the LLM in your client knows when to reach for these tools:

  • skills/seo-performance/SKILL.md - tool-routing skill. Drop into ~/.claude/skills/seo-performance/ (or .claude/skills/ per project) to auto-load in Claude Code. Routes a single question to the right tool.

  • skills/weekly-audit/SKILL.md - one-shot weekly audit playbook. Composes gsc_quick_wins + cohort_report + posts_cite_loss into a deduped, cross-signal ranked digest with proposed edits per URL. Drop in alongside the routing skill.

  • cursor/rules/seo-performance.mdc - copy to .cursor/rules/seo-performance.mdc in any Cursor workspace.

All optional. The MCP server works without them; they just shorten the "which tool do I call" round-trip.

MCP prompts

The server exposes three prompts that bundle the playbook. Any MCP client (Claude Desktop, Claude Code, Cursor, Continue) can list and invoke them:

Prompt

What it runs

audit_cohort

cohort_report on posts >=90d, then posts_refresh_brief per refresh/expand/merge row. The weekly audit.

find_quick_wins

gsc_quick_wins (positions 5-15) + per-URL posts_snapshot, then proposes verbatim-query meta_title rewrites.

citation_loss_sweep

posts_cite_loss per URL, refresh_brief for any with losses, targeted H1/lead phrasing recommendations.

Verdict engine

Deterministic, rule-based, traceable. Reason codes:

  • ctr_below_position_expected

  • position_drift

  • decay_30d_over_30pct / decay_60d_over_50pct

  • stagnant_no_clicks

  • thin_content_low_dwell

  • rising_impressions_low_ctr / rising_clicks_continue_investment

  • citation_loss / citation_growth

  • duplicate_or_cannibalizing

  • high_bounce_low_scroll

  • fresh_post_too_young

The mapping (reasons → verdict) and every threshold lives in src/verdict/rules.ts. Edit it, pin it in tests, ship your own rule book.

Development

npm install
npm run dev        # tsx src/index.ts
npm run build      # tsc
npm test           # vitest

License

MIT

Maintenance and verification

See the maintenance guide for interpretation limits, current tool names where applicable, and reproducible verification.

Available Tools

9 tools
bing_quick_winsBing quick wins (positions 5-15)A
Read-onlyIdempotent

Scan Bing Webmaster Tools for queries sitting in positions 5-15 with non-trivial impressions. Bing's index backs Copilot, ChatGPT search, and Perplexity grounding, so a Bing rank gap is an LLM-citation gap.

Query-level only: Bing has no single page+query API, so - unlike gsc_quick_wins, which returns (page, query) pairs - these carry no url. Sorted by impressions desc.

Requires BING_WEBMASTER_API_KEY (Bing Webmaster Tools -> Settings -> API Access). Best-effort: returns config_missing if unset.

Inputs: limit, window, max_position, min_position, +1 more. Returns: wins

cohort_reportCohort report across postsB
Read-only

Run the verdict engine across a cohort (filtered by tag and/or min-age) and return a ranked table sorted by verdict priority then confidence.

Practical use: 'which three posts should I refresh this week?' - the top three rows with verdict=refresh and highest confidence are the answer.

Inputs: urls, limit, window, sitemap_url, +1 more. Returns: rows

gsc_quick_winsGSC quick wins (positions 5-15)A
Read-onlyIdempotent

Scan GSC for (page, query) pairs sitting in positions 5-15 with non-trivial impressions and a CTR below their position-expected curve. These are the fastest title-rewrite wins.

Returns top results sorted by impressions desc. Pure GSC pull - platform-agnostic.

Inputs: limit, window, max_position, min_position, +1 more. Returns: wins

posts_cite_lossAI-citation losses per URLA
Read-onlyIdempotent

Return the list of LLMs that previously cited this URL but no longer do, with the prior query and last-seen date. Optionally includes the URL that replaced ours.

Requires a configured citation-intelligence MCP endpoint (CITATION_INTELLIGENCE_URL). Otherwise returns an empty list.

Inputs: url (required). Returns: url, active, losses

posts_decay_curveWeekly GSC decay curveA
Read-onlyIdempotent

Bucket GSC clicks/impressions/avg-position into ~weekly windows for the last N weeks (default 12) and classify the trend: decay / plateau / growth.

Underpins the verdict engine's decay rules. Read-only GSC query.

Inputs: url (required), weeks. Returns: url, trend, buckets, decay_pct

posts_listList posts from any platformA
Read-onlyIdempotent

Discover posts via an XML sitemap (POSTS_SITEMAP_URL or the sitemap_url arg), a JSON override list (POSTS_LIST), or - if configured - the Ghost Admin API. Pass an explicit urls[] to skip discovery entirely.

Returns metadata: url, title, published_at, age_days, tags. Filter by minimum age or published-after date.

When to use: discover which URLs are eligible for snapshot / verdict / cohort analysis. Works with any CMS that exposes a sitemap.

Inputs: urls, limit, since, sitemap_url, +1 more. Returns: posts

posts_refresh_briefRefresh brief (markdown) per postA
Read-only

Produce a markdown brief for a human (or downstream LLM) editor: verdict + reasons + raw numbers + top queries + suggested actions.

Use this as the hand-off artefact when verdict is refresh / expand / merge / double_down.

Inputs: url (required), window. Returns: markdown

posts_snapshotUnified per-URL snapshotA
Read-only

Pull a 30/60/90-day snapshot across every configured signal source for one post: GSC clicks/impressions/CTR/position + top queries, Matomo visits + dwell, GA4 pageviews, Clarity scroll/rage clicks, AI-citation counts.

Each source is best-effort: if its env vars are missing the field is omitted. Returns whatever is available.

Read-only. No third-party writes. Optionally persists to the local DuckDB cache when persist=true.

Inputs: url (required), window, persist. Returns: ga4, gsc, bing, meta, +5 more

posts_verdictVerdict per post (refresh / expand / merge / kill / double_down / hold)A
Read-only

Run the rule-based verdict engine on a single post: combine snapshot + decay curve and emit a verdict with reason codes and a 0-1 confidence score.

Reason codes are deterministic. The mapping reasons -> verdict lives in src/verdict/rules.ts and can be inspected.

Reporting only - does NOT mutate anything. To act on the verdict, hand the brief to a writer or to an AI rewrite tool.

Inputs: url (required), window, persist. Returns: url, reasons, verdict, evidence, +2 more

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 9 tools

    Disambiguation4/5

    Each tool targets a distinct stage of the pipeline (discover, snapshot, analyze, verdict, brief, cohort, citation-loss, two platform-specific quick-win scans). posts_snapshot and posts_decay_curve both draw on GSC data but are clearly differentiated by purpose (raw multi-source snapshot vs. weekly trend classification), so only minor overlap remains.

    Naming Consistency4/5

    Most tools follow a consistent domain_action pattern (posts_list, posts_snapshot, posts_verdict, gsc_quick_wins, bing_quick_wins). cohort_report and the quick_wins names break the verb-style slightly, but all remain readable and predictable.

    Tool Count5/5

    Nine tools map cleanly onto a coherent SEO-analysis workflow, each earning its place without redundancy. This is squarely in the well-scoped 3-15 range.

    Completeness4/5

    The surface covers discovery, multi-source snapshots, decay analysis, verdict, human briefs, cohort ranking, citation loss, and GSC/Bing quick wins - a full read-side lifecycle. Gaps like historical time-series comparison or competitor benchmarking are minor and workable around.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      AutomateLab AI SEO Magic Button runs a whole-site AEO/GEO audit and generates a prioritized plan an agent can execute. It combines AI-SEO and Citation Intelligence and ships as a skill, plugin, and MCP server. Product and documentation: https://automatelab.tech/products/skills-and-plugins/ai-seo-magic-button/
      1
      26 npm
      2
      MIT
    • A
      license
      B
      quality
      D
      maintenance
      Professional Google Search Console MCP server providing 40+ SEO tools for performance analysis, content decay, CTR opportunities, and more, enabling real search data in clients like Cursor and Claude.
      40
      13 npm
      6
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Open-source MCP server that audits websites for AI search readiness, providing deterministic scoring (0-100) and prioritized fix lists for metrics like JSON-LD, llms.txt, heading hierarchy, and AI crawler access.
      1
      MIT