AutomationFlowsWeb Scraping › Expose a Full Google Search Console SEO Toolkit Over Mcp

Expose a Full Google Search Console SEO Toolkit Over Mcp

BySalman Mehboob @salmanmehboob on n8n.io

Turn n8n into a Google Search Console MCP server. This workflow exposes 18 tools any MCP client (Claude, Cursor, etc.) can call — search analytics, URL inspection, sitemaps, the Indexing API, site verification, ownership management, and PageSpeed / Core Web Vitals — all through…

Event trigger★★★★☆ complexityAI-powered26 nodesMcp TriggerHTTP Request Tool
Web Scraping Trigger: Event Nodes: 26 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #17736 — we link there as the canonical source.

This workflow follows the HTTP Request Tool → Mcptrigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "4Q8wkpV1YDNRwsQC",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true,
    "templateCredsSetupCompleted": true
  },
  "name": "Google Search Console MCP",
  "tags": [
    {
      "id": "1o9SYcsyY3Rtn8Dj",
      "name": "gsc-mcp",
      "createdAt": "2026-07-25T12:15:20.667Z",
      "updatedAt": "2026-07-25T12:15:20.667Z"
    }
  ],
  "nodes": [
    {
      "id": "a47fb8a7-dc6e-4119-91a8-3ddf8a639f22",
      "name": "GSC MCP Server",
      "type": "@n8n/n8n-nodes-langchain.mcpTrigger",
      "position": [
        -432,
        -3168
      ],
      "parameters": {
        "path": "gsc-mcp"
      },
      "typeVersion": 2
    },
    {
      "id": "d5a2659a-1156-4ae7-9fde-4527022fc912",
      "name": "gsc_list_sites",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -2080,
        -2176
      ],
      "parameters": {
        "url": "https://www.googleapis.com/webmasters/v3/sites",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "List all Google Search Console properties (sites) the connected account can access. Returns each property URL and its permission level. Takes no input.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "9e8683b3-fce6-4a3f-bb98-e84863abb5dd",
      "name": "gsc_query_search_analytics",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        1184,
        -2144
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property, e.g. https://example.com/ or sc-domain:example.com\")) }}/searchAnalytics/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ (function(){ var dims = ($fromAI(\"dimensions\", \"Comma-separated dimensions to group by (query, page, country, device, date, searchAppearance). Empty = totals only.\") || \"\").split(\",\").map(function(s){ return s.trim(); }).filter(function(x){ return x; }); var body = { startDate: $fromAI(\"startDate\", \"Start date YYYY-MM-DD\"), endDate: $fromAI(\"endDate\", \"End date YYYY-MM-DD\"), rowLimit: Number($fromAI(\"rowLimit\", \"Max rows to return, default 25, max 25000 - keep small to save tokens\", \"number\")) || 25, startRow: Number($fromAI(\"startRow\", \"Row offset for pagination, default 0\", \"number\")) || 0, dataState: \"final\" }; if (dims.length) { body.dimensions = dims; } var fd = $fromAI(\"filterDimension\", \"Optional server-side filter dimension: query, page, country, or device (empty for none)\"); var fe = $fromAI(\"filterExpression\", \"Optional filter value to match, used with filterDimension\"); if (fd && fe) { var op = $fromAI(\"filterOperator\", \"Filter operator: contains, equals, notContains, includingRegex, excludingRegex (default contains)\") || \"contains\"; body.dimensionFilterGroups = [{ filters: [{ dimension: fd, operator: op, expression: fe }] }]; } return JSON.stringify(body); })() }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "toolDescription": "Query Google Search Console Search Analytics. Returns clicks, impressions, CTR, avg position. Inputs: siteUrl; startDate & endDate (YYYY-MM-DD); dimensions (comma-separated: query, page, country, device, date, searchAppearance; empty = totals); rowLimit (default 25 - keep small to save tokens); startRow (paging offset). OPTIONAL server-side filter: set filterDimension (query/page/country/device) + filterExpression + filterOperator (contains/equals/notContains/includingRegex/excludingRegex) so Google returns only matching rows (e.g. brand queries, or one page's queries). NOTE: Google CANNOT filter by position/CTR/impressions (metrics) - to find e.g. position 10-20 or low CTR, request the rows and filter them in your own analysis.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "9f83b9c5-be6e-4afb-a46f-c6ead5e57f58",
      "name": "gsc_inspect_url",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        912,
        -2144
      ],
      "parameters": {
        "url": "https://searchconsole.googleapis.com/v1/urlInspection/index:inspect",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ inspectionUrl: $fromAI(\"inspectionUrl\", \"The fully-qualified URL to inspect, e.g. https://example.com/page\"), siteUrl: $fromAI(\"siteUrl\", \"The GSC property the URL belongs to, e.g. https://example.com/ or sc-domain:example.com\") }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "toolDescription": "Inspect a URL with the Google Search Console URL Inspection API. Returns index status, coverage state, last crawl time, canonical URLs, mobile usability and rich-results verdicts.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "afddb4e1-8bc2-4b9b-8b27-5a426f0c129d",
      "name": "gsc_get_site",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -1952,
        -2176
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property, e.g. https://example.com/ or sc-domain:example.com\")) }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "Get details for a single Google Search Console property, including the account's permission level. Input: siteUrl.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "b0428ca0-a1a1-4742-a914-fe76da54fd18",
      "name": "gsc_add_site",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -1824,
        -2176
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property to add, e.g. https://example.com/ or sc-domain:example.com\")) }}",
        "method": "PUT",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "WRITE: Add (and begin verification of) a property in Google Search Console. Input: siteUrl. Requires write permission on the account.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "aa25facd-4f88-4d49-99cb-6e3d85f7fd95",
      "name": "gsc_delete_site",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -1696,
        -2176
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property to remove, e.g. https://example.com/ or sc-domain:example.com\")) }}",
        "method": "DELETE",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "WRITE: Remove a property from this Search Console account. Input: siteUrl. Removes the account's access to the property.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "82c25b62-1fa7-491a-ad88-8fe55ff2d7b8",
      "name": "gsc_list_sitemaps",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -496,
        -2112
      ],
      "parameters": {
        "url": "={{ (function(){ var si = $fromAI(\"sitemapIndex\", \"Optional. A sitemap INDEX url (e.g. https://example.com/sitemap_index.xml) to list ITS child sitemaps. Leave empty to list the property's top-level sitemaps.\"); var base = \"https://www.googleapis.com/webmasters/v3/sites/\" + encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property, e.g. https://example.com/ or sc-domain:example.com\")) + \"/sitemaps\"; return si ? base + \"?sitemapIndex=\" + encodeURIComponent(si) : base; })() }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "List sitemaps for a property. Call with only siteUrl to get top-level sitemaps (each sitemap index + its status: errors, warnings, lastDownloaded, contents). To get the CHILD/sub-sitemaps of an index, call again with sitemapIndex set to that index's URL. Combine both to present the full main+children tree with per-sitemap status.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "d8b1debc-8886-42ed-a901-e6784b1b7341",
      "name": "gsc_get_sitemap",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -336,
        -2112
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property, e.g. https://example.com/\")) }}/sitemaps/{{ encodeURIComponent($fromAI(\"sitemapUrl\", \"Full sitemap URL, e.g. https://example.com/sitemap.xml\")) }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "Get details for one submitted sitemap (status, contents, errors, warnings). Inputs: siteUrl, sitemapUrl (full sitemap URL).",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "48b380c3-b94f-476e-8723-a374d883bbaa",
      "name": "gsc_submit_sitemap",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -176,
        -2112
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property, e.g. https://example.com/\")) }}/sitemaps/{{ encodeURIComponent($fromAI(\"sitemapUrl\", \"Full sitemap URL to submit, e.g. https://example.com/sitemap.xml\")) }}",
        "method": "PUT",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "WRITE: Submit a sitemap to Google for a property. Inputs: siteUrl, sitemapUrl. Works for both the main sitemap index AND individual child/sub-sitemaps. Re-submitting an existing sitemap is safe and idempotent, and forces a fresh crawl.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "458b5060-c0a5-4661-b408-749f21adad97",
      "name": "gsc_delete_sitemap",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        0,
        -2112
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/webmasters/v3/sites/{{ encodeURIComponent($fromAI(\"siteUrl\", \"The GSC property, e.g. https://example.com/\")) }}/sitemaps/{{ encodeURIComponent($fromAI(\"sitemapUrl\", \"Full sitemap URL to delete, e.g. https://example.com/sitemap.xml\")) }}",
        "method": "DELETE",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "WRITE: Remove a submitted sitemap (index OR child/sub-sitemap) from a property. Inputs: siteUrl, sitemapUrl. PROTOCOL: before deleting, first call gsc_list_sitemaps (and drill into the index for its children) to show the user what exists, then confirm the exact sitemapUrl to delete. Note: deleting a child still referenced by the sitemap index may be re-discovered by Google on the next index read.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "f58f8319-9b11-452b-835d-701b096da8d8",
      "name": "gsc_indexing_publish",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        224,
        -2144
      ],
      "parameters": {
        "url": "https://indexing.googleapis.com/v3/urlNotifications:publish",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ url: $fromAI(\"url\", \"The URL to notify Google about\"), type: $fromAI(\"type\", \"Notification type: URL_UPDATED or URL_DELETED\") }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "toolDescription": "WRITE: Notify Google (Indexing API) that a URL was updated or deleted. Inputs: url, type (URL_UPDATED or URL_DELETED). Requires the Indexing API enabled and the service account added as an Owner of the property.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "39457f00-a289-4ffc-8620-3292e1d5e7fc",
      "name": "gsc_indexing_get_metadata",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        608,
        -2144
      ],
      "parameters": {
        "url": "=https://indexing.googleapis.com/v3/urlNotifications/metadata?url={{ encodeURIComponent($fromAI(\"url\", \"The URL to check indexing metadata for\")) }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "Get the latest Indexing API notification metadata for a URL (the last update/delete Google received). Input: url. Requires the Indexing API enabled and the service account added as an Owner.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "4452e20a-476e-4250-8b5c-e630a07ba1ef",
      "name": "gsc_indexing_batch_publish",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        416,
        -2144
      ],
      "parameters": {
        "url": "https://indexing.googleapis.com/batch",
        "body": "={{ (function(){ var b = \"gsc_batch_boundary\"; var NL = String.fromCharCode(13,10); var t = $fromAI(\"type\", \"Notification type applied to ALL urls: URL_UPDATED (new/changed page) or URL_DELETED (removed page)\"); var urls = ($fromAI(\"urls\", \"Comma-separated list of URLs to notify Google about (max 100)\") || \"\").split(\",\").map(function(s){ return s.trim(); }).filter(function(x){ return x; }); var parts = urls.map(function(u, i){ var payload = JSON.stringify({ url: u, type: t }); return \"--\" + b + NL + \"Content-Type: application/http\" + NL + \"Content-ID: <item\" + (i + 1) + \">\" + NL + NL + \"POST /v3/urlNotifications:publish\" + NL + \"Content-Type: application/json\" + NL + NL + payload + NL; }); return parts.join(\"\") + \"--\" + b + \"--\"; })() }}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "authentication": "predefinedCredentialType",
        "rawContentType": "multipart/mixed; boundary=gsc_batch_boundary",
        "toolDescription": "WRITE (bulk): Notify Google's Indexing API about MANY URLs at once (up to 100) in one batch request. Inputs: urls (comma-separated list of URLs, max 100) and type (URL_UPDATED for new/changed pages, or URL_DELETED to remove). Requires the Indexing API enabled + the service account as a property Owner. Note: the Indexing API is officially intended for JobPosting/BroadcastEvent pages.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "74705130-0764-4b03-bffe-b7d5523ab57d",
      "name": "gsc_get_verification_token",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -1536,
        -2176
      ],
      "parameters": {
        "url": "https://www.googleapis.com/siteVerification/v1/token",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ verificationMethod: $fromAI(\"method\", \"Verification method: FILE, META, or DNS_TXT\"), site: { type: $fromAI(\"siteType\", \"SITE for a URL-prefix property (https://example.com/), or INET_DOMAIN for a domain property (example.com)\"), identifier: $fromAI(\"identifier\", \"Site identifier: full URL ending in / for SITE, or bare domain for INET_DOMAIN\") } }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "toolDescription": "Get a Google site-ownership verification token. Inputs: siteType (SITE = URL-prefix like https://example.com/ ; INET_DOMAIN = domain like example.com), identifier, method. METHOD RULES: INET_DOMAIN (domain) supports ONLY DNS_TXT; SITE (URL-prefix) supports META, FILE, or DNS_TXT. Returns {method, token}. Where the user must place it: DNS_TXT -> add as a DNS TXT record on the domain (NOT the page head); META -> paste the returned meta tag into the homepage <head>; FILE -> upload an HTML file named/containing the token at the site root. After it is placed, call verify_site with the SAME siteType, identifier and method.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "78fd614d-e617-4591-ab7a-9c1ca3525001",
      "name": "gsc_verify_site",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -1376,
        -2176
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/siteVerification/v1/webResource?verificationMethod={{ encodeURIComponent($fromAI(\"method\", \"The SAME verification method used with get_verification_token: FILE, META, or DNS_TXT\")) }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ site: { type: $fromAI(\"siteType\", \"SITE or INET_DOMAIN\"), identifier: $fromAI(\"identifier\", \"Full URL ending in / for SITE, or bare domain for INET_DOMAIN\") } }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "toolDescription": "Verify site ownership AFTER the token (from get_verification_token) has been placed on the site. Inputs: siteType (SITE or INET_DOMAIN), identifier, method (the SAME method used for get_verification_token; remember INET_DOMAIN supports only DNS_TXT). On success the SERVICE ACCOUNT becomes a verified owner -- this is for AUTOMATION (lets this MCP operate on the site, including the Indexing API). It does NOT give any human dashboard access; a person must add/verify themselves in the Search Console UI. Returns the webResource {id, site, owners}.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "d3e42946-c3f3-410e-bde7-0c4043fa1494",
      "name": "gsc_list_owners",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -1072,
        -2160
      ],
      "parameters": {
        "url": "https://www.googleapis.com/siteVerification/v1/webResource",
        "options": {},
        "authentication": "predefinedCredentialType",
        "toolDescription": "List the VERIFICATION owners of each site/domain the service account has verified. This is Google's site-OWNERSHIP list, which is NOT the same as Search Console 'Users and permissions'. Returns each property's owners plus its webResource id. ALWAYS call this before set_owners to get the exact id and the CURRENT complete owners list. Also use it to confirm the service account is an owner of a site (required for the Indexing API). NOTE: Search Console Full/Restricted USERS cannot be listed via any API -- this returns verification owners only.",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "c2c67e97-68b8-47b8-91fa-8663f445b1da",
      "name": "gsc_set_owners",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        -800,
        -2144
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/siteVerification/v1/webResource/{{ $fromAI(\"id\", \"The webResource id of the target property, copied exactly from list_owners\") }}",
        "method": "PUT",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ id: $fromAI(\"id\", \"The webResource id of the target property, copied exactly from list_owners\"), site: { type: $fromAI(\"siteType\", \"SITE or INET_DOMAIN\"), identifier: $fromAI(\"identifier\", \"Full URL ending in / for SITE, or bare domain for INET_DOMAIN\") }, owners: ($fromAI(\"owners\", \"COMPLETE comma-separated list of ALL owner emails to KEEP. Include every current owner from list_owners, plus or minus your one change. Any email omitted will be REMOVED.\") || \"\").split(\",\").map(function(s){ return s.trim(); }).filter(function(x){ return x; }) }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "toolDescription": "WRITE (owners): Overwrite the COMPLETE verified-owners list of a property (Google site-OWNERSHIP list). Use to (a) ADD an owner (a person or the service account), or (b) REMOVE an owner. GRANTING ACCESS: adding a person's email makes them a delegated OWNER; that person then gets full Search Console access by opening THEIR OWN Search Console > Add property > entering the site URL, which AUTO-VERIFIES instantly (no file/tag needed since they are already an owner) and shows as Owner in the dashboard. So this DOES grant real dashboard access (OWNER level). Note: Search Console Full/Restricted USER levels are a separate system with no API. REMOVAL: works for delegated owners; a VERIFIED owner that still has a verification token on the site (meta/HTML/GA/GTM/DNS) CANNOT be removed until that token is taken off the site (Google blocks it). MANDATORY SAFE PROTOCOL: (1) ALWAYS call list_owners immediately before, to get the property id and CURRENT full owners list. (2) To ADD: owners = every current owner + the new email. To REMOVE: owners = every current owner EXCEPT the one to remove. (3) NEVER send a partial list -- ANY omitted owner is permanently removed. Inputs: id (from list_owners), siteType, identifier, owners (complete comma-separated list).",
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        },
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "5f4205c3-d70b-4788-9d87-b76ed9b2bea3",
      "name": "gsc_pagespeed_analyze",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        1472,
        -2144
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={{ encodeURIComponent($fromAI(\"url\", \"The full page URL to analyze, e.g. https://example.com/page\")) }}&strategy={{ $fromAI(\"strategy\", \"mobile or desktop (default mobile)\") || \"mobile\" }}",
        "fields": "id,loadingExperience,lighthouseResult.categories.performance.score",
        "options": {},
        "authentication": "predefinedCredentialType",
        "fieldsToInclude": "selected",
        "toolDescription": "Analyze a page's speed + Core Web Vitals via Google PageSpeed Insights. Inputs: url (full page URL), strategy (mobile or desktop, default mobile). Returns real-user Core Web Vitals (LCP, INP, CLS) and a performance score. Public API - no Search Console auth needed. Response is trimmed to the key metrics to save tokens.",
        "optimizeResponse": true,
        "nodeCredentialType": "googleOAuth2Api"
      },
      "credentials": {
        "googleOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "904d1976-2902-4a74-9b5d-8cef32cd1967",
      "name": "Group: Site management",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2160,
        -2480
      ],
      "parameters": {
        "color": 7,
        "width": 948,
        "height": 500,
        "content": "## Site management\nAdd, verify & manage properties.\n\n\u2022 gsc_list_sites \u2014 all properties you can access (+ permission)\n\u2022 gsc_get_site \u2014 details + permission for one property\n\u2022 gsc_add_site \u2014 add a new property (unverified) \u270d\ufe0f\n\u2022 gsc_delete_site \u2014 remove a property from the account \u270d\ufe0f\n\u2022 gsc_get_verification_token \u2014 FILE/META/DNS_TXT token to prove ownership\n\u2022 gsc_verify_site \u2014 verify ownership after placing the token \u2192 Owner \u270d\ufe0f"
      },
      "typeVersion": 1
    },
    {
      "id": "d8de4b68-49f7-43fb-a7ef-e746e0bde11c",
      "name": "Group: Ownership & access",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -2480
      ],
      "parameters": {
        "color": 7,
        "width": 644,
        "height": 506,
        "content": "##  Ownership & access\nWho owns a property (owner = full dashboard access).\n\n\u2022 gsc_list_owners \u2014 verification owners + webResource id per property\n\u2022 gsc_set_owners \u2014 overwrite the owners list to ADD/REMOVE an owner \u270d\ufe0f\n\nTip: an added person opens THEIR Search Console \u2192 Add property \u2192 it auto-verifies them as Owner."
      },
      "typeVersion": 1
    },
    {
      "id": "c94f29ec-8c11-470f-951f-ae141c5ead74",
      "name": "Group: Sitemaps",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -2480
      ],
      "parameters": {
        "color": 7,
        "width": 692,
        "height": 512,
        "content": "##  Sitemaps\nSubmit & monitor sitemaps (index + children).\n\n\u2022 gsc_list_sitemaps \u2014 top-level OR an index's child sitemaps + status\n\u2022 gsc_get_sitemap \u2014 full status of ONE sitemap (errors, warnings, contents)\n\u2022 gsc_submit_sitemap \u2014 submit/re-submit, forces a fresh crawl \u270d\ufe0f\n\u2022 gsc_delete_sitemap \u2014 remove a sitemap submission \u270d\ufe0f"
      },
      "typeVersion": 1
    },
    {
      "id": "ea9163f6-83ab-4058-8429-dde131721525",
      "name": "Group: Indexing API",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -2480
      ],
      "parameters": {
        "color": 7,
        "width": 628,
        "height": 512,
        "content": "##  Indexing\nPush (re)crawl / removal notices to Google.\nNeeds the account to be an Owner + the indexing scope.\n\n\u2022 gsc_indexing_publish \u2014 notify Google ONE URL updated/deleted \u270d\ufe0f\n\u2022 gsc_indexing_batch_publish \u2014 bulk, up to 100 URLs at once \u270d\ufe0f\n\u2022 gsc_indexing_get_metadata \u2014 last indexing notice for a URL (404 = none yet)"
      },
      "typeVersion": 1
    },
    {
      "id": "b019a912-846d-4776-8ff4-c355a57663d1",
      "name": "Group: Inspection & Analytics",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -2480
      ],
      "parameters": {
        "color": 7,
        "width": 940,
        "height": 512,
        "content": "##  Inspection & Analytics\nPerformance + index status + speed.\n\n\u2022 gsc_inspect_url \u2014 index status, coverage, canonical, mobile, rich results\n\u2022 gsc_query_search_analytics \u2014 clicks/impr/CTR/position by query/page/country/device/date; server-side filters + paging\n\u2022 gsc_pagespeed_analyze \u2014 Core Web Vitals + performance score (mobile/desktop)"
      },
      "typeVersion": 1
    },
    {
      "id": "251bfb31-9a51-43a7-8378-650e001f8dc2",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2768,
        -3376
      ],
      "parameters": {
        "width": 560,
        "height": 1504,
        "content": "# \ud83d\udd0d Google Search Console MCP - Full SEO Toolkit\n\nTurn n8n into a **Google Search Console MCP server**. Connect Claude / Cursor / any\nMCP client and get **18 SEO tools** \u2014 search analytics, URL inspection, sitemaps,\nthe Indexing API, site verification, ownership management, and PageSpeed / Core Web\nVitals \u2014 all under your own Google account.\n\n## \u2699\ufe0f How it works\n1. The **MCP Server Trigger** exposes this workflow as an MCP endpoint (one URL).\n2. Every tool is an **HTTP Request Tool** calling a Google API, all using **one**\n   Google credential.\n3. Point your MCP client at the endpoint URL \u2192 all 18 tools appear automatically.\n\n## \ud83d\udee0\ufe0f Setup (~10 min)\n1. **Google Cloud** \u2192 enable these APIs: Google Search Console API,\n   Web Search Indexing API, Site Verification API, PageSpeed Insights API.\n2. **Create a credential** \u2014 either a **Google OAuth2** credential (acts as you \u2192\n   you see everything in your own Search Console) or a **Service Account** (headless).\n   Scopes required:\n   \u2022 https://www.googleapis.com/auth/webmasters\n   \u2022 https://www.googleapis.com/auth/indexing\n   \u2022 https://www.googleapis.com/auth/siteverification\n   \u2022 openid   \u2190 needed for the PageSpeed tool\n3. **Select that credential** on every tool node (they all share one).\n4. Make your account / service account an **Owner** of the property\n   (required for the Indexing API).\n5. **Publish**, open the **MCP Server Trigger**, copy the **MCP URL**, add it in\n   your MCP client. Done.\n\n## \ud83e\uddf0 The 18 tools\n\ud83c\udfe0 Site management \u2014 list_sites, get_site, add_site, delete_site,\n     get_verification_token, verify_site\n\ud83d\udc65 Ownership & access \u2014 list_owners, set_owners\n\ud83d\uddfa\ufe0f Sitemaps \u2014 list_sitemaps, get_sitemap, submit_sitemap, delete_sitemap\n\u26a1 Indexing API \u2014 indexing_publish, indexing_batch_publish, indexing_get_metadata\n\ud83d\udd0d Inspection & Analytics \u2014 inspect_url, query_search_analytics (dimension filters +\n     paging), pagespeed_analyze (Core Web Vitals)\n\n## \ud83d\udcdd Good to know\n\u2022 Google can't filter analytics by position/CTR (they're metrics) \u2014 request rows and\n  filter those in your analysis (e.g. \"position 10\u201320\").\n\u2022 Indexing API is officially for JobPosting/BroadcastEvent; for normal pages it acts\n  as a recrawl nudge.\n\u2022 Search Console \"Full/Restricted USERS\" have no API \u2014 only OWNERS are API-manageable.\n\u2022 Adding an owner grants real access: they open their own Search Console \u2192 Add\n  property \u2192 it auto-verifies them as Owner.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "279efea9-a64c-4fdf-852b-e86b96466c29",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        -3056
      ],
      "parameters": {
        "width": 704,
        "height": 464,
        "content": "# Tutorial and Setup Guide\n\n@[youtube](UA_4rYF33k8)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "fb1fb944-445b-42b4-95c5-5ed7aa6cee9d",
  "nodeGroups": [],
  "connections": {
    "gsc_add_site": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_get_site": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_list_sites": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_set_owners": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_delete_site": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_get_sitemap": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_inspect_url": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_list_owners": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_verify_site": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_list_sitemaps": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_delete_sitemap": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_submit_sitemap": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_indexing_publish": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_pagespeed_analyze": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_indexing_get_metadata": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_get_verification_token": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_indexing_batch_publish": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gsc_query_search_analytics": {
      "ai_tool": [
        [
          {
            "node": "GSC MCP Server",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Turn n8n into a Google Search Console MCP server. This workflow exposes 18 tools any MCP client (Claude, Cursor, etc.) can call — search analytics, URL inspection, sitemaps, the Indexing API, site verification, ownership management, and PageSpeed / Core Web Vitals — all through…

Source: https://n8n.io/workflows/17736/ — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

Need help? Want access to this workflow + many more paid workflows + live Q&A sessions with a top verified n8n creator?

Mcp Trigger, HTTP Request Tool
Web Scraping

Need help? Want access to this workflow + many more paid workflows + live Q&A sessions with a top verified n8n creator?

Mcp Trigger, HTTP Request Tool
Web Scraping

This workflow exposes Google Blogger API operations as an MCP server endpoint so an AI agent (for example, Claude) can create, update, publish, search, and delete Blogger posts, manage static pages an

Mcp Trigger, HTTP Request Tool
Web Scraping

Complete MCP server exposing 21 api.clarify.io API operations to AI agents.

Mcp Trigger, HTTP Request Tool
Web Scraping

Complete MCP server exposing 9 NPR Listening Service API operations to AI agents.

Mcp Trigger, HTTP Request Tool