Connect Google Search Console to Claude and Claude Code: three ways, and what each is for
There are three ways to connect Google Search Console to Claude, and Google publishes none of them: as of September 26, 2026, Google ships official MCP servers for Google Analytics and Google Ads, but not for Search Console. You can run a community MCP server such as mcp-gsc on your own machine with your own Google Cloud credentials; you can add a data vendor's hosted Claude connector (Supermetrics, Windsor.ai, Porter Metrics); or you can sync the property into a data backend that Claude Code queries with read-only SQL — the route TableBI takes. The first two call the Search Console API at the moment you ask. The third keeps a stored copy that separates site totals, which include the anonymized queries Google leaves out of every query table, from the query-and-page detail. This guide compares the routes side by side, then walks through the third one: connect once with tablebi connect gsc, ask in SQL, fall back to live API calls (tablebi gsc query, inspect, sitemaps) for what the tables don't hold, and pin a self-refreshing SEO dashboard.
Three ways to connect Search Console to Claude, and what each one is for
Every "Search Console MCP server" you can install today is third-party. Google's own list of official MCP servers names a Google Analytics server and no Search Console one, and Google Cloud's list of Google-managed MCP servers (updated September 25, 2026) has no Search Console entry either. Claude's built-in Google connectors cover Gmail, Google Calendar and Google Drive — not Search Console. What remains are community MCP servers you run yourself, hosted connectors from marketing-data vendors, and synced backends.
| Route | What Claude reads | Can it change Search Console? | What you set up | Price |
|---|---|---|---|---|
| mcp-gsc (community MCP server) | 20 tools over the live API: search analytics by country, device and period, URL inspection (10 URLs per batch), sitemaps | Yes — it submits sitemaps; adding or removing properties and deleting sitemaps stay off unless you set GSC_ALLOW_DESTRUCTIVE to true | Your own Google Cloud project with the Search Console API enabled, plus an OAuth client or a service-account key; runs locally via uvx; updated September 2026 | Free, open source (MIT) |
| mcp-server-gsc (community MCP server) | Search analytics up to 25,000 rows per request, regex filters, a "quick wins" finder, URL inspection, sitemap lists | It lists a submit_sitemap tool, but its code asks Google only for the read-only Search Console scope | A service-account key whose email you add to the property; Node.js 18+ via npx; updated September 2026 | Free, open source (MIT) |
| Supermetrics' Claude connector | Performance data fetched per question — query, page, country, device, date, search type — plus sitemap and indexed-URL counts; no URL inspection | No — its write actions cover ad platforms only | Click Connect on its listing in Claude's directory, then authorize Search Console | 14-day free trial; paid plans from €49/month billed monthly |
| Windsor.ai's Claude connector | Search Console fields (10 metrics, 43 dimensions by Windsor's count), including search type: web, image, video, news, Discover | No Search Console write actions listed | Pick Search Console at Windsor.ai, then add the Windsor connector in Claude (Customize → Connectors) | Free plan (one source, last 30 days of data); paid plans from $19/month billed yearly ($23 month to month), as of September 2026 |
| TableBI (this page) | A synced copy in four tables — query × page detail, site totals with anonymized traffic, per-page totals, country × device — plus live calls (tablebi gsc query, inspect, sitemaps) for search appearance, URL inspection and sitemap status | No — read-only by design | One OAuth: tablebi connect gsc --site sc-domain:example.com; Google credentials stay on TableBI's server | Free: one source and one live dashboard; Operator $29/month, by request (pricing) |
Sources, read September 26, 2026 (prices as of September 2026): AminForou/mcp-gsc (tools, credentials, changelog), ahonn/mcp-server-gsc (tools, credentials, source code), Supermetrics' Search Console to Claude page and pricing, Windsor.ai's Search Console to Claude page and pricing, Porter Metrics' connector page, google/mcp (Google's list of official MCP servers), Google Cloud's supported MCP products, Google's Analytics and Google Ads MCP servers, and Claude's Google Workspace connectors.
Porter Metrics sells a connector in the same class and states that it is read-only: it never requests write scopes from Search Console, you paste its MCP URL into Claude as a custom connector, and it has a free plan, then $12.50 per property per month billed annually. On GitHub, mcp-gsc had about 1,700 stars and mcp-server-gsc about 270 on September 26, 2026; many smaller Search Console MCP projects exist, some of which bundle Bing Webmaster Tools or GA4 as well.
Pick by the job. An agent that should submit sitemaps — write access, not just reads — run by someone comfortable keeping Google Cloud credentials on their own machine, is what mcp-gsc is for. A marketer who works in claude.ai and already pays for a data platform gets Search Console in a few clicks through a vendor connector — and, per Claude Code's MCP documentation, connectors added in claude.ai also appear in Claude Code when you log in with the same account. A question that comes back every week, spans several properties or joins other channels is what a synced backend is built for: the numbers are stored once, with totals and query detail kept apart, instead of being re-fetched in every conversation. The rest of this page walks through that third route; the same comparison for paid search is in connect Google Ads to Claude Code.
The limit no route removes: anonymized queries
Google leaves anonymized queries — queries searched by no more than a few dozen people over two to three months — out of every query table in Search Console and in the API, but counts them in the chart totals (Google Search Central, "A deep dive into Search Console performance data filtering and limits"). Sum the rows of a query report and you get fewer clicks than the overview shows; how many fewer depends on the site. The Search Analytics API reference adds a second cap: a request returns at most 25,000 rows, and the API returns top rows rather than guaranteeing every row.
So a "top queries" answer from any MCP tool or connector describes the itemized part of your traffic, not all of it. TableBI stores both halves — site totals in search_console_totals_raw, which match the Search Console overview, and itemized queries in search_console_raw — and tablebi context reports, per site, what share of the last 28 days' clicks came from anonymized queries. The gap for every connected site, in one query:
tablebi ask "WITH totals AS (
SELECT site, SUM(clicks) AS all_clicks
FROM search_console_totals_raw
WHERE search_type = 'web'
AND date >= (SELECT MAX(date) FROM search_console_totals_raw) - 27
GROUP BY site),
by_query AS (
SELECT site, SUM(clicks) AS query_clicks
FROM search_console_raw
WHERE date >= (SELECT MAX(date) FROM search_console_raw) - 27
GROUP BY site)
SELECT site, all_clicks, query_clicks,
1 - query_clicks / NULLIF(all_clicks, 0) AS hidden_share
FROM totals JOIN by_query USING (site)
ORDER BY all_clicks DESC LIMIT 10"
The working rule that follows: take headline numbers and trends from the totals, and treat any query-level list as a subset that answers "which queries?", never "how much?".
Connect Search Console to Claude Code once
npm i -g @tablebi/cli
tablebi login
tablebi install
# browser opens for OAuth; one command per property
tablebi connect gsc --site sc-domain:example.com
tablebi install plants the TableBI skill in ~/.claude/skills/tablebi (the skill ships inside the npm package), so Claude Code knows these commands from then on — "which queries are slipping?" in plain English is enough to trigger the right query. How skills work, and which other marketing skills are worth installing, is covered in Claude Code marketing skills. The connection is read-only, and nothing is installed on your website.
Search Console data lands in four tables, each answering one kind of question:
search_console_raw— query × page detail by day:date,site,query,page,clicks,impressions,position,ctr. Anonymized queries are excluded, as in every query table.search_console_totals_raw— daily site totals per search type (web, image, video, news, Discover, Google News), anonymized traffic included; headline numbers usesearch_type = 'web'.search_console_pages_raw— daily totals per page, including clicks that came from anonymized queries.search_console_geo_raw— daily country × device totals per site, countries as three-letter lowercase codes such asusa.
Search Console rows also appear in the cross-channel facts table next to GA4, Google Ads and Meta Ads (beta), but there they carry only date, platform and account; query, page, country and device live in the four tables above. Each new session starts with tablebi context --json, one call that reloads definitions, connected sources, how fresh each one is and the per-site anonymized share.
Worth saying explicitly: this is a read-only path. tablebi ask runs read-only SQL over synced data, and tablebi gsc query, inspect and sitemaps only read from the API; nothing your agent does here can submit a sitemap, remove a URL or change a property setting.
Four Search Console queries worth stealing
1. Queries gaining or losing impressions
tablebi ask "SELECT query,
SUM(CASE WHEN date >= (SELECT MAX(date) FROM search_console_raw) - 13
THEN impressions ELSE 0 END) AS imp_recent,
SUM(CASE WHEN date < (SELECT MAX(date) FROM search_console_raw) - 13
THEN impressions ELSE 0 END) AS imp_prior
FROM search_console_raw
WHERE date >= (SELECT MAX(date) FROM search_console_raw) - 27
GROUP BY query
ORDER BY (imp_recent - imp_prior) ASC LIMIT 20"
The latest 14 days against the 14 before — the fastest way to see a core update or a decaying page in one table. The window anchors to MAX(date) in the data, not the wall clock; the query layer rejects current_date by design. Add AND site = 'example.com' to narrow it to one property.
2. Pages whose CTR underperforms their position
tablebi ask "SELECT page,
avg_position(SUM(position * impressions), SUM(impressions)) AS avg_pos,
ctr(SUM(clicks), SUM(impressions)) AS ctr,
SUM(impressions) AS impressions
FROM search_console_pages_raw
WHERE date >= (SELECT MAX(date) FROM search_console_pages_raw) - 27
GROUP BY page
HAVING avg_position(SUM(position * impressions), SUM(impressions)) <= 5
AND SUM(impressions) >= 100
ORDER BY ctr ASC LIMIT 20"
Ranking in the top five but clicked like page two usually means the title or snippet is losing the result page — the cheapest win in SEO, because a rewrite needs no new links. This reads the per-page table, so clicks from anonymized queries count. avg_position() and ctr() are definition macros: the average position is weighted by impressions instead of averaging rows equally, and the arithmetic is fixed in the engine, so the agent never re-derives it differently on a Tuesday.
3. The portfolio view
tablebi ask "SELECT site, SUM(clicks) AS clicks, SUM(impressions) AS impressions,
ctr(SUM(clicks), SUM(impressions)) AS ctr
FROM search_console_totals_raw
WHERE search_type = 'web'
AND date >= (SELECT MAX(date) FROM search_console_totals_raw) - 27
GROUP BY site ORDER BY clicks DESC"
Client sites, a programmatic portfolio, docs plus a marketing site: one row per property, from the totals table, so each figure matches that property's Search Console overview, anonymized traffic included.
4. Country × device
tablebi ask "SELECT country, device, SUM(clicks) AS clicks,
ctr(SUM(clicks), SUM(impressions)) AS ctr
FROM search_console_geo_raw
WHERE date >= (SELECT MAX(date) FROM search_console_geo_raw) - 27
GROUP BY country, device
ORDER BY clicks DESC LIMIT 20"
Where clicks come from, and whether mobile turns impressions into clicks the way desktop does. The geo table is site-level; "which queries in Germany?" is a live question for tablebi gsc, below.
When the synced tables can't answer: tablebi gsc
Some Search Console questions are too narrow or too rare to store: queries by country, search appearance, hourly data, Discover by page, indexing status. For those, the pass-through commands — tablebi gsc query, inspect and sitemaps — send the question straight to the Search Console API for a property you have connected.
# queries × device for one country (the synced geo table is site-level) tablebi gsc query --site example.com --dims query,device --filter "country = deu" --days 28 # search appearance, and Discover by page tablebi gsc query --site example.com --dims searchAppearance --days 28 tablebi gsc query --site example.com --type discover --dims page --days 28 # indexing: up to 20 URLs per call, 200 per site per day tablebi gsc inspect --site example.com https://example.com/pricing/ tablebi gsc sitemaps --site example.com
The flags mirror the API: --dims takes query, page, country, device, searchAppearance, date and hour; --type takes web, image, video, news, discover and googleNews; --data-state final keeps only finalized days; --limit goes up to 25,000 rows. Answers come back with notes — for example when a window includes preliminary days, or when grouping by query leaves anonymized traffic out. For the API-level details behind all this, see the Search Console API alternative.
Search Console's newest days are preliminary
Google's Performance report help says the newest data can be preliminary and may still change, and its troubleshooting guide says collected data is usually available in 2–3 days (Performance report, troubleshooting data discrepancies). The API makes the choice explicit: dataState "all" includes fresh data, "final" returns finalized data only. TableBI syncs with fresh data, so the tables usually run through yesterday, and the latest two days or so are re-pulled on every sync while Google finishes them.
Two mechanisms keep the agent honest about it. Every answer carries a trust block: per-source freshness (the exact date each source runs through), caveats such as "the last two days are preliminary" or "Search Console clicks are not GA4 sessions", and lineage. And windows are written against the data's own high-water mark:
-- anchors to the freshest synced day, not the wall clock, -- so a 28-day window is 28 days of *actual* data WHERE date >= (SELECT MAX(date) FROM search_console_totals_raw) - 27
Rule of thumb: treat the last two days as provisional, compare complete weeks, and let the freshness readout — not memory — say how current the numbers are.
Pin a weekly SEO dashboard
Once a query earns its keep, stop re-running it — pin it. One command turns SQL into a dashboard at a public, read-only URL that refreshes itself as new data syncs in (on a schedule, and when someone opens it):
tablebi pin --title "SEO weekly" \ --widget "Daily clicks (28d)::line=SELECT date, SUM(clicks) AS clicks FROM search_console_totals_raw WHERE search_type = 'web' AND date >= (SELECT MAX(date) FROM search_console_totals_raw) - 27 GROUP BY date ORDER BY date" \ --widget "Top queries=SELECT query, SUM(clicks) AS clicks, SUM(impressions) AS impressions FROM search_console_raw WHERE date >= (SELECT MAX(date) FROM search_console_raw) - 27 GROUP BY query ORDER BY clicks DESC LIMIT 20" ✓ published → https://dk.tablebi.com/d/dsh_… (public, read-only, self-refreshing)
::line renders a line chart; widgets without it render as tables. The daily line reads the totals table, so it matches the Search Console overview; the query table underneath is the itemized subset. Here is a real one — an SEO portfolio overview pinned from live Search Console data: