Skip to main content
Glama
kiarashedraki

search-console-mcp

README.md
# search-console-mcp

A small, stateless MCP server for the Google Search Console API, served over Streamable HTTP.

It never stores credentials. Every request must carry `Authorization: Bearer <Google access token>`, and the server uses that token for that one request. An auth proxy such as [Nango](https://nango.dev) keeps the Google login, refreshes it, and adds the header. Because the token decides which account is used, one container serves any number of Google accounts.

```
MCP client ──► auth proxy (Nango: stores + refreshes the Google login)
                  │  Authorization: Bearer ya29…
                  ▼
            search-console-mcp  ──►  Search Console API
```

## Tools

| Tool | What it does |
|---|---|
| `list_sites` | Properties the account can access, with permission level |
| `search_analytics` | Clicks, impressions, CTR, position grouped by query / page / country / device / date / searchAppearance, with filters and paging |
| `list_sitemaps` | Submitted sitemaps with download, error, warning and indexed counts |
| `get_sitemap` | Status of one sitemap |
| `inspect_url` | URL Inspection: index verdict, coverage, last crawl, canonical |
| `submit_sitemap` | Submit or resubmit a sitemap (write) |
| `delete_sitemap` | Remove a sitemap (write) |

Set `GSC_READ_ONLY=true` to hide the two write tools.

## Google scopes

The token must have `https://www.googleapis.com/auth/webmasters` (read and write) or `https://www.googleapis.com/auth/webmasters.readonly` (read only). The Google Cloud project that owns the OAuth client must have the **Google Search Console API** enabled.

## Configuration

| Env var | Default | Purpose |
|---|---|---|
| `PORT` | `8000` | Listen port |
| `HOST` | `0.0.0.0` | Listen address |
| `MCP_PATH` | `/mcp` | MCP endpoint path |
| `GSC_READ_ONLY` | `false` | Hide `submit_sitemap` / `delete_sitemap` |
| `GSC_TIMEOUT_MS` | `30000` | Timeout for each Google API call |

`GET /health` returns `{"ok":true}`. The server is stateless: only `POST /mcp` is served (GET and DELETE return 405), and a request without a bearer token gets 401.

## Run

```bash
npm ci && npm run build
PORT=8000 node dist/index.js
```

or with Docker:

```bash
docker build -t search-console-mcp-http .
docker run --rm -p 8000:8000 search-console-mcp-http
```

Keep it on a private network behind the auth proxy. It does not check who is calling, only that a Google token is present, and Google checks the token itself.

## License

MIT