seo 0.0.15 → 0.1.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.
- package/LICENSE +201 -0
- package/PRIVACY.md +95 -0
- package/README.md +338 -35
- package/SECURITY.md +55 -0
- package/TERMS.md +94 -0
- package/TRADEMARKS.md +27 -0
- package/dist/cli.js +125 -0
- package/dist/cli.js.map +1 -0
- package/dist/dist-CSY2_p-j.js +713 -0
- package/dist/dist-CSY2_p-j.js.map +1 -0
- package/dist/dist-FeAUNn9A.js +3 -0
- package/dist/index.d.ts +17921 -0
- package/dist/index.js +26769 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +57 -0
- package/dist/mcp.js +26744 -0
- package/dist/mcp.js.map +1 -0
- package/dist/package-uzXzqDW6.js +23818 -0
- package/dist/package-uzXzqDW6.js.map +1 -0
- package/package.json +101 -23
- package/skills/README.md +81 -0
- package/skills/affected-urls/SKILL.md +39 -0
- package/skills/affected-urls/agents/openai.yaml +4 -0
- package/skills/ai-readiness/SKILL.md +34 -0
- package/skills/ai-readiness/agents/openai.yaml +4 -0
- package/skills/ai-referrals/SKILL.md +31 -0
- package/skills/ai-referrals/agents/openai.yaml +4 -0
- package/skills/audit-page/SKILL.md +50 -0
- package/skills/audit-page/agents/openai.yaml +4 -0
- package/skills/audit-urls/SKILL.md +39 -0
- package/skills/audit-urls/agents/openai.yaml +4 -0
- package/skills/cannibalisation/SKILL.md +31 -0
- package/skills/cannibalisation/agents/openai.yaml +4 -0
- package/skills/community-intent/SKILL.md +39 -0
- package/skills/community-intent/agents/openai.yaml +4 -0
- package/skills/compare-crawls/SKILL.md +40 -0
- package/skills/compare-crawls/agents/openai.yaml +4 -0
- package/skills/content-optimization/SKILL.md +31 -0
- package/skills/content-optimization/agents/openai.yaml +4 -0
- package/skills/crawl-diff/SKILL.md +51 -0
- package/skills/crawl-diff/agents/openai.yaml +4 -0
- package/skills/crawl-history/SKILL.md +37 -0
- package/skills/crawl-history/agents/openai.yaml +4 -0
- package/skills/crawl-report/SKILL.md +37 -0
- package/skills/crawl-report/agents/openai.yaml +4 -0
- package/skills/crawler-rules/SKILL.md +34 -0
- package/skills/crawler-rules/agents/openai.yaml +4 -0
- package/skills/ctr-underperformers/SKILL.md +31 -0
- package/skills/ctr-underperformers/agents/openai.yaml +4 -0
- package/skills/decaying-pages/SKILL.md +31 -0
- package/skills/decaying-pages/agents/openai.yaml +4 -0
- package/skills/entity-readiness/SKILL.md +34 -0
- package/skills/entity-readiness/agents/openai.yaml +4 -0
- package/skills/explain-crawl-issue/SKILL.md +32 -0
- package/skills/explain-crawl-issue/agents/openai.yaml +4 -0
- package/skills/generate-llms-txt/SKILL.md +37 -0
- package/skills/generate-llms-txt/agents/openai.yaml +4 -0
- package/skills/geo-gaps/SKILL.md +37 -0
- package/skills/geo-gaps/agents/openai.yaml +4 -0
- package/skills/index-coverage/SKILL.md +84 -0
- package/skills/index-coverage/agents/openai.yaml +4 -0
- package/skills/index-coverage-plan/SKILL.md +50 -0
- package/skills/index-coverage-plan/agents/openai.yaml +4 -0
- package/skills/index-monitor/SKILL.md +49 -0
- package/skills/index-monitor/agents/openai.yaml +4 -0
- package/skills/index-watch/SKILL.md +77 -0
- package/skills/index-watch/agents/openai.yaml +4 -0
- package/skills/internal-links/SKILL.md +31 -0
- package/skills/internal-links/agents/openai.yaml +4 -0
- package/skills/link-recovery/SKILL.md +51 -0
- package/skills/link-recovery/agents/openai.yaml +4 -0
- package/skills/llms-txt-audit/SKILL.md +34 -0
- package/skills/llms-txt-audit/agents/openai.yaml +4 -0
- package/skills/measure-change/SKILL.md +52 -0
- package/skills/measure-change/agents/openai.yaml +4 -0
- package/skills/monthly-action-plan/SKILL.md +50 -0
- package/skills/monthly-action-plan/agents/openai.yaml +4 -0
- package/skills/monthly-report/SKILL.md +50 -0
- package/skills/monthly-report/agents/openai.yaml +4 -0
- package/skills/narrative-report/SKILL.md +51 -0
- package/skills/narrative-report/agents/openai.yaml +4 -0
- package/skills/okf-build/SKILL.md +39 -0
- package/skills/okf-build/agents/openai.yaml +4 -0
- package/skills/okf-validate/SKILL.md +43 -0
- package/skills/okf-validate/agents/openai.yaml +4 -0
- package/skills/page-opportunities/SKILL.md +31 -0
- package/skills/page-opportunities/agents/openai.yaml +4 -0
- package/skills/performance/SKILL.md +50 -0
- package/skills/performance/agents/openai.yaml +4 -0
- package/skills/performance-audit/SKILL.md +31 -0
- package/skills/performance-audit/agents/openai.yaml +4 -0
- package/skills/pseo-audit/SKILL.md +103 -0
- package/skills/pseo-audit/agents/openai.yaml +4 -0
- package/skills/query-clusters/SKILL.md +31 -0
- package/skills/query-clusters/agents/openai.yaml +4 -0
- package/skills/quick-wins/SKILL.md +31 -0
- package/skills/quick-wins/agents/openai.yaml +4 -0
- package/skills/redirect-trace/SKILL.md +51 -0
- package/skills/redirect-trace/agents/openai.yaml +4 -0
- package/skills/refresh-priorities/SKILL.md +48 -0
- package/skills/refresh-priorities/agents/openai.yaml +4 -0
- package/skills/search-performance-overview/SKILL.md +48 -0
- package/skills/search-performance-overview/agents/openai.yaml +4 -0
- package/skills/second-page/SKILL.md +50 -0
- package/skills/second-page/agents/openai.yaml +4 -0
- package/skills/segment-impact/SKILL.md +50 -0
- package/skills/segment-impact/agents/openai.yaml +4 -0
- package/skills/seo/SKILL.md +74 -0
- package/skills/seo/agents/openai.yaml +4 -0
- package/skills/seo-fix-queue/SKILL.md +50 -0
- package/skills/seo-fix-queue/agents/openai.yaml +4 -0
- package/skills/seo-geo-readiness/SKILL.md +60 -0
- package/skills/seo-geo-readiness/agents/openai.yaml +4 -0
- package/skills/seo-site-audit/SKILL.md +59 -0
- package/skills/seo-site-audit/agents/openai.yaml +4 -0
- package/skills/seo-to-ai-query/SKILL.md +31 -0
- package/skills/seo-to-ai-query/agents/openai.yaml +4 -0
- package/skills/setup-check/SKILL.md +49 -0
- package/skills/setup-check/agents/openai.yaml +4 -0
- package/skills/site-crawl/SKILL.md +39 -0
- package/skills/site-crawl/agents/openai.yaml +4 -0
- package/skills/striking-distance/SKILL.md +52 -0
- package/skills/striking-distance/agents/openai.yaml +4 -0
- package/skills/technical-watch/SKILL.md +49 -0
- package/skills/technical-watch/agents/openai.yaml +4 -0
- package/skills/top-fixes/SKILL.md +38 -0
- package/skills/top-fixes/agents/openai.yaml +4 -0
- package/skills/traffic-anomaly/SKILL.md +52 -0
- package/skills/traffic-anomaly/agents/openai.yaml +4 -0
- package/skills/update-correlation/SKILL.md +51 -0
- package/skills/update-correlation/agents/openai.yaml +4 -0
- package/skills/update-postmortem/SKILL.md +49 -0
- package/skills/update-postmortem/agents/openai.yaml +4 -0
- package/.jshintrc +0 -18
- package/.npmignore +0 -3
- package/.travis.yml +0 -3
- package/Makefile +0 -10
- package/index.js +0 -2
- package/lib/middleware.js +0 -159
- package/lib/seo.js +0 -32
- package/test/init.js +0 -43
- package/test/middleware.test.js +0 -111
- package/test/seo-page-result.html +0 -9
- package/test/seo-page.html +0 -9
- package/test/seo-routes.js +0 -5
- package/test/vendor/jquery-1.11.1.min.js +0 -4
package/package.json
CHANGED
|
@@ -1,36 +1,114 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seo",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SEO Skills CLI and MCP for finding technical problems, ranking fixes with search data, and running reports locally.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"author": "Ian Nuttall",
|
|
8
|
+
"homepage": "https://seoskills.dev",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git://github.com/
|
|
11
|
+
"url": "git+https://github.com/iannuttall/seo.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/iannuttall/seo/issues"
|
|
12
15
|
},
|
|
13
16
|
"keywords": [
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
17
|
+
"seo",
|
|
18
|
+
"search-console",
|
|
19
|
+
"google-analytics",
|
|
20
|
+
"crawler",
|
|
21
|
+
"cli",
|
|
22
|
+
"mcp"
|
|
18
23
|
],
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./mcp": {
|
|
33
|
+
"types": "./dist/mcp.d.ts",
|
|
34
|
+
"import": "./dist/mcp.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"bin": {
|
|
39
|
+
"seo": "./dist/cli.js"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"skills",
|
|
44
|
+
"PRIVACY.md",
|
|
45
|
+
"SECURITY.md",
|
|
46
|
+
"TERMS.md",
|
|
47
|
+
"TRADEMARKS.md"
|
|
48
|
+
],
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public",
|
|
51
|
+
"provenance": true
|
|
52
|
+
},
|
|
53
|
+
"packageManager": "pnpm@11.11.0",
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=22.19.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"auth:inject-shared-client": "node scripts/inject-shared-oauth-client.mjs",
|
|
59
|
+
"build": "turbo run build && pnpm run build:package",
|
|
60
|
+
"build:package": "tsdown --config tsdown.config.ts",
|
|
61
|
+
"clean": "turbo run clean && rm -rf dist",
|
|
62
|
+
"dev": "turbo run dev",
|
|
63
|
+
"lint": "biome check . && node scripts/check-emdashes.mjs && node scripts/check-report-parity.mjs && pnpm run skills:validate && turbo run lint",
|
|
64
|
+
"lint:fix": "biome check . --write",
|
|
65
|
+
"loc:audit": "node scripts/loc-audit.mjs",
|
|
66
|
+
"pack:check": "pnpm pack --dry-run",
|
|
67
|
+
"prepack": "pnpm run skills:validate && pnpm run build:package && node --test scripts/package.test.mjs",
|
|
68
|
+
"security:audit": "pnpm audit --audit-level low",
|
|
69
|
+
"security:check": "pnpm run security:audit && pnpm run security:secrets",
|
|
70
|
+
"security:secrets": "node scripts/security-secrets.mjs",
|
|
71
|
+
"skills:validate": "node scripts/validate-skills.mjs",
|
|
72
|
+
"test": "turbo run test && pnpm run build:package && node --test scripts/package.test.mjs && pnpm run skills:validate",
|
|
73
|
+
"test:package-install": "pnpm run build:package && node --test scripts/installed-package.test.mjs",
|
|
74
|
+
"typecheck": "turbo run typecheck"
|
|
23
75
|
},
|
|
24
|
-
"homepage": "https://github.com/saschagehlich/node-seo",
|
|
25
76
|
"dependencies": {
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
77
|
+
"@clack/prompts": "^1.7.0",
|
|
78
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
79
|
+
"@mozilla/readability": "^0.6.0",
|
|
80
|
+
"@napi-rs/keyring": "^1.3.0",
|
|
81
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
82
|
+
"@types/node": "^22.20.1",
|
|
83
|
+
"better-sqlite3": "^12.11.1",
|
|
84
|
+
"citty": "^0.2.2",
|
|
85
|
+
"cli-table3": "^0.6.5",
|
|
86
|
+
"consola": "^3.4.2",
|
|
87
|
+
"debug": "^4.4.3",
|
|
88
|
+
"defuddle": "^0.19.1",
|
|
89
|
+
"jsonc-parser": "^3.3.1",
|
|
90
|
+
"lighthouse": "13.4.0",
|
|
91
|
+
"linkedom": "^0.18.13",
|
|
92
|
+
"open": "^11.0.0",
|
|
93
|
+
"p-queue": "^9.3.1",
|
|
94
|
+
"p-retry": "^8.0.0",
|
|
95
|
+
"picocolors": "^1.1.1",
|
|
96
|
+
"pino": "^10.3.1",
|
|
97
|
+
"pino-pretty": "^13.1.3",
|
|
98
|
+
"playwright-core": "1.61.1",
|
|
99
|
+
"proper-lockfile": "^4.1.2",
|
|
100
|
+
"robots-parser": "^3.0.1",
|
|
101
|
+
"schema-dts": "^2.0.0",
|
|
102
|
+
"undici": "^8.7.0",
|
|
103
|
+
"update-notifier": "^7.3.1",
|
|
104
|
+
"user-agents": "2.1.117",
|
|
105
|
+
"zod": "^4.4.3"
|
|
29
106
|
},
|
|
30
107
|
"devDependencies": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
108
|
+
"@biomejs/biome": "^2.5.3",
|
|
109
|
+
"@changesets/cli": "^2.31.0",
|
|
110
|
+
"tsdown": "^0.22.4",
|
|
111
|
+
"turbo": "^2.10.4",
|
|
112
|
+
"typescript": "^6.0.3"
|
|
35
113
|
}
|
|
36
114
|
}
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Agent skills
|
|
2
|
+
|
|
3
|
+
These skills teach an agent how to use `seo` without reading the whole repo.
|
|
4
|
+
|
|
5
|
+
They work best with the MCP server installed. This command is an interactive
|
|
6
|
+
setup flow for a human:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
seo mcp install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
They can also call the CLI directly when MCP tools are not available. The npm
|
|
13
|
+
package and repository contain the same skill folders. Install the collection
|
|
14
|
+
with the standard agent skills installer:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx skills add iannuttall/seo --all
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Use `seo skills list` or `seo skills path <name>` to inspect the copies bundled
|
|
21
|
+
with the npm package.
|
|
22
|
+
|
|
23
|
+
The MCP path is deliberately small: discover ids with `seo_list_reports`, load
|
|
24
|
+
one schema with `seo_describe_report`, then execute it with `seo_run_report`.
|
|
25
|
+
The skills name the report ids for their workflow.
|
|
26
|
+
|
|
27
|
+
The same catalog is available without MCP:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
seo reports list --json
|
|
31
|
+
seo reports describe <report-id> --json
|
|
32
|
+
seo reports run <report-id> --params '<json>' --json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Adding a report skill
|
|
36
|
+
|
|
37
|
+
Register a structured report once in `packages/mcp/src/report-registry.ts`.
|
|
38
|
+
CLI and MCP discovery will then share its id, description, input schema, and
|
|
39
|
+
handler. Add the same-name skill only after that contract exists.
|
|
40
|
+
|
|
41
|
+
Every report skill must:
|
|
42
|
+
|
|
43
|
+
- explain the technical SEO question and why it is useful;
|
|
44
|
+
- show `seo_list_reports`, `seo_describe_report`, and `seo_run_report` usage;
|
|
45
|
+
- show schema discovery and one valid `seo reports run` CLI example;
|
|
46
|
+
- explain the evidence fields, partial-data states, and important caveats;
|
|
47
|
+
- turn findings into bounded actions and verification steps; and
|
|
48
|
+
- avoid turning estimates, conventions, or samples into search-engine rules.
|
|
49
|
+
|
|
50
|
+
Run `pnpm skills:validate` after adding or changing a skill. The validator
|
|
51
|
+
checks registry parity, command and tool names, frontmatter, package metadata,
|
|
52
|
+
and minimum report guidance depth.
|
|
53
|
+
|
|
54
|
+
## Curated workflow skills
|
|
55
|
+
|
|
56
|
+
- `seo-site-audit`: start with the main report, then add bounded technical evidence.
|
|
57
|
+
- `seo-geo-readiness`: check AI-search readiness and citation gaps.
|
|
58
|
+
- `seo-fix-queue`: turn crawl results into an implementation queue.
|
|
59
|
+
- `pseo-audit`: audit repeated URL templates with GSC, crawl, and URL Inspection evidence.
|
|
60
|
+
- `index-watch`: monitor exact indexed-state evidence, transitions, failures, and quota-deferred checks.
|
|
61
|
+
- `performance`: separate Lighthouse lab diagnostics, CrUX field Core Web Vitals, and unscored fallback evidence.
|
|
62
|
+
- `community-intent`: review explicit intent language in retained GSC queries without claiming a page gap.
|
|
63
|
+
- `seo-to-ai-query`: create deterministic monitoring-prompt suggestions from retained GSC queries.
|
|
64
|
+
- `measure-change`: compare equal finalized GSC windows without turning an incomplete after-period into a directional verdict.
|
|
65
|
+
|
|
66
|
+
The `seo` skill routes requests that span several focused workflows.
|
|
67
|
+
|
|
68
|
+
## Report skills
|
|
69
|
+
|
|
70
|
+
Every compact MCP report id has a same-name skill. Each skill teaches the
|
|
71
|
+
discovery flow and the evidence limits that matter for that report.
|
|
72
|
+
|
|
73
|
+
- Setup: `setup-check`.
|
|
74
|
+
- Diagnosis: `search-performance-overview`, `segment-impact`, `striking-distance`, `traffic-anomaly`, `update-correlation`.
|
|
75
|
+
- Opportunities: `cannibalisation`, `ctr-underperformers`, `decaying-pages`, `internal-links`, `query-clusters`, `quick-wins`.
|
|
76
|
+
- AI search: `ai-referrals`, `community-intent`, `content-optimization`, `page-opportunities`, `performance-audit`, `seo-to-ai-query`.
|
|
77
|
+
- Crawl: `affected-urls`, `ai-readiness`, `audit-urls`, `compare-crawls`, `site-crawl`, `entity-readiness`, `explain-crawl-issue`, `geo-gaps`, `crawl-report`, `crawl-history`, `crawler-rules`, `llms-txt-audit`, `generate-llms-txt`, `okf-build`, `okf-validate`, `top-fixes`.
|
|
78
|
+
- Monitoring: `crawl-diff`, `index-coverage`, `index-coverage-plan`, `index-monitor`, `index-watch`, `link-recovery`, `redirect-trace`.
|
|
79
|
+
- Reporting: `audit-page`, `monthly-report`, `pseo-audit`, `narrative-report`, `second-page`.
|
|
80
|
+
- Experiments: `measure-change`.
|
|
81
|
+
- Workflows: `monthly-action-plan`, `refresh-priorities`, `technical-watch`, `update-postmortem`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: affected-urls
|
|
3
|
+
description: Find the exact crawl issues attached to individual URLs and preserve their joined traffic evidence. Use when turning a rule, category, or severity group into a bounded implementation list.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Find affected URLs
|
|
7
|
+
|
|
8
|
+
Use this report after a crawl has identified a technical pattern. A rule count is useful for triage, but implementation needs the exact URLs, the observed evidence, and a stable source crawl. Prefer `reportId` so every follow-up refers to the same snapshot; pass `url` only when a new crawl is intentional.
|
|
9
|
+
|
|
10
|
+
## Run it
|
|
11
|
+
|
|
12
|
+
For MCP, call `seo_list_reports` with category `crawl` only when discovery is needed. Then call `seo_describe_report` with `{ "id": "affected-urls" }`. Finally call `seo_run_report` with:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"id": "affected-urls",
|
|
17
|
+
"params": {
|
|
18
|
+
"reportId": "crawl_example_20260710",
|
|
19
|
+
"ruleId": "missing_title",
|
|
20
|
+
"severity": "high",
|
|
21
|
+
"limit": 50
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Read MCP `structuredContent` as the contract and check `isError` before using it. The text result is a compact explanation, not the data source.
|
|
27
|
+
|
|
28
|
+
The CLI exposes the same report:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
seo reports describe affected-urls --json
|
|
32
|
+
seo reports run affected-urls --params '{"reportId":"crawl_example_20260710","ruleId":"missing_title","severity":"high","limit":50}' --json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Read and act
|
|
36
|
+
|
|
37
|
+
Each row ties a URL to a rule, category, severity, and crawler evidence. Optional clicks, impressions, and sessions help order work, but inspect `dataSources` first: unavailable provider data must not be interpreted as a real zero. Results are sorted deterministically by severity, joined demand signals, and URL. The `selection` object reports `totalMatchedRows`, `returnedRows`, `limit`, and `truncated`; preserve it whenever the URL array is passed downstream.
|
|
38
|
+
|
|
39
|
+
Check the requested filters, selection metadata, original crawl cap, warnings, and caveats before calling the set complete. `truncated: true` means more matching issue rows exist in this report than were returned. A capped or partial crawl only supports "affected among evaluated pages." Create fixes from the observed evidence, sample several URL templates, and use `explain-crawl-issue` for rule guidance. Re-run the same bounded crawl after deployment to verify that the rule no longer triggers; disappearance from a differently scoped crawl is not verification.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ai-readiness
|
|
3
|
+
description: Assess technical AI-search readiness without inventing a visibility score or citation forecast. Use when checking access, indexability, snippets, page structure, and optional agent resources from crawl evidence.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Assess AI readiness
|
|
7
|
+
|
|
8
|
+
AI-search systems can only use content they can retrieve and interpret, but technical eligibility is not selection. This report keeps access, indexability, snippet controls, content observations, bot policy, and agent resources separate. It deliberately returns an evidence-only assessment instead of an aggregate score.
|
|
9
|
+
|
|
10
|
+
## Run it
|
|
11
|
+
|
|
12
|
+
For MCP, call `seo_list_reports` with category `crawl` if the report id is not already known. Call `seo_describe_report` with `{ "id": "ai-readiness" }`, then `seo_run_report` with:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"id": "ai-readiness",
|
|
17
|
+
"params": { "reportId": "crawl_example_20260710" }
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Use `structuredContent` after confirming `isError` is false. The equivalent CLI flow is:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
seo reports describe ai-readiness --json
|
|
25
|
+
seo reports run ai-readiness --params '{"reportId":"crawl_example_20260710"}' --json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Supplying `url` instead of `reportId` starts a fresh crawl. Reusing a saved report makes this assessment comparable with other follow-ups.
|
|
29
|
+
|
|
30
|
+
## Interpret the assessment
|
|
31
|
+
|
|
32
|
+
Start with `dataStatus`, the crawl caveats, and each check's `evaluated` flag. `unknown` means the necessary evidence was unavailable; it is not a failure or a pass. Bot access describes the observed policy for the crawl entry point, not proven access to every URL. Valid JSON-LD is syntax evidence, not proof of entity recognition or rich-result eligibility. An optional protocol file can aid machine discovery but its absence is not a search defect.
|
|
33
|
+
|
|
34
|
+
Prioritize hard technical conflicts first: failed responses, blocked crawling, explicit non-indexing, or restrictive snippet directives where those settings contradict publisher intent. Then review semantic structure and answerable content as observations, not requirements. Verify changes with a fresh crawl using the same scope. Never translate a clean report into claims about indexing, rankings, AI visibility, selection, citations, or traffic; those outcomes require separate evidence.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ai-referrals
|
|
3
|
+
description: Measure sessions and landing pages attributed to known AI referral sources in GA4; use when an agent needs bounded analytics evidence without equating missing referrers with zero AI visibility.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AI referrals
|
|
7
|
+
|
|
8
|
+
Use this report to see which known AI referral domains appeared as GA4 session sources, which landing pages received those sessions, and how activity changed by day. It is useful for observed referral analysis, not for measuring every mention or citation. Referrers can be stripped, reclassified, or recorded as direct or unassigned traffic, so an empty result is not proof that no AI system sent or cited the site.
|
|
9
|
+
|
|
10
|
+
## Run the report
|
|
11
|
+
|
|
12
|
+
Use the compact MCP flow:
|
|
13
|
+
|
|
14
|
+
1. Call `seo_list_reports` with `{"category":"ai-search"}`.
|
|
15
|
+
2. Call `seo_describe_report` with `{"id":"ai-referrals"}` and inspect the current schema.
|
|
16
|
+
3. Call `seo_run_report` with `{"id":"ai-referrals","params":{"property":"123456789","startDate":"28daysAgo","endDate":"yesterday","limit":25}}`.
|
|
17
|
+
|
|
18
|
+
The CLI uses the same registry and handler:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
seo reports describe ai-referrals --json
|
|
22
|
+
seo reports run ai-referrals --params '{"property":"123456789","startDate":"28daysAgo","endDate":"yesterday","resultLimit":25}' --json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`property` is required. Dates accept `YYYY-MM-DD` or GA4 relative dates such as `28daysAgo`. `maxRows` bounds retained provider rows. `resultLimit` controls how many of the highest-session landing pages are returned (25 by default); use it to ask for a smaller or larger ranked review set. `limit` is a legacy alias for `maxRows`, so do not use it in new commands.
|
|
26
|
+
|
|
27
|
+
## Interpret and act
|
|
28
|
+
|
|
29
|
+
Start with `dataStatus`, `range`, `methodology`, and `dataSource.partialReasons`. Check `possiblyTruncated`, query-level statuses, warnings, returned rows, and the GA4 time zone before comparing totals. `summary.sessions` and `summary.eventCount` are additive; `summary.totalUsers` can be unavailable and must not be reconstructed by adding per-source or per-page values. Check `selection.landingPages` before treating `landingPages` as the whole retained breakdown: it states the output limit and any lower-ranked rows omitted from the response. Use `sources[].observedSessionSources` to preserve the exact attribution evidence, `shareOfAiSessions` only within detected AI sessions, and the returned `landingPages` to choose pages for a qualitative review.
|
|
30
|
+
|
|
31
|
+
Safe actions include checking whether high-volume landing pages answer the referring context, comparing complete like-for-like periods, and annotating material changes. Do not claim that referral sessions caused conversions, represent all AI traffic, or reveal the prompt, answer, citation, or user intent that produced the visit.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-page
|
|
3
|
+
description: Audit one fetched URL for technical and on-page evidence. Use it to inspect a specific page without turning page-level observations into sitewide claims.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Audit page
|
|
7
|
+
|
|
8
|
+
Use this report when a URL needs direct inspection: after a release, while
|
|
9
|
+
investigating a search result, or before recommending a page edit. It combines
|
|
10
|
+
the fetched document with metadata, headings, links, structured data, and
|
|
11
|
+
optional GSC evidence. It does not prove how every crawler rendered the page,
|
|
12
|
+
that Google indexed the fetched version, or that an observed convention affects
|
|
13
|
+
rankings.
|
|
14
|
+
|
|
15
|
+
## Run it
|
|
16
|
+
|
|
17
|
+
Use the exact MCP discovery flow:
|
|
18
|
+
|
|
19
|
+
1. Call `seo_list_reports` with `category: "reporting"` and select `audit-page`.
|
|
20
|
+
2. Call `seo_describe_report` with `id: "audit-page"`; do not guess fields.
|
|
21
|
+
3. Call `seo_run_report` with `id: "audit-page"` and parameters matching that schema.
|
|
22
|
+
|
|
23
|
+
The CLI has the same contract:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
seo reports describe audit-page --json
|
|
27
|
+
seo reports run audit-page --params '{"url":"https://example.com/product","site":"sc-domain:example.com","refresh":true}' --json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`url` is required. `site` adds Search Console context when access exists.
|
|
31
|
+
Enable `js` only when client rendering is necessary; omitted rendering behavior
|
|
32
|
+
is selected by the report. `refresh` bypasses reusable cached evidence.
|
|
33
|
+
|
|
34
|
+
## Interpret and act
|
|
35
|
+
|
|
36
|
+
Start with `fetchDiagnostics`, warnings, and the final fetched URL. A redirect,
|
|
37
|
+
blocked response, rendering failure, or non-HTML response limits every later
|
|
38
|
+
observation. Then inspect the observed page fields, structured-data findings,
|
|
39
|
+
issues, and recommendations. Title pixel width is an estimator for review, not
|
|
40
|
+
a Google limit. Heading counts describe document structure; more or fewer than
|
|
41
|
+
one H1 is not automatically a defect. Content length is evidence, not a quality
|
|
42
|
+
score. If GSC metrics are present, keep their window and property semantics
|
|
43
|
+
attached.
|
|
44
|
+
|
|
45
|
+
Safe actions are concrete and reversible: repair a broken canonical, make
|
|
46
|
+
important content available in the fetched HTML, correct invalid structured
|
|
47
|
+
data, or investigate a failed response. Verify intent before changing
|
|
48
|
+
`noindex`, canonicals, robots controls, headings, or snippet directives. One
|
|
49
|
+
page cannot support a sitewide conclusion. Read MCP `structuredContent` as the
|
|
50
|
+
machine contract and use Markdown only for the human explanation.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audit-urls
|
|
3
|
+
description: Audit a known URL set without implying sitewide coverage and optionally save the snapshot for follow-ups. Use for release checks, templates, migrations, or a bounded remediation list.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Audit an explicit URL list
|
|
7
|
+
|
|
8
|
+
Use this report when the URLs are already known. It avoids sitemap discovery and link traversal, so the result answers "what was observed on these pages?" rather than "what is wrong across the site?" This makes it useful for pre-release checks, representative templates, and verifying a fix list.
|
|
9
|
+
|
|
10
|
+
## Run it
|
|
11
|
+
|
|
12
|
+
For MCP, discover with `seo_list_reports` category `crawl` only if needed. Describe the contract with `seo_describe_report` and `{ "id": "audit-urls" }`. Then call `seo_run_report` with:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"id": "audit-urls",
|
|
17
|
+
"params": {
|
|
18
|
+
"urls": [
|
|
19
|
+
"https://example.com/",
|
|
20
|
+
"https://example.com/pricing"
|
|
21
|
+
],
|
|
22
|
+
"includeIssues": true,
|
|
23
|
+
"saveReport": true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Check `isError`, then consume `structuredContent`. CLI parity is exact:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
seo reports describe audit-urls --json
|
|
32
|
+
seo reports run audit-urls --params '{"urls":["https://example.com/","https://example.com/pricing"],"includeIssues":true,"saveReport":true}' --json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Read and verify
|
|
36
|
+
|
|
37
|
+
Compare requested URLs with attempted, fetched, failed, retained, and omitted counts. Review response evidence, issue summaries, `requestEvidenceStatus`, warnings, and caveats before acting. `includeIssues` returns the rule inventory; `includePages` adds larger page and request records and should only be enabled when the decision needs them. Saving the report gives later commands a stable `reportId`.
|
|
38
|
+
|
|
39
|
+
A successful sample does not prove the same template works everywhere, and a failed request may reflect a transient network condition rather than a persistent SEO defect. Group findings by shared implementation, confirm intentional canonicals, robots directives, and `noindex` settings with the publisher, then fix the template rather than individual URLs where appropriate. Re-run the identical URL list after deployment. A URL omitted from the next request is not a verified fix, and this bounded audit must never be described as complete site coverage.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cannibalisation
|
|
3
|
+
description: Find retained GSC queries with material exposure across multiple URLs; use when an agent needs an intent and technical review queue rather than an automatic consolidation verdict.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Multi-URL query exposure
|
|
7
|
+
|
|
8
|
+
Use this report to find exact normalized queries whose retained GSC impressions are materially distributed across more than one URL. It combines query/page exposure with property-level query demand, suppresses low-actionability cases, and ranks review candidates using demand and secondary exposure. Multiple ranking URLs can be correct for mixed intent, local/entity results, or distinct page purposes, so the report deliberately calls them URL-overlap candidates rather than proven harmful cannibalisation.
|
|
9
|
+
|
|
10
|
+
## Run the report
|
|
11
|
+
|
|
12
|
+
Use the compact MCP flow:
|
|
13
|
+
|
|
14
|
+
1. Call `seo_list_reports` with `{"category":"opportunities"}`.
|
|
15
|
+
2. Call `seo_describe_report` with `{"id":"cannibalisation"}`.
|
|
16
|
+
3. Call `seo_run_report` with `{"id":"cannibalisation","params":{"site":"sc-domain:example.com","days":90,"limit":20,"minImpressions":100,"includeBrand":false}}`.
|
|
17
|
+
|
|
18
|
+
The CLI runs the identical definition:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
seo reports describe cannibalisation --json
|
|
22
|
+
seo reports run cannibalisation --params '{"site":"sc-domain:example.com","days":90,"limit":20,"minImpressions":100,"includeBrand":false}' --json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`site` is required. `brandTerms` accepts up to 20 explicit terms; use `includeBrand:true` only when navigational brand overlap is part of the investigation.
|
|
26
|
+
|
|
27
|
+
## Interpret and act
|
|
28
|
+
|
|
29
|
+
Start with `dataStatus`, both `source.pageExposure` and `source.propertyDemand`, their validation counts, caps, and `source.completeness`. A partial or possibly truncated source cannot support an all-clear. Use `selection` to see why groups were excluded or suppressed. Within each item, inspect every page's clicks, impressions, position, impression share, template, `reviewContext`, HHI, and secondary exposure. `suggestedOwnerUrl` is chosen mechanically by clicks, then impressions, then position; its confidence is low and `requiresIntentReview` is true. `priority.score` is a heuristic, not estimated click lift.
|
|
30
|
+
|
|
31
|
+
Safe actions include comparing intent and live SERPs, checking canonicals and redirects, clarifying internal-link ownership, or differentiating genuinely distinct pages. Consolidate only when intent, content, technical signals, and business purpose agree. Never redirect or canonicalize a secondary URL solely because it appears in this report.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: community-intent
|
|
3
|
+
description: Find explicit forum, comparison, review, experience, and recommendation language in retained Google Search Console queries. Use when an agent needs to review community-style search intent, rank query hypotheses, or decide which ranking pages need manual intent and SERP inspection.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Community intent
|
|
7
|
+
|
|
8
|
+
Call `seo_list_reports` with category `ai-search` when discovery is needed.
|
|
9
|
+
Call `seo_describe_report` with id `community-intent`, then call
|
|
10
|
+
`seo_run_report` with that id and only the described parameters. Read
|
|
11
|
+
`structuredContent` as the machine contract. Use the CLI when MCP is
|
|
12
|
+
unavailable:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
seo reports describe community-intent --json
|
|
16
|
+
seo reports run community-intent --params '{"site":"sc-domain:example.com","days":90,"minImpressions":20,"limit":25}' --json
|
|
17
|
+
seo community-intent --project <project> --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The generic runner validates the exact MCP schema before any provider call.
|
|
21
|
+
Use the focused command when a human needs named flags and project-profile
|
|
22
|
+
selection. Both paths execute the same report.
|
|
23
|
+
|
|
24
|
+
For a reproducible report pass `startDate` and `endDate` to MCP or use `--start-date` and `--end-date` in the CLI. Keep the range inside `source.availableDateWindow`. Do not combine an exact range with `days`.
|
|
25
|
+
|
|
26
|
+
## Read the evidence first
|
|
27
|
+
|
|
28
|
+
1. Check `dataStatus`, `source.completeness`, `warnings`, and `caveats`.
|
|
29
|
+
2. Use `selection.classifiedRows` for every retained match. Use `selection.returnedRows` for the limited result set.
|
|
30
|
+
3. Treat a capped or partial zero as inconclusive. GSC may omit lower-click queries.
|
|
31
|
+
4. Report `intent`, `signals`, and `matchedTerms` as low-confidence language heuristics.
|
|
32
|
+
|
|
33
|
+
The classifier uses English patterns. It does not inspect the live SERP, identify the ranking URL, or verify page content. Never state that a page has a content gap from this report alone.
|
|
34
|
+
|
|
35
|
+
## Turn a result into an action
|
|
36
|
+
|
|
37
|
+
Use each item as a review queue. Retrieve GSC query/page rows to identify every associated URL, inspect the current search results, then check each relevant page against the observed query language. Recommend a content change only when page or SERP evidence supports it.
|
|
38
|
+
|
|
39
|
+
Use explicit `brandTerms` when the brand cannot be derived reliably from the property. Keep `includeBrand` false unless branded demand is part of the question.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compare-crawls
|
|
3
|
+
description: Compare two saved crawl snapshots with explicit provenance and completeness. Use it to separate observed page changes from crawl-scope, cap, configuration, or source noise.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Compare crawl snapshots
|
|
7
|
+
|
|
8
|
+
A crawl diff is useful only when its inputs are comparable. This report surfaces page, issue, response, indexability, title, content, and summary changes between two saved snapshots. By default, `after` means the latest report and `before` means the previous report, optionally within one `site` filter.
|
|
9
|
+
|
|
10
|
+
## Run it
|
|
11
|
+
|
|
12
|
+
For MCP, use `seo_list_reports` with category `crawl` only for discovery. Call `seo_describe_report` with `{ "id": "compare-crawls" }`, then call `seo_run_report` with:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"id": "compare-crawls",
|
|
17
|
+
"params": {
|
|
18
|
+
"after": "latest",
|
|
19
|
+
"before": "previous",
|
|
20
|
+
"site": "sc-domain:example.com"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Read `structuredContent` after checking `isError`. The CLI uses the same parameters:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
seo reports describe compare-crawls --json
|
|
29
|
+
seo reports run compare-crawls --params '{"after":"latest","before":"previous","site":"sc-domain:example.com"}' --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use explicit report ids for a release decision so "latest" cannot move between runs.
|
|
33
|
+
|
|
34
|
+
## Establish comparability first
|
|
35
|
+
|
|
36
|
+
Read `comparability.status` before interpreting any delta. The accompanying flags show whether the definition ids, config hashes, sites, start URLs, modes, request scopes, and caps match. `before` and `after` preserve each report id, status, normalized `config`, explicit `requestScope`, `caps`, request-evidence status, joined data-source status, warnings, caveats, and completeness. This is enough to assess the inputs without loading two separate reports.
|
|
37
|
+
|
|
38
|
+
Next inspect top-level `completeness`. If `truncated` is true, or either input is partial or failed, read its stable reason codes and the report-level `caveats`. An absent page from a capped, skipped, failed, or differently scoped crawl is not proven removed. Source row caps also limit joined GSC or GA4 evidence even when the document crawl completed.
|
|
39
|
+
|
|
40
|
+
Only then inspect `summary`, `pageChanges`, and `issueChanges`. These fields describe retained observations between the named snapshots. Prioritize newly observed response failures, unintended indexability flips, and issue groups that affect more URLs, then verify titles and content on the affected URLs. Confirm fixes with the same definition and request scope after deployment. When comparability requires review, describe the change as observed between snapshots and name the differing scope, cap, configuration, or incomplete source instead of attributing it to the release.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: content-optimization
|
|
3
|
+
description: Build a content brief for one URL from retained GSC queries and live page observations; use when an agent needs evidence-led edit ideas without treating query wording as a content mandate.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Content optimization
|
|
7
|
+
|
|
8
|
+
Use this report when an existing page has first-party search visibility and needs a focused review. It joins exact-URL GSC query/page rows to a fetched page, classifies query wording into broad intent heuristics, and turns verified opportunity types into title, H1, meta, section, and internal-link angles. It does not prove searcher intent, diagnose why a page ranks where it does, or guarantee that adding the suggested wording will improve traffic.
|
|
9
|
+
|
|
10
|
+
## Run the report
|
|
11
|
+
|
|
12
|
+
Use the compact MCP flow:
|
|
13
|
+
|
|
14
|
+
1. Call `seo_list_reports` with `{"category":"ai-search"}`.
|
|
15
|
+
2. Call `seo_describe_report` with `{"id":"content-optimization"}`.
|
|
16
|
+
3. Call `seo_run_report` with `{"id":"content-optimization","params":{"site":"sc-domain:example.com","url":"https://example.com/guides/seo","days":90,"limit":20,"minImpressions":50,"verifyContent":true}}`.
|
|
17
|
+
|
|
18
|
+
The CLI runs the same definition:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
seo reports describe content-optimization --json
|
|
22
|
+
seo reports run content-optimization --params '{"site":"sc-domain:example.com","url":"https://example.com/guides/seo","days":90,"limit":20,"minImpressions":50,"verifyContent":true}' --json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`site` and an HTTP(S) `url` are required. The URL must belong to the selected GSC property. Set `js:true` only when the useful content requires rendering; use `refresh:true` when stale cache evidence would change the decision.
|
|
26
|
+
|
|
27
|
+
## Interpret and act
|
|
28
|
+
|
|
29
|
+
Read `sourceReport` before the derived brief. Check its `dataStatus`, `selection`, `benchmark.possiblyTruncated`, `verification.status`, warnings, and caveats. Treat `summary.score`, `primaryIntent`, and `estimatedClickLift` as prioritisation heuristics, not quality grades or forecasts. In `topActions`, separate `technical-check` and `unverified` items from verified `content-gap`, `serp-framing`, `ctr`, or `ranking` observations. Review `intentMix` and the source query metrics so a high-impression theme does not get mistaken for a universal user need.
|
|
30
|
+
|
|
31
|
+
Safe actions are to fix contradictory technical evidence first, improve a clearly missing answer block, test clearer SERP framing when the body already covers the topic, or leave a well-covered page alone. Do not create one thin section per query, force exact-match wording, change the canonical target, or expand content solely to raise the report score.
|