gsc_get_context | accountId? | Where the account publishes and how its GSC data is set up: publishing base (reverse proxy wins), permalink structure, matched GSC properties (siteUrls, propertyType), an aggregationNote explaining multi-property aggregation, and the segmentation strategy + confidence — plus a maturity block (firstPublishDate, daysSinceFirstPublish, recommendedCadence: weekly in the first ~8 weeks publishing, then monthly) that drives which comparison cadence to use. Call this first — it also diagnoses setup problems. The placeholder flag marks accounts still on the shared placeholder space (*.sites.aigrowthagent.co — a test space, not an official domain): no property is ever matched for them (never aigrowthagent.co), and performance tools refuse to pull until the real domain is set |
gsc_list_sites | accountId? | The account’s GSC property set — the matched primary plus verified same-domain satellite properties that are aggregated for the full picture; other accounts’ properties are never returned. Empty when no property matches the account’s domain — use it to diagnose property-resolution failures |
gsc_get_overview | accountId?, days? (1–90, default 28; ends ~3 days ago) | Traffic totals (clicks/impressions/CTR/position) plus daily trend, split AGA content vs main domain with click/impression shares. AGA figures are page-filtered per-URL sums of AGA pages; shares divide by the property totals (segments.shareBasis: "property_total", explained in segments.basisNote), and main is the property total minus AGA. That is the same ratio the GSC UI gives (page-filtered ÷ unfiltered), so report the share as measured. perProperty shows the composition across properties. Read impressions first — they’re the AI-visibility signal; click shares are the human-traffic read. interpretationHints carries deterministic reading hints — state them as findings. Property-frame totals; meta.incompleteDays flags only the dates still inside the real GSC lag window (today−3 … today at call time) — historical ranges carry no flags |
gsc_get_page_performance | accountId?, pageUrl OR slug (mutually exclusive — slug resolves a published AGA article to its live URL via the permalink structure and reverse proxy), days?, rowLimit? (default 100, max 1000) | The queries driving traffic to one page: resolved URL, page totals, top queries (25-row response cap with truncated flag), queriedProperty, and whether the page is AGA content. The per-page drill-down for “is this published page picking up?” in week-over-week reads. Rows are the named-query subset — anonymized queries never appear. The page filter matches exact URL strings, so a zero-row page is retried once with the toggled trailing-slash variant and adopted when it has data |
gsc_query_analytics | accountId?, startDate?/endDate? (pass together; default last 28 days ending 3 days ago), dimensions? (default ["query"]; include page for the segment split), filters? ({dimension, operator, expression}, ANDed), searchType?, sortBy?/sortDirection?, rowLimit? (API pull, default 1000, max 25000), responseRows? (default 25, max 100) | Custom GSC query: totals summed over everything pulled, plus only the top rows in the response — never a full dump. Capped pulls are auto-partitioned and reconciled — check meta.complete/meta.coverageRatio before impression-based analysis. Rows carry tags (queryChars/queryShape — the human-vs-AI-shaped query split for the traffic story; hostname/pageClass/isWebStory on page rows); ["page", "query"] pulls also get meta.anonymization. Query-frame responses without a page denominator carry a top-level queryBiasNote — named queries are a biased floor (Google withholds rare queries, and the hidden tail is not random), so never size a segment or claim zero clicks from query rows alone. For full datasets use gsc_export_dataset |
gsc_compare_periods | accountId?, periodPreset? (wow — last 7 days vs prior 7, mom — last calendar month vs the prior one, qoq — last 3 calendar months vs the prior 3, calendar-aligned with the GSC UI compare so window lengths can differ by a few days; windows end 2 days ago) OR period1Start/period1End/period2Start/period2End (explicit YYYY-MM-DD dates, all four — mutually exclusive with periodPreset), dimensions? (default ["page"], needed for the split), limit? (initial pull size per period, default 1000, max 25000 — capped pulls auto-partition to completeness, so it doesn’t bound the dataset), responseRows? (default 25, max 100) | Period-over-period totals, deltas, and top movers — split AGA vs main domain, with two growth shares: growthShare (clicks, the human-traffic read) and impressionGrowthShare (the AI-visibility read), plus interpretationHints. Period totals, deltas, perProperty, and the growth-share denominators are exact property-frame truth — the number the GSC UI shows — from an extra ["date"]-grouped pull per period; movers and segments are in the requested dimensions’ frame (meta.aggregationFrame), and a period reconciling below 0.98 carries a period-prefixed coverageNote while the totals stay exact. Each growth share is the page-filtered AGA delta ÷ the unfiltered property delta — the same numbers the GSC UI shows; shares can be negative or exceed 1, and each falls back to an absolute-delta note when the total didn’t grow. On huge properties with an incomplete page universe, the split falls back to a verified prefix push-down (segments.pushDownNote), or segments is null with a segmentationNote when the prefix can’t be verified. Pick the cadence by account maturity (gsc_get_context’s maturity block): wow in the first ~8 weeks, mom/qoq after. Query-dimension comparisons carry queryBiasNote — named queries are a biased floor, so read query-level deltas as directional, not sized |
gsc_export_dataset | accountId?, date range? (same defaults as gsc_query_analytics), dimensions? (default ["page", "query"]), searchType?, filters?, rowLimit? (default/max 25000, per property), forceRefresh? (bypass the 6-hour reuse window) | Pulls the full dataset to a file on the MCP server, not your machine; the response is the filePath to pass to gsc_query_export, a pre-signed downloadUrl (signature expires in ~1 hour — curl it immediately; remote clients can GET it without the bearer token), row count, totals, segments, and meta — never rows. Capped properties are auto-partitioned (device → page-regex) and reconciled against an uncapped denominator, so meta.complete/meta.coverageRatio tell you whether the file is whole. File rows carry tags and the file’s meta makes it self-describing. Query-frame exports without a page denominator carry queryBiasNote — named queries are a biased floor. A ["page"]-dimension export joined against articles_search (statuses ["published"]) answers “what percent of published slugs have any impressions?” — pages published long ago with persistent zero impressions are retire candidates |
gsc_query_export | filePath (required, exactly as returned by gsc_export_dataset), groupBy? (an exported dimension), dimensionFilters? (local, case-insensitive, ANDed), sortBy? (default clicks), limit? (default 25, max 100) | Slices an exported dataset — grouped or raw top rows with summed clicks/impressions and impressions-weighted CTR/position — with no API call, so it’s free to call repeatedly (for example, slicing to zero-impression pages for the indexing-coverage check). Takes no accountId, but ownership is enforced: you can only slice exports created under one of your accounts. The export’s meta (completeness, coverage, tags basis) is echoed in every response; slices of query-frame exports without a page denominator carry queryBiasNote — named queries are a biased floor |
gsc_inspect_url | accountId?, pageUrl OR slug (same resolution as gsc_get_page_performance) | Google’s index verdict for a page: coverage and indexing state, canonicals, mobile usability, rich results, last crawl time — plus queriedProperty and isAgaContent. The Inspection API matches exact URL strings, so on a non-PASS verdict the tool re-inspects the googleCanonical URL (or the toggled trailing-slash variant when none is reported) and adopts the better verdict — canonicalNote records what happened. The diagnosis step for pages with suspicious or persistently zero performance — pair it with gsc_list_sitemaps |
gsc_list_sitemaps | accountId?, sitemapUrl? (details for one sitemap; omit to list all) | Submitted sitemaps for the account’s primary GSC property, with errors, warnings, and content counts. Use it with gsc_inspect_url to diagnose pages that aren’t getting picked up |
gsc_about_domain | accountId? OR domain? (explicit domain wins; otherwise derived from the account’s publishing URL), gl?, hl? (default en), includeThumbnails? (default false) | What Google says about a domain: an AI-overview-style markdown summary, knowledge graph, and first-indexed date |