@digestseo/mcp-gsc 0.4.29 → 0.4.30

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.30] - 2026-09-23
11
+
12
+ ### Changed
13
+ - Search Analytics filters now default an omitted operator to Google's documented `equals` behavior in both `analytics.query` and `analytics.compare`, while both tools enforce the provider's 4096-character filter-expression ceiling through one shared schema.
14
+ - URL Inspection language codes are now validated as BCP-47 language tags before `urls.inspect` or `urls.inspect_many` can reserve local inspection budget, resolve Google credentials, or call the provider.
15
+
10
16
  ## [0.4.29] - 2026-09-23
11
17
 
12
18
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digestseo/mcp-gsc",
3
- "version": "0.4.29",
3
+ "version": "0.4.30",
4
4
  "private": false,
5
5
  "main": "scripts/glama-start.mjs",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -66,6 +66,7 @@ import { CONTENT_DECAY_COMPARE_DAYS_SCHEMA } from './content-decay-schema';
66
66
  import { resolveIndexedPagesDateRange } from './indexed-pages-range';
67
67
  import { createQuickWinsInputSchema } from './quick-wins-schema';
68
68
  import { SITEMAP_URL_SCHEMA } from './sitemap-url-schema';
69
+ import { URL_INSPECTION_LANGUAGE_CODE_SCHEMA } from './url-inspection-language-schema';
69
70
  import {
70
71
  classifySearchConsolePropertyIdentifier,
71
72
  SEARCH_CONSOLE_PROPERTY_DESCRIPTION,
@@ -148,6 +149,32 @@ const SEARCH_ROW_OUTPUT_SCHEMA = {
148
149
  ),
149
150
  };
150
151
 
152
+ const SEARCH_ANALYTICS_FILTER_SCHEMA = z.object({
153
+ dimension: z.enum([
154
+ 'query',
155
+ 'page',
156
+ 'country',
157
+ 'device',
158
+ 'searchAppearance',
159
+ ]),
160
+ operator: z
161
+ .enum([
162
+ 'equals',
163
+ 'notEquals',
164
+ 'contains',
165
+ 'notContains',
166
+ 'includingRegex',
167
+ 'excludingRegex',
168
+ ])
169
+ .default('equals'),
170
+ expression: z.string().max(4096),
171
+ });
172
+
173
+ const SEARCH_ANALYTICS_FILTER_GROUP_SCHEMA = z.object({
174
+ groupType: z.literal('and').default('and'),
175
+ filters: z.array(SEARCH_ANALYTICS_FILTER_SCHEMA),
176
+ });
177
+
151
178
  const SITE_OUTPUT_SCHEMA = {
152
179
  siteUrl: z.string(),
153
180
  permissionLevel: z.string(),
@@ -943,12 +970,7 @@ class GscMcpRuntime {
943
970
  .describe(
944
971
  'The fully-qualified URL to inspect. Must belong to the site_url property: same domain for sc-domain properties, same URL prefix for URL-prefix properties.',
945
972
  ),
946
- language_code: z
947
- .string()
948
- .default('en-US')
949
- .describe(
950
- "BCP-47 language code for translatable strings in the result, e.g. 'en-US' or 'de-DE'.",
951
- ),
973
+ language_code: URL_INSPECTION_LANGUAGE_CODE_SCHEMA,
952
974
  },
953
975
  outputSchema: INSPECTION_OUTPUT_SCHEMA,
954
976
  annotations: READ_ONLY_ANNOTATIONS,
@@ -993,12 +1015,7 @@ class GscMcpRuntime {
993
1015
  .describe(
994
1016
  'Between 1 and 10 unique fully-qualified URLs to inspect. Each URL must belong to the site_url property.',
995
1017
  ),
996
- language_code: z
997
- .string()
998
- .default('en-US')
999
- .describe(
1000
- "BCP-47 language code for translatable strings in the results, e.g. 'en-US' or 'de-DE'.",
1001
- ),
1018
+ language_code: URL_INSPECTION_LANGUAGE_CODE_SCHEMA,
1002
1019
  },
1003
1020
  outputSchema: INSPECTION_BATCH_OUTPUT_SCHEMA,
1004
1021
  annotations: READ_ONLY_ANNOTATIONS,
@@ -1222,34 +1239,10 @@ class GscMcpRuntime {
1222
1239
  "How Google aggregates metrics. Leave as 'auto' unless specific semantics are needed. When grouping/filtering by page, use 'auto'; explicit 'byPage' and 'byProperty' are rejected for that request shape. 'byProperty' is also unavailable for search_type discover/googleNews. 'byNewsShowcasePanel' requires search_type discover/googleNews plus a searchAppearance equals NEWS_SHOWCASE filter, and cannot be combined with page grouping/filtering or another searchAppearance filter.",
1223
1240
  ),
1224
1241
  dimension_filter_groups: z
1225
- .array(
1226
- z.object({
1227
- groupType: z.literal('and').default('and'),
1228
- filters: z.array(
1229
- z.object({
1230
- dimension: z.enum([
1231
- 'query',
1232
- 'page',
1233
- 'country',
1234
- 'device',
1235
- 'searchAppearance',
1236
- ]),
1237
- operator: z.enum([
1238
- 'equals',
1239
- 'notEquals',
1240
- 'contains',
1241
- 'notContains',
1242
- 'includingRegex',
1243
- 'excludingRegex',
1244
- ]),
1245
- expression: z.string().max(4096),
1246
- }),
1247
- ),
1248
- }),
1249
- )
1242
+ .array(SEARCH_ANALYTICS_FILTER_GROUP_SCHEMA)
1250
1243
  .optional()
1251
1244
  .describe(
1252
- "Optional filters ANDed together, e.g. [{ groupType: 'and', filters: [{ dimension: 'country', operator: 'equals', expression: 'usa' }] }]. Countries use ISO 3166-1 alpha-3 codes. Query filters are not supported when search_type is discover or googleNews.",
1245
+ "Optional filters ANDed together, e.g. [{ groupType: 'and', filters: [{ dimension: 'country', expression: 'usa' }] }]. Filter operator defaults to 'equals' when omitted, matching Search Console. Expressions are limited to 4096 characters. Countries use ISO 3166-1 alpha-3 codes. Query filters are not supported when search_type is discover or googleNews.",
1253
1246
  ),
1254
1247
  },
1255
1248
  outputSchema: SEARCH_ANALYTICS_OUTPUT_SCHEMA,
@@ -2021,34 +2014,10 @@ class GscMcpRuntime {
2021
2014
  .default('web')
2022
2015
  .describe('Which Search Console search index to compare. The same search type is used for both periods. Discover and Google News are excluded because this tool returns average-position comparisons.'),
2023
2016
  dimension_filter_groups: z
2024
- .array(
2025
- z.object({
2026
- groupType: z.literal('and').default('and'),
2027
- filters: z.array(
2028
- z.object({
2029
- dimension: z.enum([
2030
- 'query',
2031
- 'page',
2032
- 'country',
2033
- 'device',
2034
- 'searchAppearance',
2035
- ]),
2036
- operator: z.enum([
2037
- 'equals',
2038
- 'notEquals',
2039
- 'contains',
2040
- 'notContains',
2041
- 'includingRegex',
2042
- 'excludingRegex',
2043
- ]),
2044
- expression: z.string(),
2045
- }),
2046
- ),
2047
- }),
2048
- )
2017
+ .array(SEARCH_ANALYTICS_FILTER_GROUP_SCHEMA)
2049
2018
  .optional()
2050
2019
  .describe(
2051
- "Optional Search Console filters applied identically to both periods. A caller-supplied query regex can approximate a manual brand/non-brand split, but it is not equivalent to Search Console's AI-assisted native Branded/Non-branded filter, which the Search Analytics API does not expose. Countries use ISO 3166-1 alpha-3 codes.",
2020
+ "Optional Search Console filters applied identically to both periods. Filter operator defaults to 'equals' when omitted, and expressions are limited to 4096 characters. A caller-supplied query regex can approximate a manual brand/non-brand split, but it is not equivalent to Search Console's AI-assisted native Branded/Non-branded filter, which the Search Analytics API does not expose. Countries use ISO 3166-1 alpha-3 codes.",
2052
2021
  ),
2053
2022
  limit: ANALYSIS_RESULT_LIMIT_SCHEMA,
2054
2023
  start_row: RESULT_START_ROW_SCHEMA,
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+
3
+ export const URL_INSPECTION_LANGUAGE_CODE_SCHEMA = z
4
+ .string()
5
+ .superRefine((value, ctx) => {
6
+ try {
7
+ if (Intl.getCanonicalLocales(value).length !== 1) {
8
+ throw new RangeError('Invalid language tag');
9
+ }
10
+ } catch {
11
+ ctx.addIssue({
12
+ code: 'custom',
13
+ message:
14
+ "language_code must be a valid BCP-47 language tag, e.g. 'en-US' or 'de-CH'.",
15
+ });
16
+ }
17
+ })
18
+ .default('en-US')
19
+ .describe(
20
+ "BCP-47 language code for translatable strings in the result, e.g. 'en-US' or 'de-CH'.",
21
+ );