@digestseo/mcp-gsc 0.4.14 → 0.4.15

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.15] - 2026-09-22
11
+
12
+ ### Fixed
13
+ - `analytics.query` now distinguishes fresh preliminary Search Analytics data from finalized-data lag, echoes the requested `data_state`, and reports whether preliminary data is possible instead of implying a blanket 2-3 day delay.
14
+ - Repo-owned quick-connect configs and client docs now use the verified loopback npm launcher instead of routing new users to the intentionally unadvertised hosted remote while that deployment lags the current package.
15
+
10
16
  ## [0.4.14] - 2026-09-22
11
17
 
12
18
  ### Fixed
package/README.md CHANGED
@@ -30,35 +30,37 @@ The local launcher defaults to `GSC_ACCESS_MODE=readwrite`. For least-privilege
30
30
 
31
31
  For Google OAuth and Cloudflare deployment configuration, follow [SETUP.md](SETUP.md).
32
32
 
33
- ### Connect in 30 seconds
33
+ ### Connect the local launcher
34
34
 
35
- Every deployed instance exposes the same endpoint shape:
35
+ For the current verified quick-connect path, start the npm launcher first after supplying the Google OAuth and token-encryption environment variables described in [SETUP.md](SETUP.md):
36
36
 
37
- ```
38
- https://<your-worker>.workers.dev/mcp
37
+ ```bash
38
+ npx -y @digestseo/mcp-gsc
39
39
  ```
40
40
 
41
- The DigestSEO-hosted instance is available at:
41
+ Then connect your MCP client to the launcher's loopback endpoint:
42
42
 
43
43
  ```
44
- https://mcp-gsc.digestseo.com/mcp
44
+ http://127.0.0.1:8080/mcp
45
45
  ```
46
46
 
47
+ Self-hosted Cloudflare Worker deployments continue to use `https://<your-worker>.workers.dev/mcp`. The repo does not currently advertise the owner-hosted remote as a quick-connect path because its deployed tool contract is behind the published package.
48
+
47
49
  **Claude Code**
48
50
 
49
51
  ```bash
50
- claude mcp add --transport http gsc https://<your-worker>.workers.dev/mcp
52
+ claude mcp add --transport http gsc http://127.0.0.1:8080/mcp
51
53
  ```
52
54
 
53
55
  **Cursor**
54
56
 
55
- [![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=gsc&config=eyJ1cmwiOiJodHRwczovL21jcC1nc2MuZGlnZXN0c2VvLmNvbS9tY3AifQ%3D%3D)
57
+ [![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=gsc&config=eyJ1cmwiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvbWNwIn0%3D)
56
58
 
57
59
  **Kiro**
58
60
 
59
- [![Add to Kiro](https://kiro.dev/images/add-to-kiro.svg)](https://kiro.dev/launch/mcp/add?name=mcp-gsc&config=%7B%22url%22%3A%22https%3A%2F%2Fmcp-gsc.digestseo.com%2Fmcp%22%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D)
61
+ [![Add to Kiro](https://kiro.dev/images/add-to-kiro.svg)](https://kiro.dev/launch/mcp/add?name=mcp-gsc&config=%7B%22url%22%3A%22http%3A%2F%2F127.0.0.1%3A8080%2Fmcp%22%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D)
60
62
 
61
- Uses the hosted endpoint above; complete its Google OAuth flow on first use.
63
+ Start the npm launcher before using either install button. Complete its Google OAuth flow on first use.
62
64
 
63
65
  **ChatGPT** — add it as a custom MCP app in developer mode; see [Connect in your AI client](#connect-in-your-ai-client) below.
64
66
 
@@ -77,7 +79,7 @@ By default (`GSC_ACCESS_MODE=readwrite`), this server exposes 21 tools. Read-onl
77
79
  | **`server.capabilities`** | Read | List every tool this server exposes and report whether your Google connection is currently authenticated (`connected` / `not_connected`). Takes no arguments — a good first call for discovery. |
78
80
  | **`sites.list`** | Read | List the Search Console properties the connected Google account can access (`siteUrl`, `permissionLevel`). |
79
81
  | **`sites.get`** | Read | Retrieve one exact Search Console property and the connected account's permission level for it. |
80
- | **`analytics.query`** | Read | Impressions, clicks, CTR, and average position over a date range, with dimensions, filters, safe pagination, and selectable search type. Pass `dimensions: []` for true site totals; Google's aggregate row may omit `keys`. Search Analytics does not guarantee every data row and can return only top rows, so exhausting local pagination is not proof that the provider dataset is exhaustive. Search appearance discovery is a two-step workflow: group by `searchAppearance` alone to discover the exact values Google returns for the property, then filter to one returned value in a separate query when grouping by page/query/country/device/date/hour. For `search_type: "discover"` or `"googleNews"`, `position_supported` is `false`; those reports expose clicks, impressions, and CTR but not average position, and query grouping/filtering is unavailable. Search Console's dedicated Generative AI performance reports are not exposed by the current documented Search Analytics API as a dedicated search type or filter selector; `generative_ai_report_isolatable` is therefore `false`. |
82
+ | **`analytics.query`** | Read | Impressions, clicks, CTR, and average position over a date range, with dimensions, filters, safe pagination, and selectable search type. Pass `dimensions: []` for true site totals; Google's aggregate row may omit `keys`. Search Analytics does not guarantee every data row and can return only top rows, so exhausting local pagination is not proof that the provider dataset is exhaustive. `data_state: "all"` can include fresh preliminary data, while `final` returns only finalized data; responses echo `data_state` plus `preliminary_data_possible`, and date/hour groupings preserve Google's incomplete-data boundary metadata when returned. Search appearance discovery is a two-step workflow: group by `searchAppearance` alone to discover the exact values Google returns for the property, then filter to one returned value in a separate query when grouping by page/query/country/device/date/hour. For `search_type: "discover"` or `"googleNews"`, `position_supported` is `false`; those reports expose clicks, impressions, and CTR but not average position, and query grouping/filtering is unavailable. Search Console's dedicated Generative AI performance reports are not exposed by the current documented Search Analytics API as a dedicated search type or filter selector; `generative_ai_report_isolatable` is therefore `false`. |
81
83
  | **`insights.page_queries`** / **`insights.query_pages`** | Read | Drill from one exact page to its Search Console queries, or from one exact query to the pages Google surfaced for it, with `row_limit` / `start_row` pagination. These query-centric helpers support web, image, video, and the Search results News tab; Discover and the Google News report are excluded because they do not expose query data. |
82
84
  | **`urls.inspect`** | Read | Google's URL Inspection report for the version of one page currently known in Google's index. It is not a live URL test; mobile-usability output is deprecated. |
83
85
  | **`urls.inspect_many`** | Read | Inspect Google's indexed versions of up to 10 URLs with bounded concurrency of 3 in one call while preserving input-order results. Each URL still consumes one Google URL Inspection request and one unit of the server's shared inspection safety budget; this does not run live URL tests. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digestseo/mcp-gsc",
3
- "version": "0.4.14",
3
+ "version": "0.4.15",
4
4
  "private": false,
5
5
  "main": "scripts/glama-start.mjs",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -244,6 +244,12 @@ const SEARCH_ANALYTICS_OUTPUT_SCHEMA = {
244
244
  row_count: z.number().int().nonnegative(),
245
245
  start_row: z.number().int().nonnegative(),
246
246
  rows: z.array(z.object(SEARCH_ROW_OUTPUT_SCHEMA)),
247
+ data_state: z.enum(['all', 'final', 'hourly_all']).describe(
248
+ 'The Search Analytics dataState requested from Google for this response.',
249
+ ),
250
+ preliminary_data_possible: z.boolean().describe(
251
+ 'True when the requested data state can include fresh data that is still being collected and processed. This does not assert that every returned row is incomplete.',
252
+ ),
247
253
  position_supported: z.boolean().describe(
248
254
  'Whether average position is supported for the selected Search Analytics search type. False for Google Discover and Google News.',
249
255
  ),
@@ -989,10 +995,13 @@ class GscMcpRuntime {
989
995
  ' matching dimension. Expect the returned rows to cover only a',
990
996
  ' subset of total impressions; this is normal Google behavior, not',
991
997
  ' a data error.',
992
- '- DATA FRESHNESS: Search Console data lags about 2-3 days behind',
993
- ' real time. If the user asks about "today" or "yesterday", expect',
994
- ' empty or partial rows for the most recent days; the latest',
995
- ' reliably-complete date is usually 3 days ago.',
998
+ '- DATA FRESHNESS: data_state "all" can include fresh preliminary',
999
+ ' data instead of imposing the finalized-data lag; "final" returns',
1000
+ ' only finalized data and can therefore lag recent activity. When',
1001
+ ' Google returns metadata.first_incomplete_date or',
1002
+ ' metadata.first_incomplete_hour for date/hour groupings, treat',
1003
+ ' that boundary and later rows as still subject to change. The',
1004
+ ' response also echoes data_state and preliminary_data_possible.',
996
1005
  '- AVERAGE POSITION is impression-weighted. To compute an overall',
997
1006
  ' position across multiple rows, use',
998
1007
  ' sum(position * impressions) / sum(impressions). Never plain-average',
@@ -1045,7 +1054,7 @@ class GscMcpRuntime {
1045
1054
  site_url: SEARCH_CONSOLE_PROPERTY_SCHEMA,
1046
1055
  start_date: SEARCH_CONSOLE_DATE_SCHEMA.describe('Start date (inclusive) in YYYY-MM-DD format.'),
1047
1056
  end_date: SEARCH_CONSOLE_DATE_SCHEMA.describe(
1048
- 'End date (inclusive) in YYYY-MM-DD format. Note the 2-3 day data lag: the most recent complete date is usually 3 days ago.',
1057
+ 'End date (inclusive) in YYYY-MM-DD format. Recent dates are allowed: data_state all/hourly_all can include preliminary data, while final returns only finalized data.',
1049
1058
  ),
1050
1059
  dimensions: z
1051
1060
  .array(
@@ -1173,6 +1182,8 @@ class GscMcpRuntime {
1173
1182
  row_count: bounded.items.length,
1174
1183
  start_row,
1175
1184
  rows: bounded.items,
1185
+ data_state,
1186
+ preliminary_data_possible: data_state !== 'final',
1176
1187
  position_supported:
1177
1188
  search_type !== 'discover' && search_type !== 'googleNews',
1178
1189
  ...(search_type === 'discover' || search_type === 'googleNews'