GSC Wizard MCP

GSC Wizard MCP Server

Connect Claude, Cursor, ChatGPT, and other MCP clients directly to your Google Search Console data in GSC Wizard.

This server implements the Model Context Protocol. Once connected, your AI assistant can query Search Console analytics, inspect URLs, manage topic clusters and content groups, use Google Inspection API, submit URLs to IndexNow, read Bing Webmaster Tools data, and more, all scoped to your own account.

All you need to connect: an MCP API key, free for every GSC Wizard account. Create one at tool.gscwizard.com/account/api-keys. Keys look like gscw_live_... and are shown only once at creation.

Why analysis runs server-side

Most SEO and analytics MCP servers hand the raw rows back to the model: thousands of query/page records streamed into the context window for the LLM to crunch. Language models are not built for arithmetic over large tables. They are slow at it, they burn tokens doing it, and they make mistakes (dropped rows, miscounted sums, hallucinated totals) that are hard to catch.

GSC Wizard does the opposite. Every analysis (CTR curves, decay detection, cannibalization, opportunity scoring, path breakdowns, ranking changes, full SEO reports) is computed in server-side Python and SQL, against the data warehouse, before anything reaches the model. The tool returns the finished result, not the raw input.

What that gets you

  • Far fewer tokens. A single tool call returns a compact, finished answer instead of tens of thousands of rows the model has to read, hold in context, and pay for.
  • Much faster. Aggregations run on the warehouse in milliseconds. The model spends its time reasoning about the result, not grinding through a spreadsheet one token at a time.
  • Not prone to errors. The math is deterministic. Numbers come from real queries, so there is no risk of the model miscounting or inventing totals.
  • Bigger datasets in scope. Because the heavy lifting never enters the context window, the server can analyze months of data and millions of rows that would never fit in a prompt.

The model still does what it is good at: interpreting the findings, spotting the story, and recommending what to do next. The crunching just happens where it belongs.

Endpoint

Streamable HTTP

https://mcp.gscwizard.com/mcp

Two ways to authenticate, both tied to your GSC Wizard account:

  • API key (header): send Authorization: Bearer gscw_live_.... Best for config-file clients (Claude Code, Cursor, VS Code, Windsurf).
  • OAuth 2.1 (sign-in): clients that support remote OAuth (ChatGPT, the Claude web/app Connectors UI, the native Claude Desktop connector) discover it automatically and walk you through a Google sign-in and consent screen. No key to copy or store.

In clients that render rich tool output (such as ChatGPT), summary tools like get_site_summary, query_top_queries, query_top_pages, get_ranking_changes, list_sites, and generate_seo_report display an interactive, theme-aware card/table view. Other clients receive the same data as JSON.

Connect a client

The server speaks Streamable HTTP, so any client that supports remote MCP servers can connect. The config-file clients below (Claude Code, Cursor, VS Code, Windsurf) authenticate with an API-key header: replace gscw_live_... with your key. Clients that support remote OAuth (ChatGPT, the Claude web/app Connectors UI, the native Claude Desktop connector) instead just need the URL and will sign you in: see the OAuth note in each section.

Claude Code

claude mcp add --transport http gsc-wizard \
  https://mcp.gscwizard.com/mcp \
  --header "Authorization: Bearer gscw_live_..."

Claude Desktop

Easiest (OAuth, no Node): Settings → Connectors → Add custom connector, enter https://mcp.gscwizard.com/mcp as the URL, and leave the OAuth fields blank. Claude registers itself automatically, opens a Google sign-in and consent screen, and connects. Nothing to copy or store.

Claude Desktop Add custom connector dialog with the GSC Wizard MCP URL filled in and the OAuth Client ID and Secret fields left blank
Add custom connector: paste the URL, leave the OAuth fields blank.

Alternative (static API key): Claude Desktop's config file launches only local (stdio) servers, so pasting a "type": "http" entry is rejected as invalid. To use an API key instead of OAuth, bridge the remote server through mcp-remote (requires Node.js). Settings → Developer → Edit Config, then add:

{
  "mcpServers": {
    "gsc-wizard": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "https://mcp.gscwizard.com/mcp",
        "--header", "Authorization:${AUTH_HEADER}"
      ],
      "env": { "AUTH_HEADER": "Bearer gscw_live_..." }
    }
  }
}

The key goes in env rather than inline because mcp-remote splits each --header value on spaces, so Authorization:${AUTH_HEADER} is written without a space. On Windows, if npx fails to launch, set "command": "cmd" and prepend "/c", "npx" to args. Quit and reopen Claude Desktop fully after saving.

Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json in a project:

{
  "mcpServers": {
    "gsc-wizard": {
      "url": "https://mcp.gscwizard.com/mcp",
      "headers": {
        "Authorization": "Bearer gscw_live_..."
      }
    }
  }
}

VS Code (GitHub Copilot agent mode)

Add to .vscode/mcp.json in your workspace (or run the MCP: Add Server command). VS Code uses servers, not mcpServers, and can prompt for the key so it stays out of source control:

{
  "inputs": [
    { "id": "gscw-key", "type": "promptString", "description": "GSC Wizard MCP key", "password": true }
  ],
  "servers": {
    "gsc-wizard": {
      "type": "http",
      "url": "https://mcp.gscwizard.com/mcp",
      "headers": {
        "Authorization": "Bearer ${input:gscw-key}"
      }
    }
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json. Windsurf uses serverUrl for remote servers:

{
  "mcpServers": {
    "gsc-wizard": {
      "serverUrl": "https://mcp.gscwizard.com/mcp",
      "headers": {
        "Authorization": "Bearer gscw_live_..."
      }
    }
  }
}

ChatGPT

Custom connectors need ChatGPT Plus, Pro, Business, Enterprise or Edu; they are not available on Free or Go. (The GSC Wizard ChatGPT app is the route for those plans: it needs no developer mode. A GSC Wizard subscription or trial applies either way.) Custom MCP servers live under Settings → Apps (developer mode, formerly "Connectors"). Enable Developer mode, add an app, and enter https://mcp.gscwizard.com/mcp as the Server URL. ChatGPT uses OAuth 2.1: it registers itself, then opens the GSC Wizard sign-in and consent screen. Leave the OAuth client ID/secret fields blank (the server supports dynamic client registration). There is no API-key field, which is expected: ChatGPT cannot present static bearer tokens, so it uses OAuth.

ChatGPT New App dialog in developer mode with the GSC Wizard MCP URL as the Server URL and Authentication set to OAuth
New App (Developer mode): Server URL + Authentication “OAuth”; client ID/secret left blank.

Programmatic access also works through the OpenAI Responses API, which accepts a remote MCP tool with a headers object, so there you can pass Authorization: Bearer gscw_live_... directly. Note that ChatGPT's built-in Deep Research connectors only call search and fetch tools; full tool access is via developer-mode apps and the Responses API.

Any other MCP client

Point it at the Streamable HTTP endpoint and send your key as a bearer token:

URL:    https://mcp.gscwizard.com/mcp
Header: Authorization: Bearer gscw_live_...

Key names vary between clients (for example transport vs type, url vs serverUrl), but the URL and bearer header stay the same. Check your client's MCP docs if the keys above are not recognized.

Authentication and scopes

Each API key carries a scope, chosen when you create it:

MCP tools require an active subscription or a running free trial. Creating new API keys needs the same; existing keys can always be revoked from the API keys page, where revocation takes effect immediately.

Rate limits

Tool calls are rate limited per account to protect your Search Console quota and keep the service responsive. Two windows apply at once, and a call must fit within both. The MCP transports (assistants such as Claude and ChatGPT) and the REST API each get their own budget, so a dashboard refreshing over REST cannot lock you out of your assistant session:

WindowMCP (assistants)REST API (/v1)
Per minute60 tool calls180 tool calls
Per hour1,000 tool calls2,000 tool calls

The REST minute window is the wider of the two because REST traffic is bursty by construction: a Data Studio dashboard refreshes every chart independently and concurrently, so a page arrives as one spike and then goes quiet. The hour window is what still bounds sustained load.

Within a surface the limit is shared across every key and session on your account, so opening more sessions does not raise it. Only tool invocations (tools/call) count: protocol handshakes such as initialize and tools/list are free, and a batched request that invokes several tools counts as one call per tool. A few expensive tools count for more than one call each.

When you exceed a window over REST the server returns HTTP 429 with a Retry-After header giving the seconds until the window resets, and a JSON body: { "error": { "code": "rate_limited", "message": "Rate limit exceeded (minute window). Retry after 42s." } }. Pause for Retry-After seconds and retry. Over MCP the same condition comes back as a tool error carrying that message, which most clients surface as a transient error you can simply re-run.

These limits are separate from Google's own quotas. URL Inspection tools (inspect_url, bulk_inspect_urls, check_tracked_url_now) also draw on the daily ~2,000-inspection-per-property quota you share with the GSC Wizard UI.

Tools

The server exposes 116 tools. You normally just ask your assistant in natural language ("show my top queries last month for example.com") and it picks the right tool and fills the arguments. The JSON under each tool below shows the argument shape, so you can see what each one accepts. Dates use YYYY-MM-DD and are optional on every tool that takes a date range: omit startDate/endDate and the server uses the most recent settled window automatically (never pass null or the string "null"). siteUrl is a value returned by list_sites (a URL prefix like https://example.com/ or a domain property like sc-domain:example.com).

Date ranges are optional. Every tool that takes a date range treats startDate and endDate as optional: omit them and the server analyzes the last 28 days Search Console has settled (its data lags ~2-3 days). Pass one end or both to narrow the window; the comparison tools (get_ranking_changes, find_decaying_content) default the baseline to the same-length period immediately before the current one. You never need to know today's date, and you should never send null or the string "null" for a date.
Where the numbers come from. The search-analytics tools (query_search_analytics, query_top_queries, query_top_pages, query_countries, query_devices, get_site_summary, get_query_performance, get_page_performance) and the analysis-report tools (get_ranking_changes, find_decaying_content, get_decay_overview, analyze_cannibalization, analyze_ctr_curve, find_page_poaching_opportunities, score_opportunities, breakdown_by_path, analyze_sampling_impact, get_sitemap_performance, get_cross_site_summary, get_tag_group_view) read from the GSC Wizard data warehouse when it has your property: that gives you longer history and no Search Console sampling. Otherwise they fall back to the live Search Console API automatically. Every response includes a dataSource field set to clickhouse or api so you always know which one answered. Warehouse responses also include a settledThrough date and a freshness note: warehouse data settles ~2 days behind real-time, so for the most recent day or two the live API is the better source. Requests that need the searchAppearance dimension, the googleNews type, three or more distinct dimensions, or pagination always use the live API.
Source maturity. The eight search-analytics data tools (query_search_analytics, query_top_queries, query_top_pages, query_countries, query_devices, get_site_summary, get_query_performance, get_page_performance) return a dataMaturity block on both the warehouse and the live-API path, and every response carries a top-level settledThrough. Search Console has no native settled-through field, so the server runs one small date-grouped probe with dataState: "all" over the last ten days, keeps the API's raw metadata.firstIncompleteDate, and derives settledThrough as the calendar day immediately before it. Both dates are on Search Console's own basis, Pacific time (dateBasis: "America/Los_Angeles"); probe records the exact request so the boundary can be reproduced. The lookup fails closed: when the API returns no usable firstIncompleteDate, both dates are null and source is "unavailable" with a note. Never infer a settlement date from the last returned row, since zero-activity days are omitted from row data. On warehouse responses settledThrough is the earlier of the ingest cutoff (dataMaturity.warehouseCutoff) and the API boundary. The GA4 report tools (get_ga4_overview, query_ga4_report, get_ga4_ecommerce, get_ga4_key_events, get_ga4_llm_traffic, get_ga4_error_pages) return the property's IANA reporting zone as timeZone, taken from the Data API's response metadata (falling back to the Admin API property record), which is the basis of every GA4 date they return. All of this uses the existing read-only webmasters.readonly and analytics.readonly scopes.
Metric units. Every ctr field returned by any tool is a percentage from 0 to 100 (a 2.34% click-through rate is 2.34, not 0.0234) — the same on the warehouse path, the live Search Console path, and the Bing tools. Differences between two CTRs (ctrPoints, ctrDelta, the deltas map on analyze_ctr_curve) are in percentage points. position is an impressions-weighted average where lower is better. GA4 rate metrics are the exception and keep the Data API's own units: bounceRate and engagementRate are 0-1 fractions.
Bing Webmaster Tools. The list_bing_sites and get_bing_* tools read the Bing side of organic search (Bing, Yahoo, DuckDuckGo) live from the Bing Webmaster API. They use the Bing Webmaster API key stored on the property's connected Google account in GSC Wizard, so they need no separate connection here: if no key is set up, the tool returns notConfigured: true with a hint instead of an error. Bing exposes roughly the last 6 months per endpoint, so omitting the date range returns everything Bing has (not a settled-window default like the Search Console tools).

Reads 85

list_sites read

List Search Console properties connected to the account.

{}

No arguments. Start here to get the siteUrl values the other tools expect.

get_account_info read

Profile, connected Google accounts, and subscription state.

{}

No arguments.

generate_seo_report read

Runs the whole analysis suite for a property in one call and returns a complete, self-contained HTML report (overview, top queries/pages, countries & devices, CTR curve, opportunities, ranking changes, decay, cannibalization, sections, coverage, sitemaps). Much faster than calling each tool separately.

{
  "siteUrl": "sc-domain:example.com",
  "days": 28,
  "format": "html"
}

days defaults to 28 (7-180). format: "html" (default, ready-to-open report) or "json" (raw data bundle). includeSitemap defaults to true.

query_search_analytics read

Ad-hoc searchAnalytics.query against a property. The most flexible read tool.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "dimensions": [
    "query",
    "page"
  ],
  "rowLimit": 1000,
  "filters": [
    {
      "dimension": "country",
      "operator": "equals",
      "expression": "usa"
    }
  ]
}

startDate/endDate, dimensions, rowLimit (defaults to 1000, uncapped; the live-API path auto-paginates past 25000), searchType, startRow, and filters are all optional. Omit the dates for the last 28 settled days.

get_site_summary read

Last-N-days totals plus a prior-period comparison.

{
  "siteUrl": "sc-domain:example.com",
  "days": 28
}

days defaults to 28 (max 180).

inspect_url read

Run the URL Inspection API for one URL and persist the result to history.

{
  "siteUrl": "sc-domain:example.com",
  "inspectionUrl": "https://example.com/blog/post"
}
get_inspection_quota read

Remaining URL inspections available today for a property.

{
  "siteUrl": "sc-domain:example.com"
}
list_saved_filters read

Saved filter presets, optionally restricted to one property.

{
  "siteUrl": "sc-domain:example.com"
}

siteUrl is optional; omit it to list every saved filter on the account.

list_topic_clusters read

Topic clusters defined for a property.

{
  "siteUrl": "sc-domain:example.com"
}
list_content_groups read

Content groups and their URL-matching rules for a property.

{
  "siteUrl": "sc-domain:example.com"
}
list_sitemaps read

Sitemaps submitted to Search Console for a property.

{
  "siteUrl": "sc-domain:example.com"
}
list_url_inspections read

Persisted URL inspection history (paginated).

{
  "siteUrl": "sc-domain:example.com",
  "urlContains": "/blog/",
  "limit": 100
}

urlContains is optional; limit defaults to 100 (max 500).

query_top_queries read

Top search queries by clicks for a date range.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "limit": 100
}

limit defaults to 100, uncapped (pull the whole property if you want); searchType defaults to "web". startDate/endDate are optional: omit them for the last 28 settled days.

query_top_pages read

Top landing pages by clicks for a date range.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "limit": 100
}

limit defaults to 100, uncapped (pull the whole property if you want); searchType defaults to "web". startDate/endDate are optional: omit them for the last 28 settled days.

query_countries read

Per-country clicks/impressions breakdown.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "limit": 100
}

limit defaults to 100, uncapped. startDate/endDate are optional: omit them for the last 28 settled days.

query_devices read

DESKTOP / MOBILE / TABLET split for a date range.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28"
}

startDate/endDate are optional: omit them for the last 28 settled days.

list_annotations read

Chart annotations (platform, account, or property scope).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-01-01",
  "endDate": "2026-05-28"
}

All fields optional; omit siteUrl for account-wide annotations.

list_algo_updates read

Confirmed Google ranking updates from the status feed.

{
  "startDate": "2026-01-01",
  "endDate": "2026-05-28"
}

Both dates optional; omit for the full history.

list_indexnow_submissions read

IndexNow submission history for a property.

{
  "siteUrl": "sc-domain:example.com",
  "limit": 100
}

limit defaults to 100 (max 500).

get_page_performance read

Daily clicks/impressions/CTR/position for a single URL.

{
  "siteUrl": "sc-domain:example.com",
  "pageUrl": "https://example.com/blog/post",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28"
}
get_query_performance read

Daily metrics for a single query, optionally on one URL.

{
  "siteUrl": "sc-domain:example.com",
  "query": "seo tools",
  "pageUrl": "https://example.com/blog/post",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28"
}

pageUrl is optional; omit it to measure the query site-wide.

get_ranking_changes read

New, lost, improved, and declined queries (or pages) between two periods.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "comparisonStartDate": "2026-04-01",
  "comparisonEndDate": "2026-04-28",
  "dimension": "query",
  "limit": 50
}

dimension is "query" or "page" (default query); limit defaults to 50, uncapped.

find_decaying_content read

Queries or pages losing clicks vs a baseline period, bucketed severe / moderate / mild.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "comparisonStartDate": "2026-02-01",
  "comparisonEndDate": "2026-02-28",
  "dimension": "page",
  "minImpressions": 100
}

start/end is the recent period; comparison* is the earlier baseline. dimension defaults to "page".

get_decay_overview read

Per-query or per-page matrix of clicks/impressions/position broken down by month or week (the app's Query Decay / Content Decay heatmap).

{
  "siteUrl": "sc-domain:example.com",
  "dimension": "query",
  "granularity": "month",
  "metric": "clicks",
  "months": 16,
  "limit": 50
}

Defaults to the last 16 complete months. granularity "month" or "week"; metric clicks/impressions/position/ctr. Each row has a `values` array aligned to `periods`. Pass startDate/endDate to override the window.

analyze_cannibalization read

Queries where two or more pages compete, scored by impression-split entropy.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "minImpressions": 10
}

minImpressions defaults to 10; limit defaults to 100, uncapped.

analyze_ctr_curve read

Actual CTR by position bucket (1-20) vs industry benchmarks (AWR, First Page Sage, Sistrix, Backlinko).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "minImpressions": 10,
  "benchmarkSource": "all"
}

benchmarkSource: awr | firstPageSage | sistrix | backlinko | all (default all). CTR values are percentages (0-100) and deltas are percentage points; a negative delta means the bucket underperforms that benchmark.

find_page_poaching_opportunities read

Queries ranking just outside the top, with estimated click upside if pushed to a target position.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "minPosition": 4,
  "maxPosition": 20,
  "targetPosition": 3,
  "fallbackBenchmark": "awr"
}

Click upside uses the property's OWN CTR curve at targetPosition; fallbackBenchmark (awr | firstPageSage | sistrix | backlinko, default awr) is used only where the site has no data. Response reports targetCtr and ctrSource ("own" or the benchmark key). Position band and target are tunable; limit defaults to 100, uncapped.

score_opportunities read

Impression-weighted opportunity score favoring high-impression queries near the top of page two.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "minImpressions": 10
}

Considers positions 3-30; limit defaults to 100, uncapped.

breakdown_by_path read

Aggregates page performance by host + first folder segment(s).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "depth": 1
}

depth (1-4) controls how many path segments form each group; limit defaults to 100, uncapped.

analyze_sampling_impact read

Estimates the share of clicks/impressions GSC hides via anonymization (query and page dimensions).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28"
}

Only the live-API path reveals true sampling; the warehouse is unsampled (see the response note).

get_sitemap_performance read

Fetches a sitemap, extracts its URLs, and joins each with GSC clicks/impressions/position.

{
  "siteUrl": "sc-domain:example.com",
  "sitemapUrl": "https://example.com/sitemap.xml",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "maxUrls": 500
}

The sitemap host must belong to the property. One level of sitemap-index expansion; maxUrls caps the join (defaults to 500, uncapped).

get_cross_site_summary read

Last-N-days clicks/impressions across all your properties (optionally one tag), with per-site totals.

{
  "days": 28,
  "tag": "client-a"
}

tag is optional; days defaults to 28 (max 180); maxSites is optional with no hard cap: omit it to include ALL matched properties, or pass a number to cap how many are processed.

list_tags read

Every tag on the account (global + property tags) with the number of properties carrying each.

{
  "includeSites": false
}

includeSites defaults to false; set true to also list the property URLs under each tag.

get_tag_group_view read

Aggregated cross-site report for all properties carrying a tag (the /group/tag dashboard): totals + comparison, daily trend, per-site totals, and merged top queries/pages/countries/devices.

{
  "tag": "client-a",
  "days": 28,
  "dimensions": [
    "query",
    "page",
    "country",
    "device"
  ],
  "limit": 100
}

days defaults to 28 (max 180); searchType defaults to "web"; dimensions defaults to all four; limit defaults to 100 (max 1000); maxSites is optional with no hard cap: omit it to include ALL tagged properties, or pass a number to cap.

get_indexing_tracker read

Indexing Tracker config and a status summary (indexed / not-indexed / pending / errors / warnings).

{
  "siteUrl": "sc-domain:example.com"
}

Returns tracker: null when no tracker is configured for the property.

list_tracked_urls read

Paginated list of tracked URLs with their latest indexing status, filterable and searchable.

{
  "siteUrl": "sc-domain:example.com",
  "filter": "warnings",
  "search": "/blog/",
  "page": 1,
  "pageSize": 50
}

filter: all | indexed | not_indexed | pending | errors | warnings. pageSize max 1000 (default 50); page is one-based.

get_indexing_tracker_report read

Indexing health report: score, coverage breakdown, crawl freshness, lost and newly-indexed pages.

{
  "siteUrl": "sc-domain:example.com",
  "days": 30
}

days defaults to 30 (max 90).

list_ga4_properties read

Every Google Analytics 4 property your connected Google accounts can read, and which GSC Wizard sites each is linked to.

{}

No arguments. connected: false means the Google Analytics consent has not been granted in the GSC Wizard app yet. linkedSiteUrls covers only the sites of the GSC Wizard account the connection is authenticated as (returned as account), so a property linked from another account of yours shows an empty list.

get_ga4_overview read

GA4 traffic summary (sessions, users, engagement rate, key events, and more) for the GA4 property linked to a site, always with a previous-period comparison.

{
  "siteUrl": "sc-domain:example.com",
  "includeTimeseries": false
}

GA4 must be linked to the site in the GSC Wizard app; otherwise a notConfigured explanation is returned, naming in account which GSC Wizard account it was resolved against (links are per account). Dates and the comparison window are optional; includeTimeseries adds daily points.

query_ga4_report read

One GA4 dimension breakdown per call: channel, sourceMedium, page, landingPage, country, device, or event, each with its own metric set.

{
  "siteUrl": "sc-domain:example.com",
  "dimension": "landingPage",
  "limit": 25
}

GA4 must be linked to the site in the GSC Wizard app. filters and a comparison range are optional; limit defaults to 50 (max 1000).

get_ga4_ecommerce read

GA4 ecommerce performance: revenue/transactions summary plus channel, source, page, landing-page, and product breakdowns.

{
  "siteUrl": "sc-domain:example.com",
  "limit": 25
}

GA4 must be linked to the site in the GSC Wizard app. hasEcommerce is false when the property shows no ecommerce activity; revenue is in the property currency (currencyCode).

get_ga4_llm_traffic read

Sessions, engagement, conversions and revenue referred by ChatGPT, Perplexity, Copilot, Gemini, Claude and other AI assistants, with their share of total traffic.

{
  "siteUrl": "sc-domain:example.com",
  "includeDailySplit": false,
  "limit": 25
}

GA4 must be linked to the site in the GSC Wizard app. Google AI Overviews traffic carries no distinct referrer and is NOT included. includeDailySplit adds a per-assistant daily sessions series.

get_ga4_key_events read

Segments GA4 on ONE key event (conversion): totals, conversion rates, and per channel/source/landing page/page/country/device breakdowns.

{
  "siteUrl": "sc-domain:example.com",
  "keyEvent": "form_submit",
  "limit": 25
}

GA4 must be linked to the site in the GSC Wizard app. Omit keyEvent to auto-pick the most active one; the response lists every available key event name.

get_blended_landing_pages read

Joins Search Console (clicks, impressions, CTR, position) with GA4 (sessions, bounce rate, key events, revenue) per landing page.

{
  "siteUrl": "sc-domain:example.com",
  "organicOnly": true,
  "limit": 50,
  "dateGranularity": "none"
}

GA4 must be linked to the site in the GSC Wizard app. organicOnly (default true) limits GA4 metrics to google / organic sessions so both sides describe the same traffic. dateGranularity ("day" / "week" / "month") returns a time series instead of one aggregate: every row carries the period start as date, limit applies per period, and the prev* fields compare each period against the one before it (so it cannot be combined with an explicit comparison range).

get_query_value_attribution read

Estimates GA4 sessions, key events, and revenue per Search Console query via proportional click share over the query→page→landing-page join.

{
  "siteUrl": "sc-domain:example.com",
  "organicOnly": true,
  "limit": 1000,
  "dateGranularity": "none"
}

GA4 must be linked to the site in the GSC Wizard app. Estimates, not measured revenue: page-level click-share attribution; matchedClickShare reports coverage; estRevenue only when the GA4 property records revenue. dateGranularity ("day" / "week" / "month") returns a time series instead of one aggregate — the way to chart estimated revenue from non-branded queries month by month — with every row carrying the period start as date and limit applying per period.

list_bing_sites read

List the sites verified in your linked Bing Webmaster Tools account.

{}

No arguments. Returns notConfigured: true when no Bing Webmaster API key is set up in the GSC Wizard app.

get_bing_traffic_stats read

Daily Bing clicks and impressions for a property (roughly the last 6 months).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28"
}

startDate/endDate optional; omit both for everything Bing has (~6 months).

get_bing_query_stats read

Top Bing search queries for a property (clicks, impressions, CTR, position).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "limit": 100
}

Dates optional (omit for ~6 months); limit defaults to 100, uncapped.

get_bing_page_stats read

Top Bing landing pages for a property (clicks, impressions, CTR, position).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "limit": 100
}

Dates optional (omit for ~6 months); limit defaults to 100, uncapped.

get_bing_query_page_stats read

Bing query + landing-page pairs for a property (which query drives each page).

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28",
  "limit": 100
}

Dates optional (omit for ~6 months); limit defaults to 100, uncapped.

get_bing_crawl_stats read

Bing's daily crawl stats: pages crawled/indexed, inbound links, and response-code breakdown.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-05-01",
  "endDate": "2026-05-28"
}

startDate/endDate optional; omit both for everything Bing has (~6 months).

get_bing_crawl_issues read

URLs where Bing found crawl issues (4xx/5xx, redirects, robots blocks, malware), with decoded labels.

{
  "siteUrl": "sc-domain:example.com",
  "limit": 200
}

limit defaults to 200, uncapped; results are ordered by inbound-link count.

get_bing_keyword_stats read

Bing's historical impression volume for a single keyword (weekly), plus broad-match impressions.

{
  "keyword": "seo tools",
  "country": "us",
  "language": "en-US"
}

Marketplace demand data, not tied to a property (no siteUrl). country defaults to "us", language to "en-US".

get_bing_feeds read

Sitemaps/feeds submitted to Bing for a property, with decoded status, type, dates and URL counts.

{
  "siteUrl": "sc-domain:example.com"
}
get_bing_url_submission_quota read

Remaining Bing URL-submission quota (daily and monthly) for a property.

{
  "siteUrl": "sc-domain:example.com"
}
detect_anomalies read

Flags statistically anomalous days (spikes/drops) for a metric, scored by severity.

{
  "siteUrl": "sc-domain:example.com",
  "metric": "clicks",
  "days": 90,
  "sensitivity": 3.5
}

metric: clicks | impressions | ctr | position (default clicks). days >= 21 (default 90). Lower sensitivity = more anomalies.

detect_change_points read

Finds dates where clicks or impressions shifted to a new sustained level (step changes).

{
  "siteUrl": "sc-domain:example.com",
  "metric": "clicks",
  "days": 180,
  "sensitivity": 2
}

metric: clicks | impressions. days >= 14 (default 180). Reports before/after means and % change.

forecast_traffic read

Projects future clicks/impressions via seasonal decomposition + an auto-selected trendline.

{
  "siteUrl": "sc-domain:example.com",
  "metric": "clicks",
  "granularity": "weekly",
  "forecastPeriods": 26
}

Weekly needs >= 13 weeks, monthly >= 6 months. Optional growthRate, cvr + aov (for revenue), trendlineType.

get_longtail_clusters read

Segments pages into Head / Chunky Middle / Long Tail tiers by elbow detection on cumulative clicks.

{
  "siteUrl": "sc-domain:example.com",
  "preset": "default",
  "pagesPerCluster": 10
}

preset: default | content | ecommerce | small_site | enterprise. Optional sensitivity and includeZeroClicks.

get_core_web_vitals read

Chrome UX Report field data: weekly Core Web Vitals (LCP, INP, CLS) + FCP/TTFB with ratings and regressions.

{
  "siteUrl": "sc-domain:example.com",
  "formFactor": "ALL"
}

Needs a CrUX API key configured in the app. Pass a `url` to measure a single page; formFactor: ALL | PHONE | DESKTOP | TABLET.

list_experiments read

Lists the SEO experiments (split tests) defined for a property, with their URL groups.

{
  "siteUrl": "sc-domain:example.com",
  "includeArchived": false
}
get_experiment_results read

Scores one experiment: control vs variant click growth with a significance test, uplift CI, and winner.

{
  "siteUrl": "sc-domain:example.com",
  "experimentId": "00000000-0000-0000-0000-000000000000",
  "confidenceLevel": 0.95
}

Group 0 is the control. The comparison window defaults to the prior same-length period.

compare_migration read

Before/after A-vs-B comparison for a migration: daily trend, per-side totals, query/page winners & losers.

{
  "mode": "cross-property",
  "siteUrl": "sc-domain:old.com",
  "siteUrlB": "sc-domain:new.com",
  "limit": 50
}

mode: cross-property (siteUrl + siteUrlB) | two-urls (urlPrefixA + urlPrefixB) | regex (regexA + regexB). Both sides share one date window.

audit_onpage_seo read

Crawls pages and runs a technical on-page audit per URL (indexability, titles, canonical, links, structured data, issues).

{
  "siteUrl": "sc-domain:example.com",
  "maxUrls": 10
}

Pass explicit `urls` (must belong to the property) or omit to audit top pages by impressions. Fetches each page live; keep the count modest.

get_content_group_performance read

Measures your saved content groups: clicks, impressions, CTR, average position, page count and share of clicks per group, plus an "uncategorized" bucket. Pass groupId to drill into the top pages of one group.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-01-01",
  "endDate": "2026-01-31"
}

Groups are created in the app or with create_content_group. On the warehouse path the totals cover EVERY page of the property, not just the top N. Matching is first-match-wins in the saved order of the groups.

get_topic_cluster_performance read

Measures your saved topic clusters over queries: clicks, impressions, CTR, average position, matched query count and share of clicks per cluster, plus an "unclustered" bucket. Pass clusterId to drill into the top queries of one cluster.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-01-01",
  "endDate": "2026-01-31"
}

Clusters may OVERLAP: a query matching two clusters counts fully in both, so cluster totals do not sum to the property total (overlappingQueries reports how many are double-counted).

get_branded_performance read

Splits a property into branded and non-branded search: totals, branded share of clicks, a daily trend for both sides, and the top queries on each side.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-01-01",
  "endDate": "2026-01-31",
  "limit": 25
}

Driven by the branded keywords saved on the property (set them with update_site). A keyword wrapped in slashes, like /acme ?corp/, is a regex; otherwise it is a case-insensitive substring. Returns notConfigured when none are set.

get_position_distribution read

Slices a property by where it ranks, in 1-3 / 4-10 / 11-20 / 21+ bands: impressions and clicks per band over the range, or the count of distinct queries ranking in each band day by day.

{
  "siteUrl": "sc-domain:example.com",
  "granularity": "period",
  "dimension": "query"
}

granularity: "period" (default, bucket totals) or "daily" (distinct queries per band per day, always keyed on query). Positions are impression-weighted averages, so a row sits in exactly one band.

get_ga4_error_pages read

GA4 error pages for the property linked to a site, broken down by page title AND URL: sessions, page views, active users and bounce rate.

{
  "siteUrl": "sc-domain:example.com",
  "startDate": "2026-01-01",
  "endDate": "2026-01-31"
}

GA4 has no native 404 signal, so error pages are matched against the page-title patterns saved for the site in the app. Pass titleFilters (e.g. [{ operator: "contains", value: "404" }]) to override them for one call.

list_shared_reports read

Lists the shareable reports saved on your account, each with its view URL and the clients currently granted access.

{
  "limit": 50
}

Use it to find a reportId for manage_report_access or delete_shared_report, or to audit who can see which report.

list_report_clients read

Lists the client contacts on your account: the people who can be granted access to a shareable report.

{
  "limit": 100
}

A client is an email address plus an optional name; they sign in with it to view reports shared with them.

list_migration_redirects read

Lists the saved redirect mappings (old URL to new URL) behind the Migration Compare workflow, grouped by the A/B property pair and label they belong to.

{
  "summaryOnly": true
}

Filter with label / siteUrlA / siteUrlB. summaryOnly returns just the per-migration counts, which is the right call on a large mapping.

get_indexnow_settings read

Reports whether an IndexNow API key is configured for a property, masked to its last four characters.

{
  "siteUrl": "sc-domain:example.com"
}

The full key is never returned. submit_indexnow_urls needs a configured key, so check here first when a submission fails.

analyze_query_shapes read

Classifies queries by shape to surface AI Overviews / AI Mode fingerprints: bare replies, pivot follow-ups, conversational questions, tracker probes, agent harnesses.

{
  "siteUrl": "sc-domain:example.com",
  "examplesPerBucket": 10
}

Heuristic pattern matching in 27 languages; it judges how a query looks, not what the searcher meant. Pass buckets: ["reply_artefact","pivot_follow_up","conversational_question"] for just the AI-conversation shapes.

get_query_shape_trend read

Monthly (or weekly) clicks + impressions split into AI-shaped vs conventional queries, with the AI-shaped share of each metric.

{
  "siteUrl": "sc-domain:example.com",
  "months": 12,
  "granularity": "month"
}

Answers "are AI Mode / AI Overviews queries growing on this site?". Defaults to the last 12 complete months (max 16, GSC retention).

get_merchant_listings_performance read

Search Console performance for one search appearance (default MERCHANT_LISTINGS): the appearance inventory, a daily timeline, and the top product pages behind it.

{
  "siteUrl": "sc-domain:example.com",
  "appearance": "MERCHANT_LISTINGS",
  "limit": 25
}

Always live Search Console API: search appearance is never warehoused and cannot be grouped with another dimension, only filtered on. It counts enriched product results in web Search only, so it does not reconcile with Merchant Center free-listing numbers, which also cover the Shopping tab, Images, Lens, YouTube and Maps. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

list_gmc_accounts read

Every Google Merchant Center account your connected Google accounts can read, and which GSC Wizard sites each is linked to.

{
  "siteUrl": "sc-domain:example.com"
}

siteUrl is optional and only adds the linkedAccountId for that property. connected: false means the Merchant Center consent has not been granted in the GSC Wizard app yet. isAdvanced: true marks a multi-client parent, which cannot be reported on directly: link one of its sub-accounts. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_organic_shopping_performance read

Organic (free listing) product performance from the linked Merchant Center account: daily clicks / impressions / conversions plus the top offers, groupable by brand, category or product type.

{
  "siteUrl": "sc-domain:example.com",
  "groupBy": "offer",
  "limit": 25
}

Covers every free surface (Shopping tab, Search, Images, Lens, YouTube, Maps), so it does not reconcile with the web-Search-only merchant listings numbers from get_merchant_listings_performance. Conversions need a Merchant Center conversion source. Organic excludes YouTube affiliate traffic from 1 July 2026 onward. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_product_listing_status read

Free-listing eligibility and item issues per product, sorted by click potential: which products are invisible in free listings, and why.

{
  "siteUrl": "sc-domain:example.com",
  "onlyProblems": true,
  "limit": 25
}

clickPotentialRank 1 is the product Google expects the most clicks from, so a disapproved product ranked low in number is the most expensive problem. topIssueResolution MERCHANT_ACTION needs a feed or site fix; PENDING_PROCESSING clears on its own. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_gmc_competitors read

Merchant Center competitive visibility for one country / category / traffic-source cell: daily competitor rows with a per-domain roll-up, a per-domain window aggregate (top_merchant), or your visibility trend against the category benchmark.

{
  "siteUrl": "sc-domain:example.com",
  "view": "competitor",
  "countryCode": "US",
  "categoryId": "166",
  "trafficSource": "ORGANIC",
  "limit": 50
}

countryCode and categoryId are both required: the Merchant API answers one cell per request. relativeVisibility, adsOrganicRatio, pageOverlapRate, higherPositionRate and both trends are 0-1 fractions (0.12 = 12%), not the 0-100 ctr percentage; the trends are relative to the start of the window. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_gmc_pricing_insights read

Merchant Center price competitiveness and sale-price suggestions joined per product: your price against the market benchmark (priceGapFraction) and Google's suggested price with the predicted impressions / clicks / conversions change.

{
  "siteUrl": "sc-domain:example.com",
  "sort": "opportunity",
  "limit": 100
}

Both views are dateless snapshots of the current catalog; snapshotDate is the UTC day of the call. predicted*ChangeFraction, priceGapFraction and suggestedChangeFraction are 0-1 fractions (0.12 = +12%), not the 0-100 ctr percentage. Benchmarks need valid GTINs and suggestions need conversion reporting, so an empty result usually means "not eligible". Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_gmc_best_sellers read

Google's best sellers ranking for one country from Merchant Center: top product clusters or brands per category with rank, previous rank, relative demand and, for clusters, a demandGap flag when you do not stock a ranked cluster.

{
  "siteUrl": "sc-domain:example.com",
  "view": "product_cluster",
  "granularity": "WEEKLY",
  "countryCode": "US",
  "limit": 100
}

Omit reportDate for the newest published report (reports lag up to two weeks) and read reportDate back; a WEEKLY date must be a Monday, a MONTHLY one the 1st. inventoryStatus ignores the report country, so demandGap is an account-wide signal. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_feed_audit_results read

Results of the Merchant Center feed audit: the latest run (or one runDate) with its status, Feed Score (0-100, split into feed and page planes), failure counts by severity, per-check applicable / failed / passed counts with pass rates, crawl coverage, and the score history of earlier runs.

{
  "siteUrl": "sc-domain:example.com",
  "limit": 100
}

coverage, passRate and failRate are 0-1 fractions (0.12 = 12%), not the 0-100 ctr percentage. checkKey narrows the checks list; the per-offer issue rows behind checkKey or severity live in the ClickHouse warehouse this server cannot read, so those calls answer issuesAvailable: false and point at the Feed Audit report in the app. run: null means no audit has run yet. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

get_gmc_title_hygiene read

Title and description hygiene of the linked Merchant Center catalog: title and description length histograms, missing descriptions, mean and median title length, duplicate-title groups, offers repeating a word, and the most frequent title words with brand tokens flagged.

{
  "siteUrl": "sc-domain:example.com",
  "limit": 2000,
  "topWords": 50
}

A catalog snapshot with no date range, computed over the first `limit` products of the live products list (default 2000, max 5000); truncated: true means the catalog had more and the summary describes a sample. topWords[].share is a 0-1 fraction of the sampled offers, not the 0-100 ctr percentage; lengths are in characters, CJK titles included (cjkNote). The feed-versus-page title diff lives only in the app report. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

Mutations 31

Require a read & write key. All mutations are recorded in an append-only audit log.

add_site write

Register a GSC property in GSC Wizard. The property must already exist in your Search Console account.

{
  "siteUrl": "sc-domain:example.com",
  "tags": [
    "client-a"
  ]
}

tags are optional.

create_gsc_property write

Create new URL-prefix properties in Google Search Console (e.g. folder-level properties) and register them in GSC Wizard. Auto-verified if the parent domain is owned. Use add_site instead for properties that already exist in GSC.

{
  "parentSiteUrl": "sc-domain:example.com",
  "propertyUrls": [
    "https://example.com/blog/",
    "https://example.com/docs/"
  ]
}

parentSiteUrl must be an existing registered property whose Google account owns the domain. register defaults to true; up to 50 URLs.

update_site write

Edit tags, branded keywords, or sitemap URLs on a registered property.

{
  "siteUrl": "sc-domain:example.com",
  "tags": [
    "client-a",
    "priority"
  ],
  "brandedKeywords": [
    "example",
    "example brand"
  ],
  "sitemapUrls": [
    "https://example.com/sitemap.xml"
  ]
}

Pass only the fields you want to change.

manage_tags write

Create, assign, unassign, rename, or delete property tags across the account (the tag side of the /group/tag dashboard).

{
  "action": "assign",
  "tag": "client-a",
  "siteUrls": [
    "sc-domain:example.com",
    "https://example.org/"
  ]
}

action: create | assign | unassign | rename | delete. siteUrls is required for assign/unassign; newName is required for rename. rename and delete apply across every property and the global tag list.

delete_site write

Unregister a property. Cascades to its clusters, groups, filters, inspections, and annotations.

{
  "siteUrl": "sc-domain:example.com",
  "confirm": true
}

confirm must be true; this is irreversible.

create_topic_cluster write

Create a topic cluster of keywords on a property.

{
  "siteUrl": "sc-domain:example.com",
  "name": "Pricing",
  "keywords": [
    "pricing",
    "cost",
    "plans"
  ]
}

Idempotent: an existing name returns that cluster with alreadyExisted: true, not an error.

delete_topic_cluster write

Delete a topic cluster by id.

{
  "clusterId": "00000000-0000-0000-0000-000000000000"
}
create_content_group write

Create a content group partition. Rules match URLs by prefix / contains / regex / equals.

{
  "siteUrl": "sc-domain:example.com",
  "name": "Blog",
  "rules": [
    {
      "type": "prefix",
      "value": "https://example.com/blog/"
    }
  ]
}

color and description are optional; up to 50 rules.

delete_content_group write

Delete a content group by id.

{
  "groupId": "00000000-0000-0000-0000-000000000000"
}
create_saved_filter write

Save a reusable filter preset for a property.

{
  "siteUrl": "sc-domain:example.com",
  "name": "Non-branded, mobile",
  "filters": {
    "device": "MOBILE",
    "excludeBranded": true
  }
}

filters is a free-form object matching the dashboard filter shape.

delete_saved_filter write

Delete a saved filter by id.

{
  "filterId": "00000000-0000-0000-0000-000000000000"
}
create_annotation write

Add a chart annotation on a date (e.g. a release or campaign marker).

{
  "siteUrl": "sc-domain:example.com",
  "eventDate": "2026-05-15",
  "label": "Site redesign launched",
  "description": "New template rolled out across the blog.",
  "color": "#2563eb"
}

Omit siteUrl for an account-wide annotation; description, category, color optional.

delete_annotation write

Delete a chart annotation by id.

{
  "annotationId": "00000000-0000-0000-0000-000000000000"
}
submit_indexnow_urls write

Submit up to 100 URLs to IndexNow for the property.

{
  "siteUrl": "sc-domain:example.com",
  "urls": [
    "https://example.com/new-page",
    "https://example.com/updated-page"
  ]
}

The usual 202 response means "accepted, key validation pending", not delivered: participating engines fetch your {key}.txt afterwards and discard the batch without further notice if it is unreachable. Each submission carries a status and an accepted flag, and submitted counts only what IndexNow accepted.

bulk_inspect_urls write

Inspect a list of URLs sequentially and persist each result.

{
  "siteUrl": "sc-domain:example.com",
  "urls": [
    "https://example.com/a",
    "https://example.com/b"
  ]
}

Counts against the daily 2,000-inspection/property quota (shared with the UI); stops and reports skipped URLs once the cap is hit. Pass up to 2,000 URLs.

add_tracked_urls write

Add URLs to the Indexing Tracker (creates the tracker if needed). Up to 1,800 URLs per property.

{
  "siteUrl": "sc-domain:example.com",
  "urls": [
    "https://example.com/page-1",
    "https://example.com/page-2"
  ]
}

URLs must belong to the property. New URLs start as "pending"; the hourly cron or check_tracked_url_now inspects them.

remove_tracked_urls write

Remove URLs from the Indexing Tracker.

{
  "siteUrl": "sc-domain:example.com",
  "urls": [
    "https://example.com/page-1"
  ]
}
check_tracked_url_now write

Run an immediate URL Inspection for up to 10 tracked URLs and update their status and history.

{
  "siteUrl": "sc-domain:example.com",
  "urls": [
    "https://example.com/page-1"
  ]
}

Counts against the daily 2,000-inspection/property quota; returns a quota message when exhausted.

update_content_group write

Edit an existing content group: its name, description, colour, or matching rules.

{
  "groupId": "00000000-0000-0000-0000-000000000000",
  "name": "Blog"
}

Only the fields you pass change. Passing rules REPLACES the whole rule list, so read the current rules with list_content_groups first if you mean to add one.

update_topic_cluster write

Edit the name or keyword list of a topic cluster.

{
  "clusterId": "00000000-0000-0000-0000-000000000000",
  "keywords": [
    "seo audit"
  ],
  "mode": "add"
}

mode: "replace" (default, swaps the list), "add" (merges in, deduplicated case-insensitively) or "remove" (deletes the listed keywords).

update_saved_filter write

Rename a saved filter preset and/or replace its filter payload.

{
  "filterId": "00000000-0000-0000-0000-000000000000",
  "name": "Blog, non-branded"
}

The filters payload is replaced wholesale, not merged; read the current value with list_saved_filters first.

update_annotation write

Edit a chart annotation you own: its date, label, description, category or colour.

{
  "annotationId": "00000000-0000-0000-0000-000000000000",
  "label": "Redesign launched"
}

Scope cannot be changed (an account-wide annotation cannot be moved onto a property); delete it and create a new one instead.

create_shared_report write

Save a table of rows as a shareable report and get its URL. Pass the rows from another tool plus the columns describing which fields to show.

{
  "title": "Top queries - January",
  "rows": [
    {
      "query": "seo tools",
      "clicks": 120,
      "impressions": 3400
    }
  ],
  "columns": [
    {
      "key": "query",
      "label": "Query",
      "type": "text"
    },
    {
      "key": "clicks",
      "label": "Clicks",
      "type": "number"
    }
  ]
}

STEP 1 OF 3: the URL opens for nobody (not even you) until access is granted. Then create_report_client, then manage_report_access. Up to 50 reports per account.

delete_shared_report write

Permanently delete a saved shareable report and every client grant on it.

{
  "reportId": "00000000-0000-0000-0000-000000000000"
}

Breaks the shared link for anyone who still has it. Find the id with list_shared_reports.

create_report_client write

Add a client contact (an email address plus an optional name) that shareable reports can then be granted to.

{
  "email": "client@example.com",
  "name": "Example Ltd"
}

Sends no email and grants no access on its own. Adding an address that already exists returns the existing client rather than failing.

manage_report_access write

Grant or revoke client access to a saved shareable report. This is what makes a report openable at all.

{
  "reportId": "00000000-0000-0000-0000-000000000000",
  "action": "grant",
  "clientIds": [
    "00000000-0000-0000-0000-000000000000"
  ]
}

Does NOT send a notification email. Pass the client the report URL (they sign in with their email and the app mails them a login link), or send it from Account > Shared Reports in the app, which has a per-client Resend button.

set_dashboard_visibility write

Show or hide registered properties on your GSC Wizard dashboard. Visibility is also what makes a property usable by the other MCP tools.

{
  "siteUrls": [
    "sc-domain:example.com"
  ],
  "visible": true
}

Showing a property consumes a dashboard slot from your plan and is refused when the limit is reached. Hiding one deletes no data. ClickHouse-synced properties are always shown and consume no slot.

add_migration_redirects write

Save redirect mappings (old URL to new URL) for a site migration, tied to the source property A and target property B.

{
  "siteUrlA": "sc-domain:old.com",
  "siteUrlB": "sc-domain:new.com",
  "redirects": [
    {
      "fromUrl": "https://old.com/a",
      "toUrl": "https://new.com/a"
    }
  ],
  "label": "2026-replatform"
}

Rows are APPENDED, never deduplicated against what is already stored, so re-sending the same list stores it twice. Up to 10,000 rows per call.

delete_migration_redirects write

Delete saved redirect mappings, narrowed by label and/or the A/B property pair.

{
  "label": "2026-replatform"
}

Deleting EVERY mapping on the account requires confirmDeleteAll: true. Preview what would go with list_migration_redirects using the same filters first.

update_indexnow_settings write

Set, rotate or clear the IndexNow API key for a property.

{
  "siteUrl": "sc-domain:example.com",
  "indexnowApiKey": "a1b2c3d4e5f6a7b8c9d0"
}

The key must be 8-128 characters of letters, digits and hyphens, AND published at https://your-domain/<key>.txt, or submissions are rejected. Pass clear: true to remove it.

run_feed_audit write

Queue a Merchant Center feed audit for a property: 21 deterministic checks over the synced catalog plus a crawl of the product pages on the owner-approved hosts, scored 0-100. Returns a job handle (runDate), never the results.

{
  "siteUrl": "sc-domain:example.com",
  "force": false
}

Enqueues only; the audit runs in the GSC Wizard app worker and a large catalog can take hours to crawl. enqueued: false with a skipReason means a run for today already exists or one completed inside the 28-day cadence (force: true overrides the cadence, never the one-per-day rule). Follow it with get_feed_audit_results. Shopping is in limited release: the tool is enabled for allowlisted accounts only while the feature is staged, and does not appear in tools/list for other accounts.

Calling a tool directly (curl)

Most users never need this; clients handle the JSON-RPC for you. But to test a tool by hand, POST a tools/call request to the endpoint (after the SDK has opened a session):

curl -X POST https://mcp.gscwizard.com/mcp \
  -H "Authorization: Bearer gscw_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "query_top_queries",
      "arguments": {
        "siteUrl": "sc-domain:example.com",
        "startDate": "2026-05-01",
        "endDate": "2026-05-28",
        "limit": 10
      }
    }
  }'

Troubleshooting