{
  "markdown": "# seo-performance-mcp\n\n**Know which blog posts to refresh, expand, merge, or kill - without guessing.**\n\nA 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.\n\n## What it does\n\n`seo-performance-mcp` unifies post-publish signals from every channel you already pay for:\n\n- **Google Search Console** - clicks, impressions, CTR, position, top queries\n- **Matomo** or **GA4** - visits, dwell time, bounce rate\n- **Microsoft Clarity** - scroll depth, rage clicks, dead clicks\n- **AI citation tracking** - which LLMs cite your URL today vs. last month\n- **Sitemap / CMS** - publish dates, tags, word counts (any platform via XML sitemap; optional Ghost integration for richer metadata)\n\nIt then runs a deterministic rule engine over those signals and emits a verdict per URL:\n\n> `refresh` / `expand` / `merge` / `kill` / `double_down` / `hold`\n\nwith reason codes, evidence, and a 0-1 confidence score. Reporting only - the server never mutates your posts.\n\n## Why it matters\n\nMost 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.\n\nThis MCP closes the loop:\n\n- One question, one URL in, one verdict out.\n- Same logic across the whole cohort, so the ranking is comparable.\n- All decisions traceable to numeric thresholds you can pin in `src/verdict/rules.ts`.\n- AI clients (Claude, Cursor, MCP hosts) can drive the entire content audit in plain English.\n\n## Who it's for\n\n- **Content marketers** running a blog of 50+ posts and tired of guessing what to refresh.\n- **SEO consultants** doing audits who want a portable, deterministic scoring layer instead of bespoke spreadsheets.\n- **AI-first content teams** wiring up rewrite agents - this MCP is the upstream signal layer.\n- **Indie publishers** on Ghost, WordPress, Hugo, Astro, Next, Webflow, or any CMS that exposes a sitemap.\n\n## What you get\n\nAfter one cohort run you have:\n\n- A ranked table of every post with a verdict and confidence score.\n- A markdown brief per \"refresh\" URL: numbers + top queries + suggested actions an editor (or a writing agent) can act on immediately.\n- A list of \"quick wins\": queries sitting at positions 5-15 with below-expected CTR - the fastest title-rewrite wins on the property.\n- A historical AI-citation diff: which LLMs cited you and stopped.\n\n## Install\n\n```bash\nnpx -y @automatelab/seo-performance-mcp\n```\n\nIn a Claude, Claude Code, or Cursor MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"seo-performance\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@automatelab/seo-performance-mcp\"],\n      \"env\": {\n        \"POSTS_SITEMAP_URL\": \"https://example.com/sitemap.xml\",\n        \"GSC_SERVICE_ACCOUNT_JSON\": \"<base64-encoded service-account JSON>\",\n        \"GSC_SITE_URL\": \"sc-domain:example.com\",\n        \"MATOMO_URL\": \"https://example.com/analytics\",\n        \"MATOMO_TOKEN\": \"...\",\n        \"MATOMO_SITE_ID\": \"1\",\n        \"GA4_PROPERTY_ID\": \"123456789\",\n        \"GA4_SERVICE_ACCOUNT_JSON\": \"<base64-encoded service-account JSON>\",\n        \"CLARITY_PROJECT_ID\": \"...\",\n        \"CLARITY_API_TOKEN\": \"...\",\n        \"CITATION_INTELLIGENCE_URL\": \"https://citation.example.com\"\n      }\n    }\n  }\n}\n```\n\nEvery 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.\n\n## Platform integration\n\nPoint it at any site, no CMS plugin required. The post-discovery layer resolves in priority order:\n\n1. **`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.\n2. **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.\n3. **HTML extraction** - per-URL `og:title`, `article:published_time`, and JSON-LD `datePublished` are read live from the URL.\n4. **XML sitemap** - set `POSTS_SITEMAP_URL` to your sitemap (or sitemap index) and the server enumerates posts from `<loc>` + `<lastmod>`.\n\nMost 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.\n\nTo add a brand-new platform: nothing to build - just point `POSTS_SITEMAP_URL` at it.\n\n## Tools exposed\n\n| Tool | What it returns |\n|---|---|\n| `posts_list` | Posts with `{url, title, age_days, tags}` from sitemap, Ghost, or your `POSTS_LIST`. |\n| `posts_snapshot` | Per-URL unified rollup for a 30/60/90-day window: GSC + Matomo + GA4 + Clarity + citations + meta. |\n| `posts_decay_curve` | Weekly GSC clicks/impressions/position buckets + a `decay/plateau/growth` trend label. |\n| `posts_verdict` | Verdict (`refresh/expand/merge/kill/double_down/hold`) + reason codes + 0-1 confidence. |\n| `posts_refresh_brief` | Markdown brief for a human or downstream LLM editor: numbers, top queries, suggested actions. |\n| `cohort_report` | Cohort verdict table sorted by priority + confidence. \"Which three posts should I refresh this week?\" |\n| `posts_cite_loss` | LLM citations that dropped off for a given URL. Needs `CITATION_INTELLIGENCE_URL`. |\n| `gsc_quick_wins` | `(page, query)` pairs at positions 5-15 with low CTR - fastest title-rewrite wins. |\n\n## Use as a GitHub Action\n\nRun 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.\n\n```yaml\n- uses: AutomateLab-tech/seo-performance-mcp@v1\n  with:\n    tool: cohort_report\n    format: markdown\n    input: '{\"window\": 90, \"min_age_days\": 90, \"limit\": 20}'\n    gsc-service-account-json: ${{ secrets.GSC_SERVICE_ACCOUNT_JSON }}\n    gsc-site-url: ${{ secrets.GSC_SITE_URL }}\n    posts-sitemap-url: ${{ secrets.POSTS_SITEMAP_URL }}\n```\n\nOutputs:\n\n| Output | Description |\n|---|---|\n| `result` | Tool output as a multi-line string (markdown or JSON, per `format`). |\n| `result-file` | Path of the file the tool output was written to. Hand to `peter-evans/create-issue-from-file` etc. |\n| `rows` | For `cohort_report` with `format: json` only: number of rows returned. |\n\nA complete weekly-audit workflow that opens a GitHub Issue with the cohort report is in [examples/weekly-cohort-report.yml](./examples/weekly-cohort-report.yml).\n\n## Use as a one-shot CLI\n\nThe package also ships a `seo-perf-cli` bin so you can run a single tool without an MCP client:\n\n```bash\nnpx -p @automatelab/seo-performance-mcp seo-perf-cli cohort_report \\\n  --input '{\"window\": 90, \"limit\": 20}' \\\n  --format markdown\n```\n\nSame env vars as the MCP server. `--format markdown` is supported for `cohort_report` and `posts_refresh_brief`; other tools fall back to fenced JSON.\n\n## Companion skills + Cursor rule\n\nThree thin routing files ship in the repo so the LLM in your client knows *when* to reach for these tools:\n\n- `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.\n- `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.\n- `cursor/rules/seo-performance.mdc` - copy to `.cursor/rules/seo-performance.mdc` in any Cursor workspace.\n\nAll optional. The MCP server works without them; they just shorten the \"which tool do I call\" round-trip.\n\n## MCP prompts\n\nThe server exposes three prompts that bundle the playbook. Any MCP client (Claude Desktop, Claude Code, Cursor, Continue) can list and invoke them:\n\n| Prompt | What it runs |\n|---|---|\n| `audit_cohort` | `cohort_report` on posts >=90d, then `posts_refresh_brief` per refresh/expand/merge row. The weekly audit. |\n| `find_quick_wins` | `gsc_quick_wins` (positions 5-15) + per-URL `posts_snapshot`, then proposes verbatim-query meta_title rewrites. |\n| `citation_loss_sweep` | `posts_cite_loss` per URL, refresh_brief for any with losses, targeted H1/lead phrasing recommendations. |\n\n## Verdict engine\n\nDeterministic, rule-based, traceable. Reason codes:\n\n- `ctr_below_position_expected`\n- `position_drift`\n- `decay_30d_over_30pct` / `decay_60d_over_50pct`\n- `stagnant_no_clicks`\n- `thin_content_low_dwell`\n- `rising_impressions_low_ctr` / `rising_clicks_continue_investment`\n- `citation_loss` / `citation_growth`\n- `duplicate_or_cannibalizing`\n- `high_bounce_low_scroll`\n- `fresh_post_too_young`\n\nThe mapping (reasons → verdict) and every threshold lives in `src/verdict/rules.ts`. Edit it, pin it in tests, ship your own rule book.\n\n## Development\n\n```bash\nnpm install\nnpm run dev        # tsx src/index.ts\nnpm run build      # tsc\nnpm test           # vitest\n```\n\n## License\n\nMIT\n",
  "bytes": 9096,
  "sha": "a542b490d6c66e40b905bae43cbbcfb4bd0ae39f83d274f6aa7545b930baf619",
  "repo_slug": "automatelab-tech/seo-performance-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_automatelab_tech_seo_performan_f3d6394e/readme"
}