Skip to main content
Glama
russjeffery

google-search-console-mcp

by russjeffery

Google Search Console MCP

An MCP server for the Google Search Console API — search performance data, URL index status, sitemap management and property listing.

Runs three ways from one codebase: stdio (local, via npx), Streamable HTTP (self-hosted), and Cloudflare Workers (hosted at a URL). Implements MCP 2026-07-28 with automatic fallback to 2025-11-25, 2025-06-18 and 2025-03-26, so it works with clients on either side of the protocol change.

Zero runtime dependencies.


Quick start

npx google-search-console-mcp auth

That walks you through creating a Google OAuth client, runs the consent flow, verifies the credentials against the live API, and prints a ready-to-paste config block for your MCP client. Three minutes, mostly waiting on Google Cloud's UI.

Then drop the printed JSON into your client config and restart it.


Related MCP server: searchconsole-mcp

Tools

Every method in the Search Console API v1, plus two composites.

Tool

Does

API method

list_sites

All properties you can access, with permission levels

sites.list

get_site

One property and your permission on it

sites.get

query_search_analytics

Clicks, impressions, CTR, position — grouped, filtered, paged

searchanalytics.query

compare_search_analytics

Two periods with per-row and total deltas

composite

list_sitemaps

Submitted sitemaps, or the children of a sitemap index

sitemaps.list

get_sitemap

One sitemap's status and submitted/indexed counts

sitemaps.get

submit_sitemap

Submit or resubmit a sitemap

sitemaps.submit

delete_sitemap

Unsubmit a sitemap

sitemaps.delete

inspect_url

Full index status for one URL

urlInspection.index.inspect

inspect_urls

Up to 25 URLs concurrently, with a coverage-state summary

composite

Site verification and sites.add/sites.delete are intentionally not exposed — adding and verifying properties is a browser flow that doesn't belong in an agent tool.

The server also serves prompts (performance_review, indexing_audit, query_opportunities, sitemap_health) and resources (gsc://guide/search-analytics, gsc://guide/url-inspection, gsc://guide/sitemaps) that agents can read on demand.


Authentication

Step 1 — create a Google OAuth client

You only do this once. The server can't do it for you: Google requires a human in their console.

  1. Open the Google Cloud Console and select or create a project.

  2. Enable the Search Console API for that project.

  3. Configure the OAuth consent screen. External is fine for personal use. Add your own Google account under Test users.

  4. Go to Credentials → Create credentials → OAuth client ID. Choose application type Desktop app.

  5. Copy the Client ID and Client secret.

Testing vs Published. While the consent screen is in Testing, Google expires refresh tokens after 7 days and you'll have to re-run auth weekly. Publishing the app (consent screen → Publish app) makes them durable. For a single-user internal tool, publishing is safe and doesn't require Google's verification review as long as you keep to the webmasters scopes.

Step 2 — run the setup flow

npx google-search-console-mcp auth

This opens a small setup page served from 127.0.0.1. Paste in the client ID and secret, choose full or read-only access, and it runs the consent flow, exchanges the code (with PKCE) for a refresh token, and calls list_sites to prove the credentials work — showing you the exact properties they can reach.

The final page gives you the credential blob and ready-to-paste config for Claude Desktop, Claude Code, and remote deployments, each with a copy button. The same values are printed to your terminal as a fallback.

On a headless machine or over SSH, use auth --terminal for the prompt-driven version instead.

You get back a credential blob — base64url-encoded JSON containing your client ID, client secret and refresh token:

eyJ2IjoxLCJjcmVkZW50aWFscyI6eyJ0eXBlIjoib2F1dGhfcmVmcmVzaF90b2tlbiIsImNsaWVu…

Treat the blob as a password. Anyone holding it has your Search Console access until you revoke it at myaccount.google.com/permissions.

It exists as a single opaque string so one value carries everything the server needs — it drops straight into an env var or an Authorization header without a credentials file on disk.

Alternatives to the OAuth flow

Service account. Useful for CI and for team-owned properties. Create one in Google Cloud, then add its client_email as a user on the property in Search Console (Settings → Users and permissions). Encode the downloaded key file directly:

base64 -i service-account.json | tr -d '\n'

The server accepts a raw service-account key as the blob — no envelope needed.

Existing access token. Set {"type":"access_token","access_token":"ya29..."}. No refresh is possible, so this only suits short-lived scripts.

Scopes

Scope

Grants

https://www.googleapis.com/auth/webmasters.readonly

Everything except sitemap submit/delete

https://www.googleapis.com/auth/webmasters

Full access (default)

Choosing read-only during auth requests the narrower scope. --read-only on the server is a separate, belt-and-braces block that rejects mutating tools before they reach the API.


Running it

Local (stdio)

The config printed by auth:

{
  "mcpServers": {
    "google-search-console": {
      "command": "npx",
      "args": ["-y", "google-search-console-mcp"],
      "env": { "GSC_CREDENTIALS": "<your blob>" }
    }
  }
}

Config file locations:

Client

Path

Claude Desktop (macOS)

~/Library/Application Support/Claude/claude_desktop_config.json

Claude Desktop (Windows)

%APPDATA%\Claude\claude_desktop_config.json

Claude Code

claude mcp add google-search-console --env GSC_CREDENTIALS=<blob> -- npx -y google-search-console-mcp

Cursor

~/.cursor/mcp.json

VS Code

.vscode/mcp.json

Install it properly if you'd rather not go through npx each time:

npm install -g google-search-console-mcp

Self-hosted HTTP

GSC_CREDENTIALS=<blob> npx google-search-console-mcp http --port 8787

Serves POST http://127.0.0.1:8787/mcp. Binds to loopback by default — pass --host 0.0.0.0 deliberately if you mean to expose it, and put TLS in front of it if you do.

Browser-based clients are refused unless you name them, because a server holding its own credentials would otherwise be drivable by any page you visit. Ordinary MCP clients send no Origin and are unaffected; a browser one needs its origin listed:

npx google-search-console-mcp http --allowed-origins http://localhost:6274   # MCP Inspector

A rejected origin gets a 403 the browser can't read (no CORS headers on a refusal, by design), so it surfaces as a generic CORS failure — check the server's Origins: startup line if a browser client can't connect. --allowed-origins '*' disables the check.

Cloudflare Workers

git clone https://github.com/russjeffery/google-search-console-mcp.git
cd google-search-console-mcp
npm install
npx wrangler deploy

Your endpoint is https://google-search-console-mcp.<subdomain>.workers.dev/mcp.

By default the Worker stores no secrets. Each client sends its own credential blob as the bearer token, so a shared deployment never holds anyone's Google credentials, and different users of the same URL see only their own properties.

For a private, single-tenant deployment instead:

npx wrangler secret put GSC_CREDENTIALS     # your blob
npx wrangler secret put MCP_SHARED_SECRET   # token clients must present

Clients then send the shared secret rather than a blob.

Optional vars in wrangler.jsonc:

Variable

Effect

MCP_ENDPOINT

Path to serve on. Default /mcp

GSC_READ_ONLY

"1" disables sitemap submit/delete

ALLOWED_ORIGINS

Comma-separated browser origins. Unset = non-browser clients only; * allows any

MCP_STRICT_HEADERS

"0" relaxes 2026-07-28 header-mirroring validation

Connecting a client to the remote server

{
  "mcpServers": {
    "google-search-console": {
      "type": "http",
      "url": "https://your-worker.workers.dev/mcp",
      "headers": { "Authorization": "Bearer <your blob>" }
    }
  }
}

In the Claude web or desktop UI, add it under Settings → Connectors → Add custom connector.

Print this filled in for your own deployment:

npx google-search-console-mcp config --url https://your-worker.workers.dev/mcp

CLI

google-search-console-mcp [command] [options]

  stdio     Run as a stdio MCP server (default)
  http      Run a local Streamable HTTP MCP server
  auth      Guided setup in your browser: OAuth flow, blob, client config
  config    Print client config for existing credentials
  doctor    Verify credentials by calling the API

doctor is the first thing to reach for when something isn't working — it separates "credentials are wrong" from "the client can't launch the server".

Options: --credentials <blob>, --site <siteUrl>, --read-only, --port, --host, --endpoint, --secret, --allowed-origins, --url, --terminal, --no-browser.

--allowed-origins takes a comma-separated list; unset means non-browser clients only. Entries are matched case-insensitively and a trailing slash is ignored.

--site sets a default property so tools can omit siteUrl — convenient when a deployment only ever covers one site.


Protocol support

The 2026-07-28 revision changed Streamable HTTP substantially: no initialize handshake, no sessions, no Mcp-Session-Id, no GET stream, and per-request metadata in params._meta mirrored into HTTP headers. The official TypeScript SDK does not implement it yet, so the protocol layer here is hand-written and dual-era.

Client speaks

Server behaviour

2026-07-28

Stateless. Validates _meta, MCP-Protocol-Version, Mcp-Method, Mcp-Name. Answers server/discover. Results carry resultType and serverInfo.

2025-11-25 and earlier

Standard initialize handshake. No session ID is issued — the server is stateless either way.

Era is detected per request: a request carrying modern _meta is served as modern, an initialize selects legacy. GET and DELETE on the endpoint return 405, as the revision prescribes.

Header validation is strict by default, per spec. If a client sends modern _meta without mirroring the headers, set MCP_STRICT_HEADERS=0 (or --loose-headers) rather than downgrading.

On authorization: the spec's OAuth 2.1 flow assumes the server is a resource server with its own authorization server. This server instead uses the bearer token to carry your Google credentials directly — the spec permits custom strategies, and it means a hosted deployment holds no secrets and needs no user database. The tradeoff is that clients expecting automatic OAuth discovery will need the header configured manually, as shown above.


Working with the data

Four properties of Search Console data cause most wrong conclusions. The tool descriptions and the bundled skill cover these in depth; briefly:

  1. Data lags ~3 days. Use lastDays and the tools pick a safe window. A range ending today shows a fake decline.

  2. Query data is privacy-filtered. Grouping by query silently drops rare queries, so query-level clicks never sum to the property total. That gap is not lost traffic.

  3. Position is inverted. Position 3 beats position 8; a negative change is an improvement. compare_search_analytics returns an explicit improved flag.

  4. Averages cancel. Flat headline numbers routinely hide large offsetting movements. Group by page or query before concluding nothing changed.

Quotas

  • Search analytics: ~1,200 queries/minute per property.

  • URL inspection: ~2,000/day per property — the binding constraint. Sample deliberately.

Not available via the API

The aggregate Index Coverage report, live URL testing, requesting indexing, Core Web Vitals, manual actions, security issues, links reports and removals have no API equivalent, so they aren't here. Per-URL inspect_url is the closest substitute for coverage questions.


Agent skill

skills/google-search-console/ is a ready-to-install skill teaching an agent how to use these tools well — the pitfalls above, a diagnostic ladder for traffic changes, opportunity-finding heuristics, and a coverage-state lookup table.

cp -r skills/google-search-console ~/.claude/skills/

The same reference material is available at runtime through the server's gsc://guide/* resources, so agents without the skill installed can still read it.


Development

npm install
npm run build       # compile to dist/
npm run typecheck
npm test
npm run cf:dev      # Worker locally via wrangler

Quick manual check against the HTTP transport:

GSC_CREDENTIALS=<blob> npm run build && node dist/bin/cli.js http &

curl -s http://127.0.0.1:8787/mcp \
  -H 'content-type: application/json' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: tools/list' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}' | jq '.result.tools[].name'

Troubleshooting

Symptom

Cause and fix

invalid_grant

Refresh token revoked, or the consent screen is in Testing mode (7-day expiry). Re-run auth; publish the app to stop it recurring.

403 insufficient permission on one property

The siteUrl doesn't match exactly. Run list_sites and copy the string verbatim — https://example.com/ and sc-domain:example.com are different properties.

403 mentioning the API being disabled

Enable the Search Console API in the Google Cloud project that issued the credentials.

Empty list_sites

Authenticated successfully as a Google account with no properties. You likely picked the wrong account at the consent screen.

Traffic looks like it fell off a cliff in the last few days

Data isn't final yet. Use lastDays.

Server won't start in Claude Desktop

Run npx google-search-console-mcp doctor in a terminal to isolate credentials from client launch problems.

-32020 HeaderMismatch

Client sends modern _meta without mirroring headers. Set MCP_STRICT_HEADERS=0.


Security

  • The credential blob is your Google access. Don't commit it, don't paste it into shared docs. Revoke at myaccount.google.com/permissions.

  • HTTP mode binds to 127.0.0.1 by default and validates Origin against ALLOWED_ORIGINS to block DNS rebinding. Unset means no browser origin is allowed — list them explicitly, or use * to opt out of the check. /health and / are exempt; they expose no credentialed capability.

  • Shared-secret comparison is length-checked and constant-time.

  • The default Worker deployment stores no credentials at all.

  • --read-only / GSC_READ_ONLY=1 blocks sitemap mutation independently of the granted OAuth scope.

License

MIT

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for Google Search Console, enabling querying search analytics, URL inspection, sitemap management, and more via natural language.
    267
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    A lightweight, fast MCP server for Google Search Console. Query search analytics, manage sitemaps, and inspect URLs directly from your AI assistant.
    7
    Apache 2.0
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for Google Search Console, enabling querying search performance, listing properties, and inspecting URL indexing status from MCP-compatible clients.
    4
    22
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Self-hosted MCP server for Google Search Console. Enables natural language queries to list sites, analyze search analytics, inspect URLs, and check sitemaps through AI assistants.
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for Google search results via SERP API

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • SEO MCP server: crawl your site, find AI-visibility gaps, and ship the fix from your coding agent.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/russjeffery/google-search-console-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server