GSC SEO MCP
# GSC SEO MCP
Connect Google Search Console to Cursor, Claude, or Gemini. Ask questions in plain English and get real SEO data back.
[](https://www.npmjs.com/package/gsc-seo-mcp)
[](https://modelcontextprotocol.io/)
[](LICENSE)
---
## What you can ask your AI once it's set up
```
Show me the biggest SEO opportunities for my site.
Which pages are losing clicks?
Find keywords ranking positions 4–15 that I can push to page 1.
Split branded vs non-branded traffic for the last 90 days.
Which pages have bad CTR for their ranking position?
Inspect these URLs and tell me what's wrong with indexing.
Generate a Markdown SEO report for the last 28 days.
```
---
## Setup
There are two parts:
1. **Google** — give the MCP access to your Search Console data
2. **Your AI app** — tell Cursor / Claude / Gemini how to run it
Pick your Google auth method first:
| | Service Account | OAuth |
|---|---|---|
| Best for | Agencies, client sites, teams | Personal sites, your own account |
| How it works | JSON key file, no browser login | Signs in via browser once |
| Recommended? | Yes, simpler for MCP | Works too |
---
## Part 1 — Google Setup
### Step 1: Create a Google Cloud project
This is just a container for API access. It is not your website.
1. Go to [console.cloud.google.com](https://console.cloud.google.com/)
2. Click the project dropdown at the top → **New Project**
3. Name it `GSC SEO MCP` and click **Create**
4. Make sure it's selected in the top dropdown after creation
### Step 2: Enable the Search Console API
1. Go to **APIs & Services → Library**
2. Search **Google Search Console API** → click it → click **Enable**
3. Optional: also enable **Indexing API** if you want the `indexing_*` tools (only useful for JobPosting/livestream pages)
---
### Option A: Service Account (recommended)
#### 1. Create the service account
1. Go to **IAM & Admin → Service Accounts**
2. Click **Create service account**
3. Name: `gsc-seo-mcp` → click **Create and continue**
4. Skip the role assignment → click **Continue** → click **Done**
5. Copy the service account email — looks like:
```
gsc-seo-mcp@your-project-id.iam.gserviceaccount.com
```
#### 2. Download the key file
1. Click the service account you just created
2. Go to the **Keys** tab → **Add key → Create new key → JSON → Create**
3. Google downloads a `.json` file — save it somewhere safe, like:
- Mac/Linux: `/Users/your-name/keys/gsc-seo-mcp.json`
- Windows: `C:/Users/your-name/keys/gsc-seo-mcp.json`
Don't commit this file to GitHub. Treat it like a password.
#### 3. Add it to Search Console
1. Open [search.google.com/search-console](https://search.google.com/search-console)
2. Select your property
3. Go to **Settings → Users and permissions → Add user**
4. Paste the service account email, set permission to **Full**, click **Add**
You need to be a property owner to do this.
#### 4. Your MCP config
```json
{
"mcpServers": {
"gsc-seo": {
"command": "npx",
"args": ["-y", "gsc-seo-mcp"],
"env": {
"GSC_AUTH_MODE": "service_account",
"GSC_KEY_FILE": "/absolute/path/to/gsc-seo-mcp.json",
"GSC_SITE_URL": "sc-domain:example.com"
}
}
}
}
```
Windows path tip — use forward slashes or double backslashes:
```json
"GSC_KEY_FILE": "C:/Users/your-name/keys/gsc-seo-mcp.json"
```
---
### Option B: OAuth (sign in with Google)
Use this if you want to connect with your own Google account via browser login.
#### 1. Set up the OAuth consent screen
1. Go to **APIs & Services → OAuth consent screen**
2. Choose **External** (works for Gmail accounts) → fill in app name, email → save
3. If the app is in testing mode, add your Gmail under **Test users**
#### 2. Create the OAuth client
1. Go to **APIs & Services → Credentials → Create credentials → OAuth client ID**
2. Application type: **Desktop app** → name it `GSC SEO MCP Desktop` → click **Create**
3. Click **Download JSON** — save it like:
- Mac/Linux: `/Users/your-name/keys/gsc-oauth-client.json`
- Windows: `C:/Users/your-name/keys/gsc-oauth-client.json`
#### 3. Your MCP config
```json
{
"mcpServers": {
"gsc-seo": {
"command": "npx",
"args": ["-y", "gsc-seo-mcp"],
"env": {
"GSC_AUTH_MODE": "oauth",
"GSC_OAUTH_SECRETS_FILE": "/absolute/path/to/gsc-oauth-client.json",
"GSC_TOKEN_FILE": "/absolute/path/to/gsc-oauth-token.json",
"GSC_SITE_URL": "sc-domain:example.com"
}
}
}
}
```
`GSC_TOKEN_FILE` is where the MCP saves your login token after the first browser sign-in. If you leave it out, it saves to `~/.gsc-seo-mcp/token.json` by default.
#### 4. First run
Restart your MCP client, then ask it to run `server_health` or `list_properties`. A browser window will open — sign in with Google and approve access. That's it, no repeat login needed.
If Google shows an "unverified app" warning, click **Advanced → Continue** — this is your own OAuth app, it's fine.
---
## Part 2 — Add to your AI app
Node.js 20+ is required. [Download here](https://nodejs.org/) if you don't have it.
### Cursor
Create `.cursor/mcp.json` in your project folder (or use global MCP settings):
```json
{
"mcpServers": {
"gsc-seo": {
"command": "npx",
"args": ["-y", "gsc-seo-mcp"],
"env": {
"GSC_AUTH_MODE": "service_account",
"GSC_KEY_FILE": "/absolute/path/to/service-account.json",
"GSC_SITE_URL": "sc-domain:example.com",
"GSC_BRAND_TERMS": "mybrand,mybrand.com"
}
}
}
}
```
### Claude Desktop
Edit `claude_desktop_config.json`:
- Mac: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"gsc-seo": {
"command": "npx",
"args": ["-y", "gsc-seo-mcp"],
"env": {
"GSC_AUTH_MODE": "service_account",
"GSC_KEY_FILE": "/absolute/path/to/service-account.json",
"GSC_SITE_URL": "sc-domain:example.com"
}
}
}
}
```
Restart Claude Desktop after saving.
### Claude Code
Create `.mcp.json` in your project:
```json
{
"mcpServers": {
"gsc-seo": {
"command": "npx",
"args": ["-y", "gsc-seo-mcp"],
"env": {
"GSC_AUTH_MODE": "service_account",
"GSC_KEY_FILE": "/absolute/path/to/service-account.json",
"GSC_SITE_URL": "sc-domain:example.com"
}
}
}
}
```
Or via CLI:
```bash
claude mcp add --transport stdio \
--env GSC_AUTH_MODE=service_account \
--env GSC_KEY_FILE=/absolute/path/to/service-account.json \
--env GSC_SITE_URL=sc-domain:example.com \
gsc-seo -- npx -y gsc-seo-mcp
```
### Gemini CLI
Edit `~/.gemini/settings.json` (or `.gemini/settings.json` in your project):
```json
{
"mcpServers": {
"gsc-seo": {
"command": "npx",
"args": ["-y", "gsc-seo-mcp"],
"env": {
"GSC_AUTH_MODE": "service_account",
"GSC_KEY_FILE": "/absolute/path/to/service-account.json",
"GSC_SITE_URL": "sc-domain:example.com"
},
"timeout": 120000,
"trust": false
}
}
}
```
---
## Property URL format
Use the exact format from Search Console:
```
sc-domain:example.com ← domain property (recommended)
https://www.example.com/ ← URL-prefix property (include the trailing slash)
```
---
## All config variables
| Variable | Required | What it does |
|---|---|---|
| `GSC_SITE_URL` | Recommended | Default property. Example: `sc-domain:example.com` |
| `GSC_SITE_URLS` | Optional | Comma-separated properties for multi-site dashboards |
| `GSC_AUTH_MODE` | Optional | `service_account` or `oauth`. Auto-detected when possible |
| `GSC_KEY_FILE` | Service account | Path to service account JSON key |
| `GOOGLE_APPLICATION_CREDENTIALS` | Service account | Alternative path variable |
| `GSC_OAUTH_SECRETS_FILE` | OAuth | Path to OAuth client secret JSON |
| `GSC_OAUTH_CLIENT_ID` | OAuth alternative | Client ID if not using a secrets file |
| `GSC_OAUTH_CLIENT_SECRET` | OAuth alternative | Client secret if not using a secrets file |
| `GSC_TOKEN_FILE` | Optional | Where OAuth token is saved after login |
| `GSC_BRAND_TERMS` | Optional | Comma-separated brand terms for `brand_nonbrand_split` |
| `GSC_REPORT_DIR` | Optional | Folder for Markdown reports. Defaults to `./reports` |
| `GSC_DATA_STATE` | Optional | `all`, `final`, or `hourly_all`. Defaults to `all` |
---
## Tools
### Core
| Tool | What it does |
|---|---|
| `server_health` | Shows config status, auth mode, and tool count |
| `list_properties` | Lists all Search Console properties you have access to |
| `get_site` | Gets permission details for one property |
| `add_site` | Adds a site to your account |
| `delete_site` | Removes a site from your account |
### Search Analytics
| Tool | What it does |
|---|---|
| `search_analytics` | Full query with dimensions, filters, search type, and data state |
| `advanced_filter_query` | Pulls up to 50,000 rows for deeper audits |
| `top_queries` | Top queries, optionally filtered by page |
| `top_pages` | Top pages, optionally filtered by query |
| `performance_overview` | Site snapshot with period comparison, daily trend, devices |
| `compare_periods` | Current vs previous period by page, query, country, or device |
| `dimension_breakdown` | Performance by one dimension |
| `page_query_matrix` | Maps pages to the queries driving them |
### SEO Analysis
| Tool | What it answers |
|---|---|
| `quick_wins` | Which keywords are close enough to improve fast? |
| `ctr_opportunities` | Which snippets underperform for their ranking position? |
| `content_decay` | Which pages are declining across multiple periods? |
| `traffic_drop_diagnosis` | Was the drop rankings, CTR, demand, coverage, or mixed? |
| `cannibalization_check` | Which queries are split across competing pages? |
| `brand_nonbrand_split` | How much traffic is brand vs non-brand? |
| `search_intent_breakdown` | How do queries split across informational, commercial, transactional, navigational, local? |
| `device_country_opportunities` | Which device/country/page segments have weak CTR or ranking? |
| `long_tail_questions` | Which question queries deserve content expansion? |
| `page_refresh_priorities` | Which pages should be updated first? |
| `internal_link_opportunities` | Which strong pages can support weaker pages? |
| `query_page_fit` | What does one page rank for, and does the content match? |
| `title_meta_brief` | Which queries should inform title/meta refreshes? |
| `anomaly_alerts` | Which pages had abnormal losses recently? |
### Indexing, Sitemaps, URLs
| Tool | What it does |
|---|---|
| `inspect_url` | Checks one URL for index status, canonical, crawl, coverage |
| `batch_inspect_urls` | Inspects multiple URLs |
| `index_coverage_summary` | Summarizes inspection results across a URL list |
| `list_sitemaps` | Lists submitted sitemaps with errors and indexed counts |
| `get_sitemap` | Details for one sitemap |
| `submit_sitemap` | Submits or refreshes a sitemap |
| `delete_sitemap` | Deletes a submitted sitemap |
| `indexing_publish_url` | Sends an Indexing API notification for an eligible URL |
| `indexing_batch_publish` | Sends multiple Indexing API notifications |
| `indexing_get_metadata` | Checks latest Indexing API notification status for a URL |
### Reporting
| Tool | What it does |
|---|---|
| `multi_site_dashboard` | Compares multiple properties in one view |
| `generate_markdown_report` | Saves a Markdown SEO report to disk |
| `verify_claim` | Re-queries GSC to check a number before you report it to a client |
---
## Troubleshooting
**Tools don't show up in my AI app**
Make sure Node.js 20+ is installed. Check your MCP config uses `npx -y gsc-seo-mcp` exactly. All file paths must be absolute (not `~/` or relative).
**Service account shows no properties**
You need to add the service account email to Search Console under **Settings → Users and permissions**.
**URL Inspection fails**
The URL must belong to the property in `GSC_SITE_URL`. For URL-prefix properties, use the exact prefix with protocol and trailing slash.
**OAuth doesn't open the browser**
Set `GSC_OAUTH_PORT=0` to let it pick a free port. If you're on a remote machine, you'll need to run this locally instead.
---
## Data notes
- Search Analytics rows are sorted by clicks. The API has internal row limits, so not every possible row is included.
- `GSC_DATA_STATE=all` includes fresh data. Use `final` for finalized reporting numbers.
- URL Inspection shows Google's index state, not a live crawl.
- The Indexing API is for JobPosting and BroadcastEvent pages only — it's not a general indexing shortcut.
---
## Security
- Never commit service account keys, OAuth secrets, or token files to Git.
- Use read-only Search Console permissions if you don't need write tools.
- Review `delete_site`, `delete_sitemap`, `submit_sitemap`, and `indexing_publish_url` calls before approving them.
---
## Official docs
- [Create a Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects)
- [Enable APIs](https://developers.google.com/workspace/guides/enable-apis)
- [Create credentials](https://developers.google.com/workspace/guides/create-credentials)
- [Search Console users and permissions](https://support.google.com/webmasters/answer/7687615)
- [Search Analytics API](https://developers.google.com/webmaster-tools/v1/searchanalytics/query)
- [URL Inspection API](https://developers.google.com/webmaster-tools/v1/urlInspection.index/inspect)
- [Indexing API](https://developers.google.com/search/apis/indexing-api/v3/using-api)
- [Model Context Protocol](https://modelcontextprotocol.io/)
---
## License
MIT. If this saves you time, star the repo.
TDQS
Scored across 40 tools
Most tools have clearly distinct purposes, with descriptions that differentiate similar operations (e.g., search_analytics vs. specialized queries). A few pairs like indexing_publish_url and indexing_batch_publish could cause minor confusion, but overall boundaries are clear.
Tools consistently use snake_case, but naming patterns vary between verb_noun (add_site, inspect_url) and noun_verb (cannibalization_check, content_decay). The mix is understandable and readable, with only a few deviations from a strict pattern.
With 40 tools, the server is heavily overloaded. While each tool has a specific function, the sheer number exceeds a manageable scope and risks overwhelming agents or users. Many tools could be consolidated or are redundant.
The tool set covers a broad range of Google Search Console functionality: site management, sitemaps, URL inspection, indexing, analytics, and specialized SEO analyses. Minor gaps exist (e.g., no tool for user permissions or manual actions), but core workflows are well supported.