Why use Claude Code for SEO?
Claude Code for SEO works best when the agent can see two things at once: how your pages actually perform in search and the code that produces them. Add a Search Console MCP server with claude mcp add --transport http, sign in with /mcp, and Claude Code can pull low-CTR queries, top pages and URL Inspection results, then change the title templates, internal links and routes behind them without leaving the terminal.
Most Claude Code SEO guides stop at one half. Some work from CSV exports, which go stale the day you download them. Others run a local Python or Node server that needs a Google Cloud project, an OAuth client and a cloned repository before the first query. A hosted Google Search Console MCP server removes that setup: you connect Google and Bing once in a browser and paste one URL into Claude Code.
| What Claude Code reads from search data | What it can change in your repo |
|---|---|
| Queries with high impressions and weak CTR | Title and meta description templates, CMS frontmatter |
| Pages ranking in positions 8–20 | Internal links, headings, thin sections of copy |
| Index verdict, canonicals, robots.txt state | Canonical tags, robots rules, redirects, sitemap code |
| Gaining and losing pages after a release | The commits that touched those routes |
If you work mostly in an editor, our guide to technical SEO in Cursor and VS Code covers the same tools from the IDE. This guide is about the terminal: scopes, headless runs, skills and CLAUDE.md.
How to connect Google Search Console to Claude Code
Every command below comes from Anthropic’s Claude Code MCP documentation, checked in October 2026. Replace YOUR_MCP_URL with the server URL shown on the Setup page of your dashboard; choose Claude Code there and it prints the full command with your URL filled in.
- Sign in and connect Google Search Console (and Bing Webmaster Tools, if you use it) under Data sources. The Free plan covers one account and 30 tool calls a month.
- Add the server from your terminal:
claude mcp add --transport http --scope user gscmcpserver YOUR_MCP_URL. The HTTP transport is the right one; Anthropic marks SSE as deprecated. - Start
claudein a project, run/mcp, selectgscmcpserverand authenticate. Your browser opens; sign in with Google or GitHub and allow read access. From a plain shell,claude mcp login gscmcpserverruns the same OAuth flow. - Check it with
claude mcp listorclaude mcp get gscmcpserver.
Which scope should you use?
Claude Code stores MCP servers at one of three scopes. Local is the default if you leave out --scope.
| Scope | Stored in | Available in | Use it when |
|---|---|---|---|
local (default) | ~/.claude.json | This project only, just you | You are trying it in one repo |
project | .mcp.json in the repo root | Everyone who clones the repo | A team works on the same site |
user | ~/.claude.json | All your projects | You manage several sites or repos |
Project scope writes a small file you can commit: {"mcpServers": {"gscmcpserver": {"type": "http", "url": "YOUR_MCP_URL"}}}. It holds no secrets, because each teammate signs in through /mcp with their own account. Claude Code asks each person to approve project-scoped servers before first use, and claude mcp reset-project-choices clears those answers.
First run: confirm Claude Code can see your properties
Start with the two cheapest calls. list_search_properties returns every connected Google and Bing account with its authorised properties, and get_search_overview returns clicks, impressions, CTR, average position and daily clicks.
Use gscmcpserver. Call list_search_properties, then get_search_overview for the last 28 days with provider “all”. Show clicks, impressions, CTR and average position separately for Google and Bing, and name the siteUrl each number came from.
Three details save confusion later:
- Property names are exact. Domain properties look like
sc-domain:example.com; URL-prefix properties keep their trailing slash, as inhttps://example.com/. Put the right one inCLAUDE.mdso Claude stops guessing. - Default ranges end three days ago, in Pacific Time, because Google’s data usually lands two to three days late. Ask for
dataState: "all"onquery_search_analyticswhen you need fresher, unfinalised rows. - Bing daily totals have no average position. Query and page rows from Bing do, so compare position at that level.
Claude Code shows the tools as mcp__gscmcpserver__get_search_overview and so on, and asks before calling them. Every tool on this server is read-only, so you can safely allow them all with a mcp__gscmcpserver__* rule in the permissions.allow list of .claude/settings.json.
Workflow 1: rewrite titles and meta descriptions from low-CTR data
The low_ctr strategy of get_search_opportunities returns queries with at least 100 impressions, CTR under 3% and an average position of 20 or better. These are pages Google already shows, but searchers skip. In a codebase, the cause is often a template rather than a single page, which is where Claude Code beats a spreadsheet.
Call get_search_opportunities with strategy “low_ctr”, range “90” and limit 50 for sc-domain:example.com. Then call query_search_analytics with dimensions query and page, limit 200, to find the ranking page for each query. Find where each page’s title and meta description are generated in this repo, and propose changes as a diff. Don’t edit anything yet.
On a typical documentation site, the result looks something like this (illustrative numbers):
| Query | Impr. | Pos. | CTR | What Claude found in the code |
|---|---|---|---|---|
| nextjs sitemap | 6,200 | 4.8 | 1.2% | The shared metadata helper appends “ | Acme Docs – Developer Platform” to every title, pushing the topic past the cut-off |
| postgres connection pooling | 3,900 | 7.6 | 0.9% | The title comes from the frontmatter field title: "Part 3: Going further" |
| webhook retry policy | 2,100 | 3.1 | 2.4% | No meta description is set, so the snippet is taken from a code sample |
The decision rules are simple:
- Fix templates first. One change to a title suffix can improve hundreds of URLs. Check that the change still reads well on the pages that were performing.
- Then fix page-level fields, starting with the query that has the most impressions.
- Skip branded and navigational queries where a competitor or your own homepage rightly wins the click.
- Expect Google to rewrite some titles anyway. Judge the change by CTR, not by whether your exact wording appears.
After Google recrawls the pages, run compare_search_periods with dimension: "page" over 28 days to see whether CTR moved. The striking distance and low-CTR playbook explains how to prioritise the list before you touch any code.
Workflow 2: internal links from your strongest pages
Internal links are the SEO change developers can ship fastest, and search data tells you exactly where they belong. Pages ranking in positions 8–20 are the targets. Pages with the most clicks are the donors, because they are crawled often and already trusted. Our guide to finding internal linking opportunities in Search Console covers the method; this is the repo version.
- Targets:
get_search_opportunitieswithstrategy: "striking_distance"returns queries with at least 50 impressions at average positions 8–20. - Donors:
get_search_pagesreturns your landing pages sorted by clicks. - Safety check:
find_keyword_cannibalizationlists queries where two or more of your pages split impressions. Don’t point new links at the weaker of two competing pages. - Edit: Claude searches the content directory for each donor’s source file and adds a link where the paragraph already discusses the topic.
Get striking distance queries for the last 90 days (limit 30) and my top 20 pages by clicks. Run find_keyword_cannibalization with minImpressions 50 and leave out any query that appears there. For each remaining target page, pick two donor pages on a related topic, find their source files in content/, and propose one link per donor with a descriptive anchor that fits the existing sentence.
Keep it to two or three new links per donor page, use anchors that describe the target page rather than repeating an exact-match query, and link only between pages a reader would plausibly move between. If the cannibalization check finds real overlap, sort that out first with our keyword cannibalization guide.
Workflow 3: check indexing of new and changed routes
After a release, Claude Code can work out which URLs changed from your git history and router, then check each one with inspect_url. The tool calls Google’s URL Inspection API and returns the index verdict, coverage state, last crawl time, page fetch state, robots.txt state, the canonical you declared, the canonical Google chose, the sitemaps that list the URL, and any detected rich results.
Run git diff --name-only against the v2.4.0 tag and work out which public URLs on https://example.com changed. For each one, call inspect_url and report the verdict, coverage state, last crawl time, and whether the Google-selected canonical matches ours. Then call list_sitemaps and tell me whether the sitemap that should contain the new URLs was downloaded after the release date.
Read the results with two limits in mind:
- It reports Google’s indexed copy, not your live page. Google’s URL Inspection API reference states that you cannot test the indexability of a live URL. A brand-new route usually comes back as unknown to Google until it is crawled. Pair it with a live check: Claude can fetch the deployed HTML and read the robots meta tag and canonical directly.
- Quotas are tight. Google allows 2,000 inspections per day and 600 per minute per property, according to its Search Console API usage limits. Each inspection is also one tool call against your plan, so inspect changed URLs, not the whole sitemap.
When a page needs to be indexed, the request still happens in Search Console: open URL inspection, paste the URL and choose Request indexing. The API offers no such method, and GSC MCP Server is read-only in any case. For Bing, Claude Code can add an IndexNow ping to your own deploy script; see why Bing indexing matters for AI search. To read a coverage state, look up what each Page indexing status means.
Make it repeatable: CLAUDE.md, skills and a weekly SEO check
Put SEO conventions in CLAUDE.md
Claude Code loads a project CLAUDE.md (at the repo root or in .claude/) at the start of every session. Anthropic recommends keeping each file under 200 lines. A short SEO section is enough:
- Search data comes from the gscmcpserver MCP tools. Google property:
sc-domain:example.com. Bing property:https://example.com/. - Titles are built in
src/lib/seo.ts. Keep them under 60 characters with the main topic first. - Don’t change canonical tags, robots rules or redirects without showing
inspect_urlresults first. - Use limit 50 on MCP calls unless I ask for more.
Build a /seo-weekly skill
A Claude Code skill is a folder with a SKILL.md file. Save this one as .claude/skills/seo-weekly/SKILL.md and commit it, so the whole team runs the same check with /seo-weekly. (Custom commands in .claude/commands/ have been merged into skills and still work.)
| Frontmatter field | Value | Why |
|---|---|---|
name | seo-weekly | Becomes the slash command |
description | Weekly SEO check using Search Console and Bing data | Tells Claude what the skill does |
disable-model-invocation | true | Runs only when you type it, so it never spends calls unasked |
The body is plain instructions:
- Make one
multicallwithcompare_search_periods(range 7, dimension page, limit 10),get_search_opportunitieswithlow_ctr(limit 10), the same withstriking_distance(limit 10), andlist_sitemaps. - Flag any page that lost more than 20% of its clicks week on week and check the git log for commits that touched it.
- Write a summary to
seo/weekly/with today’s date as the file name. - Propose no more than three changes, each with the file path, and wait for approval before editing.
multicall runs up to ten tools in one request, but each tool inside it counts as a call. This skill uses four a week, about 17 a month, which fits the Free plan’s 30 calls. Add URL inspections or a second property and you will want Pro (10,000 calls a month, see pricing).
Running Claude Code SEO checks headlessly with claude -p
claude -p runs a prompt non-interactively and exits, which makes it suitable for cron jobs and CI. Skills work there: Anthropic’s headless docs say you include /skill-name in the prompt string. Two things trip people up.
- OAuth can’t happen headless. A
claude -prun or an Agent SDK session has no/mcppanel, so it cannot complete a sign-in. Sign in once interactively with/mcporclaude mcp login gscmcpserver; later headless runs on the same machine reuse that sign-in. - Tools need pre-approval. By default, a headless run denies any call that needs approval. Allow the server’s tools explicitly.
A Monday-morning cron entry on your own machine looks like this:
0 8 * * 1 cd ~/code/acme-site && claude -p "/seo-weekly" --allowedTools "mcp__gscmcpserver__*,Write"
On a CI runner there is no stored OAuth token, so use an API key from a secret. Add the server in the job with the --header "Authorization: Bearer …" form shown in the setup section, then run the same claude -p command. If you use --bare for faster, reproducible CI runs, note that it skips your saved MCP servers, so pass the server with --mcp-config instead. Add --output-format json when another script needs to parse the result.
Limits and troubleshooting
The limit that bites first is output size. Claude Code warns when an MCP result passes 10,000 tokens and caps it at 25,000 tokens by default. Separately, a text result longer than 50,000 characters is saved to a file that Claude reads when needed. Each row from these tools carries the query or page, five metrics and account details, so a few hundred rows can cross that line. Keep limit between 50 and 200, filter by page or query, page through with startRow, or raise the cap with MAX_MCP_OUTPUT_TOKENS=50000 before starting Claude Code.
| Symptom | Likely cause | Fix |
|---|---|---|
/mcp shows the server needs authentication | OAuth not completed | Select it in /mcp and authenticate, or run claude mcp login gscmcpserver |
| Headless run fails on the first tool call | No sign-in, or tools not allowed | Sign in interactively first and pass --allowedTools "mcp__gscmcpserver__*" |
| 401 Unauthorized with an API key | Key expired, revoked or mistyped | Create a new key; the header must read Authorization: Bearer <key> |
| “Select an authorized property” | siteUrl doesn’t match exactly | Copy the siteUrl from list_search_properties |
| Result saved to a file, or a large-output warning | limit too high | Lower the limit or add filters |
| Monthly tool call limit reached | Plan quota used up | Batch less, inspect fewer URLs, or upgrade under Billing |
Same setup in Codex and Antigravity CLI
The prompts and workflows above work in any agent that speaks MCP over Streamable HTTP. Only the setup differs.
- Codex:
codex mcp add gscmcpserver --url YOUR_MCP_URL, thencodex mcp login gscmcpserverfor OAuth. The entry is saved under[mcp_servers.gscmcpserver]in~/.codex/config.toml, which the Codex MCP docs say is shared with the IDE extension and the ChatGPT desktop app. For an API key, setbearer_token_env_varto the name of an environment variable that holds it. - Antigravity CLI (which replaced Gemini CLI for most individual users in June 2026): add the server to
~/.gemini/config/mcp_config.jsonor a workspace’s.agents/mcp_config.jsonusing aserverUrlfield. The olderhttpUrlkey is not supported. Per the Antigravity MCP docs, servers with dynamic client registration need no extra OAuth settings, and/mcpopens the MCP Manager.
For Claude, ChatGPT, Cursor and VS Code, follow the step-by-step connection guide. Once you are connected, our library of Search Console prompts gives you 40 more questions to put to the same tools.
Frequently asked questions
Can Claude Code read my Google Search Console data?
Yes, through an MCP server. Add a remote Search Console MCP server with claude mcp add --transport http, sign in with /mcp, and Claude Code can call tools that return clicks, impressions, CTR, position, URL Inspection results and sitemaps for the properties you authorised.
Do I need a Google Cloud project or an API key from Google?
Not with a hosted server. Local open-source servers usually need your own Google Cloud project with an OAuth client or a service account. A hosted server handles the Google OAuth for you: you sign in once in the browser. The Search Console API itself has no API keys; it only accepts OAuth or service accounts.
Can Claude Code fix SEO issues automatically?
It can edit the code that causes them, such as title templates, internal links, canonical tags and sitemap generation, and it shows you the diff first. It cannot change anything inside Search Console: GSC MCP Server is read-only, so requesting indexing or submitting a sitemap still happens in the Search Console interface.
How do I run a weekly SEO check headlessly?
Save the check as a project skill, sign in to the MCP server once in an interactive session, then schedule claude -p "/seo-weekly" with --allowedTools "mcp__gscmcpserver__*" from cron or CI. Headless runs cannot complete OAuth, so CI runners should use an API key sent as an Authorization header instead.
What happens if a tool returns too much data?
Claude Code warns when an MCP result passes 10,000 tokens and limits output to 25,000 tokens by default; text results longer than 50,000 characters are saved to a file that Claude reads in pieces. Keep the limit parameter between 50 and 200, filter by page or query, or raise MAX_MCP_OUTPUT_TOKENS.
Does this work with Codex and Gemini CLI?
Codex works with codex mcp add and codex mcp login. Gemini CLI was replaced by Antigravity CLI for most individual users in June 2026; Antigravity CLI reads remote servers from mcp_config.json using a serverUrl field.