@iflow-mcp/serpfire-gsc-mcp-server
v1.0.0
Published
MCP server wrapping Google Search Console API with built-in SEO analysis tools
Downloads
65
Readme
Google Search Console MCP Server
An MCP server that gives Claude direct access to your Google Search Console data — search performance, URL indexation, sitemaps, and built-in SEO analysis tools including trending queries, cannibalization detection, traffic drop diagnostics, and automated query/page grouping.
Prerequisites
- Node.js >= 18.0.0
- A C++ compiler (required by the
better-sqlite3dependency):
| Platform | Install |
|----------|---------|
| macOS | xcode-select --install |
| Windows | Visual Studio Build Tools — select "Desktop development with C++" |
| Linux (Debian/Ubuntu) | sudo apt-get install build-essential python3 |
| Linux (Fedora/RHEL) | sudo dnf groupinstall "Development Tools" && sudo dnf install python3 |
Quick Start
git clone https://github.com/serpfire/gsc-mcp-server.git
cd gsc-mcp-server
npm install1. Create Google OAuth credentials
- Go to Google Cloud Console
- Create an OAuth 2.0 Client ID (type: Desktop app)
- Enable the Google Search Console API in your project
2. Authenticate
GSC_OAUTH_CLIENT_ID=your-client-id \
GSC_OAUTH_CLIENT_SECRET=your-client-secret \
npm run setupThis opens your browser to sign in with Google. Tokens are stored at ~/.gsc-mcp/tokens.json and auto-refresh. Run setup again anytime to switch accounts.
3. Add to Claude Code
claude mcp add --transport stdio gsc -s user \
-e GSC_OAUTH_CLIENT_ID=your-client-id \
-e GSC_OAUTH_CLIENT_SECRET=your-client-secret \
-- node /absolute/path/to/gsc-mcp-server/src/index.jsOr manually add to ~/.claude.json:
{
"mcpServers": {
"gsc": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/gsc-mcp-server/src/index.js"],
"env": {
"GSC_OAUTH_CLIENT_ID": "your-client-id",
"GSC_OAUTH_CLIENT_SECRET": "your-client-secret"
}
}
}
}Service Account Alternative
For automation or server-to-server use:
{
"env": {
"GSC_AUTH_MODE": "service_account",
"GSC_SERVICE_ACCOUNT_KEY_PATH": "/path/to/key.json"
}
}Tools
Core GSC Tools
| Tool | Description |
|------|-------------|
| list_sites | List all verified GSC properties |
| get_site | Get details for a specific site |
| query_search_analytics | Query clicks, impressions, CTR, position with dimensions/filters/pagination |
| inspect_url | Check URL index/crawl status (2,000/day limit) |
| list_sitemaps | List sitemaps for a site |
| get_sitemap | Get sitemap details |
| submit_sitemap | Submit a new sitemap |
| delete_sitemap | Remove a sitemap from GSC |
| switch_account | Re-authenticate with a different Google account (OAuth only) |
Data Sync
| Tool | Description |
|------|-------------|
| sync_search_data | Fetch all performance data into local SQLite cache. Incremental by default. Required before analysis tools. |
Analysis Tools
| Tool | Description |
|------|-------------|
| find_low_hanging_fruit | Find queries ranking 2-20 with high impressions but low CTR, scored by untapped potential |
| detect_cannibalization | Detect queries ranking on 2+ URLs using HHI scoring with action recommendations |
| find_trending_queries | Find queries with biggest growth/decline (period-over-period or year-over-year) |
| find_trending_pages | Find pages with biggest growth/decline with impact scoring |
| analyze_traffic_drop | Diagnose traffic drops across 5 views: site-level, GBP vs organic, groups, segments, brand vs non-brand |
| get_group_performance | Aggregated metrics broken down by named groups with share percentages |
Group Management
| Tool | Description |
|------|-------------|
| create_group | Create a group with OR/AND/NOT regex rules for URL segments or query groups |
| list_groups | List all groups, optionally filtered by dimension |
| get_group | Get group details including rules |
| update_group | Update group description and/or rules |
| delete_group | Delete a group and its rules |
| test_group | Test a group against cached data — match count, rate, samples |
Auto-Discovery
| Tool | Description |
|------|-------------|
| discover_query_groups | Auto-cluster queries using word overlap, n-gram similarity, and page co-occurrence |
| promote_cluster_to_group | Convert a discovered cluster into a named group |
| auto_segment_pages | Auto-create URL segment groups from page URL patterns |
| auto_group_queries | Auto-create query groups: brand, topic n-grams, intent modifiers |
Resources
| URI | Description |
|-----|-------------|
| sites://list | All verified sites (auto-discovery) |
Prompts
| Name | Description |
|------|-------------|
| seo_performance_analysis | Guided full SEO review (queries, pages, devices, trends) |
| index_coverage_check | Systematic URL indexation report |
Example Queries
- "List my Search Console sites"
- "Show top 20 queries for sc-domain:example.com last 7 days"
- "Compare mobile vs desktop for https://example.com/"
- "Check if https://example.com/new-page is indexed"
- "Show sitemaps for sc-domain:example.com"
- "Sync data for sc-domain:example.com and find low-hanging fruit"
- "Detect keyword cannibalization on sc-domain:example.com"
- "Show trending queries for sc-domain:example.com last 28 days"
- "Auto-create query groups for sc-domain:example.com"
Architecture
src/
├── index.js # Entry: auth -> client -> db -> server -> stdio
├── server.js # McpServer factory
├── auth/
│ ├── index.js # Auth factory (auto-detects mode from env)
│ ├── service-account.js # Service account key file auth
│ ├── oauth.js # Browser flow + token persistence + auto-recovery
│ ├── token-store.js # ~/.gsc-mcp/tokens.json
│ └── setup.js # Standalone setup script
├── gsc/ # Pure GSC API wrappers (no MCP knowledge)
│ ├── client.js
│ ├── sites.js
│ ├── search-analytics.js
│ ├── sitemaps.js
│ └── url-inspection.js
├── db/
│ ├── connection.js # SQLite setup with WAL mode
│ └── schema.js # Migrations
├── analysis/ # SEO analysis engine (uses local SQLite)
│ ├── sync.js # GSC API -> SQLite incremental sync
│ ├── low-hanging-fruit.js # Opportunity scoring
│ ├── cannibalization.js # HHI-based detection
│ ├── trending.js # PoP / YoY trending queries & pages
│ ├── traffic-drop.js # Multi-view drop diagnostics
│ ├── group-performance.js # Group-level aggregation
│ ├── auto-segment.js # Automatic URL segmentation
│ ├── auto-group.js # Automatic query grouping
│ ├── shared.js # Shared SQL helpers
│ ├── groups/
│ │ ├── manager.js # CRUD for groups + rules
│ │ ├── compiler.js # OR/AND/NOT rule compilation
│ │ └── matcher.js # Regex matching engine
│ └── semantic/
│ ├── discover.js # Cluster discovery orchestrator
│ ├── clustering.js # Connected components algorithm
│ ├── similarity.js # Multi-signal similarity scoring
│ └── labeler.js # Cluster naming
├── tools/
│ ├── definitions.js # Core GSC tools (declarative)
│ ├── analysis-definitions.js # Analysis tools (declarative)
│ ├── middleware.js # Rate limiting + error handling wrapper
│ ├── auth.js # switch_account tool
│ └── index.js # Registration loop
├── resources.js # sites://list resource
├── prompts.js # SEO analysis + index check prompts
└── utils/
├── logger.js # stderr-only (stdout = MCP protocol)
├── errors.js # Google API error -> MCP error
├── constants.js # Scopes, rate limits, defaults
├── rate-limiter.js # Sliding window
└── open-url.js # Cross-platform browser openerTwo-layer separation: gsc/ knows nothing about MCP. tools/ knows nothing about Google's API. analysis/ operates on local SQLite data. Each layer is independently testable.
Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| GSC_AUTH_MODE | No | Auto-detected | oauth or service_account. Auto-detected from which credentials are set. |
| GSC_OAUTH_CLIENT_ID | OAuth | — | OAuth client ID |
| GSC_OAUTH_CLIENT_SECRET | OAuth | — | OAuth client secret |
| GSC_OAUTH_REFRESH_TOKEN | No | — | Skip browser flow with a pre-existing token |
| GSC_SERVICE_ACCOUNT_KEY_PATH | Service acct | — | Path to JSON key file |
| GSC_API_SCOPES | No | webmasters.readonly | Override scopes (comma-separated) |
| GSC_LOG_LEVEL | No | info | debug / info / warn / error |
| GSC_TOKEN_PATH | No | ~/.gsc-mcp/tokens.json | Custom token storage path |
| GSC_DB_PATH | No | ~/.gsc-mcp/data.db | Custom SQLite database path |
Debugging
Launch the MCP Inspector for interactive testing:
npm run inspectWindows note: The inspect script uses bash. Run it from Git Bash, WSL, or replace with:
npx @modelcontextprotocol/inspector node src/index.js
