@digestseo/mcp-gsc 0.4.33 → 0.4.34

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 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.34] - 2026-09-24
11
+
12
+ ### Fixed
13
+ - `analytics.query` now rejects documented-invalid cross-field request combinations before reserving local Search Analytics safety budget or resolving Google credentials, while retaining the lower-level provider compatibility guard for internal callers.
14
+ - `indexing.status`, `indexing.request`, and `indexing.remove` now reject URLs outside the supplied Search Console property before reserving local safety budget, resolving Google credentials, or calling Search Console for owner authorization.
15
+
10
16
  ## [0.4.33] - 2026-09-24
11
17
 
12
18
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digestseo/mcp-gsc",
3
- "version": "0.4.33",
3
+ "version": "0.4.34",
4
4
  "private": false,
5
5
  "main": "scripts/glama-start.mjs",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -34,6 +34,7 @@ import {
34
34
  getIndexingNotificationMetadata,
35
35
  processPerformanceComparison,
36
36
  assertSearchAnalyticsFilterCompatible,
37
+ assertSearchAnalyticsQueryCompatible,
37
38
  type PaginatedSearchAnalyticsResult,
38
39
  } from './google';
39
40
  import {
@@ -1387,12 +1388,8 @@ class GscMcpRuntime {
1387
1388
  dimension_filter_groups,
1388
1389
  }) => {
1389
1390
  assertDateRange(start_date, end_date);
1390
- const googleId = this.requireGoogleId();
1391
- const rateLimitError = await this.rateLimitError(googleId, 'analytics.query');
1392
- if (rateLimitError) return rateLimitError;
1393
- const accessToken = await this.getAccessToken(googleId);
1394
1391
  const sourceRowLimit = Math.min(row_limit, MAX_DIRECT_SOURCE_ROWS);
1395
- const response = await querySearchAnalytics(accessToken, site_url, {
1392
+ const query = {
1396
1393
  startDate: start_date,
1397
1394
  endDate: end_date,
1398
1395
  dimensions,
@@ -1404,7 +1401,13 @@ class GscMcpRuntime {
1404
1401
  ...(dimension_filter_groups !== undefined
1405
1402
  ? { dimensionFilterGroups: dimension_filter_groups }
1406
1403
  : {}),
1407
- });
1404
+ };
1405
+ assertSearchAnalyticsQueryCompatible(query);
1406
+ const googleId = this.requireGoogleId();
1407
+ const rateLimitError = await this.rateLimitError(googleId, 'analytics.query');
1408
+ if (rateLimitError) return rateLimitError;
1409
+ const accessToken = await this.getAccessToken(googleId);
1410
+ const response = await querySearchAnalytics(accessToken, site_url, query);
1408
1411
  // Search Analytics pagination is complete only after Google returns an
1409
1412
  // explicit empty page. A short non-empty page can still be followed by
1410
1413
  // later rows, so preserve a continuation for dimensioned queries.
@@ -1957,6 +1960,7 @@ class GscMcpRuntime {
1957
1960
  annotations: READ_ONLY_ANNOTATIONS,
1958
1961
  },
1959
1962
  async ({ site_url, url }) => {
1963
+ assertUrlWithinSearchConsoleProperty(url, site_url);
1960
1964
  const googleId = this.requireGoogleId();
1961
1965
  const rateLimitError = await this.rateLimitError(googleId, 'indexing.status');
1962
1966
  if (rateLimitError) return rateLimitError;
@@ -2000,6 +2004,7 @@ class GscMcpRuntime {
2000
2004
  annotations: WRITE_TOOL_ANNOTATIONS['indexing.request'],
2001
2005
  },
2002
2006
  async ({ site_url, url }) => {
2007
+ assertUrlWithinSearchConsoleProperty(url, site_url);
2003
2008
  const googleId = this.requireGoogleId();
2004
2009
  const rateLimitError = await this.rateLimitError(googleId, 'indexing.request');
2005
2010
  if (rateLimitError) return rateLimitError;
@@ -2041,6 +2046,7 @@ class GscMcpRuntime {
2041
2046
  annotations: WRITE_TOOL_ANNOTATIONS['indexing.remove'],
2042
2047
  },
2043
2048
  async ({ site_url, url }) => {
2049
+ assertUrlWithinSearchConsoleProperty(url, site_url);
2044
2050
  const googleId = this.requireGoogleId();
2045
2051
  const rateLimitError = await this.rateLimitError(googleId, 'indexing.remove');
2046
2052
  if (rateLimitError) return rateLimitError;