# Google Seo Mcp

> SEO & GEO MCP server for Claude, Codex, Cursor and any MCP client: Google Search Console, Google Analytics 4, PageSpeed Insights, Core Web Vitals, structured data, llms.txt, AI crawler checks, WordPress (Yoast, WP-CLI over SSH) and GitHub — 80 tools for technical SEO, content optimization and generative engine optimization

- **Type:** MCP server
- **Install:** `agentstack add mcp-akxan-google-seo-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Akxan](https://agentstack.voostack.com/s/akxan)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Akxan](https://github.com/Akxan)
- **Source:** https://github.com/Akxan/google-seo-mcp
- **Website:** https://github.com/Akxan/google-seo-mcp#readme

## Install

```sh
agentstack add mcp-akxan-google-seo-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# google-seo-mcp

**SEO & GEO MCP server for Claude, Codex, Cursor and any MCP client — Google Search Console, Google Analytics 4, PageSpeed Insights, structured data, llms.txt, WordPress and GitHub as 80 tools, so an assistant can diagnose and fix technical SEO, content and generative-engine-optimization issues in one conversation.**

[](https://github.com/Akxan/google-seo-mcp/stargazers)
[](LICENSE)
[](https://nodejs.org)
[](https://www.typescriptlang.org)
[](https://modelcontextprotocol.io)
[](#what-it-can-do)
[](https://github.com/Akxan/google-seo-mcp/releases)
[](https://github.com/Akxan/google-seo-mcp/actions/workflows/deploy.yml)
[](https://github.com/Akxan/google-seo-mcp/commits/main)

Google Search Console · Google Analytics 4 · PageSpeed & CrUX · on-page and GEO audits · WordPress over SSH · GitHub

[Quick start](#quick-start) · [Tools](#what-it-can-do) · [Any agent](#works-with-any-agent) · [Architecture](#architecture) · [Configuration](#configuration) · [Deploy 24/7](#running-as-a-247-http-server) · [中文文档](README.zh-CN.md)

---

## Why

**google-seo-mcp** is a [Model Context Protocol](https://modelcontextprotocol.io) server for **SEO automation with AI agents**. It connects **Google Search Console**, **Google Analytics 4 (GA4)**, **PageSpeed Insights / Core Web Vitals**, the **Chrome UX Report**, **Knowledge Graph**, **Wikidata**, **IndexNow**, **WordPress** (Yoast SEO, WP-CLI over SSH) and **GitHub**, and adds **GEO (generative engine optimization)** checks: AI crawler access for GPTBot, OAI-SearchBot, ClaudeBot and PerplexityBot, `llms.txt`, JSON-LD / schema.org structured data, E-E-A-T signals and AI citation tracking.

Most SEO MCP servers wrap one API. Real SEO work crosses several: you find a striking-distance keyword in Search Console, check the landing page's engagement in GA4, audit the page, rewrite its title and FAQ, publish the change to WordPress or a static-site repo, then watch the numbers. This server gives an assistant every step of that loop as tools, with the guard-rails a public-facing site needs: read-only mode, destructive-action annotations, and untrusted-content instructions.

## What it can do

| Area | Tools |
|---|---|
| **Search Console** (16) | `gsc_list_sites`, `gsc_search_analytics`, `gsc_site_snapshot`, `gsc_compare_periods`, `gsc_opportunities` (position 8–20 quick wins), `gsc_ctr_opportunities`, `gsc_cannibalization`, `gsc_question_queries`, `gsc_rich_results_report`, `gsc_inspect_url`, `gsc_index_coverage`, `gsc_list_sitemaps` / `gsc_submit_sitemap` / `gsc_delete_sitemap`, `gsc_add_site` / `gsc_delete_site` |
| **Google Analytics 4** (11) | `ga_list_properties`, `ga_property_config` (streams, custom dimensions/metrics, key events, audiences, Ads links, retention — read-only), `ga_run_report`, `ga_batch_run_reports`, `ga_run_pivot_report`, `ga_run_funnel_report`, `ga_run_realtime_report`, `ga_get_metadata`, `ga_check_compatibility`, `ga_compare_periods`, `ga_landing_page_seo` (organic landing pages merged with Search Console) |
| **Page & site audits** (9) | `page_audit`, `site_crawl`, `pagespeed`, `sitemap_check`, `robots_check`, `hreflang_check`, `social_preview_check`, `compare_pages`, `keyword_suggest` |
| **GEO** (12) | `ai_crawler_access`, `llms_txt_check`, `llms_txt_generate`, `structured_data_audit`, `schema_generate`, `schema_validate`, `geo_page_score`, `eeat_audit`, `knowledge_graph_check`, `indexnow_submit`, `ai_citation_check`, `brand_mentions` |
| **Analysis** (5) | `migration_check` (pre-migration URL safety net), `cross_site_links`, `content_refresh_candidates`, `crux_history`, `reviews_snapshot` |
| **WordPress** (21, optional) | `wp_site_info`, `wp_list_posts`, `wp_get_post`, `wp_update_post`, `wp_seo_status`, `wp_update_seo`, `wp_bulk_update_seo` (Yoast fields), `wp_builder_check`, `wp_builder_list_items`, `wp_builder_update` (BeTheme / Muffin Builder content), `wp_list_media`, `wp_update_media` (alt text), `wp_list_terms`, `wp_update_term`, `wp_internal_link_suggestions`, `wp_list_redirects`, `wp_add_redirect`, `wp_delete_redirect` (Yoast Premium), `wp_get_schema`, `wp_set_schema` (JSON-LD injection), `wp_run` (raw WP-CLI) |
| **GitHub** (5, optional) | `github_get_file`, `github_list_dir`, `github_search_code`, `github_list_commits`, `github_commit_files` (atomic multi-file commits, so a static site can be edited from any client) |

Plus `google_auth_status` for diagnostics. Every tool carries MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`), the server publishes `instructions` for the model, and there is a read-only mode and toolset filtering.

Example prompts

- *"Give me a snapshot of example.com for the last 28 days."*
- *"Which queries rank between 8 and 20 with the most impressions, and which posts are they on?"*
- *"Audit https://example.com/guide and score it for AI answer engines."*
- *"Find question-style queries we already get impressions for and tell me where a FAQ is missing."*
- *"Check whether GPTBot, PerplexityBot and ClaudeBot can reach the homepage."*
- *"Before we move to the new host, verify every URL with traffic still resolves on new.example.com."*
- *"Rewrite the SEO title and meta description of post 515 and publish it."*

## Tech stack

| Layer | Choice | Notes |
|---|---|---|
| Runtime | Node.js ≥ 18, TypeScript 5, ES modules | no build-time codegen, `tsc` only |
| Protocol | `@modelcontextprotocol/sdk` | stdio for local clients, stateless Streamable HTTP for servers |
| Google | `googleapis` (Search Console v1, Analytics Data v1beta, Analytics Admin v1beta) + `google-auth-library` | REST clients, no gRPC; service account or OAuth |
| Web audits | `cheerio`, `image-size`, native `fetch` | PageSpeed Insights, CrUX, Knowledge Graph, Wikidata, Google Autocomplete, IndexNow, Perplexity, Brave, Places APIs over HTTPS |
| WordPress | `ssh` + WP-CLI, two PHP helpers uploaded on first use | Yoast indexable rebuild, cache purge (WP Rocket / Super Cache / W3TC / LiteSpeed), mu-plugin for JSON-LD |
| GitHub | REST + Git Data API | token from `GITHUB_TOKEN` or `gh auth token` |
| Validation | `zod` schemas per tool | descriptions double as LLM documentation |
| Quality | smoke test with tool-list snapshot, secret-scan git hooks | `npm test`, `npm run check:secrets` |

## Architecture

```mermaid
flowchart LR
    subgraph Clients
        CC[Claude Code]
        CD[Claude Desktop]
        HTTP[Any MCP clientover HTTPS]
    end

    subgraph Server["google-seo-mcp"]
        direction TB
        T1[stdio transport]
        T2[Streamable HTTPBearer auth · /healthz]
        S["createServer()annotations · read-only · toolsets · instructions"]
        subgraph Tools
            GSC[gsc.ts]
            GA[ga.ts]
            WEB[web.ts · crawl.ts]
            GEO[geo.ts]
            AN[analysis.ts]
            WP[wp.ts]
            GH[github.ts]
        end
        T1 --> S
        T2 --> S
        S --> Tools
    end

    subgraph External
        G[(Google APIsSearch Console · GA4PageSpeed · CrUX · KG)]
        SITES[(Your websites)]
        WPH[(WordPress hostWP-CLI over SSH)]
        GHA[(GitHub)]
        X[(Wikidata · IndexNowPerplexity · Brave · Places)]
    end

    CC --> T1
    CD --> T1
    HTTP --> T2
    GSC & GA --> G
    WEB & GEO & AN --> SITES
    GEO & AN --> X
    AN --> G
    WP --> WPH
    GH --> GHA
```

**Request path.** A client calls a tool → `src/util.ts` `tool()` wraps the handler (JSON result or an actionable `isError`) → the handler talks to one or more upstreams → results are flattened into compact JSON (`{dimension: value, metric: number}` rows, totals first). Long-running tools (`pagespeed`, `site_crawl`, `migration_check`) send progress notifications.

**Cross-source analyses** (`ga_landing_page_seo`, `migration_check`, `cross_site_links`, `content_refresh_candidates`, `gsc_opportunities`) reuse the Search Console query function and a shared URL-path normaliser so pages line up across GA4, Search Console, sitemaps and WordPress post IDs.

**WordPress path.** Every call is `ssh host 'cd  && wp …'` with POSIX-quoted arguments; large payloads go over stdin. Two PHP helpers are uploaded to `~/.google-seo-mcp/` on the host when their hash changes. Yoast meta writes trigger an indexable rebuild and a cache purge so changes are live immediately.

**Safety.** Write tools are recognised by name and receive `readOnlyHint:false` (`destructiveHint:true` for deletes, raw WP-CLI and commits). `--read-only` drops them at registration; `--toolsets=gsc,web` trims the tool list (80 definitions ≈ 22k tokens). Server instructions tell the model that fetched page text and CMS content are untrusted data.

## Quick start

Requirements: Node 18+, a Google Cloud project with the **Search Console API**, **Google Analytics Data API** and **Google Analytics Admin API** enabled.

```bash
git clone https://github.com/Akxan/google-seo-mcp.git
cd google-seo-mcp
npm install
npm run build
cp .env.example .env      # fill in credentials (see below)
```

### Google credentials

**Service account (recommended, works unattended):** create a service account in the Cloud project, download its JSON key, set `GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json` in `.env`, then add the service-account email as a user on each Search Console property (permission *Full*) and each GA4 property (role *Viewer*).

**Your own Google account (OAuth):** create an OAuth client ID of type *Desktop app*, download `client_secret.json`, run

```bash
npm run auth -- --client-secret ./client_secret.json
```

and the resulting `~/.config/google-seo-mcp/credentials.json` is picked up automatically.

Lookup order: `GOOGLE_CREDENTIALS_JSON` (inline) → `GOOGLE_APPLICATION_CREDENTIALS` → `~/.config/google-seo-mcp/credentials.json` → Application Default Credentials.

### Connect a client

The server speaks standard MCP over **stdio** (a local process the client starts) and **Streamable HTTP** (a remote server, see [Running as a 24/7 HTTP server](#running-as-a-247-http-server)), so any MCP client works, not only Claude. For a remote server the recipe is the same everywhere: the URL `https://mcp.example.com/mcp` plus the header `Authorization: Bearer `. For a local server the client needs nothing but the command, because the server reads `.env` from its own directory at startup (environment variables passed by the client take precedence).

**Claude Code**

```bash
claude mcp add google-seo -- node /absolute/path/google-seo-mcp/dist/index.js                                     # local
claude mcp add --transport http google-seo https://mcp.example.com/mcp --header "Authorization: Bearer "   # remote
```

**Claude Desktop, claude.ai and the mobile apps**: Settings → Connectors → *Add custom connector*, URL `https://mcp.example.com/mcp`, authentication *None*, and `Authorization: Bearer ` under *Request headers*. Local alternative for Claude Desktop (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "google-seo": { "command": "node", "args": ["/absolute/path/google-seo-mcp/dist/index.js"] }
  }
}
```

**OpenAI Codex** (`~/.codex/config.toml`; the token is read from an environment variable, so `export GOOGLE_SEO_MCP_TOKEN=…` in your shell profile):

```toml
[mcp_servers.google-seo]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "GOOGLE_SEO_MCP_TOKEN"
tool_timeout_sec = 600          # pagespeed and site_crawl outlive Codex's 60 s default

# local alternative
# [mcp_servers.google-seo]
# command = "node"
# args = ["/absolute/path/google-seo-mcp/dist/index.js"]
```

**Cursor** (`~/.cursor/mcp.json`, or `.cursor/mcp.json` inside a project):

```json
{
  "mcpServers": {
    "google-seo": {
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer " }
    }
  }
}
```

**VS Code** (Copilot agent mode; `.vscode/mcp.json` or the user-level file from *MCP: Open User Configuration*):

```json
{
  "servers": {
    "google-seo": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer " }
    }
  }
}
```

**Gemini CLI** (`~/.gemini/settings.json`; `httpUrl` selects Streamable HTTP, `timeout` is in milliseconds):

```json
{
  "mcpServers": {
    "google-seo": {
      "httpUrl": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer " },
      "timeout": 600000
    }
  }
}
```

**Any other MCP client**: point it at `https://mcp.example.com/mcp` with that header (Streamable HTTP, stateless: every call is a `POST`, there is no session to keep), or launch `node dist/index.js` over stdio. A quick check from a shell:

```bash
curl -s https://mcp.example.com/mcp -H "Authorization: Bearer " -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Two things to know: `pagespeed`, `site_crawl` and `gsc_index_coverage` stream progress notifications but can run for minutes, so raise the client's per-tool timeout if it defaults to 60 s; and ChatGPT's custom connectors accept only OAuth, so they cannot use a static token yet.

## Works with any agent

MCP is an open standard, so nothing here is tied to Claude. Whatever speaks MCP connects directly; whatever can call functions connects through a thin bridge. The one hard limit is a model without function calling: it cannot call tools at all, whichever vendor it comes from.

| You have | How it connects | Notes |
|---|---|---|
| An MCP client: Claude apps, Codex, Cursor, VS Code, Gemini CLI, Cline, Cherry Studio, n8n, Dify, … | URL + `Authorization: Bearer ` ([Connect a client](#connect-a-client)) | Raise the per-tool timeout for `pagespeed` and `site_crawl` |
| An agent you write: Claude Agent SDK, OpenAI Agents SDK, LangChain, Google ADK, Vercel AI SDK | The SDK's MCP client, same URL and header | Examples below |
| A third-party or local model: DeepSeek, Qwen, GLM, Kimi, Ollama | An MCP client that lets you choose the model (Cherry Studio, Cline), or an SDK pointed at the provider's OpenAI-compatible `base_url` | Needs function calling; give it a trimmed read-only instance (below) |
| A no-code platform that can send a URL but no headers | A read-only instance behind a reverse-proxy path that injects the header | Keeps the main instance's token out of any URL |

### From an agent SDK

Claude Agent SDK (TypeScript; Python has the same shape):

```ts
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const m of query({
  prompt: "Snapshot example.com for the last 28 days and list the queries ranking 8-20 with the most impressions",
  options: {
    mcpServers: {
      "google-seo": {
        type: "http",
        url: "https://mcp.example.com/mcp",
        headers: { Authorization: `Bearer ${process.env.GOOGLE_SEO_MCP_TOKEN}` },
      },
    },
    allowedTools: ["mcp__google-seo__*"], // without this the agent sees the tools but will not call them
  },
})) {
  if (m.type === "result" && m.subtype === "success") console.log(m.result);
}
```

OpenAI Agents SDK (Python). The same code drives any OpenAI-compatible provider; DeepSeek shown, drop the `model=` line for OpenAI itself:

```python
import os
from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel, set_tracing_disabled
from agents.mcp import MCPServerStreamableHttp

async def main():
    async with MCPServerStreamableHttp(
        name="google-seo",
        params={"url": "https://mcp.example.com/mcp",
                "headers": {"Authorization": f"Bearer {os.environ['GOOGLE_SEO_MCP_TOKEN']}"}},
    ) as seo:
        set_tracing_disabled(disabled=True)
        deepseek = AsyncOpenAI(base_url="https://api.deepseek.com", api_key=os.environ["DEEPSEEK_API_KEY"])
        agent = Agent(
            name="seo",
            instructions="Use the tools; quote numbers with their period and source.",
            model=OpenAIChatCompletionsModel(model="deepseek-v4-flash", openai_client=deepseek),
            mcp_servers=[seo],

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Akxan](https://github.com/Akxan)
- **Source:** [Akxan/google-seo-mcp](https://github.com/Akxan/google-seo-mcp)
- **License:** MIT
- **Homepage:** https://github.com/Akxan/google-seo-mcp#readme

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-akxan-google-seo-mcp
- Seller: https://agentstack.voostack.com/s/akxan
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
