Skip to main content
Glama
samalyxx

GSC SEO MCP

by samalyxx
README.md
# GSC SEO MCP

Connect Google Search Console to Cursor, Claude, or Gemini. Ask questions in plain English and get real SEO data back.

[![npm](https://img.shields.io/npm/v/gsc-seo-mcp)](https://www.npmjs.com/package/gsc-seo-mcp)
[![MCP](https://img.shields.io/badge/MCP-Server-blue)](https://modelcontextprotocol.io/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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

B3.1/5.0

Scored across 40 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count2/5

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.

Completeness4/5

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.

Maintenance

ActivityInactive
ResponsivenessNo issues