@digestseo/mcp-gsc 0.4.34 → 0.4.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +5 -1
- package/package.json +1 -1
- package/src/google.ts +4 -5
- package/src/index.ts +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.35] - 2026-09-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Search Analytics pagination now treats provider responses shorter than the requested page size as terminal, matching Google's documented contract and avoiding false continuations or unnecessary follow-up requests across direct and higher-level workflows.
|
|
14
|
+
- `insights.page_queries` now rejects exact page URLs outside the supplied Search Console property before reserving local Search Analytics safety budget, resolving Google credentials, or calling the provider, preventing misleading empty cross-property drilldowns.
|
|
15
|
+
|
|
10
16
|
## [0.4.34] - 2026-09-24
|
|
11
17
|
|
|
12
18
|
### Fixed
|
package/README.md
CHANGED
|
@@ -66,6 +66,8 @@ Codex CLI and the Codex IDE extension share MCP configuration, so registering th
|
|
|
66
66
|
|
|
67
67
|
When this repository is installed as a Cursor plugin, Cursor also auto-discovers three bundled Agent Skills that compose the MCP tools into evidence-safe workflows: `gsc-weekly-review`, `gsc-indexing-triage`, and `gsc-search-opportunities`. The **Add to Cursor** button above installs the MCP connection only; the bundled skills are part of the repository's Cursor plugin package.
|
|
68
68
|
|
|
69
|
+
The button and plugin MCP configuration above are for Cursor running on the same machine as the npm launcher. **Cursor Cloud Agents run in isolated cloud VMs, so they cannot reach `127.0.0.1` on your computer.** For Cloud Agents, deploy your own externally reachable HTTPS Worker and add its `/mcp` URL from the MCP controls at [cursor.com/agents](https://cursor.com/agents); Cursor supports HTTP MCP servers and OAuth there. Do not reuse the loopback URL for a Cloud Agent.
|
|
70
|
+
|
|
69
71
|
**GitHub Copilot CLI**
|
|
70
72
|
|
|
71
73
|
```bash
|
|
@@ -89,7 +91,9 @@ The Gemini CLI extension bundles the verified local loopback MCP configuration p
|
|
|
89
91
|
|
|
90
92
|
Start the npm launcher before using either install button or the Copilot plugin. Complete its Google OAuth flow on first use.
|
|
91
93
|
|
|
92
|
-
**ChatGPT** — ChatGPT cannot connect directly to this loopback `127.0.0.1` endpoint.
|
|
94
|
+
**ChatGPT** — ChatGPT cannot connect directly to this loopback `127.0.0.1` endpoint. For private/local use, create an OpenAI **Secure MCP Tunnel**, then run `tunnel-client` on the same machine as the launcher so it can reach `http://127.0.0.1:8080/mcp`; when creating the ChatGPT app, choose the **Tunnel** connection and select that tunnel. The tunnel setup requires an OpenAI `tunnel_id` and runtime API key; see OpenAI's [Secure MCP Tunnel guide](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels). The tunnel keeps the MCP server private and is intended for private/developer-mode connectivity, not public plugin distribution.
|
|
95
|
+
|
|
96
|
+
Alternatively, deploy your own remote Cloudflare Worker and add its HTTPS `/mcp` URL as a custom MCP app in Developer mode; see [Connect in your AI client](#connect-in-your-ai-client) below.
|
|
93
97
|
|
|
94
98
|
A self-hostable [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for **Google Search Console**. Connect it to Claude.ai, Cursor, ChatGPT, or any MCP-compatible client and ask your AI assistant about your site's organic search performance — impressions, clicks, top queries, index status, and sitemap health — straight from your own Google account.
|
|
95
99
|
|
package/package.json
CHANGED
package/src/google.ts
CHANGED
|
@@ -785,10 +785,9 @@ export async function querySearchAnalytics(
|
|
|
785
785
|
|
|
786
786
|
/**
|
|
787
787
|
* Fetches Search Analytics rows in 25,000-row pages for higher-level tools.
|
|
788
|
-
* Google's documented pagination contract
|
|
789
|
-
*
|
|
790
|
-
*
|
|
791
|
-
* can have more rows even when Search Console's own internal limits apply.
|
|
788
|
+
* Google's documented pagination contract treats a response shorter than the
|
|
789
|
+
* requested rowLimit as exhausted. An exactly full final page still requires
|
|
790
|
+
* a following empty-page probe unless the local safety ceiling is reached.
|
|
792
791
|
*/
|
|
793
792
|
export async function querySearchAnalyticsPaginated(
|
|
794
793
|
accessToken: string,
|
|
@@ -820,7 +819,7 @@ export async function querySearchAnalyticsPaginated(
|
|
|
820
819
|
|
|
821
820
|
const acceptedRows = page.rows.slice(0, requestedRows);
|
|
822
821
|
rows.push(...acceptedRows);
|
|
823
|
-
if (page.rows.length
|
|
822
|
+
if (page.rows.length < requestedRows) {
|
|
824
823
|
return { rows, pagesFetched, localLimitReached: false };
|
|
825
824
|
}
|
|
826
825
|
if (rows.length >= maximumRows || page.rows.length > requestedRows) {
|
package/src/index.ts
CHANGED
|
@@ -1408,11 +1408,10 @@ class GscMcpRuntime {
|
|
|
1408
1408
|
if (rateLimitError) return rateLimitError;
|
|
1409
1409
|
const accessToken = await this.getAccessToken(googleId);
|
|
1410
1410
|
const response = await querySearchAnalytics(accessToken, site_url, query);
|
|
1411
|
-
//
|
|
1412
|
-
//
|
|
1413
|
-
// later rows, so preserve a continuation for dimensioned queries.
|
|
1411
|
+
// Google documents a short page as terminal. An exactly full page can
|
|
1412
|
+
// still have a following page, so expose continuation only then.
|
|
1414
1413
|
const sourceMayHaveMore =
|
|
1415
|
-
dimensions.length > 0 && response.rows.length
|
|
1414
|
+
dimensions.length > 0 && response.rows.length === sourceRowLimit;
|
|
1416
1415
|
const bounded = windowSourceRows(
|
|
1417
1416
|
response.rows,
|
|
1418
1417
|
start_row,
|
|
@@ -1463,10 +1462,10 @@ class GscMcpRuntime {
|
|
|
1463
1462
|
'insights.page_queries',
|
|
1464
1463
|
{
|
|
1465
1464
|
title: 'Find queries for a page',
|
|
1466
|
-
description: 'For one exact page URL
|
|
1465
|
+
description: 'For one exact page URL within the supplied Search Console property, return the queries that produced impressions for it over a date range. This wraps an exact page dimension filter so agents do not need to construct analytics.query filter groups manually. Exact page matching is case-sensitive in Search Console. Use row_limit and start_row to page through bounded results; Search Console can still omit anonymized queries. Google Discover and Google News are intentionally unavailable because those reports do not expose query data.',
|
|
1467
1466
|
inputSchema: {
|
|
1468
1467
|
site_url: SEARCH_CONSOLE_PROPERTY_SCHEMA,
|
|
1469
|
-
page_url: z.string().url().describe('Exact fully-qualified page URL to filter on, e.g. https://example.com/guides/seo/. Search Console exact page filters are case-sensitive.'),
|
|
1468
|
+
page_url: z.string().url().describe('Exact fully-qualified page URL to filter on, e.g. https://example.com/guides/seo/. The URL must belong to site_url; Search Console exact page filters are case-sensitive.'),
|
|
1470
1469
|
start_date: SEARCH_CONSOLE_DATE_SCHEMA.describe(
|
|
1471
1470
|
searchConsoleDateDescription('Start date (inclusive) in YYYY-MM-DD format.'),
|
|
1472
1471
|
),
|
|
@@ -1498,6 +1497,7 @@ class GscMcpRuntime {
|
|
|
1498
1497
|
},
|
|
1499
1498
|
async ({ site_url, page_url, start_date, end_date, search_type, row_limit = 100, start_row = 0 }) => {
|
|
1500
1499
|
assertDateRange(start_date, end_date);
|
|
1500
|
+
assertUrlWithinSearchConsoleProperty(page_url, site_url, 'page_url');
|
|
1501
1501
|
const googleId = this.requireGoogleId();
|
|
1502
1502
|
const rateLimitError = await this.rateLimitError(googleId, 'insights.page_queries');
|
|
1503
1503
|
if (rateLimitError) return rateLimitError;
|
|
@@ -2124,7 +2124,7 @@ class GscMcpRuntime {
|
|
|
2124
2124
|
pages,
|
|
2125
2125
|
start_row,
|
|
2126
2126
|
row_limit,
|
|
2127
|
-
response.rows.length
|
|
2127
|
+
response.rows.length === sourceRowLimit,
|
|
2128
2128
|
start_row + sourceRowLimit,
|
|
2129
2129
|
);
|
|
2130
2130
|
|