pagesight 0.16.0 → 0.18.0

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.
Files changed (70) hide show
  1. package/README.md +17 -83
  2. package/docs/credentials.md +54 -0
  3. package/docs/diagnostics.md +85 -0
  4. package/docs/snapshots.md +123 -0
  5. package/docs/usage.md +130 -0
  6. package/package.json +26 -29
  7. package/src/api/bing.ts +83 -0
  8. package/src/api/compare-snapshots.ts +377 -0
  9. package/src/api/discover.ts +39 -0
  10. package/src/api/doctor.ts +35 -0
  11. package/src/api/evidence-schema.ts +78 -0
  12. package/src/api/evidence.ts +99 -0
  13. package/src/api/execute.ts +147 -0
  14. package/src/api/index.ts +5 -0
  15. package/src/api/reports.ts +90 -0
  16. package/src/api/schema.ts +207 -0
  17. package/src/api/snapshot.ts +183 -0
  18. package/src/api/ui-findings.ts +68 -0
  19. package/src/cli.ts +182 -0
  20. package/src/http.ts +39 -0
  21. package/src/index.ts +8 -25
  22. package/src/mcp-server.ts +27 -0
  23. package/src/mcp.ts +5 -0
  24. package/src/providers/bing.ts +48 -0
  25. package/src/{lib → providers}/crux.ts +4 -9
  26. package/src/providers/ga.ts +114 -0
  27. package/src/providers/google-tokens.ts +86 -0
  28. package/src/providers/gsc-auth.ts +93 -0
  29. package/src/{lib → providers}/gsc.ts +27 -24
  30. package/src/{lib/psi.ts → providers/pagespeed.ts} +3 -14
  31. package/src/shared/dates.ts +32 -0
  32. package/src/shared/http.ts +63 -0
  33. package/src/tools/ai.ts +19 -27
  34. package/src/tools/audit.ts +26 -97
  35. package/src/tools/observe.ts +28 -0
  36. package/src/tools/page/analyze.ts +194 -0
  37. package/src/tools/page/batch.ts +163 -0
  38. package/src/tools/page/contrast.ts +128 -0
  39. package/src/tools/page/links.ts +200 -0
  40. package/src/tools/page/metadata.ts +225 -0
  41. package/src/tools/page/structured-data.ts +288 -0
  42. package/src/tools/page/tool.ts +48 -0
  43. package/src/tools/search/actions.ts +56 -0
  44. package/src/tools/search/analytics.ts +266 -0
  45. package/src/tools/search/coverage.ts +247 -0
  46. package/src/tools/search/gaps.ts +129 -0
  47. package/src/tools/search/inspection.ts +160 -0
  48. package/src/tools/search/result.ts +3 -0
  49. package/src/tools/search/sample.ts +110 -0
  50. package/src/tools/search/schema.ts +62 -0
  51. package/src/{lib/sitemap.ts → tools/search/sitemap-sampling.ts} +1 -45
  52. package/src/tools/search/sites.ts +86 -0
  53. package/src/tools/search/tool.ts +11 -0
  54. package/src/tools/setup.ts +59 -20
  55. package/src/tools/speed/analyze.ts +191 -0
  56. package/src/tools/speed/batch.ts +265 -0
  57. package/src/tools/speed/crux.ts +176 -0
  58. package/src/tools/speed/pagespeed.ts +273 -0
  59. package/src/tools/speed/schema.ts +39 -0
  60. package/src/tools/speed/tool.ts +11 -0
  61. package/src/web/fetch.ts +31 -0
  62. package/src/web/images.ts +62 -0
  63. package/src/web/page-observation.ts +69 -0
  64. package/src/{lib → web}/robots.ts +20 -12
  65. package/src/web/sitemap-inventory.ts +64 -0
  66. package/src/web/sitemap-parser.ts +59 -0
  67. package/src/lib/auth.ts +0 -187
  68. package/src/tools/page.ts +0 -1241
  69. package/src/tools/search.ts +0 -852
  70. package/src/tools/speed.ts +0 -956
package/README.md CHANGED
@@ -1,94 +1,28 @@
1
1
  # Pagesight
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/pagesight.svg)](https://www.npmjs.com/package/pagesight)
3
+ SEO, analytics, page, and performance evidence for developers and AI assistants.
4
+ Use it through the TypeScript API, CLI, local HTTP server, or MCP.
4
5
 
5
- See your site the way search engines and AI see it.
6
+ Requires Bun. Try a page check without provider credentials:
6
7
 
7
- ```bash
8
- npm install pagesight
8
+ ```sh
9
+ bun add pagesight
10
+ bunx --bun pagesight page --url https://example.com
9
11
  ```
10
12
 
11
- Your AI assistant can write your code. Now it can see your site. Index status, performance, real-user metrics, search traffic, meta tags, structured data, AI crawler access, link health — one package, one call.
13
+ ```ts
14
+ import { execute } from "pagesight";
12
15
 
16
+ const result = await execute({ operation: "page", url: "https://example.com" });
17
+ console.log(result);
13
18
  ```
14
- === Site Audit: https://example.com ===
15
19
 
16
- 2 checks failed — results below are partial:
20
+ Provider reports need access to the relevant Google or Bing account. Results keep
21
+ raw observations, failures, and limits; missing data is not zero.
17
22
 
18
- FAIL PageSpeed: quota exceeded
19
- FAIL Sitemaps: permission denied
23
+ - [API, CLI, HTTP, and MCP](docs/usage.md)
24
+ - [Snapshots and comparisons](docs/snapshots.md)
25
+ - [Provider access](docs/credentials.md)
26
+ - [Bing diagnostics, HTML images, and UI findings](docs/diagnostics.md)
20
27
 
21
- 5 findings:
22
-
23
- HIGH Missing canonical URL
24
- HIGH 22 sitemap URLs submitted, 0 indexed
25
- Auto-inspected 5 URLs:
26
- - 2/5 indexed
27
- - 3/5 Discovered - currently not indexed: /docs/, /pricing/, /about/
28
- MEDIUM Missing og:image — no social preview image
29
- LOW Missing Twitter Card tags
30
- LOW 6/139 AI crawlers blocked
31
- ```
32
-
33
- ## Tools
34
-
35
- 6 tools organized by intent:
36
-
37
- | Tool | Intent | What it does |
38
- |------|--------|-------------|
39
- | `audit` | How's my site? | One-call site audit. Runs all checks in parallel. Prioritized findings with auto-drill-down on indexing issues. |
40
- | `page` | What's on this URL? | Meta tags, OG, Twitter Card, JSON-LD validation (19 schema types), internal link health, redirect chains, WCAG contrast checker. Batch mode for multiple URLs. |
41
- | `speed` | How fast is it? | PageSpeed single/batch/compare with Lighthouse scores and opportunities. CrUX real-user metrics (snapshot + history trends). |
42
- | `search` | How's Google seeing me? | URL inspection, sample-inspect from sitemaps, sitemap management, search analytics with period-over-period comparison. |
43
- | `ai` | How's AI seeing me? | AI crawler audit (139+ bots by category), robots.txt validation (RFC 9309), llms.txt detection, path access checks. |
44
- | `setup` | Auth config | Auth status check and OAuth setup flow. |
45
-
46
- ## Setup
47
-
48
- Add to your MCP config:
49
-
50
- ```json
51
- {
52
- "mcpServers": {
53
- "pagesight": {
54
- "command": "npx",
55
- "args": ["pagesight"],
56
- "env": {
57
- "GSC_CLIENT_ID": "your-client-id",
58
- "GSC_CLIENT_SECRET": "your-secret",
59
- "GSC_REFRESH_TOKEN": "your-token",
60
- "GOOGLE_API_KEY": "your-api-key"
61
- }
62
- }
63
- }
64
- }
65
- ```
66
-
67
- `page`, `speed`, and `ai` work without credentials. `search` and `audit` (for GSC checks) require OAuth or a service account.
68
-
69
- ### Full setup
70
-
71
- 1. [Google Cloud Console](https://console.cloud.google.com/) — enable Search Console API, PageSpeed Insights API, Chrome UX Report API
72
- 2. Create OAuth client ID (Desktop app) + API key
73
- 3. Configure:
74
-
75
- ```env
76
- GSC_CLIENT_ID=your-client-id.apps.googleusercontent.com
77
- GSC_CLIENT_SECRET=your-client-secret
78
- GSC_REFRESH_TOKEN=your-refresh-token
79
- GOOGLE_API_KEY=your-api-key
80
- ```
81
-
82
- ## Why Pagesight
83
-
84
- Every data point comes from a verifiable source. Google's APIs, real Chrome users, RFC 9309, schema.org, a community-maintained bot registry. No invented scores. No rules we can't cite.
85
-
86
- - **"Title must be under 60 characters"** — Gary Illyes: "an externally made-up metric."
87
- - **"Only one H1 per page"** — John Mueller: "You can use H1 tags as often as you want."
88
- - **"Minimum 300 words per page"** — Mueller: "not a quality factor."
89
-
90
- Pagesight reports what the sources report. Nothing more.
91
-
92
- ## License
93
-
94
- MIT
28
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,54 @@
1
+ # Provider access
2
+
3
+ ## Credentials
4
+
5
+ | Provider | Configuration |
6
+ | -------------- | ------------------------------------------------------------------------------------------------------- |
7
+ | Search Console | `GSC_SERVICE_ACCOUNT_KEY`, or `GSC_CLIENT_ID`, `GSC_CLIENT_SECRET`, `GSC_REFRESH_TOKEN` |
8
+ | GA4 | `PAGESIGHT_GA_CREDENTIALS`, then `GOOGLE_APPLICATION_CREDENTIALS`, then the usual local gcloud ADC file |
9
+ | PageSpeed | `GOOGLE_API_KEY` optional |
10
+ | CrUX | `GOOGLE_API_KEY` required |
11
+
12
+ GA accepts service-account JSON or `authorized_user` ADC JSON. Use
13
+ `analytics.readonly` permission and grant property access. Enable both Analytics
14
+ Admin and Data APIs. GSC authentication remains separate with `webmasters.readonly`.
15
+ No new consent flow or provider settings are created by the read API.
16
+
17
+ Keep credentials in an environment file outside the repository and use Bun's
18
+ `--env-file` option. No tokens, API-key URLs, or provider error bodies are included
19
+ in report envelopes. Configuration files and operation requests must contain only
20
+ nonsecret identifiers and report parameters.
21
+
22
+ ## Bing Webmaster reports
23
+
24
+ Set `BING_WEBMASTER_API_KEY` from Bing Webmaster Tools API Access, then discover
25
+ sites before copying a verified `Url` verbatim into `bingSite` in your config
26
+ (including its scheme and trailing-slash form):
27
+
28
+ ```sh
29
+ pagesight discover --url https://example.com/ --providers bing
30
+ pagesight bing sites
31
+ pagesight bing queries --site https://example.com/
32
+ pagesight bing pages --site https://example.com/
33
+ pagesight bing traffic --site https://example.com/
34
+ ```
35
+
36
+ The API operations are `bing.sites`, `bing.queries`, `bing.pages` and `bing.traffic`.
37
+ MCP `observe` and HTTP use the same operation objects. A configured `bingSite`
38
+ adds all three reports to snapshots; doctor checks traffic access. Google discovery
39
+ remains the default; use `--providers gsc,ga,bing` to include all providers.
40
+
41
+ These methods accept no date range or pagination options. Snapshot requested dates
42
+ apply to Google reports; Bing returns its provider-defined range. Responses retain
43
+ Bing's raw `d` envelope, numeric fields and `/Date(...)/` strings; reporting timezone
44
+ and coverage remain unknown. Query/page statistics update weekly, traffic daily.
45
+ `GetPageStats` uses `Query` for the page URL. Since March 24, 2023 traffic includes
46
+ Web, Chat, News, Images, Videos and Knowledge Panel; this is not isolated AI-citation
47
+ evidence or a Google Web equivalent. Site verification is not indexing evidence.
48
+
49
+ Contracts were checked against Microsoft Learn's [GetUserSites](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getusersites),
50
+ [GetQueryStats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getquerystats),
51
+ [GetPageStats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getpagestats)
52
+ and [GetRankAndTrafficStats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getrankandtrafficstats).
53
+ Fixture tests verify these contracts and safe failures. Live Bing access has not
54
+ been verified because no API key is configured in the development environment.
@@ -0,0 +1,85 @@
1
+ # Provider diagnostics and imported findings
2
+
3
+ ## Bing crawl, URL and backlink evidence
4
+
5
+ ```sh
6
+ pagesight bing crawl-stats --site https://example.com/
7
+ pagesight bing crawl-issues --site https://example.com/
8
+ pagesight bing url-info --site https://example.com/ --url https://example.com/page
9
+ pagesight bing link-counts --site https://example.com/ --max-pages 4
10
+ pagesight bing url-links --site https://example.com/ --url https://example.com/page --max-pages 4
11
+ ```
12
+
13
+ These read operations use `BING_WEBMASTER_API_KEY` and the registered site URL.
14
+ They expose Microsoft's `GetCrawlStats`, `GetCrawlIssues`, `GetUrlInfo`,
15
+ `GetLinkCounts` and `GetUrlLinks` JSON methods. Link reports start at page zero;
16
+ `maxPages` defaults to one and accepts 1–20. Hitting the limit returns partial
17
+ status (CLI exit 3); raise the limit to repeat from page zero. `nextOffset` is a
18
+ provider page number. Failed later requests preserve successful pages. Changing
19
+ `TotalPages` stops pagination with partial coverage.
20
+
21
+ Raw provider dates and counts stay intact. Do not derive daily error rates without
22
+ verifying their periods and units. `HttpStatus: 0` in URL metadata is not an HTTP
23
+ success. Link report exhaustion does not establish a complete backlink inventory;
24
+ empty rows are not zero links, and link counts do not measure domain quality.
25
+ `InIndex` and sitemap counts have different scopes. Crawl issues are not the UI
26
+ recommendations list. These operations are explicit reads; existing snapshot
27
+ provider selection and call counts are unchanged.
28
+
29
+ ## HTML image evidence
30
+
31
+ `pagesight page --url https://example.com/` now includes `descriptionLength`
32
+ (Unicode code points, or null) and `imageEvidence`. Images include raw `src`,
33
+ `altPresent`, `altText`, `inNoscript`, width/height, role and aria-hidden attributes.
34
+ Missing ALT has `altPresent: false, altText: null`; an explicitly empty ALT is
35
+ `altPresent: true, altText: ""`. Empty ALT can be appropriate for decorative images.
36
+ No description-length threshold or image-purpose verdict is imposed.
37
+
38
+ The inventory includes noscript fallback markup, retains at most 200 images,
39
+ and reports `omittedImages` and `truncated`. Fallback images follow ordinary images
40
+ in output; this is not DOM order. No scripts run or image URLs are requested.
41
+ The existing 2 MB page limit still applies. This is markup evidence, not a full
42
+ accessibility or rendered-page audit.
43
+
44
+ ## Import provider UI findings
45
+
46
+ Use a small JSON transcription when a UI report has no verified API equivalent:
47
+
48
+ ```json
49
+ {
50
+ "provider": "bing",
51
+ "site": "https://example.com/",
52
+ "source": {
53
+ "kind": "csv",
54
+ "label": "Affected URLs export; rule copied from report screen",
55
+ "capturedAt": null,
56
+ "scannedAt": null,
57
+ "coverage": "Only affected URLs were exported; total site coverage unknown"
58
+ },
59
+ "findings": [
60
+ {
61
+ "rule": "Meta descriptions are too short",
62
+ "severity": "unknown",
63
+ "urls": ["https://example.com/explore"]
64
+ }
65
+ ]
66
+ }
67
+ ```
68
+
69
+ ```sh
70
+ pagesight evidence import --request findings.json --out imported.json
71
+ ```
72
+
73
+ This validates JSON, preserves its attribution and labels it `user-import` and
74
+ `unverified`. It does not parse screenshots/CSV automatically, contact the provider,
75
+ fetch listed URLs or verify the finding. Use null for unknown capture/scan dates;
76
+ known dates must be ISO timestamps with offsets. Do not infer severity from a
77
+ URL-only CSV. Sources can be `csv`, `screenshot` or `manual`; providers can be
78
+ `bing`, `gsc` or `other`. An optional `source.artifactSha256` is caller supplied,
79
+ not verified. The generated `normalizedDocumentSha256` identifies normalized JSON,
80
+ not original file bytes. Import at most 100 findings and 1,000 URL references.
81
+
82
+ All additions use the shared API: operation names are `bing.crawl-stats`,
83
+ `bing.crawl-issues`, `bing.url-info`, `bing.link-counts`, `bing.url-links`, and
84
+ `evidence.import` (with a `document` field). They are also available through HTTP
85
+ `POST /v1/query`, CLI `api --request`, and MCP `observe`.
@@ -0,0 +1,123 @@
1
+ # Snapshots and comparisons
2
+
3
+ ## Site snapshots
4
+
5
+ A minimal config needs only a site:
6
+
7
+ ```json
8
+ { "site": "https://example.com/" }
9
+ ```
10
+
11
+ It collects that page without Google credentials. Add `gscSite` or `gaProperty`
12
+ to select those providers independently. Omitted providers appear as `not_selected`;
13
+ a selected provider that fails produces error evidence. `sitemap` is opt-in, and
14
+ `pages` defaults to the site URL. `productionHostname` defaults to its hostname.
15
+ Existing full configurations still work. Context defaults identify unspecified
16
+ objectives, locale and country rather than inferring them.
17
+
18
+ `discover` lists candidates from the selected Google providers and returns a usable
19
+ site-only config in `pages[0].response.config`. Copy that object to a config file,
20
+ then add the property IDs you verified. It does not automatically select properties:
21
+ GA account display names are not proof of hostname ownership. Discovery failures
22
+ remain independent; inspect raw responses and `nextPageToken` for incomplete lists.
23
+
24
+ A config holds nonsecret provider IDs and the site's meaning:
25
+
26
+ ```json
27
+ {
28
+ "site": "https://example.com/",
29
+ "productionHostname": "example.com",
30
+ "gscSite": "sc-domain:example.com",
31
+ "gaProperty": "123456",
32
+ "sitemap": "https://example.com/sitemap.xml",
33
+ "pages": ["https://example.com/"],
34
+ "context": {
35
+ "objective": "Help visitors use the product",
36
+ "successEvents": [],
37
+ "excludedKeyEvents": [],
38
+ "locale": "en-US",
39
+ "country": "US",
40
+ "routes": [{ "pattern": "/", "purpose": "Public entry", "indexing": "index" }],
41
+ "measurementCaveats": []
42
+ }
43
+ }
44
+ ```
45
+
46
+ CLI snapshots default to 28 days ending Pacific today minus three days. Supply both
47
+ `--start YYYY-MM-DD` and `--end YYYY-MM-DD` to reproduce another interval. The API
48
+ requires explicit dates. The country and locale are context, not implicit filters.
49
+
50
+ A snapshot collects independent GSC property/page/query/date reports and sitemaps;
51
+ GA property/key-event configuration, unfiltered hostname census, production channels,
52
+ named events and organic landing reports; configured page fetches and GSC inspections;
53
+ and a sitemap inventory bounded to five same-origin XML files and 8 MB.
54
+ This inventory accepts ordinary unprefixed sitemap XML; unsupported prefixed or
55
+ compressed documents are reported as incomplete rather than empty coverage.
56
+
57
+ Snapshots embed the config used, observations, content hashes, requested/observed
58
+ dates and unknown deployment/reference identities. A failed observation remains
59
+ visible while successful data is retained. `doctor` probes GSC, GA Admin, GA Data
60
+ when selected, plus live HTML. Run speed operations to probe PSI/CrUX separately.
61
+ Snapshot responses carry `snapshotVersion: 1` and stable observation `name` values,
62
+ also present in the summary, so identity does not depend on array position.
63
+
64
+ Interpretation rules:
65
+
66
+ - GSC query privacy exclusions and aggregation differences mean row sums are not
67
+ property totals. Missing rows are not zero. Comparisons are descriptive, not causal.
68
+ - GA key events must be interpreted by name and the site's selected objective.
69
+ A hostname filter excludes development hosts but not internal use of production.
70
+ - Sitemap membership is not indexing. Google's `contents[].indexed` field is deprecated.
71
+ URL inspections describe the selected URLs in Google's stored state, not live access
72
+ or a statistically representative whole-site coverage rate.
73
+ - PSI is a lab run. CrUX NOT_FOUND is no record for that scope, not zero performance.
74
+ CrUX history periods overlap. AI referrals do not establish citations.
75
+ - Keep raw landing query strings and observed canonicals. Functional URL parameters
76
+ need site-specific interpretation; Pagesight does not silently join GA to GSC.
77
+
78
+ ## Compare saved snapshots
79
+
80
+ Capture two snapshots with the same config and equal-length, nonoverlapping report
81
+ periods, then compare them locally:
82
+
83
+ ```sh
84
+ pagesight snapshot --config seo.config.json --start 2026-07-04 --end 2026-07-31 --out before.json
85
+ pagesight snapshot --config seo.config.json --start 2026-08-01 --end 2026-08-28 --out after.json
86
+ pagesight compare --baseline before.json --current after.json --max-rows 100
87
+ ```
88
+
89
+ The shared operation is `{ operation: "compare", baseline, current, maxRows: 100 }`,
90
+ where baseline and current are parsed snapshot evidence objects. Only the CLI reads
91
+ file paths. HTTP accepts objects up to 32 MB per request; larger pairs can use the
92
+ local API or CLI. MCP `observe` accepts the same object. `evidenceSchema` and
93
+ `snapshotEvidenceSchema` are exported for callers validating stored reports.
94
+
95
+ This first comparison supports GSC reports with non-time row keys and GA reports
96
+ using snapshot dimensions: `hostName`, `sessionDefaultChannelGroup`,
97
+ `sessionSourceMedium`, `eventName`, `landingPagePlusQueryString`, and `sessionSource`.
98
+ Reports without dimensions are also supported. Other GA dimensions and
99
+ `dimensionExpression` aliases require a separate comparison policy. It checks
100
+ snapshot format version 1, unique observation names, site, property, dimensions,
101
+ metrics, filters, aggregation, report periods and GA timezone/currency/metric types.
102
+ GSC data must be finalized. Time dimensions, Bing's provider-defined windows, HTML,
103
+ sitemap and provider metadata observations are explicitly unsupported for comparison.
104
+ Recapture snapshots created before versioned, named observations were introduced.
105
+
106
+ Each observation is `compared`, `limited`, `incompatible`, `unavailable`, or
107
+ `unsupported`. The outer evidence reports whether the comparison operation ran;
108
+ inspect the response status-count summary and per-observation statuses before using deltas. Partial pagination,
109
+ sampling, thresholding and high-cardinality aggregation remain visible limitations.
110
+ Missing trailing GSC date rows and recently collected GA data also mark comparisons
111
+ as limited; observed dates cannot prove complete coverage.
112
+ Only keys observed in both periods get numeric deltas. Keys seen in one period stay
113
+ unknown in the other, and their bounded lists include full counts. No row sums or
114
+ site-wide extrapolations are generated. Each row retains the original numeric values,
115
+ including GA strings; invalid or unsafe numbers get a null delta. Percent change is
116
+ null when the baseline is zero. CTR and position remain in their provider units.
117
+
118
+ `maxRows` defaults to 100 and is capped at 1,000 per observation/list; omitted counts
119
+ are explicit. The comparison includes `canonicalSha256` hashes of validated source objects, with
120
+ object keys sorted lexically and array order retained. These identify comparison
121
+ inputs, not raw file bytes; whitespace changes in saved JSON do not change them. Keep source snapshots for their full requests,
122
+ responses and metadata. Changes are descriptive and do not establish that an SEO
123
+ edit caused traffic changes; Pagesight does not apply SEO edits automatically.
package/docs/usage.md ADDED
@@ -0,0 +1,130 @@
1
+ # Using Pagesight
2
+
3
+ ## API
4
+
5
+ ```ts
6
+ import { execute } from "pagesight";
7
+
8
+ const report = await execute({
9
+ operation: "gsc.report",
10
+ site: "sc-domain:example.com",
11
+ request: {
12
+ startDate: "2026-08-01",
13
+ endDate: "2026-08-28",
14
+ dimensions: ["page"],
15
+ },
16
+ maxPages: 4,
17
+ });
18
+ ```
19
+
20
+ Each result contains `schemaVersion`, `provider`, `operation`, `target`, collection
21
+ timestamps, `status`, request/response `pages`, `warnings`, and any `error` and
22
+ `failedRequest`. Reports include `pagination` with `exhausted`, `nextOffset` and
23
+ `rowsReturned`. Raw provider metadata, aggregation, quota, sampling and thresholding
24
+ are retained. Exhausted pagination does **not** imply exhaustive search coverage.
25
+ GA evidence identifies the credential source variable, credential type, and service
26
+ account email when present. It never includes the token or private key. Aggregate
27
+ results include a concise per-observation `summary` alongside full observations.
28
+
29
+ | Operation | Required inputs |
30
+ | -------------------------------------------- | -------------------------------------------------------- |
31
+ | `discover` | `url`; optional `providers` (`["gsc", "ga"]` by default) |
32
+ | `bing.sites` | None |
33
+ | `bing.queries`, `bing.pages`, `bing.traffic` | `site` |
34
+ | `gsc.sites` | None |
35
+ | `gsc.sitemaps` | `site` |
36
+ | `gsc.inspect` | `site`, `url` |
37
+ | `gsc.report` | `site`, `request`; optional `maxPages` |
38
+ | `ga.accounts` | None |
39
+ | `ga.property`, `ga.key-events` | `property` |
40
+ | `ga.report` | `property`, `request`; optional `maxPages` |
41
+ | `page` | `url` |
42
+ | `speed.psi` | `url`; optional `strategy` (`mobile` or `desktop`) |
43
+ | `speed.crux`, `speed.history` | `url`; optional `origin: true`, `formFactor` |
44
+ | `doctor` | `config` |
45
+ | `snapshot` | `config`, `startDate`, `endDate`; optional `maxPages` |
46
+
47
+ `operationSchema` and `configSchema` are exported for typed validation. The MCP
48
+ `observe` input uses the same schema. `page` observes fetched HTML, status,
49
+ redirects, canonical, robots directives, JSON-LD and a content hash. It does not
50
+ execute browser JavaScript. The original MCP page tool retains its additional
51
+ link, social-meta and contrast checks.
52
+
53
+ ## CLI
54
+
55
+ ```sh
56
+ pagesight --help
57
+ pagesight discover --url https://example.com/ --providers gsc,ga
58
+ pagesight doctor --config seo.config.json
59
+ pagesight gsc report --site sc-domain:example.com --request report.json --max-pages 4
60
+ pagesight ga report --property 123456 --request ga-report.json
61
+ pagesight page --url https://example.com/
62
+ pagesight speed psi --url https://example.com/
63
+ pagesight speed crux --url https://example.com/ --origin
64
+ pagesight snapshot --config seo.config.json --out observations/baseline.json
65
+ pagesight api --request operation.json
66
+ ```
67
+
68
+ A GSC `report.json` uses the provider request shape. Defaults are finalized data,
69
+ Web search, no dimensions, 25,000 rows, offset zero. Ad hoc commands fetch one page
70
+ unless `--max-pages` is supplied (maximum 20). Request examples:
71
+
72
+ ```json
73
+ { "startDate": "2026-08-01", "endDate": "2026-08-28", "dimensions": ["page"] }
74
+ ```
75
+
76
+ ```json
77
+ {
78
+ "dateRanges": [{ "startDate": "2026-08-01", "endDate": "2026-08-28" }],
79
+ "dimensions": [{ "name": "eventName" }],
80
+ "metrics": [{ "name": "eventCount" }, { "name": "keyEvents" }],
81
+ "dimensionFilter": {
82
+ "filter": { "fieldName": "hostName", "stringFilter": { "matchType": "EXACT", "value": "example.com" } }
83
+ }
84
+ }
85
+ ```
86
+
87
+ GA report defaults are 10,000 rows, offset zero and quota metadata requested.
88
+ `rowCount` determines remaining pages. For discovery/key-event lists, retain and
89
+ check any `nextPageToken`; these small metadata requests currently return one page.
90
+ They return `status: partial` when another metadata page is available.
91
+
92
+ All data commands output JSON; `--json` is accepted. `--out` writes the same result.
93
+ Exit codes: 0 success, 1 provider failure, 2 invalid input, 3 partial evidence.
94
+ Partial snapshots are saved. A successful report can still have provider coverage
95
+ limitations; inspect warnings and metadata before making comparisons.
96
+
97
+ ## Local HTTP interface
98
+
99
+ ```sh
100
+ # Set PAGESIGHT_API_TOKEN in your private environment file (at least 24 characters).
101
+ pagesight serve --port 6095
102
+ ```
103
+
104
+ Send the shared operation JSON to `POST http://127.0.0.1:6095/v1/query` with
105
+ `Authorization: Bearer <PAGESIGHT_API_TOKEN>`. The server binds only to loopback.
106
+ Missing/invalid authentication returns 401; invalid operations return 400; provider
107
+ failures return 502; partial evidence returns 200 with `status: partial`.
108
+ This interface is for local agents, not an Internet deployment.
109
+
110
+ ## MCP compatibility
111
+
112
+ Run `pagesight mcp` to start the stdio MCP server. Configure your host to run
113
+ `bun /path/to/pagesight/packages/pagesight/src/index.ts mcp` with the environment above. Existing MCP
114
+ launch configurations must include the `mcp` argument; no arguments show CLI help.
115
+
116
+ The new `observe` tool accepts `{ "request": <operation object> }` and returns
117
+ structured API evidence. The original six tools remain available:
118
+
119
+ | Tool | Capability |
120
+ | -------- | ------------------------------------------------------------------------- |
121
+ | `audit` | PageSpeed, metadata, robots, sitemap processing errors and URL inspection |
122
+ | `page` | Metadata, links, JSON-LD checks, redirects and contrast |
123
+ | `speed` | PageSpeed and CrUX snapshots/history |
124
+ | `search` | GSC reports, sitemap metadata and selected URL inspection |
125
+ | `ai` | Robots and crawler-registry checks, llms.txt detection |
126
+ | `setup` | Existing GSC authentication helpers |
127
+
128
+ The legacy text tools do not invent indexed counts from deprecated sitemap fields,
129
+ extrapolate sample verdicts to the whole site, or treat missing comparison rows as zero.
130
+ Use `observe` for exact request/response evidence and pagination status.
package/package.json CHANGED
@@ -1,54 +1,51 @@
1
1
  {
2
2
  "name": "pagesight",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "See your site the way search engines and AI see it.",
5
5
  "keywords": [
6
- "seo",
6
+ "ai-crawlers",
7
+ "core-web-vitals",
7
8
  "geo",
8
9
  "google-search-console",
10
+ "mcp",
9
11
  "pagespeed-insights",
10
- "core-web-vitals",
11
- "web-performance",
12
12
  "robots-txt",
13
- "ai-crawlers",
14
- "mcp"
13
+ "seo",
14
+ "web-performance"
15
15
  ],
16
+ "homepage": "https://github.com/caiopizzol/pagesight",
17
+ "license": "MIT",
18
+ "author": "Caio Pizzol",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/caiopizzol/pagesight.git",
22
+ "directory": "packages/pagesight"
23
+ },
24
+ "bin": {
25
+ "pagesight": "src/index.ts"
26
+ },
16
27
  "files": [
17
28
  "src",
18
29
  "README.md",
19
- "LICENSE"
30
+ "LICENSE",
31
+ "docs"
20
32
  ],
21
33
  "type": "module",
22
- "main": "src/index.ts",
23
- "bin": {
24
- "pagesight": "src/index.ts"
34
+ "main": "src/api/index.ts",
35
+ "exports": {
36
+ ".": "./src/api/index.ts"
25
37
  },
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/caiopizzol/pagesight.git"
29
- },
30
- "homepage": "https://github.com/caiopizzol/pagesight",
31
- "author": "Caio Pizzol",
32
38
  "scripts": {
33
39
  "start": "bun run src/index.ts",
34
- "test": "bun test",
35
- "lint": "biome check src/",
36
- "format": "biome format --write src/"
40
+ "typecheck": "tsc -p tsconfig.json",
41
+ "test": "bun test __tests__"
37
42
  },
38
- "license": "MIT",
39
43
  "dependencies": {
40
44
  "@modelcontextprotocol/sdk": "^1.12.1",
45
+ "saxes": "^6.0.0",
41
46
  "zod": "^3.24.4"
42
47
  },
43
48
  "devDependencies": {
44
- "@biomejs/biome": "^2.4.10",
45
- "@semantic-release/commit-analyzer": "^13.0.1",
46
- "@semantic-release/git": "^10.0.1",
47
- "@semantic-release/github": "^12.0.6",
48
- "@semantic-release/npm": "^13.1.5",
49
- "@types/bun": "^1.3.11",
50
- "lefthook": "^2.1.4",
51
- "semantic-release": "^25.0.3",
52
- "semantic-release-ai-notes": "^0.2.3"
49
+ "@types/bun": "^1.3.11"
53
50
  }
54
51
  }