Launching the seo-performance MCP

A post-publish SEO MCP that unifies GSC, GA4, Matomo, Clarity, and AI-citation signals per URL and emits a verdict per post with reason codes.

AutomateLab title card for the seo-performance MCP launch, dark slate gradient with a Lucide gauge icon in the AI Agents accent.
seo-performance-mcp ships free on npm with eight read-only MCP tools that emit per-URL refresh verdicts from GSC, GA4, Matomo, Clarity, and AI-citation data.

TL;DR: seo-performance-mcp pulls Google Search Console, GA4, Matomo, Clarity, and AI-citation data per URL and emits a verdict per post (refresh, expand, merge, kill, double_down, hold) with explicit reason codes.

We just published @automatelab/seo-performance-mcp on npm. It is a Model Context Protocol server for the part of SEO that starts after the post goes live: triage. Which URLs are decaying, which are quietly winning, which lost an AI citation last week, which sit at position 7 with a low CTR and want a title rewrite. Free, MIT-licensed, no email gate.

What does seo-performance-mcp do?

Most SEO tooling stops at "the post is live." This MCP starts there. For any URL on your site it pulls Search Console (clicks, impressions, CTR, position, top queries), GA4 (pageviews), Matomo (visits, dwell), Microsoft Clarity (scroll depth, rage clicks), and AI-citation counts from a configured citation-intelligence endpoint. Every signal source is optional. Provide the env vars for the platforms you use; the rest are skipped silently.

Architecture diagram: five optional signal sources (Google Search Console, GA4, Matomo, Microsoft Clarity, and a citation-intelligence endpoint) fan into the seo-performance-mcp snapshot and 12-week GSC decay curve, which feed a deterministic rules-based verdict engine that emits one of six per-URL verdicts: double_down, refresh, expand, merge, hold, kill, each with a reason code and a 0-1 confidence score.
Every source is optional. The verdict engine is rules-based, so the same inputs always produce the same call - and it never edits anything.

The data flows through a deterministic verdict engine. It combines the snapshot with a 12-week GSC decay curve and emits one of six calls per post: refresh, expand, merge, kill, double_down, or hold. Each verdict carries explicit reason codes (the rules live in src/verdict/rules.ts and can be inspected) and a 0-1 confidence score. The mapping is rules-based, not LLM-based, so the same inputs always produce the same call.

Reporting only. The server never edits a post, never publishes anything, never touches a third-party platform with anything other than a read. The verdict and the refresh brief are hand-off artefacts for a writer, an editor, or a downstream rewrite tool.

Which tools does it ship?

Eight tools, organised as a dot-notation tree: posts.* for per-URL analysis, cohort.* for cross-post roll-ups, gsc.* for direct Search Console scans.

  • posts.list: Discover indexable posts via an XML sitemap, a JSON override list, or the Ghost Admin API. Filter by minimum age or published-after date.
  • posts.snapshot: Pull a 30, 60, or 90-day snapshot across every configured signal source for one URL. Each source is best-effort.
  • posts.decay_curve: Bucket GSC clicks, impressions, and average position into weekly windows and classify the trend: decay, plateau, or growth. Underpins the verdict engine's decay rules.
  • posts.verdict: Run the rule-based verdict engine on one URL. Returns verdict, reason codes, and confidence.
  • posts.refresh_brief: Produce a markdown brief for a human or downstream LLM editor: verdict, reasons, raw numbers, top queries, suggested actions.
  • posts.cite_loss: Return the list of LLMs that previously cited this URL but no longer do, with the prior query and last-seen date. Optionally identifies the URL that replaced yours.
  • cohort.report: Run the verdict engine across a cohort filtered by tag and minimum age. Returns a ranked table sorted by verdict priority then confidence. Answers "which three posts should I refresh this week?"
  • gsc.quick_wins: Scan GSC for (page, query) pairs at positions 5 to 15 with non-trivial impressions and a CTR below the position-expected curve. The fastest title-rewrite wins. Platform-agnostic pure GSC pull.
Taxonomy of the eight seo-performance-mcp tools: six under posts.* for per-URL analysis (list, snapshot, decay_curve, verdict, refresh_brief, cite_loss), one under cohort.* for cross-post roll-up (cohort.report), and one under gsc.* as a platform-agnostic GSC pull (gsc.quick_wins). Three discoverable MCP prompts ship alongside: audit_cohort, find_quick_wins, citation_loss_sweep.
posts.* drills into one URL. cohort.* rolls up a tag-filtered set. gsc.* hits Search Console directly for position 5-15 quick wins.

Three discoverable prompts ship alongside: audit_cohort, find_quick_wins, citation_loss_sweep. No skill loader required; any MCP-capable client picks them up.

Install

Requires Node 20+. Add the server to your MCP host config (~/.cursor/mcp.json for Cursor, claude_desktop_config.json for Claude Desktop, .mcp.json for Claude Code), then restart the host.

{
  "mcpServers": {
    "seo-performance": {
      "command": "npx",
      "args": ["-y", "@automatelab/seo-performance-mcp"],
      "env": {
        "GSC_SERVICE_ACCOUNT_JSON": "/abs/path/to/gsc-service-account.json",
        "GSC_SITE_URL": "sc-domain:example.com",
        "MATOMO_BASE_URL": "https://example.com/analytics",
        "MATOMO_TOKEN": "...",
        "MATOMO_SITE_ID": "1",
        "GA4_PROPERTY_ID": "123456789",
        "CLARITY_PROJECT_ID": "...",
        "GHOST_ADMIN_KEY": "id:secret"
      }
    }
  }
}

Every env var is optional. Provide the ones you have; the rest are skipped at runtime. Discovery falls back to a sitemap if Ghost is not configured.

What does a weekly run look like?

The intended loop, run from a chat with any MCP-capable agent:

Run cohort.report on posts older than 90 days, window 30, limit 20. For every row with verdict refresh, expand, merge, or double_down, call posts.refresh_brief. Sort by verdict priority then confidence and pick the top three to act on this week.

The same prompt ships as the audit_cohort MCP prompt, so it appears in your client's prompt menu without any setup. find_quick_wins does the same for position 5-15 SERP rewrites; citation_loss_sweep chains posts.list into posts.cite_loss into posts.refresh_brief for any URLs that lost LLM citations.

The verdict is reporting, not action. The brief tells you which URL to touch and why. Whether the rewrite happens in Cursor, in Claude Code, or in a human editor's tab, is up to you.