opengsc
Let Claude (or any MCP client) read your Google Search Console data and help you with SEO.
- Read-only. It can see your data, never change it.
- Small. 4 tools, ~700 lines of Python you can audit in one sitting.
- Private. Talks only to Google. No telemetry, no third-party servers.
Ask things like "Which queries get impressions but few clicks?" or "Is this page indexed?" and Claude pulls the real numbers from Search Console.
Setup (about 10 minutes)
You need:
- A Google account with access to at least one Search Console property.
- uv installed. It also installs Python for you if needed.
- Windows:
winget install astral-sh.uv - macOS/Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
- Windows:
- Git installed (
git --versionto check).
Then follow the four steps below.
Note: opengsc is not on PyPI yet, so the commands below install it straight from GitHub.
Step 1. Create a Google OAuth client
This gives opengsc permission to ask Google for your data. You do it once.
-
Create a project. Open console.cloud.google.com/projectcreate, name it
opengscand click Create. Make sure it is selected in the project picker at the top.Tip: use a dedicated project. The consent screen is shared by everything in a project.
-
Enable the API. Open the Search Console API page and click Enable.
-
Set up the consent screen. Open Google Auth Platform and click Get started:
- App name:
opengsc - User support email: your email
- Audience: External
- Contact email: your email
- Accept the policy and click Create.
- App name:
-
Publish the app. Open Audience and click Publish app, then confirm. The status should read In production.
- Why: in Testing mode, Google expires your login every 7 days.
- Is it safe? Yes. Publishing does not make your data public. Anyone who logs in through it only sees their own Search Console, and nobody can read yours without your Google login.
-
Create the client. Open Clients, click Create client:
- Application type: Desktop app (not Web application)
- Name:
opengsc - Click Create, then Download JSON right away. Google won't show the secret again.
Step 2. Put the JSON file in place
Rename the downloaded file to client_secret.json and move it here:
| OS | Location |
|---|---|
| Windows | C:\Users\<you>\.config\opengsc\client_secret.json |
| macOS / Linux | ~/.config/opengsc/client_secret.json |
Windows (PowerShell):
mkdir $HOME\.config\opengsc -Force
Move-Item $HOME\Downloads\client_secret_*.json $HOME\.config\opengsc\client_secret.json
macOS / Linux:
mkdir -p ~/.config/opengsc
mv ~/Downloads/client_secret_*.json ~/.config/opengsc/client_secret.json
Windows gotcha: if you rename the file in Explorer with extensions hidden, it can end up as
client_secret.json.json. Check withdir $HOME\.config\opengsc.
Step 3. Log in
uvx --from git+https://github.com/diegomm27/opengsc opengsc auth
Your browser opens:
- Pick the Google account that has access to Search Console.
- You'll see "Google hasn't verified this app". That's expected for a personal app: click Advanced → Go to opengsc.
- Allow read access to Search Console.
Your login is saved to ~/.config/opengsc/token.json. On a machine without a browser, add --no-browser and open the printed URL yourself.
Check that everything works:
uvx --from git+https://github.com/diegomm27/opengsc opengsc doctor
You should see auth check: OK and a property count above 0.
Step 4. Connect it to Claude
opengsc runs on your computer, so it works in Claude Desktop and Claude Code (not in claude.ai in the browser).
Claude Desktop: open Settings → Developer → Edit Config and add opengsc to claude_desktop_config.json:
{
"mcpServers": {
"opengsc": {
"command": "uvx",
"args": ["--from", "git+https://github.com/diegomm27/opengsc", "opengsc"]
}
}
}
If the file already has other servers, add only the "opengsc": {...} block inside mcpServers. Then quit Claude Desktop completely (including the tray/menu bar icon) and reopen it.
Claude Code (pick one):
# as a plugin
claude plugin marketplace add diegomm27/opengsc
claude plugin install opengsc@opengsc
# or as a plain MCP server
claude mcp add opengsc -- uvx --from git+https://github.com/diegomm27/opengsc opengsc
Any other MCP client: run uvx --from git+https://github.com/diegomm27/opengsc opengsc over stdio.
Try it
Start a new chat and ask:
- "List my Search Console properties."
- "Top 50 queries by impressions in the last 28 days for sc-domain:example.com."
- "Which pages have lots of impressions but a CTR under 2%?"
- "Queries where I rank between 5 and 15 on mobile."
- "Check the status of my sitemaps."
- "Is https://example.com/blog/post indexed?"
Start with the first one: it returns the exact property names (sc-domain:... or https://.../) the other tools need.
Tools
| Tool | What it returns |
|---|---|
list_sites() |
Properties you can read, with your permission level. |
search_analytics(site_url, ...) |
Clicks, impressions, CTR and position, by query, page, country, device, date or search appearance. Supports filters. |
list_sitemaps(site_url) |
Submitted sitemaps, last download, errors and warnings. |
inspect_url(site_url, url) |
Index status, canonical, last crawl, mobile usability. Limited by Google to 2,000 calls/day per property. |
Data comes back unprocessed (TSV or Google's raw JSON), so Claude works with exact numbers.
search_analytics parameters
| Parameter | Default | Options |
|---|---|---|
start_date, end_date |
last 28 days, ending 3 days ago (GSC data lag) | YYYY-MM-DD |
dimensions |
["query"] |
query, page, country, device, date, searchAppearance |
filters |
none | list of {"dimension", "operator", "expression"}; operators equals, notEquals, contains, notContains, includingRegex, excludingRegex |
search_type |
web |
web, image, video, news, discover, googleNews |
data_state |
final |
final, all (includes fresh data) |
row_limit |
1000 |
1 to 25000 |
start_row |
0 |
for pagination |
The output ends with a metadata block. more_may_exist: true means the page was full; ask for the next one with start_row.
Troubleshooting
| Problem | Fix |
|---|---|
No OAuth client configured |
client_secret.json isn't where opengsc looks. Check the path and the name (Step 2). |
auth fails right away with a valid-looking file |
The client must be Desktop app. Open the JSON: it should start with {"installed":. If it starts with {"web":, create a new Desktop client. |
| "Google hasn't verified this app" | Normal. Click Advanced → Go to opengsc. |
401 / invalid_grant |
Login expired or was revoked. Usually the app was left in Testing (Step 1.4). Run opengsc auth again. |
403 / "User does not have permission" |
Wrong property name or no access. Use the exact string from list_sites(): sc-domain:example.com for domain properties, https://example.com/ (with the trailing slash) for URL-prefix ones. |
doctor shows 0 properties |
You logged in with an account that has no Search Console access. Run auth again with the right one. |
| Claude doesn't see the tools | Fully restart Claude Desktop. In Claude Code, run claude mcp list. |
429 / quota exceeded |
Google's daily limits. Wait and retry. |
| No data for old dates | Search Console only keeps 16 months. |
| Query totals don't add up | Google hides rare queries for privacy, so per-query sums are lower than the site total. |
To revoke access at any time: myaccount.google.com/permissions → opengsc → Remove access.
Security and transparency
- Permission requested: only
https://www.googleapis.com/auth/webmasters.readonly. opengsc cannot submit sitemaps, edit properties or manage users. - Network lock: every request goes through one guard (
src/opengsc/allowlist.py) that only allowswww.googleapis.com,searchconsole.googleapis.com,oauth2.googleapis.comandaccounts.google.com. Anything else, redirects included, fails before it's sent. - Endpoints used:
sites.list,searchAnalytics.query,sitemaps.list,urlInspection.index.inspect. Nothing else. - Files on disk:
~/.config/opengsc/client_secret.json(yours) and~/.config/opengsc/token.json(your login, saved with0600permissions; best effort on Windows). Keeptoken.jsonprivate: whoever has it can read your Search Console. - Dependencies:
mcp,google-auth,google-auth-oauthlib, pinned exactly. That's all. - Not included on purpose: writes, analysis or scoring, telemetry, update checks, bundled prompts.
Advanced: other ways to authenticate
opengsc looks for credentials in this order (doctor shows which one it used):
- Service account: set
OPENGSC_SERVICE_ACCOUNT_FILEto the path of a service account JSON key. Then add the service account's email as a user of your property in Search Console (Settings → Users and permissions). No browser login needed, good for servers. - Refresh token from the environment:
opengsc authprintsOPENGSC_REFRESH_TOKEN=...once. Set that variable (plus the OAuth client, see below) to run without atoken.jsonfile, for example in a container. Treat it like a password. - Saved login:
~/.config/opengsc/token.json, created byopengsc auth.
Instead of client_secret.json, you can provide the OAuth client with the OPENGSC_CLIENT_ID and OPENGSC_CLIENT_SECRET environment variables.
Development
git clone https://github.com/diegomm27/opengsc.git
cd opengsc
uv sync # install with dev dependencies
uv run pytest # tests (no network, HTTP is mocked)
uv run ruff check src tests && uv run ruff format --check src tests
claude plugin validate . # check the plugin manifest
CI runs lint and tests on Linux, macOS and Windows (Python 3.10 and 3.12). Releases are published to PyPI through Trusted Publishing.
License
MIT. See LICENSE.
Metadata
Release files for opengsc 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| opengsc-0.1.0.tar.gz | 118.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| opengsc-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 135.8 kB
Release files / opengsc-0.1.0.tar.gz
| Download URL | opengsc-0.1.0.tar.gz |
|---|---|
| Size | 118.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
65e18b9edd2a48239c406b9d456b7bd2a5c24c88b6cbc61c6b92123ce777a336
|
|
BLAKE2b-256 checksum How to use checksums |
fd638626dba9a331637b68ca50b76da9e66255c0dc76e9bb903cec1fe9681296
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logRelease files / opengsc-0.1.0-py3-none-any.whl
| Download URL | opengsc-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c984f4b2deedf0eedd86c65c0bf49391801de5103b1a95bc0907f9d91d8037e1
|
|
BLAKE2b-256 checksum How to use checksums |
7a50cc4d5fb8ac310f8adf0287f82c683fea9a4ab0cd34569c454030f5113657
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency log