MCP server for Google Search Console: properties, sitemaps, search analytics and URL inspection
google-search-console-mcp
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
A Model Context Protocol (MCP) server for
Google Search Console, the
service that tells you how Google sees your site — this reads it and sets it up.
Lets MCP clients like Claude Code, Claude Desktop or Codex create a property and
prove ownership of it, submit and refresh sitemaps, ask what any URL's index
status is, and query the whole Performance report — with the irreversible
operations put to a person first and the write tools switchable off
entirely.
21 tools is the ceiling, not the floor: GSC_ALLOW_TOOLS=essential registers a
curated five instead, and a model picks the right tool far more reliably from
five than from 21 — see
choosing which tools load.
What makes it different
**It can actually create a working property.** Getting one takes four steps in a
fixed order — obtain a verification token, place it in DNS or on the page,
verify ownership, add the property — and nothing in Google's APIs enforces that
order. Calling sites.add first _succeeds_ and leaves a property that appears in
every listing and answers 403 for every piece of data, which looks like a
permissions bug and is not. setup_site reports which step is missing and hands
over the exact DNS record to paste. Servers that expose sites.add alone can
only add properties somebody already verified by hand.
**Three APIs, not one.** Search Console v1 is ten methods and does not include
ownership. Site Verification is a separate service with its own scope, its own
host and an incompatible way of naming the same site —
sc-domain:example.com there is {type: INET_DOMAIN, identifier: example.com},
and passing the property spelling straight through is accepted and verifies a
domain literally called sc-domain:example.com. The Indexing API is a third.
All three are covered, and the translation between them is in
src/site-identity.ts.
**The numbers are right.** Search analytics come back as a table with totals
where CTR is computed from the totals rather than averaged across rows, and
average position is weighted by impressions. Unweighted, a thousand rare queries
ranking 80th drag a property's real average of 12 up into the nineties. The
result also says plainly that the rows do not sum to the property total when the
query dimension is used — Google withholds rare queries for anonymity, commonly a
third or more of all impressions, and a total printed without that caveat is a
number people will quote.
**It knows where these APIs are sharp.** The trailing slash on
https://example.com/ is mandatory and its absence is a 403; a domain property
and a URL-prefix property for the same site are different properties with
different data, so a bare hostname is refused rather than guessed at; days are
counted in **Pacific Time**, so a last7days computed in UTC asks for a day
Google has no data for; the hour dimension silently returns nothing without
dataState: HOURLY_ALL; Google omits empty arrays entirely, so a fresh
credential's property list arrives as {}; and the Indexing API returns 200 for
any owned URL while only acting on JobPosting and BroadcastEvent pages.
Requirements
- Node.js 22 or newer (or the container image)
- A Google credential — a service account key, an OAuth2 refresh token, or
application default credentials
- The APIs you intend to use enabled in a Google Cloud project: **Search
Console API**, and separately **Site Verification API** and **Indexing API**
Configuration
The server starts without credentials and lists its tools; every call then fails
with setup instructions rather than a Google error. That is deliberate, so
registries and sandbox inspectors can introspect it.
| Variable | Description |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| GSC_SERVICE_ACCOUNT_KEY | Service account key as raw JSON, or base64-encoded JSON |
| GSC_SERVICE_ACCOUNT_KEY_FILE | Path to a service account key file. Alternative to the above — setting both is an error |