{"openapi":"3.1.0","info":{"title":"GSC Wizard REST API","version":"1.0.0","description":"Read Google Search Console and GA4 data for the connected account. Authenticate with a `gscw_live_...` API key from the GSC Wizard app (Account -> API keys) as a Bearer token. Curated GET resource routes cover the common reports; every tool is also callable generically at POST /tools/{name}. A read-scoped key cannot call write tools. An OAuth access token works in place of a key: mcp:read for reads, mcp:write for write tools."},"servers":[{"url":"https://mcp.gscwizard.com/v1"}],"security":[{"bearerAuth":[]},{"oauth2":["mcp:read"]}],"tags":[{"name":"Resources","description":"Idiomatic GET routes for common reports"},{"name":"Tools","description":"Generic per-tool endpoints (full surface)"}],"paths":{"/sites":{"get":{"operationId":"rest_list_sites","summary":"List connected Search Console properties","description":"Lists all Google Search Console properties connected to the authenticated GSC Wizard account. Returns the site URL (which may be a domain property prefixed with `sc-domain:` or a URL prefix property), tags, and which data source backs the property. Properties another user has shared with you are included too, badged with `sharedBy` (the owner) and `accessLevel` (READ_ONLY or FULL). `permissionLevel` is the Google Search Console permission (siteOwner / siteFullUser / siteRestrictedUser / siteUnverifiedUser), and `readable: false` means Google will refuse every data request for that property: it is listed in Search Console but not verified, so the user must verify it at search.google.com/search-console before any report will work. Do not attempt reads on a property with `readable: false`; tell the user to verify it instead. `activated: false` means the property is connected but is not shown on the account dashboard and is not synced to full storage, so every other property-scoped tool will refuse it with a selection error. Do not attempt reads on those either: either call `set_dashboard_visibility` to activate the property first, or choose one with `activated: true`. Properties shared with the caller are always `activated: true`, because the grant is itself the selection; a share whose owner no longer has an active GSC Wizard plan is left out, since no tool can read it. `gscScope` is the Search Console access of the Google connection behind the property: \"full\" allows submit_sitemap and create_gsc_property, \"readonly\" means Google will refuse those two (reads still work); absent when unknown.","tags":["Resources"],"parameters":[],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/account":{"get":{"operationId":"rest_get_account_info","summary":"Account, connected Google accounts, and subscription state","description":"Returns the authenticated user, the connected Google accounts (email + scopes), and the subscription status. Useful as a first call to confirm the MCP server is wired up correctly and the user has the data sources you expect.","tags":["Resources"],"parameters":[],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/summary":{"get":{"operationId":"rest_get_site_summary","summary":"Clicks, impressions, CTR, and position with a prior-period comparison","description":"Returns clicks, impressions, CTR, and average position for a property over the last N days (default 28), with a same-length prior period for comparison. Use this for quick health checks before drilling into details. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). For an explicit window pass startDate/endDate (YYYY-MM-DD) instead: a date you pass always wins, and `days` only sizes an edge you leave out. The comparison period is always the same length as the window and sits immediately before it. `avgPosition` is impression-weighted, as Search Console reports it. `dailyRows` is the window day by day and `previousDailyRows` the comparison period day by day, in the same shape; `previousDailyRows` is omitted for a window longer than 180 days.","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":180,"default":28,"description":"Length of the trailing window in days (default 28, max 180). Ignored for any edge you pin with startDate/endDate; when exactly one of those is given it sizes the other edge."},"description":"Length of the trailing window in days (default 28, max 180). Ignored for any edge you pin with startDate/endDate; when exactly one of those is given it sizes the other edge."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date: omit both startDate and endDate to use the trailing `days` window instead (Search Console data lags ~2-3 days, so the window ends at the latest settled date). Passed alone, the window runs from here to the latest settled date. Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date: omit both startDate and endDate to use the trailing `days` window instead (Search Console data lags ~2-3 days, so the window ends at the latest settled date). Passed alone, the window runs from here to the latest settled date. Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the window ends at the latest settled Search Console date (data lags ~2-3 days). Passed alone, the window is `days` long and ends here. Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the window ends at the latest settled Search Console date (data lags ~2-3 days). Passed alone, the window is `days` long and ends here. Never pass null or the string \"null\"."},{"name":"brand","in":"query","required":false,"schema":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},{"name":"contentGroupId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},{"name":"topicClusterId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."},"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/top-queries":{"get":{"operationId":"rest_query_top_queries","summary":"Top search queries by clicks","description":"Returns the top search queries for a property over a date range, sorted by clicks. Convenience wrapper around query_search_analytics for the most common request. Served from the GSC Wizard ClickHouse warehouse (longer history, no sampling) when available, otherwise from the live Search Console API; the response `dataSource` field says which. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return per call (default 100, max 1000)."},"description":"Rows to return per call (default 100, max 1000)."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},{"name":"searchType","in":"query","required":false,"schema":{"type":"string","enum":["web","image","video","news"],"default":"web"}},{"name":"brand","in":"query","required":false,"schema":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},{"name":"contentGroupId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},{"name":"topicClusterId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."},"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/top-pages":{"get":{"operationId":"rest_query_top_pages","summary":"Top landing pages by clicks","description":"Returns the top landing pages for a property over a date range, sorted by clicks. Convenience wrapper around query_search_analytics. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see the response `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return per call (default 100, max 1000)."},"description":"Rows to return per call (default 100, max 1000)."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},{"name":"searchType","in":"query","required":false,"schema":{"type":"string","enum":["web","image","video","news","discover"],"default":"web"}},{"name":"brand","in":"query","required":false,"schema":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},{"name":"contentGroupId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},{"name":"topicClusterId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."},"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/countries":{"get":{"operationId":"rest_query_countries","summary":"Per-country performance breakdown","description":"Returns per-country performance (clicks, impressions, CTR, position) for a property over a date range. Country codes are ISO 3166-1 alpha-3. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return per call (default 100, max 1000)."},"description":"Rows to return per call (default 100, max 1000)."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},{"name":"brand","in":"query","required":false,"schema":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},{"name":"contentGroupId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},{"name":"topicClusterId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."},"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/devices":{"get":{"operationId":"rest_query_devices","summary":"Per-device performance breakdown","description":"Returns per-device-category performance (DESKTOP, MOBILE, TABLET) for a property over a date range. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see the response `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},{"name":"brand","in":"query","required":false,"schema":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},{"name":"contentGroupId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},{"name":"topicClusterId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."},"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/page-performance":{"get":{"operationId":"rest_get_page_performance","summary":"Daily metrics for one page (pass ?pageUrl=)","description":"Daily performance for a single page (clicks, impressions, CTR, position). Useful for diagnosing post-deploy regressions on a specific URL. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"pageUrl","in":"query","required":true,"schema":{"type":"string","format":"uri"}},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/query-performance":{"get":{"operationId":"rest_get_query_performance","summary":"Daily metrics for one query (pass ?query=)","description":"Daily performance for a single search query, optionally restricted to one landing page. Useful for tracking position changes after on-page edits. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"query","in":"query","required":true,"schema":{"type":"string","minLength":1}},{"name":"pageUrl","in":"query","required":false,"schema":{"type":"string","format":"uri"}},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/ranking-changes":{"get":{"operationId":"rest_get_ranking_changes","summary":"New / lost / improved / declined movers between two periods","description":"Compares a current period against a comparison period and classifies movers by query or page into new, lost, improved, and declined buckets (improvement = better/lower average position). Useful for spotting what gained or lost visibility between two date ranges. `limit` (1-10000, default 50) applies PER BUCKET; `counts` gives the full size of each bucket before that cut. Each period reads its top `scanLimit` rows ranked by clicks (warehouse: max(limit*10, 1000), capped at 50000; live API: 25000), so `counts` are measured within those keys. On the warehouse every key in either period's top `scanLimit` is read in both periods, so new and lost are real; on the live API the two reads are independent, and a key just below one cut can show as new or lost. It is served from the GSC Wizard ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},{"name":"comparisonStartDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},"description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},{"name":"comparisonEndDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},"description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},{"name":"dimension","in":"query","required":false,"schema":{"type":"string","enum":["query","page"],"default":"query"}},{"name":"searchType","in":"query","required":false,"schema":{"type":"string","enum":["web","image","video","news"],"default":"web"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":10000,"default":50}}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sites/{site}/ga4/overview":{"get":{"operationId":"rest_get_ga4_overview","summary":"GA4 traffic overview for the linked property","description":"Google Analytics 4 summary for the GA4 property linked to a GSC Wizard site: sessions, active/total/new users, page views, engagement rate, session duration, bounce rate, event count, and key events, with an automatic previous-period comparison (`prevSummary`). When the comparison period has no GA4 data at all (e.g. before the data stream existed), `comparisonHasData` is false and prevSummary is null instead of all zeros. Set `includeTimeseries` for daily points. engagementRate and bounceRate are fractions 0-1, not percentages; averageSessionDuration is in seconds. Returns `notConfigured` (with a reason and hint) instead of data when Google Analytics is not connected or no GA4 property is linked to the site in the GSC Wizard app. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Resources"],"parameters":[{"name":"site","in":"path","required":true,"schema":{"type":"string"},"description":"URL-encoded Search Console property. URL-prefix (https%3A%2F%2Fexample.com%2F) or domain (sc-domain%3Aexample.com)."},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},{"name":"comparisonStartDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},"description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},{"name":"comparisonEndDate","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},"description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},{"name":"includeTimeseries","in":"query","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_sites":{"post":{"operationId":"tool_list_sites","summary":"List Search Console properties","description":"Lists all Google Search Console properties connected to the authenticated GSC Wizard account. Returns the site URL (which may be a domain property prefixed with `sc-domain:` or a URL prefix property), tags, and which data source backs the property. Properties another user has shared with you are included too, badged with `sharedBy` (the owner) and `accessLevel` (READ_ONLY or FULL). `permissionLevel` is the Google Search Console permission (siteOwner / siteFullUser / siteRestrictedUser / siteUnverifiedUser), and `readable: false` means Google will refuse every data request for that property: it is listed in Search Console but not verified, so the user must verify it at search.google.com/search-console before any report will work. Do not attempt reads on a property with `readable: false`; tell the user to verify it instead. `activated: false` means the property is connected but is not shown on the account dashboard and is not synced to full storage, so every other property-scoped tool will refuse it with a selection error. Do not attempt reads on those either: either call `set_dashboard_visibility` to activate the property first, or choose one with `activated: true`. Properties shared with the caller are always `activated: true`, because the grant is itself the selection; a share whose owner no longer has an active GSC Wizard plan is left out, since no tool can read it. `gscScope` is the Search Console access of the Google connection behind the property: \"full\" allows submit_sitemap and create_gsc_property, \"readonly\" means Google will refuse those two (reads still work); absent when unknown.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_account_info":{"post":{"operationId":"tool_get_account_info","summary":"Get account info","description":"Returns the authenticated user, the connected Google accounts (email + scopes), and the subscription status. Useful as a first call to confirm the MCP server is wired up correctly and the user has the data sources you expect.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_search_analytics":{"post":{"operationId":"tool_query_search_analytics","summary":"Query Search Console analytics","description":"Runs a Search Console searchAnalytics.query against one of the user's properties. Supports date / query / page / country / device / searchAppearance dimensions, dimension filters, and any of the supported search types (web, image, video, news, discover, googleNews). Use this for ad-hoc questions like \"top queries last 28 days\" or \"page-level performance for /pricing\". Eligible requests are served from the GSC Wizard ClickHouse warehouse (longer history, no sampling); requests using searchAppearance, the googleNews type or 3+ distinct dimensions fall back to the live Search Console API. The response `dataSource` says which path ran. Rows are sorted by clicks, or by date first when date is one of the dimensions. Regex filters use RE2 (no lookahead or backreferences; use excludingRegex to exclude). Returns 100 rows by default: read `pagination` in the response to see whether the result was truncated, and page through with startRow or ask for more at once with rowLimit. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"dimensions":{"type":"array","items":{"type":"string","enum":["date","query","page","country","device","searchAppearance"]},"maxItems":4},"searchType":{"type":"string","enum":["web","image","video","news","discover","googleNews"],"default":"web"},"rowLimit":{"type":"integer","minimum":1,"maximum":25000,"default":100,"description":"Rows to return per call (default 100, max 25000). Large values return a lot of raw rows; prefer paging with startRow."},"startRow":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"filters":{"type":"array","items":{"type":"object","properties":{"dimension":{"type":"string","enum":["query","page","country","device"]},"operator":{"type":"string","enum":["contains","equals","notContains","notEquals","includingRegex","excludingRegex"],"default":"contains"},"expression":{"type":"string","minLength":1}},"required":["dimension","expression"],"additionalProperties":false},"description":"Dimension filters joined with AND. Pass an empty list or omit for no filtering."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_site_summary":{"post":{"operationId":"tool_get_site_summary","summary":"Get site performance summary","description":"Returns clicks, impressions, CTR, and average position for a property over the last N days (default 28), with a same-length prior period for comparison. Use this for quick health checks before drilling into details. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). For an explicit window pass startDate/endDate (YYYY-MM-DD) instead: a date you pass always wins, and `days` only sizes an edge you leave out. The comparison period is always the same length as the window and sits immediately before it. `avgPosition` is impression-weighted, as Search Console reports it. `dailyRows` is the window day by day and `previousDailyRows` the comparison period day by day, in the same shape; `previousDailyRows` is omitted for a window longer than 180 days.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"days":{"type":"integer","minimum":1,"maximum":180,"default":28,"description":"Length of the trailing window in days (default 28, max 180). Ignored for any edge you pin with startDate/endDate; when exactly one of those is given it sizes the other edge."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date: omit both startDate and endDate to use the trailing `days` window instead (Search Console data lags ~2-3 days, so the window ends at the latest settled date). Passed alone, the window runs from here to the latest settled date. Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the window ends at the latest settled Search Console date (data lags ~2-3 days). Passed alone, the window is `days` long and ends here. Never pass null or the string \"null\"."},"brand":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"contentGroupId":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"topicClusterId":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/inspect_url":{"post":{"operationId":"tool_inspect_url","summary":"Inspect a URL","description":"Runs the Google URL Inspection API for one URL and stores the result in the GSC Wizard inspection history. Returns the verdict, coverage state, robots.txt state, last crawl time, the fetched/crawled-as info, the Google-selected canonical (googleCanonical), the user-declared canonical (userCanonical), and a link to the result in Search Console (inspectionResultLink). A canonical field is null when Google did not report it for this URL (common for pages it has not indexed); it is never inferred from the page. GSC enforces a daily per-property quota, so call get_inspection_quota first if you plan to inspect many URLs.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"inspectionUrl":{"type":"string","format":"uri","description":"The fully-qualified URL to inspect. Must belong to siteUrl."}},"required":["siteUrl","inspectionUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_inspection_quota":{"post":{"operationId":"tool_get_inspection_quota","summary":"Get URL inspection quota","description":"Returns the remaining URL inspection quota for a property today. GSC enforces a 2,000 inspection/day/property cap; GSC Wizard tracks usage across both UI and MCP calls. Call this before bulk inspections to avoid surprises.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_saved_filters":{"post":{"operationId":"tool_list_saved_filters","summary":"List saved filters","description":"Lists saved filter presets, optionally restricted to one property. Each preset stores a JSON filter spec that mirrors the filter UI in the GSC Wizard dashboard. Presets belong to the property: with siteUrl you get every preset on it, including a property shared with you; without it you get the presets on the properties you own.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"Restrict to the presets on one property (one you own or one shared with you). Omit to list the presets on every property you own."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_topic_clusters":{"post":{"operationId":"tool_list_topic_clusters","summary":"List topic clusters","description":"Lists topic clusters for a property. Each cluster groups a set of keywords under a name and is used by the dashboard to aggregate query-level metrics.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_content_groups":{"post":{"operationId":"tool_list_content_groups","summary":"List content groups","description":"Lists content groups for a property. Content groups partition the URL space using JSON rules (e.g. prefix matches, regex). Used in the dashboard for page-level aggregations.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_filter_options":{"post":{"operationId":"tool_get_filter_options","summary":"Get report filter options","description":"Lists the scope filters available on a property for get_site_summary, query_top_queries, query_top_pages, query_countries and query_devices: whether branded keywords are set (for brand: 'branded' | 'non_branded'), and every content group (contentGroupId) and topic cluster (topicClusterId) with `filterable` and, when false, the reason. Works on properties shared with you as well as your own. Reads configuration only; no Search Console data is fetched.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_sitemaps":{"post":{"operationId":"tool_list_sitemaps","summary":"List submitted sitemaps","description":"Lists every sitemap submitted to Google Search Console for a property, including submission timestamps, warning/error counts, and per-content-type submitted/indexed URL counts.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_url_inspections":{"post":{"operationId":"tool_list_url_inspections","summary":"List URL inspection history","description":"Returns the inspection history GSC Wizard has stored for a property: verdict, coverage, indexing state, last-crawl time, the Google-selected and user-declared canonicals, and the Search Console link per URL. Most recent first. A null canonical with a non-null inspection_result_link means Google did not report it; when the link is null too, the row predates canonical storage (re-run inspect_url for a fresh result). Paged: follow pagination.nextOffset to walk the whole stored history.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urlContains":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Rows to return per call (default 100, max 500)."},"offset":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"latestPerUrl":{"type":"boolean","default":false,"description":"Collapse repeat inspections of the same URL to the most recent one. Applied to the page after paging, so a page can return fewer rows than limit."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_top_queries":{"post":{"operationId":"tool_query_top_queries","summary":"Top search queries","description":"Returns the top search queries for a property over a date range, sorted by clicks. Convenience wrapper around query_search_analytics for the most common request. Served from the GSC Wizard ClickHouse warehouse (longer history, no sampling) when available, otherwise from the live Search Console API; the response `dataSource` field says which. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return per call (default 100, max 1000)."},"offset":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"brand":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"contentGroupId":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"topicClusterId":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_top_pages":{"post":{"operationId":"tool_query_top_pages","summary":"Top landing pages","description":"Returns the top landing pages for a property over a date range, sorted by clicks. Convenience wrapper around query_search_analytics. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see the response `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return per call (default 100, max 1000)."},"offset":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"searchType":{"type":"string","enum":["web","image","video","news","discover"],"default":"web"},"brand":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"contentGroupId":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"topicClusterId":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_countries":{"post":{"operationId":"tool_query_countries","summary":"Country breakdown","description":"Returns per-country performance (clicks, impressions, CTR, position) for a property over a date range. Country codes are ISO 3166-1 alpha-3. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return per call (default 100, max 1000)."},"offset":{"type":"integer","minimum":0,"default":0,"description":"Rows to skip. Use pagination.nextOffset from a previous call to get the next page."},"brand":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"contentGroupId":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"topicClusterId":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_devices":{"post":{"operationId":"tool_query_devices","summary":"Device breakdown","description":"Returns per-device-category performance (DESKTOP, MOBILE, TABLET) for a property over a date range. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see the response `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"brand":{"type":"string","enum":["branded","non_branded"],"description":"Optional. Narrow to queries matching the property's branded keywords ('branded') or to all others ('non_branded'). Needs branded keywords set (update_site brandedKeywords); see get_filter_options."},"contentGroupId":{"type":"string","minLength":1,"description":"Optional. Narrow to pages in this content group (id from get_filter_options or list_content_groups). Groups whose rules cannot be applied as a filter are refused; get_filter_options says which."},"topicClusterId":{"type":"string","minLength":1,"description":"Optional. Narrow to queries in this topic cluster (id from get_filter_options or list_topic_clusters). Clusters whose keywords cannot be applied as a filter are refused."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_annotations":{"post":{"operationId":"tool_list_annotations","summary":"List chart annotations","description":"Lists chart annotations visible to the user across scopes: platform-wide (Google ranking updates synced from the Search Status dashboard), account-wide (user notes), and property-scoped. Optionally restrict to one property. Property-scoped annotations are returned only when siteUrl is passed, and include every note on that property, whoever added it (the owner or a collaborator it is shared with), as on the GSC Wizard chart.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional filter: only include annotations on or after this date (YYYY-MM-DD). Omit to include all. Never pass null or \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional filter: only include annotations on or before this date (YYYY-MM-DD). Omit to include all. Never pass null or \"null\"."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_algo_updates":{"post":{"operationId":"tool_list_algo_updates","summary":"List Google algorithm updates","description":"Fetches confirmed Google ranking/algorithm updates from the official Search Status Dashboard. Filters to service_name=\"Ranking\" so indexing/crawling incidents are excluded. Optionally clip to a date range: an update is included when its rollout (beginISO to endISO) overlaps the range, so one that started before startDate but was still rolling out inside it is listed. The feed is cached for 15 minutes.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional filter: only include updates still rolling out on or after this date (YYYY-MM-DD). Omit to include all. Never pass null or \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional filter: only include updates that began on or before this date (YYYY-MM-DD). Omit to include all. Never pass null or \"null\"."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_indexnow_submissions":{"post":{"operationId":"tool_list_indexnow_submissions","summary":"List IndexNow submissions","description":"Returns the IndexNow submission history for a property: URL, response code, submission source (manual / cron / mcp), and timestamp. Most recent first.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"limit":{"type":"integer","minimum":1,"maximum":500,"default":100}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_page_performance":{"post":{"operationId":"tool_get_page_performance","summary":"Page performance over time","description":"Daily performance for a single page (clicks, impressions, CTR, position). Useful for diagnosing post-deploy regressions on a specific URL. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"pageUrl":{"type":"string","format":"uri"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."}},"required":["siteUrl","pageUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_query_performance":{"post":{"operationId":"tool_get_query_performance","summary":"Query performance over time","description":"Daily performance for a single search query, optionally restricted to one landing page. Useful for tracking position changes after on-page edits. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"query":{"type":"string","minLength":1},"pageUrl":{"type":"string","format":"uri"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."}},"required":["siteUrl","query"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/add_site":{"post":{"operationId":"tool_add_site","summary":"Add a property to GSC Wizard","description":"Registers a GSC property the user already has access to (in Google Search Console) inside GSC Wizard. The property URL must appear in Search Console and be VERIFIED for the connected Google account: an unverified property is rejected, because Google refuses every data request for one. It is not provisioned by this call. Pass a URL prefix (https://example.com/) or a domain property (sc-domain:example.com); the scheme and host are matched case-insensitively and a missing trailing slash is added. Adding a property that is already registered is not an error: the result has `alreadyRegistered: true` and the existing row (with `activated`, as in list_sites).\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"tags":{"type":"array","items":{"type":"string","minLength":1},"maxItems":20}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_gsc_property":{"post":{"operationId":"tool_create_gsc_property","summary":"Create GSC properties","description":"Creates one or more URL-prefix properties in Google Search Console (Webmasters sites.add) and registers them in GSC Wizard. Use this to add folder-level properties (e.g. https://example.com/blog/) that do not yet exist in Search Console. They are auto-verified if the connected Google account owns the parent domain property. `parentSiteUrl` is an existing GSC Wizard property whose Google account has access; the new properties inherit it. Every property URL must be under the `parentSiteUrl` domain (that domain or a subdomain of it). Created properties are added hidden and consume no plan slot until you show them with set_dashboard_visibility, which enforces the dashboard limit. For properties that already exist in GSC, use add_site instead.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"parentSiteUrl":{"type":"string","minLength":1,"description":"An already-registered GSC Wizard property whose Google account owns the domain."},"propertyUrls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":50,"description":"URL-prefix properties to create, e.g. [\"https://example.com/blog/\"]. Max 50. Each must be under the parentSiteUrl domain (that domain or a subdomain)."},"register":{"type":"boolean","default":true,"description":"Also register the created properties in GSC Wizard (default true)."}},"required":["parentSiteUrl","propertyUrls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/update_site":{"post":{"operationId":"tool_update_site","summary":"Update a property","description":"Updates the GSC Wizard metadata for a property: tags, branded keywords, sitemap URL list, and how fast GSC Wizard may crawl the site. Only fields you pass are updated; omit a field to leave it unchanged. Pass null for a crawl-rate field to clear the override and go back to the app default. On a property shared with you, FULL access is needed (as in the property settings of the web app); READ_ONLY access is refused.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"tags":{"type":"array","items":{"type":"string","minLength":1},"maxItems":20},"brandedKeywords":{"type":"array","items":{"type":"string","minLength":1},"maxItems":500},"sitemapUrls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":50},"crawlMaxConcurrency":{"type":"integer","minimum":1,"maximum":10,"nullable":true,"description":"Pages GSC Wizard may fetch from this site at once (1-10). Lower it if the site answers 429 during an audit. null = app default."},"crawlMinDelayMs":{"type":"integer","minimum":0,"maximum":60000,"nullable":true,"description":"Minimum milliseconds between crawl batches (0-60000). Composes with robots.txt Crawl-delay; the longer wait wins. null = app default."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_site":{"post":{"operationId":"tool_delete_site","summary":"Remove a property from GSC Wizard","description":"Unregisters a property from GSC Wizard. Cascades to topic clusters, content groups, saved filters, inspections, and annotations scoped to this property. Does NOT remove the property from Google Search Console itself. Pass confirm=true to acknowledge; this guards against accidental deletes.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"confirm":{"type":"boolean","enum":[true],"description":"Required confirmation. Must be true."}},"required":["siteUrl","confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_topic_cluster":{"post":{"operationId":"tool_create_topic_cluster","summary":"Create a topic cluster","description":"Creates a topic cluster on a property by grouping keywords under a name. Cluster names are unique per property, and the call is idempotent: if the name already exists the existing cluster is returned with alreadyExisted: true instead of an error, so there is never anything to retry. Use update_topic_cluster to change an existing cluster's keywords. Keywords are stored as text and matched against GSC queries in the dashboard.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200},"keywords":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":1000}},"required":["siteUrl","name","keywords"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_topic_cluster":{"post":{"operationId":"tool_delete_topic_cluster","summary":"Delete a topic cluster","description":"Deletes a topic cluster by id. The property it belongs to must be one you own or one shared with you with full access.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"clusterId":{"type":"string","format":"uuid"}},"required":["clusterId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_content_group":{"post":{"operationId":"tool_create_content_group","summary":"Create a content group","description":"Creates a content group partition on a property. Rules are an array of { type, value } objects (prefix / contains / regex / equals) that match URLs into the group. Group names are unique per site. A `regex` rule that cannot compile is rejected; one that is valid but unsupported by the warehouse (a lookahead, lookbehind or backreference) or skipped as ReDoS-prone is accepted and reported in `ruleWarnings`. Relay those to the user, since a skipped pattern matches no pages at all.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"rules":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prefix","contains","regex","equals"]},"value":{"type":"string","minLength":1}},"required":["type","value"],"additionalProperties":false},"minItems":1,"maxItems":50}},"required":["siteUrl","name","rules"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_content_group":{"post":{"operationId":"tool_delete_content_group","summary":"Delete a content group","description":"Deletes a content group by id. The property it belongs to must be one you own or one shared with you with full access.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"groupId":{"type":"string","format":"uuid"}},"required":["groupId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_saved_filter":{"post":{"operationId":"tool_create_saved_filter","summary":"Create a saved filter","description":"Stores a filter preset against a property, as the dashboard's filter panel would. `filters` is the list of filter rows (dimension / operator / value), in the same shape list_saved_filters returns, and `filterLogic` says whether they combine with AND or OR. Saving a preset does not apply it to anything on its own: it appears in the property's filter presets for the user to pick.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200},"filters":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"description":"Stable row id. Omit it and one is generated."},"dimension":{"type":"string","enum":["query","page","country","device","branded"],"description":"Which GSC dimension the row filters on."},"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How `value` is matched. `regex` is RE2."},"value":{"type":"string","minLength":1,"description":"What to match. For `device` use MOBILE / DESKTOP / TABLET, for `country` an ISO-3166-1 alpha-3 code or a comma-separated list of them (e.g. NLD,BEL), for `branded` exactly \"branded\" or \"non_branded\"."}},"required":["dimension","operator","value"],"additionalProperties":false},"description":"The filter rows, in the shape list_saved_filters returns. Pass [] for a preset with no rows."},"filterLogic":{"type":"string","enum":["and","or"],"description":"How the rows combine: \"and\" (default, every row must match) or \"or\" (any one row). Matches the dashboard's Match All / Match Any toggle."},"clientRequestId":{"type":"string","format":"uuid","description":"Optional idempotency key (a UUID, one per form session). Resending the same key returns the row the first call created instead of inserting a duplicate."}},"required":["siteUrl","name","filters"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_saved_filter":{"post":{"operationId":"tool_delete_saved_filter","summary":"Delete a saved filter","description":"Deletes a saved filter preset by id. Presets belong to the property, so its owner or anyone with full access to it may delete any of them, as in the GSC Wizard app; read-only access is not enough.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"filterId":{"type":"string","format":"uuid"}},"required":["filterId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_annotation":{"post":{"operationId":"tool_create_annotation","summary":"Create a chart annotation","description":"Adds a chart annotation. Scope is \"account\" by default (visible only to the user); pass siteUrl to scope the annotation to a single property. Platform-wide annotations are reserved for system events and cannot be created via this tool.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"Omit for account-wide; pass to scope to a property."},"eventDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Required. The date the event occurred, as YYYY-MM-DD (e.g. 2026-06-08)."},"label":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000},"category":{"type":"string","maxLength":50},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"clientRequestId":{"type":"string","format":"uuid","description":"Optional idempotency key (a UUID, one per form session). Resending the same key returns the row the first call created instead of inserting a duplicate."}},"required":["eventDate","label"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_annotation":{"post":{"operationId":"tool_delete_annotation","summary":"Delete a chart annotation","description":"Deletes a chart annotation by id. Only annotations the user owns can be removed; platform-scoped annotations cannot be deleted via this tool.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"annotationId":{"type":"string","format":"uuid"}},"required":["annotationId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/submit_indexnow_urls":{"post":{"operationId":"tool_submit_indexnow_urls","summary":"Submit URLs to IndexNow","description":"Pings IndexNow for the given URLs, telling participating search engines (Bing, Yandex, Seznam) that the pages have changed. The property needs an IndexNow API key and a published key file: check get_indexnow_settings first. If no key is set: 1) call update_indexnow_settings with generateKey: true; 2) publish the returned keyFileContent as a plain-text file at the returned keyFileUrl (the root of every host you submit URLs for); 3) call submit_indexnow_urls again. URLs are grouped by host before submission. Up to 100 URLs per call. Note that the usual 202 response means \"accepted, key validation pending\", not delivered: engines fetch the site key file afterwards and silently discard the batch if it is not reachable, so do not report a 202 as confirmed indexing.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":100}},"required":["siteUrl","urls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/submit_sitemap":{"post":{"operationId":"tool_submit_sitemap","summary":"Submit a sitemap to Search Console","description":"Submits (or re-submits) an existing sitemap URL to Google Search Console for a property, the same action as \"Add a new sitemap\" in the Sitemaps report. It does not create or host a sitemap: the file must already be published and reachable at the URL you pass; this only registers it with Google or asks Google to fetch it again after new content went live. Every sitemap URL must be on the property host or a subdomain of it. Up to 20 sitemaps per call. Submitting is idempotent and queues a download; it does not index anything by itself, and Google reports parse warnings/errors only after it has fetched the file, so a freshly submitted sitemap normally comes back pending. Requires a Google account connected with full Search Console access (a read-only connection is refused before anything is sent). If a rate limit or a permission refusal stops a batch after some sitemaps were accepted, the accepted ones are still reported and the rest are listed in notAttempted, with stopReason. Use list_sitemaps to see what is already submitted.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"sitemapUrls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":20,"description":"Absolute URLs of already-published sitemaps, e.g. [\"https://example.com/sitemap_index.xml\"]. Each must be on the property host or a subdomain of it. Max 20."}},"required":["siteUrl","sitemapUrls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/bulk_inspect_urls":{"post":{"operationId":"tool_bulk_inspect_urls","summary":"Inspect multiple URLs","description":"Runs the Google URL Inspection API against a list of URLs, persisting each result to GSC Wizard's inspection history. Each result carries the verdict, coverage, the Google-selected and user-declared canonicals (null when Google did not report one) and a Search Console link. Google caps inspections at 2,000 per property per day (shared across the UI and every MCP call); this tool counts each inspection against that cap and stops once it is reached, returning the URLs it could not get to. A Google rate limit, quota refusal or property-level permission refusal also stops the run: the URLs not yet inspected come back skipped, with skipReason, and the result carries stopReason (and retryAfterSeconds when Google gave one). Call get_inspection_quota first if you want to see remaining headroom. Each inspection takes about 7 seconds at Google, run 5 at a time, so a call takes up to 25 URLs (about 35 seconds); for larger sets add them with add_tracked_urls and let the Indexing Tracker inspect them in the background (check_tracked_url_now inspects a few of them immediately).\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":25,"description":"Up to 25 URLs per call; use add_tracked_urls for more."}},"required":["siteUrl","urls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_ranking_changes":{"post":{"operationId":"tool_get_ranking_changes","summary":"Get ranking changes between two periods","description":"Compares a current period against a comparison period and classifies movers by query or page into new, lost, improved, and declined buckets (improvement = better/lower average position). Useful for spotting what gained or lost visibility between two date ranges. `limit` (1-10000, default 50) applies PER BUCKET; `counts` gives the full size of each bucket before that cut. Each period reads its top `scanLimit` rows ranked by clicks (warehouse: max(limit*10, 1000), capped at 50000; live API: 25000), so `counts` are measured within those keys. On the warehouse every key in either period's top `scanLimit` is read in both periods, so new and lost are real; on the live API the two reads are independent, and a key just below one cut can show as new or lost. It is served from the GSC Wizard ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},"dimension":{"type":"string","enum":["query","page"],"default":"query"},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"limit":{"type":"integer","minimum":1,"maximum":10000,"default":50}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/find_decaying_content":{"post":{"operationId":"tool_find_decaying_content","summary":"Find decaying content","description":"Finds queries or pages losing traffic between a baseline (earlier) period and a recent period, bucketed by severity of click loss (severe > 50%, moderate 20-50%, mild < 20%). Only keys with a meaningful baseline (clicks > 0 and impressions >= minImpressions) are considered. startDate/endDate is the RECENT period; comparisonStartDate/comparisonEndDate is the BASELINE period. For a full period-by-period matrix (clicks/impressions/position per month or week, like the app's Query Decay / Content Decay pages) use get_decay_overview instead. Returns at most `limit` rows (default 100, max 1000), worst decliners first. The baseline is scanned for its top `scanLimit` keys by clicks (warehouse: max(limit*10, 1000), capped at 50000; live API: 25000 rows per period). On the warehouse every scanned key's recent figure is exact. On the live API the recent period is its own top 25000, so a key missing from a full recent read is not known to be at zero: its recent clicks are at most the smallest count that read kept. When that ceiling is still below the key's baseline, the row is reported with `recentIsUpperBound: true`: `recentClicks` is the ceiling, the real loss is AT LEAST |clickChangePct|, `severity` is a floor, and its recent impressions and position are unknown (0). When the ceiling shows no loss, the key is left out and counted in `unresolvedKeys`. When the baseline window has a different length than the recent one, the comparison is per day: baseline clicks are scaled to the recent window's length (`windowNormalization` says so, and each row adds `baselineClicksScaled`; `baselineClicks` stays the raw total). `positionDelta` is 0 for a key with no recent row. `truncated: true` means a read hit its cap, so `counts` are measured within the scan, not across the whole property. Served from the GSC Wizard ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},"dimension":{"type":"string","enum":["query","page"],"default":"page"},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"minImpressions":{"type":"integer","minimum":0,"default":100},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Maximum decaying rows to return (1-1000)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_decay_overview":{"post":{"operationId":"tool_get_decay_overview","summary":"Decay overview (per-period matrix)","description":"Per-query or per-page performance broken down by month or week: the same matrix the app's Query Decay and Content Decay pages render (a row per query/page, one column per period). Use this to SEE how traffic trended period by period; use find_decaying_content instead when you only need decliners between two fixed ranges. Returns the top `limit` rows by total clicks, each with a `values` array aligned to `periods` for the chosen `metric`, plus a TOTALS-style per-period aggregate across all matched rows. Defaults to the last `months` complete months (through the end of last month). Served from the GSC Wizard ClickHouse warehouse when available (longer history, no GSC sampling), otherwise the live Search Console API (see `dataSource`). On the live API each period is read separately; `truncated: true` with a `note` means a period's read was capped or did not finish in time, and `incompletePeriods` lists any period that reads 0 because it was not read.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"dimension":{"type":"string","enum":["query","page"],"default":"query"},"granularity":{"type":"string","enum":["month","week"],"default":"month"},"metric":{"type":"string","enum":["clicks","impressions","position","ctr"],"default":"clicks"},"months":{"type":"integer","minimum":1,"maximum":24,"default":16},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD. Provide BOTH startDate and endDate to override the default window, or omit both to use the last `months` complete months. Never pass null or \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD. Provide BOTH startDate and endDate to override the default window, or omit both to use the last `months` complete months. Never pass null or \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":50},"search":{"type":"string","minLength":1},"clusterKeywords":{"type":"array","items":{"type":"string","minLength":1},"maxItems":200}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/analyze_cannibalization":{"post":{"operationId":"tool_analyze_cannibalization","summary":"Analyze keyword cannibalization","description":"Finds queries where multiple pages of the property compete for the same search, ranked by a cannibalization score (Shannon entropy over the pages’ impressions: higher means impressions split more evenly across pages, i.e. worse cannibalization). Served from the GSC Wizard ClickHouse warehouse when available: it keeps only queries ranked by at least two pages before any cut, then scores them most impressions first, up to 10,000 queries or 25,000 page-query rows, whichever comes first. Each query lists at most 50 pages (most impressions first); `pageCount` always covers every competing page, and the score is taken over the listed ones. `totalClicks` and `totalImpressions` (on both sources) are the query’s own figures as Search Console’s query view reports them (a search showing two of the pages counts once), so `totalImpressions` can be lower than the sum of the listed pages’ impressions, which count that search once per page; `minImpressions` applies to the query’s own figure. Otherwise the live Search Console API (see `dataSource`) reads the top 25,000 page-query rows by clicks, which drops zero-click competing pages first. `truncated: true` means the cut was hit; `scanLimit` is that cut (on the warehouse, the number of queries scored when truncated, else the query cap; on the live API, page-query rows). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"minImpressions":{"type":"integer","minimum":0,"default":10},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/analyze_ctr_curve":{"post":{"operationId":"tool_analyze_ctr_curve","summary":"Analyze CTR-by-position curve","description":"Builds the property’s actual click-through-rate curve bucketed by average position (1-20) and compares each bucket to one or more industry benchmarks. Available sources: awr (Advanced Web Ranking 2026), awr2026 (AWR 2026 CTR study, organic across all SERPs), awrAio (same study, SERPs carrying an AI Overview), firstPageSage (First Page Sage 2026), sistrix (Sistrix 2024), backlinko (Backlinko 2019), or \"all\" (default) to compare against every source at once. Comparing awr2026 with awrAio is the AI Overview click tax for that position. Each bucket reports a `benchmarks` map (expected CTR per source) and a `deltas` map (actual minus expected; negative = underperforming); when a single source is selected the bucket also carries flat `expectedCtr`/`ctrDelta`. CTR values are percentages (0-100); deltas are percentage points. Served from the GSC Wizard ClickHouse warehouse when available, where every query in the window is measured; otherwise the live Search Console API (see `dataSource`), which returns only the top 25,000 queries by clicks. `truncated: true` means that cut was hit: zero-click queries are dropped first, so bucket CTRs read HIGH, not low. `scanLimit` is the cut applied (null on the warehouse, which has none). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"minImpressions":{"type":"integer","minimum":0,"default":10},"benchmarkSource":{"type":"string","enum":["awr","awr2026","awrAio","firstPageSage","sistrix","backlinko","all"],"default":"all"}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/find_page_poaching_opportunities":{"post":{"operationId":"tool_find_page_poaching_opportunities","summary":"Find page poaching opportunities","description":"Finds queries ranking just outside the top positions (between minPosition and maxPosition) and estimates the click upside of pushing them to a target position. The upside is computed from the property's OWN CTR at the target position (measured over every query in the window on the warehouse), not a broad industry benchmark, so the estimate reflects how this site actually converts impressions at that position. When the property has no queries at the target position, or fewer than 100 impressions there, it falls back to the industry benchmark named by `fallbackBenchmark`: awr (Advanced Web Ranking 2026, default), awr2026 (AWR 2026 CTR study, organic), awrAio (same study, SERPs with an AI Overview), firstPageSage (First Page Sage 2026), sistrix (Sistrix 2024), or backlinko (Backlinko 2019). The response reports `targetCtr` (the expected CTR used), `ctrSource` (\"own\" or the benchmark key) and `ctrSourceNote` (why). Sorted by potential click gain. Scans up to 25,000 queries: on the warehouse the ones with the most impressions; on the live API its click order. `truncated: true` means the scan hit that cap (`scanNote` says what that left out). Served from the GSC Wizard ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"minPosition":{"type":"number","minimum":1,"default":4},"maxPosition":{"type":"number","minimum":1,"default":20},"targetPosition":{"type":"number","minimum":1,"default":3},"minImpressions":{"type":"integer","minimum":0,"default":10},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100},"fallbackBenchmark":{"type":"string","enum":["awr","awr2026","awrAio","firstPageSage","sistrix","backlinko"],"default":"awr"}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/score_opportunities":{"post":{"operationId":"tool_score_opportunities","summary":"Score ranking opportunities","description":"Ranks queries by an impression-weighted opportunity score that favours near-threshold positions (positions 3-30) with low current CTR, and estimates the extra clicks available if CTR improved. `potentialClicks` is the extra clicks a 25% CTR would bring a query ranked lower than position 3. It is 0 when the query already clicks at or above that benchmark (common for small or navigational queries), which says nothing about its rank. Sorted by score. CTR values are percentages (0-100). Scans up to 25,000 queries: on the warehouse the ones with the most impressions; on the live API its click order. `truncated: true` means the scan hit that cap (`scanNote` says what that left out). Served from the GSC Wizard ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"minImpressions":{"type":"integer","minimum":0,"default":10},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/breakdown_by_path":{"post":{"operationId":"tool_breakdown_by_path","summary":"Breakdown by subdomain / path","description":"Aggregates page-level performance into a subdomain and first-folder breakdown. Each page URL is parsed and grouped by its host plus the first `depth` path segments (depth 1 -> /folder, depth 2 -> /folder/subfolder, etc.). Returns per-group clicks, impressions, CTR, impression-weighted average position, and the number of distinct pages. Served from the ClickHouse warehouse when available (every page is grouped), otherwise the live Search Console API (up to 25,000 page rows are grouped; see `dataSource`). `truncated` says when pages or groups were left out. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"depth":{"type":"integer","minimum":1,"maximum":4,"default":1},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/analyze_sampling_impact":{"post":{"operationId":"tool_analyze_sampling_impact","summary":"Analyze GSC sampling / anonymization impact","description":"Estimates how much click/impression data Google Search Console hides through anonymization (privacy-threshold row dropping) for a property over a date range. Compares the per-day totals against the summed top query rows and top page rows; the gap is the lost share. On the live API path this reveals true GSC sampling. On the ClickHouse warehouse path the data is unsampled, so the reported loss reflects only top-N row truncation (see the `note` field). The response `dataSource` says which path served the request. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_sitemap_performance":{"post":{"operationId":"tool_get_sitemap_performance","summary":"Sitemap URL performance","description":"Fetches a sitemap belonging to the property, extracts its URLs, and joins them with Search Console page performance over a date range. Each URL gets its clicks, impressions, CTR, and average position (zeros if the page has no GSC data). Reports how many sitemap URLs actually received impressions (indexedInGscCount). The warehouse reads the sitemap URLs themselves, so a zero is exact. The live API cannot, so it pages through the property's pages (top 100,000 by clicks at most) until every URL is found; `truncated: true` means some URLs were not reached, so their zeros are unknown rather than \"no impressions\" (`scanLimit` is the rows read). Expands one level of a sitemap index (up to 5 child sitemaps; a child that cannot be read is named in `childSitemapNote` instead of failing the call), caps extracted URLs at maxUrls (default 500, max 2000), and only fetches http(s) URLs on the property host or a subdomain of it. Served from the ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). The sitemap is fetched with the user agent \"GSCWizard-Bot/1.0 (On-Page SEO Checker)\"; if the server blocks it (403/401/429) or no URLs come back, relay the whitelisting advice in the error or `crawlNote`. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"sitemapUrl":{"type":"string","format":"uri"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"maxUrls":{"type":"integer","minimum":1,"maximum":2000,"default":500}},"required":["siteUrl","sitemapUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_cross_site_summary":{"post":{"operationId":"tool_get_cross_site_summary","summary":"Cross-site performance summary","description":"Aggregates a last-N-days clicks/impressions summary across the authenticated account's registered Search Console properties (optionally filtered to those carrying a given tag), with a same-length prior period for comparison and per-site totals. Without a tag it also covers properties shared with the account (marked `shared: true`; tags are the caller's own, so a tag filter covers owned properties only). Useful for a portfolio-level health check, and the MCP equivalent of the app's Global Reports page. Set `includeSearchTypes` to also split every property across web / image / video / news / discover, and `includeCountries` for a country leaderboard aggregated over the whole portfolio. Each site routes independently to the ClickHouse warehouse or the live Search Console API, so `dataSource` is reported per site. A site whose read fails is reported in `errors` rather than failing the whole call. Processes at most `maxSites` properties per call (default and maximum 100; `scope.truncated` says when more matched, so narrow by `tag`). The rate-limit cost scales with the number of properties and the breakdowns requested.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"integer","minimum":1,"maximum":180,"default":28},"tag":{"type":"string"},"maxSites":{"type":"integer","minimum":1,"maximum":100,"default":100,"description":"How many properties to process, at most 100 (the default). When more match, `scope.truncated` is true; filter by `tag` to cover the rest."},"searchType":{"type":"string","enum":["web","image","video","news","discover"],"default":"web","description":"Search type of the headline totals and the per-site comparison."},"includeSearchTypes":{"type":"boolean","default":false,"description":"Also break every property down by search type (web, image, video, news, discover) for the current period. Costs five extra reads per property."},"includeCountries":{"type":"boolean","default":false,"description":"Also return a country leaderboard aggregated across every property, with the number of properties contributing to each country. Costs one extra read per property."},"countryLimit":{"type":"integer","minimum":1,"maximum":250,"default":25,"description":"How many countries to return when includeCountries is set."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_tags":{"post":{"operationId":"tool_list_tags","summary":"List property tags","description":"Lists every tag defined on the account: account-level global tags plus any tag attached to a registered Search Console property, with the number of properties carrying each tag. Tags group properties into portfolios; feed a tag name to get_tag_group_view for an aggregated cross-site report, or to get_cross_site_summary for a totals-only view. Pass includeSites=true to also get the list of property URLs under each tag.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"includeSites":{"type":"boolean","default":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_tag_group_view":{"post":{"operationId":"tool_get_tag_group_view","summary":"Tag group performance view","description":"Aggregated cross-site report for every property carrying a given tag (the data behind the app's /group/tag/<tag> dashboard). Returns last-N-days totals with a same-length prior-period comparison, a merged daily clicks/impressions trend, per-site totals, and merged top-N breakdowns by query, page, country, and device. Each site routes independently to the ClickHouse warehouse (longer history, no sampling) or the live Search Console API; `dataSource` is reported per site and a site whose read fails is reported in `errors` rather than failing the whole call. Use list_tags first to discover tag names; use get_cross_site_summary for a lighter totals-only view across all properties. Processes at most `maxSites` properties per call (default and maximum 100; `scope.truncated` says when more carry the tag). The rate-limit cost scales with the number of properties and `dimensions`.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tag":{"type":"string","minLength":1},"days":{"type":"integer","minimum":1,"maximum":180,"default":28},"searchType":{"type":"string","enum":["web","image","video","news","discover"],"default":"web"},"dimensions":{"type":"array","items":{"type":"string","enum":["query","page","country","device"]},"default":["query","page","country","device"]},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100},"maxSites":{"type":"integer","minimum":1,"maximum":100,"default":100,"description":"How many tagged properties to process, at most 100 (the default). When more carry the tag, `scope.truncated` is true."}},"required":["tag"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_indexing_tracker":{"post":{"operationId":"tool_get_indexing_tracker","summary":"Get indexing tracker config + stats","description":"Returns the GSC Wizard Indexing Tracker configuration for a property plus summary stats (total tracked URLs, indexed / not-indexed / pending / error counts, active warnings, and the most recent check time). Returns tracker: null if no tracker is configured for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_tracked_urls":{"post":{"operationId":"tool_list_tracked_urls","summary":"List tracked URLs","description":"Paginated list of URLs in the GSC Wizard Indexing Tracker for a property, with optional status filter and URL substring search. Filter options: all, indexed, not_indexed, pending, errors, warnings. Returns the current verdict / coverage / indexing state, last-crawl time, the Google-selected and user-declared canonicals, and the Search Console link per URL, all from the latest inspection. A canonical is null when Google did not report it or the URL has not been inspected yet.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"filter":{"type":"string","enum":["all","indexed","not_indexed","pending","errors","warnings"],"default":"all"},"search":{"type":"string"},"page":{"type":"integer","minimum":1,"default":1},"pageSize":{"type":"integer","minimum":1,"maximum":1000,"default":50}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_indexing_tracker_report":{"post":{"operationId":"tool_get_indexing_tracker_report","summary":"Indexing tracker health report","description":"Aggregate indexing-health report for a property over the last N days (default 30, max 90). Computes a 0-100 health score from indexed %, crawl freshness, and warning-free %, plus a coverage-state breakdown, crawl-freshness buckets, recently lost pages, and newly indexed pages. A property with no tracker yet answers configured: false with empty figures; add URLs with add_tracked_urls to start one.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"days":{"type":"integer","minimum":1,"maximum":90,"default":30}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/add_tracked_urls":{"post":{"operationId":"tool_add_tracked_urls","summary":"Add URLs to the indexing tracker","description":"Adds URLs to the GSC Wizard Indexing Tracker for a property, creating the tracker if it does not exist yet. Each URL must belong to the property's domain. Enforces the 1,800-URL-per-tracker cap (URLs over the cap are skipped and reported). Newly added URLs start as \"pending\"; call check_tracked_url_now to inspect them immediately, or wait for the app's hourly cron.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":1800}},"required":["siteUrl","urls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/remove_tracked_urls":{"post":{"operationId":"tool_remove_tracked_urls","summary":"Remove URLs from the indexing tracker","description":"Removes URLs from the GSC Wizard Indexing Tracker for a property. Pass the full URL strings to stop tracking. Returns the number of rows actually removed.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urls":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":1800}},"required":["siteUrl","urls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/check_tracked_url_now":{"post":{"operationId":"tool_check_tracked_url_now","summary":"Check tracked URLs now","description":"Triggers an immediate Google URL Inspection for up to 10 tracked URLs in the GSC Wizard Indexing Tracker, updating each URL's status, warnings, and append-only history. Each result carries the Google-selected and user-declared canonicals (null when Google did not report one). Counts against the daily 2,000-inspection/property quota. If the quota is exhausted, the call returns a quota message instead of running. URLs are inspected five at a time (about 7 seconds each at Google). If Google rate-limits the property or refuses access to it, the URLs not yet inspected come back with skipped: true and a skipReason (plus retryAfterSeconds when Google gave one) and are left untouched; retry them later. Use sparingly; the app's hourly cron checks tracked URLs automatically. This is a server-side write and is audit-logged.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":10}},"required":["siteUrl","urls"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/manage_tags":{"post":{"operationId":"tool_manage_tags","summary":"Manage property tags","description":"Create, assign, unassign, rename, or delete property tags. Tags group Search Console properties into portfolios surfaced by list_tags and get_tag_group_view. Actions: \"create\" defines an account-level global tag (so it appears before any property uses it); \"assign\" adds a tag to the given properties; \"unassign\" removes it from the given properties; \"rename\" renames a tag across every property and the global list; \"delete\" removes a tag from every property and the global list. siteUrls is required for assign/unassign and ignored otherwise; newName is required for rename. assign/unassign also work on a property shared with you with full access (the tag is stored on that property, as in the app); create, rename and delete only touch your own properties and global tag list. A batch that would push any property past 50 tags changes nothing. For wholesale replacement of one property's tag set, use update_site instead.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["create","assign","unassign","rename","delete"]},"tag":{"type":"string","minLength":1,"maxLength":100},"newName":{"type":"string","minLength":1,"maxLength":100},"siteUrls":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":100}},"required":["action","tag"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/generate_seo_report":{"post":{"operationId":"tool_generate_seo_report","summary":"Generate full SEO report","description":"Runs the full analysis suite for one property in a single call and returns a complete, self-contained HTML report styled like the GSC Wizard app (overview, top queries/pages, countries & devices, CTR curve vs benchmark, opportunities, ranking changes, decaying content, query decay matrix, cannibalization, section breakdown, data coverage, sitemaps). This is far faster than calling each analysis tool separately (one round trip, shared auth + property resolution, server-side parallel reads) and is served from the ClickHouse warehouse when available. Use format=\"html\" (default) for a ready-to-open report, or format=\"json\" for the underlying data bundle.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"Property URL from list_sites (e.g. \"sc-domain:example.com\")."},"days":{"type":"integer","minimum":7,"maximum":180,"default":28,"description":"Length of the reporting window (and each comparison window)."},"format":{"type":"string","enum":["html","json"],"default":"html"},"includeSitemap":{"type":"boolean","default":true,"description":"Fetch + join the property’s sitemap (adds a network fetch)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_ga4_properties":{"post":{"operationId":"tool_list_ga4_properties","summary":"List GA4 properties","description":"Lists every Google Analytics 4 property readable by the connected Google accounts of the authenticated user, and which GSC Wizard sites each property is linked to (via `linkedSiteUrls`). Use it to discover GA4 property IDs or to verify the Analytics setup of a site. `linkedSiteUrls` covers only the sites of the GSC Wizard account this connection is authenticated as (returned as `account`): links made from a different GSC Wizard account come back empty here even though the app shows them. An empty result with `connected: false` means the Google Analytics consent has not been granted in the GSC Wizard app yet (connect Google Analytics at tool.gscwizard.com first), or, with `reauthRequired: true`, that it was granted but Google now rejects every such account, so it has to be reconnected. `errors` lists every Google account whose properties could not be read (its properties are missing from the list), with the reason.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_ga4_overview":{"post":{"operationId":"tool_get_ga4_overview","summary":"GA4 traffic overview","description":"Google Analytics 4 summary for the GA4 property linked to a GSC Wizard site: sessions, active/total/new users, page views, engagement rate, session duration, bounce rate, event count, and key events, with an automatic previous-period comparison (`prevSummary`). When the comparison period has no GA4 data at all (e.g. before the data stream existed), `comparisonHasData` is false and prevSummary is null instead of all zeros. Set `includeTimeseries` for daily points. engagementRate and bounceRate are fractions 0-1, not percentages; averageSessionDuration is in seconds. Returns `notConfigured` (with a reason and hint) instead of data when Google Analytics is not connected or no GA4 property is linked to the site in the GSC Wizard app. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to start a baseline of the same length here."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the baseline / comparison period as YYYY-MM-DD. Omit both comparison dates to use the same-length period immediately before the current window; give only this one to end a baseline of the same length here."},"includeTimeseries":{"type":"boolean","default":false},"filters":{"type":"object","properties":{"channel":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionDefaultChannelGroup names, matched exactly (any of), e.g. [\"Organic Search\", \"Direct\"]."},"sourceMedium":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionSourceMedium values, matched exactly (any of), e.g. [\"google / organic\"]."},"pagePath":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 pagePath dimension (path only, e.g. \"/pricing\"), with an operator."},"landingPage":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 landingPage dimension (path only), with an operator."},"country":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 country names, matched exactly (any of), e.g. [\"Netherlands\", \"Belgium\"]."},"device":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 deviceCategory values, matched exactly (any of): \"desktop\", \"mobile\", and/or \"tablet\"."},"event":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 eventName values, matched exactly (any of), e.g. [\"purchase\"]."},"hostName":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 hostName values, matched exactly (any of), e.g. [\"www.example.com\"]. When the linked GA4 property is shared with other sites, results are already limited to this site's hostnames (see `siteScope` in the response). For the property owner, setting hostName replaces that automatic scope, e.g. to read another stream or several hosts at once; on a property shared with you it only narrows within the scope."}},"additionalProperties":false,"description":"Optional GA4 dimension filters applied to every report in the call. Within a list field the values OR together; different fields AND together. Omit entirely for unfiltered data."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_ga4_report":{"post":{"operationId":"tool_query_ga4_report","summary":"GA4 breakdown report","description":"Runs ONE Google Analytics 4 dimension breakdown for the GA4 property linked to a GSC Wizard site: channel, sourceMedium, page, landingPage, country, device, event, date (daily trend) or hostName. Each dimension carries its own metric set (returned in `metrics`). Set `secondaryDimension` to \"date\" or \"hostName\" to split every row further, e.g. dimension \"event\" + secondaryDimension \"date\" shows on which days an event fired; each row then carries that field (dates as YYYY-MM-DD). Rows include prev* fields that are only meaningful when a comparison range is given (`hasComparison`); date breakdowns take no comparison range. Only the first `limit` rows are returned (`truncated` and `note` say when more exist); to follow one event, pass filters: { event: [\"<eventName>\"] }. When the GA4 property is shared with other sites, results are limited to this site's hostnames and `siteScope` says so (on a shared property a hostName filter narrows within that scope; only the owner can replace it). Rates (engagementRate, bounceRate) are fractions 0-1, not percentages. Returns a `notConfigured` result (not an error) when Google Analytics is not connected or no GA4 property is linked to the site in the GSC Wizard app. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"dimension":{"type":"string","enum":["channel","sourceMedium","page","landingPage","country","device","event","date","hostName"]},"secondaryDimension":{"type":"string","enum":["date","hostName"],"description":"Optional second dimension that splits every row: \"date\" (per day) or \"hostName\" (per site/stream host). Must differ from `dimension`."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"filters":{"type":"object","properties":{"channel":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionDefaultChannelGroup names, matched exactly (any of), e.g. [\"Organic Search\", \"Direct\"]."},"sourceMedium":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionSourceMedium values, matched exactly (any of), e.g. [\"google / organic\"]."},"pagePath":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 pagePath dimension (path only, e.g. \"/pricing\"), with an operator."},"landingPage":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 landingPage dimension (path only), with an operator."},"country":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 country names, matched exactly (any of), e.g. [\"Netherlands\", \"Belgium\"]."},"device":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 deviceCategory values, matched exactly (any of): \"desktop\", \"mobile\", and/or \"tablet\"."},"event":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 eventName values, matched exactly (any of), e.g. [\"purchase\"]."},"hostName":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 hostName values, matched exactly (any of), e.g. [\"www.example.com\"]. When the linked GA4 property is shared with other sites, results are already limited to this site's hostnames (see `siteScope` in the response). For the property owner, setting hostName replaces that automatic scope, e.g. to read another stream or several hosts at once; on a property shared with you it only narrows within the scope."}},"additionalProperties":false,"description":"Optional GA4 dimension filters applied to every report in the call. Within a list field the values OR together; different fields AND together. Omit entirely for unfiltered data."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":50}},"required":["siteUrl","dimension"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_ga4_ecommerce":{"post":{"operationId":"tool_get_ga4_ecommerce","summary":"GA4 ecommerce report","description":"GA4 ecommerce performance for the GA4 property linked to a GSC Wizard site: a revenue / transactions / purchasers summary plus channel, source-medium, page, landing-page, and product (itemName) breakdowns. Revenue is in the property currency (`currencyCode`). `hasEcommerce` is false when the property shows no ecommerce activity in the period. When active filters are incompatible with the item-scoped Products report, `itemsFilterSkipped` is true and `items` is unfiltered while every other table reflects the filters. `totalRows` gives the full row count of every table before `limit`. Returns a `notConfigured` result (not an error) when Google Analytics is not connected or no GA4 property is linked to the site in the GSC Wizard app. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"filters":{"type":"object","properties":{"channel":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionDefaultChannelGroup names, matched exactly (any of), e.g. [\"Organic Search\", \"Direct\"]."},"sourceMedium":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionSourceMedium values, matched exactly (any of), e.g. [\"google / organic\"]."},"pagePath":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 pagePath dimension (path only, e.g. \"/pricing\"), with an operator."},"landingPage":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 landingPage dimension (path only), with an operator."},"country":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 country names, matched exactly (any of), e.g. [\"Netherlands\", \"Belgium\"]."},"device":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 deviceCategory values, matched exactly (any of): \"desktop\", \"mobile\", and/or \"tablet\"."},"event":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 eventName values, matched exactly (any of), e.g. [\"purchase\"]."},"hostName":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 hostName values, matched exactly (any of), e.g. [\"www.example.com\"]. When the linked GA4 property is shared with other sites, results are already limited to this site's hostnames (see `siteScope` in the response). For the property owner, setting hostName replaces that automatic scope, e.g. to read another stream or several hosts at once; on a property shared with you it only narrows within the scope."}},"additionalProperties":false,"description":"Optional GA4 dimension filters applied to every report in the call. Within a list field the values OR together; different fields AND together. Omit entirely for unfiltered data."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":25}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_ga4_llm_traffic":{"post":{"operationId":"tool_get_ga4_llm_traffic","summary":"GA4 traffic from AI assistants","description":"Sessions, engagement, conversions (key events) and revenue referred to the site by ChatGPT, Perplexity, Microsoft Copilot, Google Gemini, Claude and 13 other AI assistants (identified by referrer domain and combined with GA4’s own \"AI Assistant\" channel), from the GA4 property linked to the site, with the share of total traffic they represent and per-assistant and per-landing-page breakdowns. Note: Google AI Overviews / AI Mode traffic carries no distinct referrer, is indistinguishable from google/organic, and is NOT included. llmShareOfSessions, engagementRate and bounceRate are fractions 0-1, not percentages. An assistant's activeUsers adds up its referrer domains (e.g. chatgpt.com + chat.openai.com), so a user who came through two of them counts twice; summary.activeUsers is exact. Returns a notConfigured result when Google Analytics is not connected or no GA4 property is linked. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"includeDailySplit":{"type":"boolean","default":false,"description":"Include a per-assistant daily sessions split for the current period."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":25,"description":"Maximum number of landing page rows returned."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_ga4_key_events":{"post":{"operationId":"tool_get_ga4_key_events","summary":"GA4 key events (conversions)","description":"Segments the GA4 property linked to the site on ONE key event (conversion, e.g. form_submit): totals, session/user conversion rates, and per channel, source, landing page, page, country and device breakdowns. Also lists the available key events on the property. When keyEvent is omitted, the most active key event in the period is picked automatically. A keyEvent that is not marked as a key event in GA4 returns plain event counts instead (isKeyEvent: false, with a note). A key event whose name has characters other than letters, digits and _ (e.g. \"Sign Up\") is reported through an event filter instead, with metricMode \"event_filter\" and a note on what the numbers mean. rawEventCount is the plain count of the event; when GA4 counted fewer key events than that (marked as a key event after it fired, or counted once per session), a note explains the gap. Rates (sessionKeyEventRate, userKeyEventRate) are fractions 0-1, not percentages. Returns a notConfigured result when Google Analytics is not connected or no GA4 property is linked. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"keyEvent":{"type":"string","pattern":"^[\\w .\\-]{1,64}$","description":"GA4 key event name to segment on (e.g. form_submit). Omit to pick the most active key event of the period automatically; the response lists all available names."},"filters":{"type":"object","properties":{"channel":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionDefaultChannelGroup names, matched exactly (any of), e.g. [\"Organic Search\", \"Direct\"]."},"sourceMedium":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionSourceMedium values, matched exactly (any of), e.g. [\"google / organic\"]."},"pagePath":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 pagePath dimension (path only, e.g. \"/pricing\"), with an operator."},"landingPage":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 landingPage dimension (path only), with an operator."},"country":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 country names, matched exactly (any of), e.g. [\"Netherlands\", \"Belgium\"]."},"device":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 deviceCategory values, matched exactly (any of): \"desktop\", \"mobile\", and/or \"tablet\"."},"event":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 eventName values, matched exactly (any of), e.g. [\"purchase\"]."},"hostName":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 hostName values, matched exactly (any of), e.g. [\"www.example.com\"]. When the linked GA4 property is shared with other sites, results are already limited to this site's hostnames (see `siteScope` in the response). For the property owner, setting hostName replaces that automatic scope, e.g. to read another stream or several hosts at once; on a property shared with you it only narrows within the scope."}},"additionalProperties":false,"description":"Optional GA4 dimension filters applied to every report in the call. Within a list field the values OR together; different fields AND together. Omit entirely for unfiltered data."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":25,"description":"Maximum number of rows per breakdown table."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_ga4_custom_dimensions":{"post":{"operationId":"tool_list_ga4_custom_dimensions","summary":"GA4 custom dimensions & metrics","description":"Lists the custom dimensions and custom metrics REGISTERED on the GA4 property linked to a site (GA4 Admin > Custom definitions) - the event parameters and user properties that property collects on top of the standard GA4 fields, such as a source_format or target_path sent with an internal_link_click event. Each entry carries the exact `apiName` (e.g. customEvent:source_format) that query_ga4_custom_dimensions takes. Call this FIRST: an event parameter that is not registered cannot be reported on at all, and GA4 answers an unregistered name with an empty report rather than an error, so a name must never be guessed. Returns a notConfigured result (not an error) when Google Analytics is not connected or no GA4 property is linked to the site in the GSC Wizard app.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/query_ga4_custom_dimensions":{"post":{"operationId":"tool_query_ga4_custom_dimensions","summary":"GA4 custom dimension breakdown","description":"Breaks GA4 traffic down by ONE custom dimension registered on the property linked to a site (the site's own event parameters or user properties, e.g. customEvent:source_format), optionally CROSSED with a second dimension - which is how a question like \"which article sent how many readers to which page\" is answered: primary customEvent:source_path, secondary customEvent:target_path, filtered to the one event that carries them. Metrics per row are eventCount, sessions, activeUsers and keyEvents, plus any registered custom metrics asked for. Run list_ga4_custom_dimensions first for the exact names; an unregistered name is rejected here rather than silently returning an empty report. Returns a notConfigured result (not an error) when Google Analytics is not connected or no GA4 property is linked. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"dimension":{"type":"string","pattern":"^custom(Event|User|Item):[A-Za-z0-9_]{1,64}$","description":"apiName of the custom dimension to break down by, from list_ga4_custom_dimensions (e.g. customEvent:source_format). Omit to use the property's first registered custom dimension; the response reports the choice."},"secondaryDimension":{"type":"string","maxLength":128,"description":"Optional second dimension to cross the first with, producing one row per PAIR of values. Either another custom dimension apiName, or one of: eventName, pagePath, landingPage, sessionDefaultChannelGroup, sessionSourceMedium, country, deviceCategory."},"customMetrics":{"type":"array","items":{"type":"string","pattern":"^custom(Event|User|Item):[A-Za-z0-9_]{1,64}$"},"maxItems":3,"description":"Up to 3 registered custom METRIC apiNames to add as extra columns (from list_ga4_custom_dimensions metricNames)."},"valueFilters":{"type":"array","items":{"type":"object","properties":{"dimension":{"type":"string","pattern":"^custom(Event|User|Item):[A-Za-z0-9_]{1,64}$","description":"apiName of the custom dimension to match on."},"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The value to match."}},"required":["dimension","operator","value"],"additionalProperties":false},"maxItems":5,"description":"Narrow the whole report to rows whose custom dimension matches a value - the way to drill from \"every source_path\" into \"the target pages of ONE source_path\". Filters AND together."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"filters":{"type":"object","properties":{"channel":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionDefaultChannelGroup names, matched exactly (any of), e.g. [\"Organic Search\", \"Direct\"]."},"sourceMedium":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 sessionSourceMedium values, matched exactly (any of), e.g. [\"google / organic\"]."},"pagePath":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 pagePath dimension (path only, e.g. \"/pricing\"), with an operator."},"landingPage":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How to match the value against the dimension (case-insensitive; regex may match anywhere)."},"value":{"type":"string","minLength":1,"maxLength":256,"description":"The text or pattern to match, 1-256 characters."}},"required":["operator","value"],"additionalProperties":false,"description":"Filter on the GA4 landingPage dimension (path only), with an operator."},"country":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 country names, matched exactly (any of), e.g. [\"Netherlands\", \"Belgium\"]."},"device":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 deviceCategory values, matched exactly (any of): \"desktop\", \"mobile\", and/or \"tablet\"."},"event":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 eventName values, matched exactly (any of), e.g. [\"purchase\"]."},"hostName":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":300,"description":"GA4 hostName values, matched exactly (any of), e.g. [\"www.example.com\"]. When the linked GA4 property is shared with other sites, results are already limited to this site's hostnames (see `siteScope` in the response). For the property owner, setting hostName replaces that automatic scope, e.g. to read another stream or several hosts at once; on a property shared with you it only narrows within the scope."}},"additionalProperties":false,"description":"Optional GA4 dimension filters applied to every report in the call. Within a list field the values OR together; different fields AND together. Omit entirely for unfiltered data."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":50,"description":"Maximum number of breakdown rows returned."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_blended_landing_pages":{"post":{"operationId":"tool_get_blended_landing_pages","summary":"Blended GSC + GA4 landing pages","description":"Joins Search Console (clicks, impressions, CTR, position) with GA4 (sessions, bounce rate, key events, revenue) per landing page, on the canonical path (no query/hash, no trailing slash). Flags GSC-only and GA4-only pages so neither side is silently dropped. By default GA4 metrics are limited to google / organic sessions so both sides describe the same traffic (set organicOnly to false for all-traffic GA4 metrics). Units differ by source: ctr is a percentage 0-100 (like every GSC CTR here) while bounceRate is a GA4 fraction 0-1. For a URL-prefix property with a path (e.g. https://example.com/blog/) only GA4 landing pages under that path are joined. Requires a GA4 property linked to the site in GSC Wizard; returns a notConfigured explanation otherwise. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"organicOnly":{"type":"boolean","default":true,"description":"Limit GA4 metrics to google / organic sessions so they line up with GSC. Default true; set false for all-traffic GA4 metrics."},"limit":{"type":"integer","minimum":1,"maximum":500,"default":50,"description":"Rows to return. Applies per period when dateGranularity is set."},"dateGranularity":{"type":"string","enum":["none","day","week","month"],"default":"none","description":"Split the range into periods and return one set of rows per period, each tagged with a `date` (the period start, clamped to the requested range). Use this to chart a tool's output over time instead of getting a single aggregate: \"month\" gives month-on-month, \"week\" gives Monday-aligned weeks, \"day\" gives a daily series. Default \"none\" returns one aggregate over the whole range, unchanged. `limit` applies per period when set. Comparison fields (prev*) compare each period against the period before it."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_query_value_attribution":{"post":{"operationId":"tool_get_query_value_attribution","summary":"Estimated GA4 value per GSC query","description":"Estimates GA4 sessions, key events, and revenue per Search Console query via proportional click share: a query with 80% of a page's GSC clicks is credited 80% of that page's GA4 outcomes. Page-level estimates with known blind spots (device/country/date mismatches are invisible; every click is treated as equally likely to convert). matchedClickShare reports how much of the click volume the estimates cover; estRevenue appears only when the GA4 property records revenue. Requires a GA4 property linked to the site in GSC Wizard; returns a notConfigured explanation otherwise. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"organicOnly":{"type":"boolean","default":true,"description":"Limit GA4 outcomes to google / organic sessions so only organic value is distributed across queries. Default true; set false to distribute all-traffic GA4 outcomes."},"limit":{"type":"integer","minimum":1,"maximum":5000,"default":1000,"description":"Rows to return. Applies per period when dateGranularity is set."},"dateGranularity":{"type":"string","enum":["none","day","week","month"],"default":"none","description":"Split the range into periods and return one set of rows per period, each tagged with a `date` (the period start, clamped to the requested range). Use this to chart a tool's output over time instead of getting a single aggregate: \"month\" gives month-on-month, \"week\" gives Monday-aligned weeks, \"day\" gives a daily series. Default \"none\" returns one aggregate over the whole range, unchanged. `limit` applies per period when set. Comparison fields (prev*) compare each period against the period before it."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_bing_sites":{"post":{"operationId":"tool_list_bing_sites","summary":"List Bing Webmaster sites","description":"Lists the sites verified in the Bing Webmaster Tools account linked to GSC Wizard (via the stored Bing Webmaster API key). Use this to discover the exact site URLs Bing recognises before calling the other get_bing_* tools. Returns notConfigured: true when no Bing Webmaster API key is set up in the GSC Wizard app.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_traffic_stats":{"post":{"operationId":"tool_get_bing_traffic_stats","summary":"Bing daily traffic","description":"Daily clicks and impressions from Bing Webmaster Tools (Bing/Yahoo/DuckDuckGo organic) for a property, roughly the last 6 months. Complements Google Search Console data with the Bing side of organic search. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_query_stats":{"post":{"operationId":"tool_get_bing_query_stats","summary":"Bing top queries","description":"Top search queries on Bing Webmaster Tools for a property, aggregated across the window (clicks, impressions, CTR as a 0-100 percentage, and impression-weighted average position). The Bing counterpart to query_top_queries. `rowCount` is how many rows this response holds (at most `limit`); `totalRows` is how many distinct queries Bing reported for the window before that cut. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"limit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"default":100,"description":"Max queries to return, ranked by clicks then impressions (default 100, uncapped)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_page_stats":{"post":{"operationId":"tool_get_bing_page_stats","summary":"Bing top pages","description":"Top landing pages on Bing Webmaster Tools for a property, aggregated across the window (clicks, impressions, CTR as a 0-100 percentage, and impression-weighted average position). The Bing counterpart to query_top_pages. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"limit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"default":100,"description":"Max pages to return, ranked by clicks then impressions (default 100, uncapped)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_query_page_stats":{"post":{"operationId":"tool_get_bing_query_page_stats","summary":"Bing query + page pairs","description":"Bing Webmaster Tools query+landing-page pairs for a property, aggregated across the window (clicks, impressions, CTR as a 0-100 percentage, and impression-weighted average position per pair). Shows which query drives each page on Bing, the basis for per-page keyword analysis and cannibalisation checks. Bing has no endpoint that returns these combinations, so they are assembled with one request per top page; pass `query` to pair from a single query instead, or use get_bing_page_queries for one page's queries. Coverage is bounded by seedLimit and by Bing's own top-value sampling, so totals are a lower bound (`truncated` says when). Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"query":{"type":"string","minLength":1,"description":"Optional. Pair from this single search query (Bing lists the pages that ranked for it) instead of fanning out over the top pages. Use it to answer \"which pages compete for this term?\"."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"limit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"default":100,"description":"Max query/page pairs, ranked by clicks then impressions (default 100, uncapped)."},"seedLimit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"maximum":100,"default":25,"description":"How many top pages to expand into pairs (default 25, max 100). Each one is a separate Bing request, so raising it widens coverage but is slower and likelier to hit Bing rate limits. Only applies to the page fan-out, so a call that passes `query` uses it only if that path has to fall back to pairing by page."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_page_queries":{"post":{"operationId":"tool_get_bing_page_queries","summary":"Bing queries for a page","description":"The Bing search queries that led to ONE landing page (clicks, impressions, CTR as a 0-100 percentage, and impression-weighted average position per query). The per-page keyword view Bing Webmaster Tools shows when you drill into a URL, and the natural drill-down after get_bing_page_stats. Pass the page URL exactly as get_bing_page_stats returns it. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"page":{"type":"string","minLength":1,"description":"The landing page URL to break down, exactly as get_bing_page_stats returns it (e.g. https://example.com/blog/post/). Bing matches the full URL, not a prefix."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"limit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"default":100,"description":"Max queries to return, ranked by clicks then impressions (default 100, uncapped)."}},"required":["siteUrl","page"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_query_page_trend":{"post":{"operationId":"tool_get_bing_query_page_trend","summary":"Bing query + page daily trend","description":"Daily clicks, impressions, CTR (0-100 percentage) and average position for ONE exact query+landing-page combination on Bing. The only Bing endpoint that carries a true pair-level position, so this is what a \"did this page slip for this term?\" check needs. Take the query and page verbatim from get_bing_query_page_stats or get_bing_page_queries. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"query":{"type":"string","minLength":1,"description":"The search query, exactly as Bing reports it."},"page":{"type":"string","minLength":1,"description":"The landing page URL, exactly as Bing reports it (full URL, not a prefix)."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."}},"required":["siteUrl","query","page"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_crawl_stats":{"post":{"operationId":"tool_get_bing_crawl_stats","summary":"Bing crawl stats","description":"Bing's daily crawl statistics for a property (roughly the last 6 months): pages crawled, pages in the index, inbound links, and a breakdown of response codes (2xx, 301, 302, 4xx, 5xx), robots.txt blocks, crawl errors and malware flags. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-01-01). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). Omit BOTH startDate and endDate to return everything Bing has (roughly the last 6 months). Never pass null or the string \"null\"."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_crawl_issues":{"post":{"operationId":"tool_get_bing_crawl_issues","summary":"Bing crawl issues","description":"URLs where Bing found crawl issues for a property: HTTP 4xx/5xx, 301/302 redirects, robots.txt blocks, DNS/timeout errors and malware, each with the HTTP code, inbound-link count, and decoded human-readable issue labels. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"limit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"default":200,"description":"Max issue URLs to return, most inbound links first (default 200, uncapped)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_link_counts":{"post":{"operationId":"tool_get_bing_link_counts","summary":"Bing inbound link counts","description":"Inbound (backlink) counts per URL that Bing Webmaster Tools has recorded for a property, one page of results at a time (Bing returns roughly 100 rows per page). Pass `page` to paginate; totalPages tells you how many pages exist. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"page":{"type":"integer","minimum":0,"default":0,"description":"Zero-based page index for pagination (default 0)."},"limit":{"type":"integer","exclusiveMinimum":true,"minimum":0,"default":100,"description":"Max link rows to return from the page (default 100). Bing returns up to ~100 rows per page but large properties can exceed that; lower this to keep the payload small."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_keyword_stats":{"post":{"operationId":"tool_get_bing_keyword_stats","summary":"Bing keyword impression history","description":"Bing Webmaster Tools' historical impression volume for a single keyword (weekly buckets), plus its broad-match impressions. This is Bing marketplace demand data, not tied to any of your properties, so it needs no siteUrl. Useful for gauging Bing search demand and seasonality for a term. Returns notConfigured: true when no Bing Webmaster API key is set up in the GSC Wizard app.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"description":"The keyword / search term to look up."},"country":{"type":"string","minLength":2,"default":"us","description":"Two-letter market/country code Bing scopes the demand to (default \"us\")."},"language":{"type":"string","minLength":2,"default":"en-US","description":"BCP-47 language tag for the market (default \"en-US\")."}},"required":["keyword"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_feeds":{"post":{"operationId":"tool_get_bing_feeds","summary":"Bing submitted sitemaps","description":"Sitemaps and feeds submitted to Bing Webmaster Tools for a property, with each feed's decoded status (Success / Pending / Warning / Error), type (Sitemap / RSS / Atom / ...), submitted and last-crawled dates, URL count and file size. The Bing counterpart to list_sitemaps. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_bing_url_submission_quota":{"post":{"operationId":"tool_get_bing_url_submission_quota","summary":"Bing URL submission quota","description":"Remaining Bing Webmaster Tools URL-submission quota for a property: the daily and monthly allowances left for submitting URLs to Bing's index. Returns notConfigured: true when no Bing Webmaster API key is set up for the property.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_yandex_sites":{"post":{"operationId":"tool_list_yandex_sites","summary":"Yandex sites","description":"Lists the sites in the connected Yandex Webmaster account, with their verification status and the canonical mirror Yandex resolved for each. Use this to find out which properties have Yandex data available. Only sites already added AND verified in Yandex Webmaster itself report data. The list is cached for ten minutes. Returns notConfigured: true when no Yandex account is connected, or when the connection has to be granted again (reason: reauth).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_yandex_site_summary":{"post":{"operationId":"tool_get_yandex_site_summary","summary":"Yandex site summary","description":"Yandex Webmaster's summary for a property: site quality index (SQI), pages in search, excluded pages, and the problems Yandex is currently reporting, by severity. Complements Google Search Console with the Yandex side of organic search, which matters for Russian, Turkish, Kazakh, Belarusian and Uzbek traffic. SQI and the problem severities are Yandex's own taxonomy with no Google equivalent, and Yandex serves no previous-period series, so there is nothing to compare against: the response carries these caveats in `limitations`, which should be passed on when reporting the numbers. When the problem list could not be read (a Yandex rate limit or timeout), `problems` is empty and `warnings` says so. Returns notConfigured: true (with a `reason`) when no Yandex account is connected, the connection has to be granted again, the property is not in it, or the caller holds a share of the property rather than owning it: Yandex data is owner-only.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_yandex_query_stats":{"post":{"operationId":"tool_get_yandex_query_stats","summary":"Yandex query stats","description":"Search queries from Yandex Webmaster for a property, with impressions, clicks, average impression position and average clicked position. IMPORTANT COVERAGE LIMIT: Yandex exposes its top queries for the period, at most 3,000 of them, so totals derived from these rows are a floor, not a complete figure; say so when reporting them. Yandex serves 500 rows per request and this tool pages through as many as `limit` allows, defaulting to the first 500 by `orderBy`; `totalAvailable` and `truncated` say how much of the pool was left. CTR is a percentage (0-100, like every other CTR this server returns), calculated from impressions and clicks because Yandex publishes no CTR metric; null when there were no impressions. Yandex has no query-by-page report, so these queries cannot be attributed to URLs. The dates select a real window, so a longer range returns more queries and larger totals; omitting them gives the last week only. Yandex finishes a day about four days late, so `range` echoes the window it actually served. The full set of caveats is in `limitations` on every response. Returns notConfigured: true (with a `reason`) when no Yandex account is connected, the connection has to be granted again, the property is not in it, or the caller holds a share of the property rather than owning it: Yandex data is owner-only.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date (YYYY-MM-DD). Defaults to the last week Yandex holds."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date (YYYY-MM-DD). Defaults to the last week Yandex holds."},"orderBy":{"type":"string","enum":["TOTAL_SHOWS","TOTAL_CLICKS"],"default":"TOTAL_SHOWS","description":"Which metric decides the 500 queries Yandex returns."},"deviceType":{"type":"string","enum":["ALL","DESKTOP","MOBILE","TABLET","MOBILE_AND_TABLET"],"default":"ALL","description":"Device filter. Yandex filters rather than breaking down by device, so each value is a separate query. MOBILE_AND_TABLET overlaps MOBILE and TABLET, so do not sum them."},"limit":{"type":"integer","minimum":1,"maximum":3000,"default":500,"description":"Rows to return, across pages. Yandex serves 500 per request and at most 3,000 for a window, so a limit above 500 costs one extra round trip per 500 rows. The default is one page: ask for more only when the long tail matters, since a few thousand rows can exceed a host response-size ceiling and be refused."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_yandex_indexing_history":{"post":{"operationId":"tool_get_yandex_indexing_history","summary":"Yandex indexing history","description":"How Yandex crawls and indexes a property over time: the HTTP status codes Yandex's crawler received by day, how many pages are in Yandex search, and the count of pages that appeared in or were removed from Yandex results each day. Use the appeared/removed series to spot day-to-day indexing swings in Yandex: it has no Google Search Console equivalent, so it is the one place to watch pages entering and leaving an index day by day. These series carry no country or device dimension and no previous-period comparison; the response repeats that in `limitations`. When one of the two secondary series could not be read (a Yandex rate limit or timeout), it comes back empty and `warnings` says so. Returns notConfigured: true (with a `reason`) when no Yandex account is connected, the connection has to be granted again, the property is not in it, or the caller holds a share of the property rather than owning it: Yandex data is owner-only.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date (YYYY-MM-DD). Defaults to what Yandex returns by default."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date (YYYY-MM-DD). Defaults to what Yandex returns by default."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/detect_anomalies":{"post":{"operationId":"tool_detect_anomalies","summary":"Detect traffic anomalies","description":"Flags statistically anomalous days in a property's Search Console series for a chosen metric (clicks, impressions, CTR, or position). Uses a robust Modified Z-score with median absolute deviation and day-of-week baselines (mean absolute deviation when most days are identical, as on a low-traffic property), then scores each spike/drop by severity (critical → info). Days without rows count as zero for clicks and impressions, so a drop to zero (deindexing) is flagged; the 21-day minimum is measured in calendar days from the first day with data. CTR and position use only days with impressions. `coverage` reports the days analysed and how an empty tail at the end of the window was treated. Good for \"did something break / spike on a specific day?\". Reads the ClickHouse warehouse when available, else the live Search Console API.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"metric":{"type":"string","enum":["clicks","impressions","ctr","position"],"default":"clicks","description":"Which metric to scan for anomalies."},"days":{"type":"integer","minimum":21,"maximum":480,"default":90,"description":"Trailing days of daily data to analyze (min 21, default 90)."},"sensitivity":{"type":"number","minimum":2,"maximum":6,"default":3.5,"description":"Modified Z-score threshold: lower = more sensitive (more anomalies). Default 3.5; 3-4 is typical."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/detect_change_points":{"post":{"operationId":"tool_detect_change_points","summary":"Detect traffic change points","description":"Finds the dates where a property's clicks or impressions shifted to a new sustained level (step changes / level shifts), reporting the before vs after average and the % change at each break. Unlike anomaly detection (one-off spikes), this locates durable regime changes: a migration, an algorithm update, a redesign. Each date is the day the shift is strongest (the first day of the new level). Days without rows count as zero, so a drop to zero (deindexing) is a change point; `coverage` reports how an empty tail at the end of the window was treated. Reads the ClickHouse warehouse when available, else the live Search Console API. When a shift starts from a zero baseline (beforeMean 0) it has no percentage: changePercent is 0 by convention, which does not mean no change; describe it as new traffic from zero using afterMean.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"metric":{"type":"string","enum":["clicks","impressions"],"default":"clicks","description":"Which metric to segment."},"days":{"type":"integer","minimum":14,"maximum":480,"default":180,"description":"Trailing days of daily data to analyze (min 14, default 180)."},"sensitivity":{"type":"number","minimum":1,"maximum":5,"default":2,"description":"Mean-shift threshold in std-devs: lower = more sensitive (more change points). Default 2."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/forecast_traffic":{"post":{"operationId":"tool_forecast_traffic","summary":"Forecast organic traffic","description":"Projects future Search Console clicks (or impressions) for a property using the app's forecasting model: multiplicative seasonal decomposition (ratio-to-moving-average) plus an auto-selected trendline (linear / polynomial / log / exponential / power by best R-squared), re-seasonalised for each future period. Optionally applies a manual growth rate and derives revenue from a conversion rate and average order value. History needs: weekly needs 13 complete weeks and monthly 6 complete months, after the first and last (possibly partial) period are dropped, so about 105 days (weekly) or 240 days (monthly) of data. Days and periods without rows count as zero. A constant history (for example all zero) gets a flat forecast with `forecastNote`. Reads the ClickHouse warehouse when available, else the live Search Console API.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"metric":{"type":"string","enum":["clicks","impressions"],"default":"clicks","description":"Metric to forecast (treated as \"sessions\" by the model)."},"granularity":{"type":"string","enum":["weekly","monthly"],"default":"weekly","description":"Forecast granularity. Weekly needs about 105 days of history (13 complete weeks), monthly about 240 days (6 complete months)."},"forecastPeriods":{"type":"integer","minimum":1,"maximum":104,"default":26,"description":"How many future periods (weeks or months) to project. Default 26."},"historyDays":{"type":"integer","minimum":90,"maximum":1000,"default":480,"description":"Trailing days of history to fit on (default 480 ≈ 16 months; more improves seasonality)."},"growthRate":{"type":"number","default":0,"description":"Optional manual growth rate per period as a decimal (0.05 = +5%). Default 0."},"compoundGrowth":{"type":"boolean","default":true,"description":"Compound the growth rate across periods (default true)."},"additionalSessions":{"type":"number","default":0,"description":"Optional flat sessions added to every forecast period. Default 0."},"trendlineType":{"type":"string","enum":["auto","linear","polynomial","logarithmic","exponential","power"],"default":"auto","description":"Force a trendline model, or \"auto\" for the best R-squared (default)."},"cvr":{"type":"number","minimum":0,"default":0,"description":"Optional conversion rate as a decimal (0.025 = 2.5%) to derive forecast revenue."},"aov":{"type":"number","minimum":0,"default":0,"description":"Optional average order value (in currency units) used with cvr for revenue."},"currency":{"type":"string","default":"USD","description":"Currency label for the revenue fields (display only)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_longtail_clusters":{"post":{"operationId":"tool_get_longtail_clusters","summary":"Long-tail page clustering","description":"Segments a property's pages into Head / Chunky Middle / Long Tail tiers by elbow detection on the cumulative-clicks curve (the app's Long-tail Clustering report). Returns each tier's page count, click/impression share, average CTR/position/query-diversity, the knee points, and the top pages per tier. Useful for spotting over-reliance on a few pages or a bloated long tail to prune. Page clicks/impressions/position (and the totals) are the page figures Search Console's page filter shows, including anonymized-query traffic; query diversity counts the page's query x page rows. Reads the ClickHouse warehouse when available, else the live Search Console API. `truncated: true` (with `truncationNote`) means a cap was hit: the warehouse clusters at most the 100,000 pages with the most clicks, the live API reads at most 100,000 pages and 100,000 query x page rows. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"preset":{"type":"string","enum":["default","content","ecommerce","small_site","enterprise"],"default":"default","description":"Tuning preset: default | content | ecommerce | small_site | enterprise."},"sensitivity":{"type":"string","enum":["low","normal","high"],"description":"Override the preset's knee sensitivity: low | normal | high."},"includeZeroClicks":{"type":"boolean","description":"Include pages with zero clicks (impressions only). Defaults per preset (usually true)."},"pagesPerCluster":{"type":"integer","minimum":0,"maximum":200,"default":10,"description":"How many top pages to list per tier (default 10). 0 returns tier stats only."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_core_web_vitals":{"post":{"operationId":"tool_get_core_web_vitals","summary":"Core Web Vitals history (CrUX)","description":"Chrome UX Report field data for a property (or a single page): the weekly history of Core Web Vitals (LCP, INP, CLS) plus FCP and TTFB, each with its p75 value, good/needs-improvement/poor rating, and the good-bucket density trend. Also reports any week-over-week rating regressions. Where Chrome detected ads, adMetrics adds its four experimental ad metrics (ad count, ad density, ad CPU, ad network weight) as a p75 trend each. These have no thresholds and no rating, and are absent for sites with no ads. Needs a Chrome UX Report API key configured in the app; returns notConfigured otherwise, or noData when CrUX has too little real-world traffic for the target.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"url":{"type":"string","format":"uri","description":"Optional single page URL to measure instead of the whole origin."},"formFactor":{"type":"string","enum":["ALL","PHONE","DESKTOP","TABLET"],"default":"ALL","description":"Device class: ALL (default), PHONE, DESKTOP, or TABLET."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_experiments":{"post":{"operationId":"tool_list_experiments","summary":"List SEO experiments","description":"Lists the SEO experiments (split tests) defined for a property in GSC Wizard, each with its control/variant URL groups, source, status, and start date. Use get_experiment_results to score one. By default only active experiments are returned.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"includeArchived":{"type":"boolean","default":false,"description":"Include archived experiments as well as active ones."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_experiment_results":{"post":{"operationId":"tool_get_experiment_results","summary":"Score an SEO experiment","description":"Scores one SEO experiment: assigns the property's landing pages to the experiment's control and variant URL groups, then compares each variant against the control (group 0) on click growth period-over-period. Returns per-group clicks/impressions/CTR (with a confidence interval) and an impression-weighted average position, plus for each variant the uplift in growth (percentage points) with its CI, a significance test of that growth difference (significant exactly when the CI excludes 0), the winner, and a low-power warning. `ctrPValue` is a separate test of the CTR difference, for reference only. The comparison window is the prior same-length period. Reads the ClickHouse warehouse when available, else the live Search Console API.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"experimentId":{"type":"string","minLength":1,"description":"The experiment id from list_experiments."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"confidenceLevel":{"type":"number","minimum":0.8,"maximum":0.999,"default":0.95,"description":"Confidence level for the significance test and CIs (default 0.95)."}},"required":["siteUrl","experimentId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/compare_migration":{"post":{"operationId":"tool_compare_migration","summary":"Compare a site migration (A vs B)","description":"Before/after Search Console comparison for a site migration or restructure. Three modes: \"cross-property\" compares two GSC properties (old domain vs new); \"two-urls\" compares two URL-prefix sections within one property; \"regex\" splits one property by two regexes. Returns the daily clicks/impressions trend for each side, per-side totals, and the query and page winners/losers by click delta. Without goLiveDate both sides use the same date window (startDate/endDate): A vs B over one period. With goLiveDate it becomes a before/after comparison around the launch: side A is read over the before window and side B over the after window, placed by windowStrategy (\"recent\", the default: the last windowDays settled days vs the windowDays days before go-live; \"from-go-live\": the first windowDays days from go-live vs the windowDays days before it; \"full\": the 90 days before go-live vs everything since). windowDays defaults to 28; yoyBaseline compares with the same weeks a year earlier instead. The go-live result adds `windows` (dates, days since go-live, warnings), `recoveryPct` (B clicks per day as a % of A clicks per day; null under 10 baseline clicks) and trend buckets (lost / declined / stable / improved / new) for queries and pages; pages of two properties are joined by path. For the full health verdict (risk score, redirect checks, recommendations, projected recovery) use get_migration_health. Reads the ClickHouse warehouse when available, else the live Search Console API. Query and page lists cover at most the top 25,000 rows by clicks per side; `truncated` and `truncationNote` say when a cap was reached. Regexes are capped at 2,000 characters and must not nest quantifiers (for example (a+)+). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["cross-property","two-urls","regex"],"description":"cross-property | two-urls | regex."},"siteUrl":{"type":"string","minLength":1,"description":"Side A property (and the single property for two-urls/regex)."},"siteUrlB":{"type":"string","minLength":1,"description":"Side B property (required for cross-property)."},"urlPrefixA":{"type":"string","description":"Side A URL prefix (required for two-urls): a full URL (\"https://acme.com/old-blog/\"), a host (\"blog.acme.com/\") or a path on any host (\"/old-blog/\"), as list_migrations returns them."},"urlPrefixB":{"type":"string","description":"Side B URL prefix (required for two-urls), in the same forms as urlPrefixA."},"regexA":{"type":"string","description":"Side A page regex (required for regex mode)."},"regexB":{"type":"string","description":"Side B page regex (required for regex mode)."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"goLiveDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. First day the new setup was live, as YYYY-MM-DD. When given, side A is read over the before window and side B over the after window around this date (see windowStrategy), and the result adds windows, recoveryPct and trend buckets. Do not combine with startDate/endDate."},"windowStrategy":{"type":"string","enum":["recent","from-go-live","full"],"description":"Only with goLiveDate. \"recent\" (default): the last windowDays days vs the windowDays days before go-live, where the migration stands now. \"from-go-live\": the first windowDays days after go-live vs the windowDays days before, the launch dip included. \"full\": the 90 days before go-live vs every day since (lengths differ; per-day figures and recovery stay comparable)."},"windowDays":{"type":"integer","minimum":1,"maximum":365,"description":"Only with goLiveDate. Window length in days for \"recent\" and \"from-go-live\" (default 28). Shortened to the post-launch days available."},"yoyBaseline":{"type":"boolean","description":"Only with goLiveDate. Compare the after window with the same weeks one year (364 days) earlier instead of the days before go-live, which removes seasonality. Default false."},"limit":{"type":"integer","minimum":1,"maximum":500,"default":50,"description":"Max query/page winners and losers to return per list (default 50)."}},"required":["mode","siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_migration_health":{"post":{"operationId":"tool_get_migration_health","summary":"Get migration health","description":"Health check of a site migration around its go-live date: the Migration Compare analysis of the GSC Wizard app (without brand terms, the search-type split or the country / device filters of a saved migration; `notes` says what differs). Returns recovery (side B clicks per day as a % of side A clicks per day before go-live), pace against the recovery a migration on track reaches by now, momentum, a projected recovery with milestone dates, URL success per migration unit, a 0-100 risk score with its factors, prioritised recommendations, redirect status counts from the stored redirect checks, the top lost pages, redirect problems, lost queries and losing sections, the old-to-new impression handover, the click change split into demand / position / CTR effects, the country and device splits (`segments`) with their recommendations, and a launch checklist. siteUrl is the OLD property (side A); pass siteUrlB (the new property) for a domain move and omit it when the migration happened inside one property. Pass goLiveDate, or a migrationId from list_migrations to reuse a migration saved in the app (its properties, URL prefixes or regexes, go-live date, windows, mapping label and Only mapped URLs setting; explicit arguments override it). Redirect mappings are the ones saved for the property pair (add_migration_redirects or the app); without any, pages are joined by path. onlyMapped is the app's \"Only mapped URLs\": with saved mappings, the totals, recovery and health count only the pages the mappings claim, and so do the country and device splits of a side read from the warehouse (`segments.scope` says which; each 10 warehouse queries of those splits cost one more rate-limit unit). Windows as in compare_migration: windowStrategy \"recent\" (default), \"from-go-live\" or \"full\", windowDays (default 28), yoyBaseline. Page and query reads cover at most the top 25,000 rows by clicks per side and window, and at most 10,000 redirect mappings are analysed (each 2,000 costs one more rate-limit unit); `truncated` says when a cap was reached. health is null until a post-launch day has final data.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The OLD property (side A), as returned by list_sites. With migrationId it must be the saved migration's old property."},"siteUrlB":{"type":"string","minLength":1,"description":"The NEW property (side B) for a move between properties. Omit when the migration happened inside one property."},"goLiveDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day the new setup was live, as YYYY-MM-DD. Required unless migrationId supplies one."},"migrationId":{"type":"string","format":"uuid","description":"Id of a migration saved in the app (list_migrations). Its setup supplies everything the arguments leave out."},"windowStrategy":{"type":"string","enum":["recent","from-go-live","full"],"description":"\"recent\" (default): the last windowDays days vs the windowDays days before go-live. \"from-go-live\": the first windowDays days after go-live vs the windowDays days before. \"full\": the 90 days before go-live vs every day since."},"windowDays":{"type":"integer","minimum":1,"maximum":365,"description":"Window length in days for \"recent\" and \"from-go-live\" (default 28)."},"yoyBaseline":{"type":"boolean","description":"Compare with the same weeks one year (364 days) earlier instead of the days before go-live. Default false."},"mappingLabel":{"type":"string","minLength":1,"maxLength":200,"description":"Only the redirect mappings carrying this label (\"__none__\" = only unlabelled ones). Omit to use every mapping saved for the property pair."},"onlyMapped":{"type":"boolean","description":"Only mapped URLs: count only the pages the redirect mappings claim (the old URLs' pages on side A, their new URLs' pages on side B) in the totals, recovery and health. Default: the saved migration's setting with migrationId, else false. No effect without saved mappings."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_migrations":{"post":{"operationId":"tool_list_migrations","summary":"List saved migrations","description":"Lists the site migrations saved on the account in the GSC Wizard app (Migration Compare), most recently updated first: id, name, mode (cross-property, two-urls or regex), the old (siteUrlA) and new (siteUrlB) property, go-live date, window settings, the redirect-mapping label, whether daily re-check alerts are on, and the last health snapshot from that re-check (status, recovery, risk score, redirect problem counts). Pass an id to get_migration_health as migrationId for the full analysis. Takes no arguments.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/audit_onpage_seo":{"post":{"operationId":"tool_audit_onpage_seo","summary":"On-page SEO audit","description":"Crawls a property's pages and runs a technical on-page/SEO audit per URL: HTTP status, indexability (noindex / canonicalised), title & meta-description length, H1s, word count, canonical, internal/external links, image alt coverage, structured data, Open Graph, viewport, hreflang, and a scored list of issues by severity. Pass explicit `urls`, or omit them to audit the top pages by Search Console impressions. URLs must belong to the property. Fetches each page live and stops after about 50 seconds: when truncated is true, the pages in notAudited were not fetched, so call again with urls set to that list to finish.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"urls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":25,"description":"Explicit page URLs to audit (max 25). Omit to auto-pick top pages."},"maxUrls":{"type":"integer","minimum":1,"maximum":25,"default":10,"description":"How many pages to audit when auto-picking (default 10, max 25)."},"minImpressions":{"type":"integer","minimum":0,"default":0,"description":"When auto-picking, only consider pages with at least this many impressions (28-day)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_content_group_performance":{"post":{"operationId":"tool_get_content_group_performance","summary":"Content group performance","description":"Measures a property's content groups: clicks, impressions, CTR, impression-weighted average position, distinct page count and share of clicks per group, plus an \"uncategorized\" bucket for pages no group claims. Pass groupId to drill into one group's top pages instead. Matching is first-match-wins in the groups' saved order, the same as the web app. Served from the GSC Wizard ClickHouse warehouse when available (where group totals are EXACT over every page of the property), otherwise from the live Search Console API over the top 25,000 pages by clicks (see `dataSource` and `truncated`). Use list_content_groups to see or create_content_group to add the definitions this reports on. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"searchType":{"type":"string","enum":["web","image","video","news","discover"],"default":"web"},"groupId":{"type":"string","minLength":1,"maxLength":64,"description":"Drill into one group: returns its top pages instead of the per-group aggregates. Accepts a content group id or the literal \"uncategorized\"."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Row cap for the groupId page drill-down."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_topic_cluster_performance":{"post":{"operationId":"tool_get_topic_cluster_performance","summary":"Topic cluster performance","description":"Measures a property's topic clusters: clicks, impressions, CTR, impression-weighted average position, matched query count and share of clicks per cluster, plus an \"unclustered\" bucket for queries no cluster claims. Pass clusterId to drill into one cluster's top queries (each row lists which of the cluster's keywords matched). A cluster keyword is a case-insensitive substring unless wrapped in slashes (/seo ?tools/), which makes it a regex. IMPORTANT: 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 queries are double-counted. Matching runs over the top `scanLimit` queries by clicks (default 50,000), read from the GSC Wizard ClickHouse warehouse when available (which scans at most 50,000 queries; `scanLimit` in the response is the limit actually applied), otherwise the live Search Console API (see `dataSource`). Use list_topic_clusters / create_topic_cluster to see or add the definitions this reports on. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"clusterId":{"type":"string","minLength":1,"maxLength":64,"description":"Drill into one cluster: returns its top matched queries instead of the per-cluster aggregates. Accepts a topic cluster id or the literal \"unclustered\"."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Row cap for the clusterId query drill-down."},"scanLimit":{"type":"integer","minimum":1000,"maximum":200000,"default":50000,"description":"How many top queries by clicks to match against the clusters. Raise it when a long-tail property reports `truncated: true`. Clamped at 50,000 on the ClickHouse path."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_branded_performance":{"post":{"operationId":"tool_get_branded_performance","summary":"Branded vs non-branded performance","description":"Splits a property's search performance into BRANDED and NON-BRANDED using the branded keywords saved on the property (set them with update_site; a keyword wrapped in slashes like /acme ?corp/ is treated as a regex, otherwise it is a case-insensitive substring). Returns totals, the branded share of clicks, a daily clicks trend for both sides, and the top queries on each side, with optional comparison-period totals. `nonBranded` is the property total minus `branded`, so the two sides add up to the property total (`total`) and `brandedClickShare` is branded clicks over that total. Search Console leaves anonymised queries out of any query-filtered read, so they cannot be matched against the keywords; they are rare, long-tail searches, counted in `nonBranded` and also reported on their own as `anonymized`. `topNonBrandedQueries` lists named queries only. Returns notConfigured (not an error) when the property has no branded keywords yet. Served from the GSC Wizard ClickHouse warehouse when available, otherwise the live Search Console API (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"limit":{"type":"integer","minimum":1,"maximum":500,"default":25,"description":"How many top queries to return per side."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_ga4_error_pages":{"post":{"operationId":"tool_get_ga4_error_pages","summary":"GA4 error pages","description":"Reports GA4 error pages for the property linked to a site: sessions, page views, active users and bounce rate per error page, broken down by page title AND URL. GA4 has no native 404 signal, so error pages are identified by matching the pageTitle dimension against saved patterns (operators contains / equals / starts_with / ends_with / regex, case-insensitive, OR-ed together). By default it uses the patterns saved for the site in GSC Wizard; pass `titleFilters` to override them for one call without saving anything. Returns notConfigured when Google Analytics is not connected or no GA4 property is linked, and noPatterns when the site has no saved patterns and none were passed. `totals` counts each session and user once across all matching pages (not the sum of the rows), and bounceRate is a fraction 0-1, not a percentage. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"comparisonStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Start of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"comparisonEndDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. End of the comparison period as YYYY-MM-DD. Provide BOTH comparison dates to compare two periods; omit both for no comparison (prev* fields are then 0 and hasComparison false)."},"titleFilters":{"type":"array","items":{"type":"object","properties":{"operator":{"type":"string","enum":["contains","equals","starts_with","ends_with","regex"]},"value":{"type":"string","minLength":1,"maxLength":256}},"required":["operator","value"],"additionalProperties":false},"minItems":1,"maxItems":50,"description":"Override the page-title patterns for this call only (nothing is saved). Omit to use the patterns saved on the site in GSC Wizard's Error Pages report."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"How many error-page rows to return, ordered by sessions."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_position_distribution":{"post":{"operationId":"tool_get_position_distribution","summary":"Ranking position distribution","description":"Slices a property by where it ranks, using the same 1-3 / 4-10 / 11-20 / 21+ bands as the GSC Wizard dashboard. granularity \"period\" (default) returns impressions, clicks and the number of queries (or pages) in each band over the whole range, showing how top-heavy the property's visibility is. granularity \"daily\" returns one row per day with the count of DISTINCT queries ranking in each band, which is how you see a ranking shift build up or a drop land on a specific date. Positions are impression-weighted averages, so a row sits in one band only. Served from the GSC Wizard ClickHouse warehouse when available (both views are computed in the warehouse over every query or page, never truncated; `scanLimit` is null there), otherwise from the live Search Console API over the top `scanLimit` rows by clicks, which drops zero-click rows first and so understates the deep bands when `truncated` is true (see `dataSource`). Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"granularity":{"type":"string","enum":["period","daily"],"default":"period","description":"\"period\" = one bucket summary over the range; \"daily\" = distinct query counts per band per day (always keyed on query, ignores `dimension`)."},"dimension":{"type":"string","enum":["query","page"],"default":"query","description":"What a \"row\" is on the period path: a search query or a page."},"scanLimit":{"type":"integer","minimum":1000,"maximum":200000,"default":50000,"description":"How many top rows by clicks to bucket on the live Search Console API. Raise it when a long-tail property reports `truncated: true`. Ignored on the ClickHouse warehouse, which buckets every row in SQL."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/update_content_group":{"post":{"operationId":"tool_update_content_group","summary":"Update a content group","description":"Edits an existing content group: its name, description, color, or matching rules. Only the fields you pass change; omit a field to leave it untouched. Passing `rules` REPLACES the whole rule list (rules have no stable ids across edits), so read the current rules with list_content_groups first if you mean to add one. Changing rules reassigns pages immediately in every report that uses the group; nothing is recomputed or stored, so the next get_content_group_performance call reflects the edit. A `regex` rule that cannot compile is rejected; one that is valid but unsupported by the warehouse or skipped as ReDoS-prone is accepted and reported in `ruleWarnings`. Relay those, since a skipped pattern matches no pages at all.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"groupId":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000,"nullable":true},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","nullable":true},"rules":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["prefix","contains","regex","equals"]},"value":{"type":"string","minLength":1}},"required":["type","value"],"additionalProperties":false},"minItems":1,"maxItems":50,"description":"Replaces the entire rule list. Same { type, value } shape as create_content_group."}},"required":["groupId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/update_topic_cluster":{"post":{"operationId":"tool_update_topic_cluster","summary":"Update a topic cluster","description":"Edits an existing topic cluster's name or keyword list. Only the fields you pass change. `keywords` REPLACES the whole list by default; pass mode \"add\" or \"remove\" to merge into or subtract from the current keywords instead, which is what you usually want when extending a cluster. A keyword is matched as a case-insensitive substring unless it is wrapped in slashes (/seo ?tools/), which makes it a regex. Read the current list with list_topic_clusters first when replacing.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"clusterId":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":200},"keywords":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":1000},"mode":{"type":"string","enum":["replace","add","remove"],"default":"replace","description":"How `keywords` is applied: \"replace\" (default) swaps the list, \"add\" merges new keywords in (deduplicated, case-insensitively), \"remove\" deletes the listed ones."}},"required":["clusterId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/update_saved_filter":{"post":{"operationId":"tool_update_saved_filter","summary":"Update a saved filter","description":"Renames a saved filter preset and/or replaces its filter rows. Only the fields you pass change. `filters` is the list of filter rows (dimension / operator / value), in the same shape list_saved_filters returns, and is REPLACED wholesale, not merged: read the current rows with list_saved_filters and pass them back with your edits applied. Passing `filters` without `filterLogic` resets the preset to AND, so pass both when the preset used OR. The property's owner or anyone with full access to it may edit any preset on it.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"filterId":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":200},"filters":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"description":"Stable row id. Omit it and one is generated."},"dimension":{"type":"string","enum":["query","page","country","device","branded"],"description":"Which GSC dimension the row filters on."},"operator":{"type":"string","enum":["contains","equals","not_contains","not_equals","regex"],"description":"How `value` is matched. `regex` is RE2."},"value":{"type":"string","minLength":1,"description":"What to match. For `device` use MOBILE / DESKTOP / TABLET, for `country` an ISO-3166-1 alpha-3 code or a comma-separated list of them (e.g. NLD,BEL), for `branded` exactly \"branded\" or \"non_branded\"."}},"required":["dimension","operator","value"],"additionalProperties":false},"description":"Replaces the stored filter rows. Omit to keep the current ones."},"filterLogic":{"type":"string","enum":["and","or"],"description":"Only read when `filters` is passed; the two are stored together."}},"required":["filterId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/update_annotation":{"post":{"operationId":"tool_update_annotation","summary":"Update a chart annotation","description":"Edits a chart annotation the user owns: its date, label, description, category or colour. Only the fields you pass change. Scope cannot be changed (an account-wide annotation cannot be moved onto a property or vice versa); delete it and create a new one instead. Platform-scoped annotations are system events and cannot be edited via this tool.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"annotationId":{"type":"string","format":"uuid"},"eventDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The date the event occurred, as YYYY-MM-DD (e.g. 2026-06-08)."},"label":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000,"nullable":true},"category":{"type":"string","maxLength":50,"nullable":true},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","nullable":true}},"required":["annotationId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_shared_reports":{"post":{"operationId":"tool_list_shared_reports","summary":"List shareable reports","description":"Lists the shareable reports saved on the account, newest first, each with its view URL and the clients currently granted access. Use it to find a reportId before calling manage_report_access or delete_shared_report, or to audit who can see which report.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100,"default":50}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_shared_report":{"post":{"operationId":"tool_create_shared_report","summary":"Create a shareable report","description":"Saves a table of rows as a shareable GSC Wizard report. Pass the `rows` you got from another tool (e.g. query_top_queries, get_content_group_performance) plus the `columns` describing which fields to show; the report renders at view time, so the stored payload stays small. THIS IS STEP 1 OF 3: the returned URL opens for NOBODY until access is granted, not even for the account owner, because the viewer is the client portal and requires a client login. To actually share it: (2) create_report_client with the recipient's email, then (3) manage_report_access to grant them the report. Do not hand the URL to anyone before step 3; it will not open. Up to 50 reports per account; delete old ones with delete_shared_report.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}},"minItems":1,"maxItems":5000,"description":"The table rows. Each row is an object keyed by the column `key` values."},"columns":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":100,"description":"Field name to read from each row."},"label":{"type":"string","minLength":1,"maxLength":200,"description":"Column header shown in the report."},"type":{"type":"string","enum":["text","number","percent","date","url"],"description":"How the value is formatted. Defaults to text."}},"required":["key","label"],"additionalProperties":false},"minItems":1,"maxItems":50,"description":"Column definitions, in display order."},"siteUrl":{"type":"string","minLength":1,"description":"Property this report is about; recorded on the report for context."},"reportType":{"type":"string","minLength":1,"maxLength":50,"default":"mcp","description":"Free-form label for what produced the report (e.g. \"top-queries\")."},"dataSourceType":{"type":"string","enum":["inline","queries","pages","countries","rankings","content-group","page-performance","migration"],"default":"inline","description":"Which kind of report this is, for the viewer."},"dateRange":{"type":"object","properties":{"startDate":{"type":"string","minLength":1},"endDate":{"type":"string","minLength":1}},"required":["startDate","endDate"],"additionalProperties":false,"description":"Reporting period, shown in the report header."},"comparisonRange":{"type":"object","properties":{"startDate":{"type":"string","minLength":1},"endDate":{"type":"string","minLength":1}},"required":["startDate","endDate"],"additionalProperties":false,"description":"Comparison period, shown alongside the reporting period."}},"required":["title","rows","columns"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_shared_report":{"post":{"operationId":"tool_delete_shared_report","summary":"Delete a shareable report","description":"Permanently deletes a saved shareable report and every client grant on it, breaking the shared link for anyone who still has it. Only reports owned by the authenticated user can be deleted. Find the id with list_shared_reports.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reportId":{"type":"string","format":"uuid"}},"required":["reportId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_report_clients":{"post":{"operationId":"tool_list_report_clients","summary":"List report clients","description":"Lists the client contacts on the account: the people who can be granted access to a shareable report. A client is just an email address (plus an optional name); they sign in with it to view reports shared with them. Use this to find a clientId for manage_report_access, or create_report_client to add a new contact.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":500,"default":100}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/create_report_client":{"post":{"operationId":"tool_create_report_client","summary":"Add a report client","description":"Adds a client contact (an email address, plus an optional name) that shareable reports can then be granted to with manage_report_access. Adding a client does NOT email them and does not give them access to anything on its own; it only creates the contact. Emails are stored lowercased and must be unique per account; adding an address that already exists returns the existing client rather than failing.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":255},"name":{"type":"string","minLength":1,"maxLength":200}},"required":["email"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/manage_report_access":{"post":{"operationId":"tool_manage_report_access","summary":"Grant or revoke report access","description":"Grants or revokes client access to a saved shareable report. This is what makes a report openable at all: an ungranted report opens for nobody, including the account owner. After granting, the client opens the report URL, enters their email, and GSC Wizard emails them a login link. That self-serve sign-in only works once they hold a grant. Clients must already exist on the account: add them with create_report_client, find ids with list_report_clients. NOTE: unlike the web app's share dialog, this tool does NOT itself send a \"report shared with you\" notification. Either pass the recipient the report URL, or send the notification from Account > Shared Reports in GSC Wizard (https://tool.gscwizard.com/account/shared-reports), where each client has a Resend button. action \"revoke\" withdraws access. Granting is idempotent: a client who already had access stays granted and is reported as unchanged.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reportId":{"type":"string","format":"uuid"},"action":{"type":"string","enum":["grant","revoke"]},"clientIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"description":"Client ids from list_report_clients / create_report_client."}},"required":["reportId","action","clientIds"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/set_dashboard_visibility":{"post":{"operationId":"tool_set_dashboard_visibility","summary":"Show or hide properties on the dashboard","description":"Shows or hides registered properties on the GSC Wizard dashboard, the same switch as the app's Dashboard Management page. Visibility is also what makes a property usable by the other MCP tools, so use this to bring a newly added property into scope. Showing a property consumes a dashboard slot from the plan and is refused when the plan limit is reached; ClickHouse-synced properties are always shown and consume no slot. Hiding a property only removes it from the workspace: no data is deleted, and it can be shown again at any time. The response reports slot usage before and after.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrls":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"maxItems":100,"description":"Registered property URLs, as returned by list_sites."},"visible":{"type":"boolean","description":"true = show on the dashboard (consumes a slot), false = hide."}},"required":["siteUrls","visible"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_migration_redirects":{"post":{"operationId":"tool_list_migration_redirects","summary":"List migration redirect mappings","description":"Lists the saved redirect mappings (old URL -> new URL) used by the Migration Compare report, newest first. Mappings are grouped by the A/B property pair they belong to and optionally by a label, so one account can hold several migrations at once. Pass `label` or `siteUrlA`/`siteUrlB` to narrow. Use `summaryOnly` to get just the per-migration counts instead of the rows, which is the right call on a large mapping.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200,"description":"Only mappings carrying this label."},"siteUrlA":{"type":"string","minLength":1,"description":"Only mappings whose source property is this."},"siteUrlB":{"type":"string","minLength":1,"description":"Only mappings whose target property is this."},"summaryOnly":{"type":"boolean","default":false,"description":"Return only the per-migration row counts, not the individual mappings."},"limit":{"type":"integer","minimum":1,"maximum":5000,"default":500}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/add_migration_redirects":{"post":{"operationId":"tool_add_migration_redirects","summary":"Add migration redirect mappings","description":"Saves redirect mappings (old URL -> new URL) for a site migration, tied to the source property A and target property B they move traffic between. These back the Migration Compare workflow: use compare_migration for the before/after performance read, and these mappings to record which old URL became which new one. Pass `label` to keep several migrations apart on one account. Rows are APPENDED, never deduplicated against what is already stored, so re-sending the same list stores it twice; clear a set first with delete_migration_redirects if you are re-uploading.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrlA":{"type":"string","minLength":1,"description":"Source property (the old site), as registered in GSC."},"siteUrlB":{"type":"string","minLength":1,"description":"Target property (the new site), as registered in GSC."},"redirects":{"type":"array","items":{"type":"object","properties":{"fromUrl":{"type":"string","minLength":1,"maxLength":2048,"description":"The old URL, as it was before the migration."},"toUrl":{"type":"string","minLength":1,"maxLength":2048,"description":"The new URL it now redirects to."}},"required":["fromUrl","toUrl"],"additionalProperties":false},"minItems":1,"maxItems":10000},"label":{"type":"string","minLength":1,"maxLength":200,"description":"Groups this batch, e.g. \"2026-blog-restructure\". Also what delete targets."}},"required":["siteUrlA","siteUrlB","redirects"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/delete_migration_redirects":{"post":{"operationId":"tool_delete_migration_redirects","summary":"Delete migration redirect mappings","description":"Permanently deletes saved redirect mappings. Narrow the deletion with `label` and/or the A/B property pair; to delete EVERY mapping on the account you must pass confirmDeleteAll: true, since an unnarrowed delete would also wipe unrelated migrations. Preview exactly what would go with list_migration_redirects using the same filters first.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200,"description":"Only mappings carrying this label."},"siteUrlA":{"type":"string","minLength":1,"description":"Only mappings whose source property is this."},"siteUrlB":{"type":"string","minLength":1,"description":"Only mappings whose target property is this."},"confirmDeleteAll":{"type":"boolean","default":false,"description":"Required when no label or property filter is given: deletes every mapping."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_indexnow_settings":{"post":{"operationId":"tool_get_indexnow_settings","summary":"Get IndexNow settings","description":"Reports whether IndexNow is set up for a property: whether an API key is configured (masked to its last four characters, the full key is never returned) AND whether the key file is actually reachable on the site. Both are required before search engines accept submissions. When keyFileVerified is false, keyFileUrl is the exact file the site owner must publish, containing the key and nothing else. keyFileVerified is null when the check was inconclusive (timeout or a bot rule), which is not a failure. Check here before submit_indexnow_urls and whenever a submission fails. When no key is set, call update_indexnow_settings with generateKey: true and publish the key file it returns.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/update_indexnow_settings":{"post":{"operationId":"tool_update_indexnow_settings","summary":"Set the IndexNow API key","description":"Sets, generates, rotates or clears the IndexNow API key for a property. The key is what search engines use to verify submissions from submit_indexnow_urls. To set IndexNow up, pass generateKey: true: a valid key is created and returned with keyFileUrl and keyFileContent. IMPORTANT: the site owner must then publish keyFileContent as a plain-text file at keyFileUrl (at the root of every host whose URLs will be submitted), or every submission is discarded. generateKey refuses to replace an existing key; to rotate, pass clear: true first. You can also pass your own indexnowApiKey (8-128 letters, digits and hyphens), for example one whose key file the site already publishes: the file is checked right after saving and keyFileVerified reports the result (true = ready to submit). Pass clear: true to remove the key, which disables IndexNow submissions for the property. Reading the key back later (get_indexnow_settings) only ever returns it masked.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"indexnowApiKey":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[a-zA-Z0-9-]+$","description":"The new key. Omit when using generateKey or clear."},"generateKey":{"type":"boolean","default":false,"description":"Create a new valid key and return the key file to publish. Only when the property has no key yet; clear the old key first to rotate."},"clear":{"type":"boolean","default":false,"description":"Remove the stored key instead of setting one. Disables IndexNow submissions."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/analyze_query_shapes":{"post":{"operationId":"tool_analyze_query_shapes","summary":"Query shape analysis (AI Mode fingerprints)","description":"Classifies a property's queries by SHAPE to surface the fingerprints of AI Overviews / AI Mode fan-out traffic (the app's Query Analysis report). Buckets: reply artefacts (\"yes\", \"show me\"), pivot follow-ups (\"what about gemini\"), conversational questions, LLM tracker probes, agent harnesses, pasted strings, long uncategorised, and conventional keywords. Returns per-bucket query/click/impression counts and shares, zero-click counts, average position, and top example queries, plus an `aiShaped` roll-up of the conversational buckets. Heuristic pattern matching in 27 languages: it judges how a query LOOKS, not what the searcher meant, so treat single rows as evidence rather than proof. Reads the ClickHouse warehouse when available, else the live Search Console API. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"examplesPerBucket":{"type":"integer","minimum":0,"maximum":100,"default":10,"description":"How many top example queries (by impressions) to return per bucket. 0 returns counts only."},"buckets":{"type":"array","items":{"type":"string","enum":["reply_artefact","pivot_follow_up","tracker_probe","agent_harness","search_operator","pasted_string","conversational_question","long_uncategorised","conventional"]},"maxItems":9,"description":"Optional. Only return these buckets, e.g. [\"reply_artefact\",\"pivot_follow_up\",\"conversational_question\"] for the AI-conversation shapes. Omit for all buckets."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_query_shape_trend":{"post":{"operationId":"tool_get_query_shape_trend","summary":"Query shape trend over time","description":"Tracks how much of a property's search traffic comes from AI-shaped queries over time: the trend chart on the app's Query Analysis report. Returns one row per month (or week) with clicks and impressions split into AI-shaped (reply artefacts, pivot follow-ups, conversational questions) versus conventional keywords, plus the AI-shaped share of each metric. Use this to answer \"are AI Overviews / AI Mode queries growing on this site?\", which no single-period report can show. Defaults to the last 12 complete months. Served from the GSC Wizard ClickHouse warehouse when available (longer history, no sampling), otherwise the live Search Console API.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1},"months":{"type":"integer","minimum":1,"maximum":16,"default":12,"description":"How many complete months to cover, ending with last month (1-16; Search Console keeps ~16 months)."},"granularity":{"type":"string","enum":["month","week"],"default":"month"},"searchType":{"type":"string","enum":["web","image","video","news"],"default":"web"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD. Provide BOTH startDate and endDate to override the default window, or omit both to use the last `months` complete months. Never pass null or \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD. Provide BOTH startDate and endDate to override the default window, or omit both to use the last `months` complete months. Never pass null or \"null\"."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/list_gmc_accounts":{"post":{"operationId":"tool_list_gmc_accounts","summary":"List Merchant Center accounts","description":"Lists every Google Merchant Center account readable by the connected Google accounts of the authenticated user, and which GSC Wizard sites each account is linked to (via `linkedSiteUrls`). Use it to discover the Merchant Center account id to link to a property, or to verify the Shopping setup of a site. `isAdvanced: true` marks a multi-client parent account: reporting runs against a standalone account or one of its sub-accounts, never the parent itself. `linkedSiteUrls` covers only the sites of the GSC Wizard account this connection is authenticated as (returned as `account`). `incomplete: true` means the list is a floor, not the whole set: `gaps` and `unprobedAccountIds` say what could not be read or checked for sub-accounts, and `errors` names each connected Google account whose listing failed; retry for a complete list. An empty result with `connected: false` carries a `reason`: \"no_scope\" means the Merchant Center consent has not been granted in the GSC Wizard app yet (connect Merchant Center at tool.gscwizard.com first); \"credentials_revoked\" means it was granted but Google now rejects the stored credentials, so the Google account has to be reconnected on the Account page. On a shared property, `linkedAccountId` is withheld (null, with a `note`) until the owner enables the Merchant Center opt-in on your invite.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"Optional property URL as returned by list_sites. When given, the response also reports which Merchant Center account is currently linked to that property (`linkedAccountId`)."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_organic_shopping_performance":{"post":{"operationId":"tool_get_organic_shopping_performance","summary":"Organic shopping performance","description":"Organic (free listing) product performance from the Google Merchant Center account linked to a GSC Wizard site: a daily clicks / impressions / conversions timeline plus the top offers, groupable by brand, Google category or merchant product type. Optionally includes the non-product timeline (category and home pages reached from Merchant Center surfaces). Merchant Center free-listing numbers cover the Shopping tab, Search, Images, Lens, YouTube and Maps, while Search Console merchant listings (get_merchant_listings_performance) counts enriched product results in web Search only, so the two do not reconcile to one figure. Conversions exist only where the merchant configured a Merchant Center conversion source. Returns a `notConfigured` result (not an error) when Merchant Center is not connected or no Merchant Center account is linked to the site in the GSC Wizard app. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"groupBy":{"type":"string","enum":["offer","brand","category","productType"],"default":"offer","description":"How the table rows are grouped: \"offer\" (one row per product / offer id, the default), \"brand\", \"category\" (Google product taxonomy level 1) or \"productType\" (the merchant's own taxonomy level 1)."},"limit":{"type":"integer","minimum":1,"maximum":200,"default":25,"description":"Table rows to return, ordered by organic clicks (default 25, max 200)."},"includeNonProduct":{"type":"boolean","default":true,"description":"Include the non-product timeline: clicks to category / home pages from Merchant Center surfaces, which never appear in the product numbers."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_product_listing_status":{"post":{"operationId":"tool_get_product_listing_status","summary":"Product free-listing status","description":"Free-listing eligibility and item issues per product, from the Google Merchant Center account linked to a GSC Wizard site, sorted by `clickPotentialRank` (1 = the product Google expects the most clicks from). Answers \"which products are invisible in free listings, and why\": each row carries the aggregated status (ELIGIBLE / ELIGIBLE_LIMITED / PENDING / NOT_ELIGIBLE_OR_DISAPPROVED), the free-listings status when the synced catalog has it, the top issue code and whether fixing it needs a merchant action or is just pending Google processing. `statusCounts`, `issueCounts`, `problemCount` and `merchantActionCount` (problems that need a feed or site fix) summarise the whole scan, not just the returned page; page through every row with `offset`, passing back `nextOffset` until it is null. Answered from the catalog snapshot GSC Wizard syncs daily into its warehouse when the site has one (`dataSource: \"clickhouse\"`, `syncedAt` says when, `stale: true` when it is more than two days old; every offer is counted), with a live Merchant API scan of up to 5,000 products as the fallback (`dataSource: \"merchant-api\"`, `truncated` when the catalog had more or Merchant Center was too slow to read it all within about 40 seconds; `truncationReason` says which). `itemIssuesUnavailable: true` means Google refused the issue data, so a missing issue code is unknown rather than clean. `syncPaused` (with a one-line `staleNote`) means the daily sync is paused because Merchant Center no longer lets the connected Google account read the merchant: the data is still returned but may be stale, and `syncPaused.message` says how to fix it. `syncNotice` (reason \"gmc_on_other_account\") means Merchant Center is connected on another Google login than the property's Search Console one, so the snapshot cannot refresh; the data is still returned. This is catalog state, not traffic: pair it with get_organic_shopping_performance for the clicks a product actually got. Returns a `notConfigured` result (not an error) when Merchant Center is not connected, its credentials were revoked, no Merchant Center account is linked to the site in the GSC Wizard app, or (reason \"gmc_on_other_account\") nothing was ever synced because Merchant Center sits on another Google login and no live read is possible.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"onlyProblems":{"type":"boolean","default":true,"description":"Return only products that are not plainly serving (limited, pending, disapproved, or carrying an item issue). Set false to list the whole catalog by click potential."},"limit":{"type":"integer","minimum":1,"maximum":200,"default":25,"description":"Product rows to return, highest click potential first (default 25, max 200)."},"offset":{"type":"integer","minimum":0,"maximum":100000,"default":0,"description":"Rows to skip, for reading past the first page: pass the previous answer's nextOffset (default 0, max 100,000)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_merchant_listings_performance":{"post":{"operationId":"tool_get_merchant_listings_performance","summary":"Merchant listings performance","description":"Search Console performance for one search appearance, defaulting to MERCHANT_LISTINGS: the appearance inventory of the property, a daily clicks / impressions / CTR / position timeline, and the top pages (product URLs) behind it. Answers \"how visible are my product results in Search, and which products carry it\". Search Console merchant listings counts enriched product results in web Search only, while Google Merchant Center free-listing numbers (get_organic_shopping_performance) cover the Shopping tab, Images, Lens, YouTube and Maps too, so the two do not reconcile to one figure. Always served from the live Search Console API: search appearance is never stored in the GSC Wizard warehouse, and it can be filtered on but never grouped with another dimension. `hasAppearance` is false when the property has no rows for the requested appearance, which is normal for non-ecommerce sites. The window may span at most 16 months (Search Console retention); a longer one is rejected with bad_request. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"appearance":{"type":"string","minLength":1,"default":"MERCHANT_LISTINGS","description":"Search appearance code to report on. Defaults to MERCHANT_LISTINGS; other common values are PRODUCT_SNIPPETS and ORGANIC_SHOPPING. Read `appearances` in the response to see which codes this property actually has."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":25,"description":"Top pages to return, ordered by clicks (default 25, max 1000)."},"includeAppearances":{"type":"boolean","default":true,"description":"Include the unfiltered per-appearance breakdown, which is the only way to learn which appearance codes the property has and how big each one is."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_gmc_competitors":{"post":{"operationId":"tool_get_gmc_competitors","summary":"Merchant Center competitors","description":"Competitive visibility from the Google Merchant Center account linked to a GSC Wizard site, for one (country, Google product category, traffic source) cell. \"competitor\" (default) returns one row per day per competing domain (rank, relativeVisibility, adsOrganicRatio, pageOverlapRate, higherPositionRate) plus a per-domain roll-up over the window; \"top_merchant\" returns one aggregate row per domain for the window (Google does not expose a date on that view); \"benchmark\" returns one row per day with yourDomainVisibilityTrend and categoryBenchmarkVisibilityTrend, both relative to the start of the window. relativeVisibility and adsOrganicRatio are RATIOS (200 = two hundred times as often as you); pageOverlapRate, higherPositionRate and the trends are 0-1 FRACTIONS as Google reports them (0.12 = 12%), not the 0-100 percentage ctr uses elsewhere in this server. countryCode (ISO 3166-1 alpha-2) and categoryId (Google product taxonomy id, digits) are both required because the Merchant API answers one cell per request. `reportUnavailable` (with no rows) means Google refuses this report for the Merchant Center account (eligibility); the other reports are unaffected. Returns a `notConfigured` result (not an error) when Merchant Center is not connected or no Merchant Center account is linked to the site in the GSC Wizard app. Date range is optional: omit startDate/endDate to analyze the last 28 settled days (data lags ~2-3 days).","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"view":{"type":"string","enum":["competitor","top_merchant","benchmark"],"default":"competitor","description":"\"competitor\" (daily rows per competing domain, the default), \"top_merchant\" (one aggregate row per domain for the window) or \"benchmark\" (daily trend of your domain against the category benchmark)."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Required. Report country as ISO 3166-1 alpha-2 (e.g. \"US\", \"NL\"). Case-insensitive."},"categoryId":{"type":"string","minLength":1,"maxLength":12,"description":"Required. Google product taxonomy id as a digits-only string (e.g. \"166\" for Apparel & Accessories, \"222\" for Electronics). Top-level ids work for every account."},"trafficSource":{"type":"string","enum":["ORGANIC","ADS","ALL"],"default":"ORGANIC","description":"\"ORGANIC\" (free listings, the default), \"ADS\" or \"ALL\"."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window start as YYYY-MM-DD (e.g. 2026-05-03). You do NOT need to know today's date. Omit BOTH startDate and endDate to analyze the last 28 settled days automatically (Search Console data lags ~2-3 days). Never pass null or the string \"null\"."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. Window end as YYYY-MM-DD (e.g. 2026-05-31). You do NOT need to know today's date or the latest available date: omit this and the server uses the latest settled Search Console date (data lags ~2-3 days behind today). Never pass null or the string \"null\"."},"limit":{"type":"integer","minimum":1,"maximum":200,"default":50,"description":"Rows to return, ordered by (date, rank, domain) (default 50, max 200). The per-domain roll-up in `domains` always covers every fetched row regardless of this cap."}},"required":["siteUrl","countryCode","categoryId"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_gmc_pricing_insights":{"post":{"operationId":"tool_get_gmc_pricing_insights","summary":"Merchant Center pricing insights","description":"Price competitiveness and sale-price suggestions from the Google Merchant Center account linked to a GSC Wizard site, joined per product: your price against the market benchmark for the same product (priceGapFraction, positive = you are more expensive), and Google's suggested sale price with the predicted change in impressions, clicks and conversions if you adopt it. Sort by \"opportunity\" (largest predicted clicks gain first, the default) or \"gap\" (largest absolute price gap first). Both views are dateless snapshots of the current catalog. All predicted*ChangeFraction and *Fraction fields are 0-1 FRACTIONS as Google reports them (0.12 = +12%), not the 0-100 percentage ctr uses elsewhere in this server. Benchmarks need valid GTINs and suggestions need conversion reporting, so an empty result usually means \"not eligible\", not \"no data\"; `reportUnavailable` (with no rows) means Google refuses the pricing report for the Merchant Center account outright, and the other reports are unaffected. Returns a `notConfigured` result (not an error) when Merchant Center is not connected or no Merchant Center account is linked to the site in the GSC Wizard app.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Optional. Restrict price benchmarks to one country (ISO 3166-1 alpha-2, e.g. \"US\"). Omit for every benchmark country; a product benchmarked in several countries then keeps its first benchmark and reports benchmarkCountryCode. Sale-price suggestions are never country-filtered."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Products to return after sorting (default 100, max 1000)."},"sort":{"type":"string","enum":["opportunity","gap"],"default":"opportunity","description":"\"opportunity\" (largest predictedClicksChangeFraction first, the default) or \"gap\" (largest absolute priceGapFraction first). Products without the sort key go last."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_gmc_best_sellers":{"post":{"operationId":"tool_get_gmc_best_sellers","summary":"Merchant Center best sellers","description":"Google's best sellers ranking for one country from the Google Merchant Center account linked to a GSC Wizard site: the most popular product clusters (\"product_cluster\", the default) or brands (\"brand\") per Google product category, with rank, previous rank, relative demand (VERY_LOW..VERY_HIGH), its direction (SINKER / FLAT / RISER) and, for product clusters, whether any of your offers matches (inventoryStatus). Each product-cluster row carries `demandGap`: true when Google ranks the cluster but you do not stock it, the classic assortment-gap signal; note that inventory status ignores the report country. Pick WEEKLY (Monday-dated) or MONTHLY (1st-dated) reports; omit reportDate for the newest report Google has published (reports lag up to two weeks). countryCode is required because the Merchant API answers one country per request; categoryId (Google product taxonomy id) narrows to one category, otherwise every top-level category is returned. `reportUnavailable` (with no rows) means Google refuses this report for the Merchant Center account (eligibility); the other reports are unaffected. Returns a `notConfigured` result (not an error) when Merchant Center is not connected or no Merchant Center account is linked to the site in the GSC Wizard app.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"view":{"type":"string","enum":["product_cluster","brand"],"default":"product_cluster","description":"\"product_cluster\" (ranked product clusters with title, category path, GTINs and your inventory status, the default) or \"brand\" (ranked brands, no inventory data)."},"granularity":{"type":"string","enum":["WEEKLY","MONTHLY"],"default":"WEEKLY","description":"\"WEEKLY\" (Monday-dated reports, the default) or \"MONTHLY\" (1st-of-month reports)."},"countryCode":{"type":"string","minLength":2,"maxLength":2,"description":"Required. Report country as ISO 3166-1 alpha-2 (e.g. \"US\", \"NL\"). Case-insensitive."},"categoryId":{"type":"string","minLength":1,"maxLength":12,"description":"Optional. Google product taxonomy id as a digits-only string (e.g. \"166\" for Apparel & Accessories). Omit for every top-level category."},"reportDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional. The report to read as YYYY-MM-DD: a Monday for WEEKLY, the 1st of a month for MONTHLY. Omit for the newest published report (recommended: reports lag up to two weeks). Never pass null or the string \"null\"."},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":100,"description":"Rows to return, ordered by (country, category, rank) (default 100, max 1000)."}},"required":["siteUrl","countryCode"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/run_feed_audit":{"post":{"operationId":"tool_run_feed_audit","summary":"Run feed audit","description":"Queues a Merchant Center feed audit for a GSC Wizard site: 21 deterministic checks over the synced product catalog (title and description length, duplicate titles / descriptions / images / URLs, GTIN, category, product type and required attributes, image size and ratio) plus a crawl of the product pages on the owner-approved host allowlist (HTTP status, JSON-LD Product schema, price and title consistency, H1 and title-element counts, page images missing from the feed), rolled up into a 0-100 Feed Score. The tool only ENQUEUES: the audit runs in the GSC Wizard app worker (the feed plane within minutes, the page crawl at a politeness-bounded pace over every distinct product URL, so a large catalog can take hours), and `enqueued: false` with a `skipReason` means a run is still in progress (`run_in_progress`, with the run summary in `run`), a run for today already exists, or one completed inside the 28-day cadence (pass force: true to override the cadence; the one-per-day rule cannot be overridden). Each user may start at most 3 runs per 24 hours (rate_limited beyond that; a call that queues nothing does not count). Poll get_feed_audit_results with the returned runDate for status and the score. Returns a `notConfigured` result (not an error) when Merchant Center is not connected, is connected on another Google login than the property's Search Console one (reason \"gmc_on_other_account\": the audit runs through the sync, which reads only through the Search Console account), its credentials were revoked, or no Merchant Center account is linked to the site in the GSC Wizard app. Requires full access on a shared property.\n\nRequires a write-scoped API key or the mcp:write OAuth scope.","tags":["Tools","Write"],"security":[{"bearerAuth":[]},{"oauth2":["mcp:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"force":{"type":"boolean","default":false,"description":"Queue an audit even when one completed inside the last 28 days (default false). Cannot bypass the one-audit-per-property-per-day rule or a run still in progress."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_feed_audit_results":{"post":{"operationId":"tool_get_feed_audit_results","summary":"Feed audit results","description":"Results of the Merchant Center feed audit for a GSC Wizard site: the latest run (or the run of a given runDate) with its status, Feed Score (0-100, split into scoreFeed and scorePage), failure counts by severity, per-check applicable / failed / passed counts with pass rates, offers audited, pages fetched and crawl coverage, plus the score history of earlier runs for the trend. coverage and the rates are 0-1 fractions (0.12 = 12%), not the 0-100 percentage ctr uses elsewhere. checkKey narrows the checks list to one check; severity is accepted for parity with the app report, but the per-offer issue rows behind either filter live in the ClickHouse warehouse this server cannot read, so such a call answers `issuesAvailable: false` with a pointer at the Feed Audit report in the GSC Wizard app. `run.crawlBlocked: true` means the page crawl stopped early because the site refused GSCWizard-Bot (401/403 or robots.txt), so the page-plane checks and scorePage cover few or no pages; allow the crawler and queue a new run. `run: null` means no audit has run yet (queue one with run_feed_audit). `syncPaused` (with a one-line `staleNote`) means the Merchant Center sync is paused because Merchant Center no longer lets the connected Google account read the merchant: the stored results are still returned but may be stale, and `syncPaused.message` says how to fix it. `syncNotice` (reason \"gmc_on_other_account\") means Merchant Center is connected on another Google login than the property's Search Console one, so no new audit can run; stored results are still returned. Returns a `notConfigured` result (not an error) when Merchant Center is not connected, its credentials were revoked, no Merchant Center account is linked to the site, or (reason \"gmc_on_other_account\") no audit was ever stored because Merchant Center sits on another Google login.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"runDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Optional run date (YYYY-MM-DD, the runDate returned by run_feed_audit). Omit for the latest run."},"checkKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$","description":"Optional check key to narrow the checks list to (e.g. \"title_length\", \"jsonld_product_schema\", \"price_mismatch\"). Per-offer issues for it are not readable here (see issuesAvailable)."},"severity":{"type":"string","enum":["critical","warning","info"],"description":"Optional severity filter (\"critical\", \"warning\" or \"info\") for the per-offer issue list, which this server cannot serve (see issuesAvailable); accepted for parity with the app report."},"limit":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Maximum checks rows to return (default 100, max 500). Reserved for the per-offer issue list once a warehouse reader exists; the checks list never exceeds 21 rows."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tools/get_gmc_title_hygiene":{"post":{"operationId":"tool_get_gmc_title_hygiene","summary":"Merchant Center title hygiene","description":"Title and description hygiene of the product catalog in the Google Merchant Center account linked to a GSC Wizard site: title length distribution (0-29 / 30-69 / 70-150 / 151+ characters), description length distribution (0-49 / 50-499 / 500-5000 / 5001+) and how many offers have no description, mean and median title length, duplicate titles (offers sharing the same normalised title, largest groups first), offers whose title repeats a word, and the most frequent title words with brand tokens flagged. Computed over a sample of the live catalog: the first `limit` products in feed order (default 2000, max 5000); `truncated: true` means the catalog had more. `topWords[].share` is a 0-1 FRACTION of the sampled offers, not the 0-100 ctr percentage; lengths are in characters, CJK titles included. A catalog snapshot, so it takes no date range. Returns a `notConfigured` result (not an error) when Merchant Center is not connected or no Merchant Center account is linked to the site in the GSC Wizard app.","tags":["Tools","Read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteUrl":{"type":"string","minLength":1,"description":"The property URL as returned by list_sites (e.g. \"sc-domain:example.com\")."},"limit":{"type":"integer","minimum":1,"maximum":5000,"default":2000,"description":"Products to sample from the catalog, in feed order (default 2000, max 5000). The summary describes this sample; truncated says when the catalog had more."},"topWords":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Most frequent title words to return (default 50, max 100)."}},"required":["siteUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"The tool result object.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid parameters (validation failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active subscription or the trial has ended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or access to the property is not granted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown tool or route","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-account REST rate limit exceeded (180/min, 2,000/hour; see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Upstream (Google / warehouse) error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A gscw_live_... API key issued in the GSC Wizard app."},"oauth2":{"type":"oauth2","description":"OAuth 2.1 authorization code flow with PKCE (S256). Clients can register dynamically at https://tool.gscwizard.com/api/oauth/register (RFC 7591).","flows":{"authorizationCode":{"authorizationUrl":"https://tool.gscwizard.com/oauth/authorize","tokenUrl":"https://tool.gscwizard.com/api/oauth/token","refreshUrl":"https://tool.gscwizard.com/api/oauth/token","scopes":{"mcp:read":"Read Search Console, GA4 and other connected data","mcp:write":"Read, plus write tools (annotations, saved filters, sitemaps, IndexNow, ...)"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine code: bad_request, unauthorized, forbidden, not_found, rate_limited, upstream_error, or internal_error."},"message":{"type":"string"}}}}}}}}