gscserpmcp
GSC + SERP Data: Combined SEO Workflow via MCP
GSC shows clicks and impressions. SERP API shows rankings, competitors, and AI Overview citations. Combined they answer why traffic changed, not just what.
9 min
Combining Google Search Console (GSC) data with live SERP API data via MCP gives you the complete SEO picture: GSC shows your clicks, impressions, and CTR; SERP API shows where you actually rank, who outranks you, and whether AI Overviews cite your pages. Together, they answer "why" your traffic changed, not just "what" changed.
What each data source provides
Text
Data source | Provides | Misses
GSC | Clicks, impressions, CTR | Competitor data, AI Overviews
SERP API | Rankings, competitors, AIO | Your click/impression data
Combined | Full picture | Nothing materialMCP config for combined workflow
JSON
{
"mcpServers": {
"scavio": {
"url": "https://mcp.scavio.dev/mcp",
"headers": {
"x-api-key": "YOUR_KEY"
}
}
}
}Combined analysis pipeline
Python
import requests
# Step 1: Get your top queries from GSC
# (This data comes from GSC API or exported CSV)
gsc_queries = [
{"query": "search api for ai agents", "clicks": 45, "impressions": 1200, "ctr": 0.038},
{"query": "serp api pricing comparison", "clicks": 30, "impressions": 800, "ctr": 0.038},
{"query": "tavily alternatives 2026", "clicks": 20, "impressions": 600, "ctr": 0.033},
]
# Step 2: Enrich with live SERP data
def enrich_gsc_query(gsc_data: dict) -> dict:
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": "YOUR_KEY"},
json={
"query": gsc_data["query"],
"num_results": 20,
"include_ai_overview": True
}
)
serp = resp.json()
# Find your rank
my_domain = "yourdomain.com"
rank = None
for r in serp.get("organic_results", []):
if my_domain in r.get("url", ""):
rank = r["position"]
break
# Check AI Overview
ai_cited = any(
my_domain in c.get("url", "")
for c in serp.get("ai_overview", {}).get("citations", [])
)
# Get competitors above you
competitors_above = [
r["url"] for r in serp.get("organic_results", [])
if r["position"] < (rank or 999) and my_domain not in r["url"]
]
return {
**gsc_data,
"current_rank": rank,
"ai_overview_cited": ai_cited,
"competitors_above": competitors_above[:3],
"has_ai_overview": bool(serp.get("ai_overview"))
}
enriched = [enrich_gsc_query(q) for q in gsc_queries]
for e in enriched:
print(f"Query: {e['query']}")
print(f" GSC: {e['clicks']} clicks, {e['impressions']} impressions")
print(f" Rank: #{e['current_rank']}, AI Cited: {e['ai_overview_cited']}")
print(f" Competitors above: {e['competitors_above']}")
Insights from combined data
JavaScript
// Identify optimization opportunities
function analyzeOpportunities(enrichedQueries) {
const opportunities = [];
for (const q of enrichedQueries) {
// High impressions, low CTR, not in AI Overview
if (q.impressions > 500 && q.ctr < 0.03 && !q.ai_overview_cited) {
opportunities.push({
query: q.query,
type: "AEO optimization",
reason: "High visibility but low CTR -- AI Overview citation could help"
});
}
// Ranking 4-10 with AI Overview existing
if (q.current_rank >= 4 && q.current_rank <= 10 && q.has_ai_overview) {
opportunities.push({
query: q.query,
type: "Content improvement",
reason: "Rank " + q.current_rank + " -- improve content to get AI citation"
});
}
// Ranking 1-3 but losing clicks (AI Overview taking clicks)
if (q.current_rank <= 3 && q.ctr < 0.02 && q.has_ai_overview) {
opportunities.push({
query: q.query,
type: "AI Overview defense",
reason: "Top 3 rank but low CTR -- AI Overview absorbing clicks"
});
}
}
return opportunities;
}
Run as a weekly workflow
- Export GSC top 100 queries (weekly)
- Enrich each with SERP API (100 queries = $0.50)
- Generate opportunity report
- Track week-over-week changes in AI Overview citations
Cost
Weekly enrichment of 100 GSC queries: 400 queries/month = $2.00. Daily enrichment of top 20 queries: 600 queries/month = $3.00. GSC API access is free. Total: under $5/month for a combined SEO intelligence pipeline.