Skip to main content
Glama
drewbeechler

GSC MCP Server

by drewbeechler
README.md
# GSC MCP Server

A [Model Context Protocol](https://modelcontextprotocol.io/) server that gives Claude (and any MCP client) read-only access to your Google Search Console data. Ask Claude about your SEO performance, rankings, click-through rates, and indexing status — all from natural conversation.

## What You Get

**10 tools** that cover the full range of GSC data analysis:

| Tool | What it does |
|---|---|
| `gsc_query_performance` | Flexible raw queries with full control — dimensions, filters, sort, pagination, file output |
| `gsc_top_pages` | Top performing pages ranked by clicks, impressions, CTR, or position |
| `gsc_top_queries` | Top search queries by clicks *or impressions* (includes zero-click queries) |
| `gsc_page_queries` | "What queries does this page rank for?" (exact or contains URL match) |
| `gsc_query_pages` | "Which pages rank for this query?" — cannibalization detection |
| `gsc_compare_performance` | **Period-over-period & rolling-baseline comparison** — per-query/page deltas, %change |
| `gsc_position_tracker` | Compare two date ranges to find ranking changes — flags significant movers |
| `gsc_ctr_analysis` | Quick wins: pages with high impressions but low CTR (title/meta optimization targets) |
| `gsc_list_sites` | List all GSC properties your account can access |
| `gsc_inspect_url` | Check index status, crawl info, mobile usability, and rich results for any URL |

All query tools support `response_format: "markdown" | "json"`, a `site_url` parameter for multi-site use, and these shared capabilities:

- **Flexible date ranges** — `days: 90` for an arbitrary lookback (never capped), or explicit `start_date`/`end_date`. Default window is 28 days.
- **Any-metric sort** — `sort_by: impressions | clicks | ctr | position` with `sort_order`. Impression sorts fetch the full result set first, so high-impression zero-click terms are never buried.
- **Row limits & pagination** — `row_limit` defaults to 1000 (max 25000), plus `start_row` and `fetch_all: true` to auto-paginate result sets larger than 25000 rows.
- **Dimension filters with operators** — `page_filter`/`query_filter` each take an operator (`equals`, `contains`, `notContains`, `includingRegex`, `excludingRegex`). Use `equals` for an exact single-URL match; `notContains` for non-branded splits.
- **File output** — large results (or any call with `output_path`) are written to disk as `csv`/`json`/`markdown` (`output_format`) and a preview + file path is returned, instead of truncating. Files default to `./gsc-exports/` (override with `GSC_OUTPUT_DIR`).
- **Data freshness** — `data_state: all` includes the freshest 2–3 days of (incomplete, upward-revising) data; default is `final`.

## Example Usage

Once configured, just ask Claude things like:

- "What are my top search queries this month?"
- "What is alloypartners.com/blog/venture-builder ranking for?"
- "Find pages with high impressions but low CTR — where can I improve titles?"
- "Which of my pages rank for 'venture studio'? Is there cannibalization?"
- "How have my rankings changed compared to last month?"
- "Which queries lost the most impressions this week vs. the prior week?"
- "Compare this week's queries to the 6-week rolling average — what's declining?"
- "Is this URL indexed by Google?"

## Quick Start

### 1. Clone and build

```bash
git clone https://github.com/drewbeechler/gsc-mcp-server.git
cd gsc-mcp-server
npm install
npm run build
```

### 2. Set up Google Cloud credentials (one-time)

You need OAuth 2.0 credentials to authenticate with the Search Console API. See [Google Cloud Setup](#google-cloud-setup) below for the full walkthrough.

### 3. Add to Claude

**Claude Code** — add to `~/.claude.json`:

```json
{
  "mcpServers": {
    "gsc": {
      "command": "node",
      "args": ["/path/to/gsc-mcp-server/dist/index.js"],
      "env": {
        "GSC_OAUTH_SECRETS_FILE": "/path/to/client_secrets.json",
        "GSC_SITE_URL": "sc-domain:yoursite.com"
      }
    }
  }
}
```

**Claude Desktop** — add the same config to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows).

### 4. Authorize

The first time a GSC tool is called, your browser will open for Google OAuth authorization. Sign in, approve, and the token is cached at `~/.gsc-mcp/token.json` for all future sessions.

---

## Google Cloud Setup

One-time setup to get OAuth credentials. Takes about 5 minutes.

### Step 1: Create a Google Cloud Project

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Click the project dropdown at the top → **New Project**
3. Name it something like `gsc-mcp-server` → click **Create**
4. Make sure the new project is selected

### Step 2: Enable the Search Console API

1. Go to **APIs & Services → Library**
2. Search for **"Google Search Console API"**
3. Click on it → click **Enable**

### Step 3: Configure OAuth Consent Screen

1. Go to **APIs & Services → OAuth consent screen** (may show as "Google Auth Platform")
2. Fill in **App name** (e.g., `GSC MCP Server`) and your **email**
3. For **Audience/User type**, select **External** (or Internal if you're on Google Workspace)
4. Add your email as a **test user** if prompted
5. Complete the setup

> Note: The scopes are requested at runtime by the server — you don't need to manually add them in the console.

### Step 4: Create OAuth Credentials

1. Go to **APIs & Services → Credentials** (or **Clients** in the new Auth Platform UI)
2. Click **+ Create Credentials → OAuth client ID**
3. Application type: **Desktop app**
4. Click **Create** → **Download JSON**
5. Save the file somewhere safe:
   ```bash
   mkdir -p ~/.gsc-mcp
   mv ~/Downloads/client_secret_*.json ~/.gsc-mcp/client_secrets.json
   ```

### Step 5: Test it

```bash
npx @modelcontextprotocol/inspector node dist/index.js
```

This opens an interactive UI where you can test any tool. Try `gsc_list_sites` first to verify auth works.

> **"Unverified app" warning:** If you set user type to External, you'll see this on first auth. Click **Advanced → Go to GSC MCP Server (unsafe)**. This is normal for personal-use OAuth apps.

---

## Environment Variables

| Variable | Required | Description |
|---|---|---|
| `GSC_OAUTH_SECRETS_FILE` | Yes | Path to your `client_secrets.json` from Google Cloud |
| `GSC_SITE_URL` | No | Default GSC property (e.g., `sc-domain:example.com`). Can also be passed per-tool call. |
| `GSC_OUTPUT_DIR` | No | Directory for file exports of large result sets. Defaults to `./gsc-exports/` under the server's working directory. |

You can set these in a `.env` file in the project root — the server loads it automatically via `dotenv`.

---

## Troubleshooting

**"Authentication failed (401)"** — Delete `~/.gsc-mcp/token.json` and restart to re-authorize.

**"Site not found (404)"** — Check the `site_url` format. Domain properties use `sc-domain:example.com`, URL-prefix properties use the full URL like `https://example.com/`.

**"Access denied (403)"** — Make sure your Google account has access to the Search Console property. Verify at [search.google.com/search-console](https://search.google.com/search-console).

**"No data returned"** — GSC data lags 2-3 days. Default date ranges account for this, but if you've overridden dates to include today, that's likely the issue.

---

## Tech Stack

- **TypeScript** + Node.js
- **MCP SDK** (`@modelcontextprotocol/sdk`) — stdio transport
- **Google APIs** (`googleapis`) — handles OAuth + token refresh natively
- **Zod** — runtime input validation

## License

MIT