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.
Files changed (146) hide show
  1. package/LICENSE +201 -0
  2. package/PRIVACY.md +95 -0
  3. package/README.md +338 -35
  4. package/SECURITY.md +55 -0
  5. package/TERMS.md +94 -0
  6. package/TRADEMARKS.md +27 -0
  7. package/dist/cli.js +125 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/dist-CSY2_p-j.js +713 -0
  10. package/dist/dist-CSY2_p-j.js.map +1 -0
  11. package/dist/dist-FeAUNn9A.js +3 -0
  12. package/dist/index.d.ts +17921 -0
  13. package/dist/index.js +26769 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/mcp.d.ts +57 -0
  16. package/dist/mcp.js +26744 -0
  17. package/dist/mcp.js.map +1 -0
  18. package/dist/package-uzXzqDW6.js +23818 -0
  19. package/dist/package-uzXzqDW6.js.map +1 -0
  20. package/package.json +101 -23
  21. package/skills/README.md +81 -0
  22. package/skills/affected-urls/SKILL.md +39 -0
  23. package/skills/affected-urls/agents/openai.yaml +4 -0
  24. package/skills/ai-readiness/SKILL.md +34 -0
  25. package/skills/ai-readiness/agents/openai.yaml +4 -0
  26. package/skills/ai-referrals/SKILL.md +31 -0
  27. package/skills/ai-referrals/agents/openai.yaml +4 -0
  28. package/skills/audit-page/SKILL.md +50 -0
  29. package/skills/audit-page/agents/openai.yaml +4 -0
  30. package/skills/audit-urls/SKILL.md +39 -0
  31. package/skills/audit-urls/agents/openai.yaml +4 -0
  32. package/skills/cannibalisation/SKILL.md +31 -0
  33. package/skills/cannibalisation/agents/openai.yaml +4 -0
  34. package/skills/community-intent/SKILL.md +39 -0
  35. package/skills/community-intent/agents/openai.yaml +4 -0
  36. package/skills/compare-crawls/SKILL.md +40 -0
  37. package/skills/compare-crawls/agents/openai.yaml +4 -0
  38. package/skills/content-optimization/SKILL.md +31 -0
  39. package/skills/content-optimization/agents/openai.yaml +4 -0
  40. package/skills/crawl-diff/SKILL.md +51 -0
  41. package/skills/crawl-diff/agents/openai.yaml +4 -0
  42. package/skills/crawl-history/SKILL.md +37 -0
  43. package/skills/crawl-history/agents/openai.yaml +4 -0
  44. package/skills/crawl-report/SKILL.md +37 -0
  45. package/skills/crawl-report/agents/openai.yaml +4 -0
  46. package/skills/crawler-rules/SKILL.md +34 -0
  47. package/skills/crawler-rules/agents/openai.yaml +4 -0
  48. package/skills/ctr-underperformers/SKILL.md +31 -0
  49. package/skills/ctr-underperformers/agents/openai.yaml +4 -0
  50. package/skills/decaying-pages/SKILL.md +31 -0
  51. package/skills/decaying-pages/agents/openai.yaml +4 -0
  52. package/skills/entity-readiness/SKILL.md +34 -0
  53. package/skills/entity-readiness/agents/openai.yaml +4 -0
  54. package/skills/explain-crawl-issue/SKILL.md +32 -0
  55. package/skills/explain-crawl-issue/agents/openai.yaml +4 -0
  56. package/skills/generate-llms-txt/SKILL.md +37 -0
  57. package/skills/generate-llms-txt/agents/openai.yaml +4 -0
  58. package/skills/geo-gaps/SKILL.md +37 -0
  59. package/skills/geo-gaps/agents/openai.yaml +4 -0
  60. package/skills/index-coverage/SKILL.md +84 -0
  61. package/skills/index-coverage/agents/openai.yaml +4 -0
  62. package/skills/index-coverage-plan/SKILL.md +50 -0
  63. package/skills/index-coverage-plan/agents/openai.yaml +4 -0
  64. package/skills/index-monitor/SKILL.md +49 -0
  65. package/skills/index-monitor/agents/openai.yaml +4 -0
  66. package/skills/index-watch/SKILL.md +77 -0
  67. package/skills/index-watch/agents/openai.yaml +4 -0
  68. package/skills/internal-links/SKILL.md +31 -0
  69. package/skills/internal-links/agents/openai.yaml +4 -0
  70. package/skills/link-recovery/SKILL.md +51 -0
  71. package/skills/link-recovery/agents/openai.yaml +4 -0
  72. package/skills/llms-txt-audit/SKILL.md +34 -0
  73. package/skills/llms-txt-audit/agents/openai.yaml +4 -0
  74. package/skills/measure-change/SKILL.md +52 -0
  75. package/skills/measure-change/agents/openai.yaml +4 -0
  76. package/skills/monthly-action-plan/SKILL.md +50 -0
  77. package/skills/monthly-action-plan/agents/openai.yaml +4 -0
  78. package/skills/monthly-report/SKILL.md +50 -0
  79. package/skills/monthly-report/agents/openai.yaml +4 -0
  80. package/skills/narrative-report/SKILL.md +51 -0
  81. package/skills/narrative-report/agents/openai.yaml +4 -0
  82. package/skills/okf-build/SKILL.md +39 -0
  83. package/skills/okf-build/agents/openai.yaml +4 -0
  84. package/skills/okf-validate/SKILL.md +43 -0
  85. package/skills/okf-validate/agents/openai.yaml +4 -0
  86. package/skills/page-opportunities/SKILL.md +31 -0
  87. package/skills/page-opportunities/agents/openai.yaml +4 -0
  88. package/skills/performance/SKILL.md +50 -0
  89. package/skills/performance/agents/openai.yaml +4 -0
  90. package/skills/performance-audit/SKILL.md +31 -0
  91. package/skills/performance-audit/agents/openai.yaml +4 -0
  92. package/skills/pseo-audit/SKILL.md +103 -0
  93. package/skills/pseo-audit/agents/openai.yaml +4 -0
  94. package/skills/query-clusters/SKILL.md +31 -0
  95. package/skills/query-clusters/agents/openai.yaml +4 -0
  96. package/skills/quick-wins/SKILL.md +31 -0
  97. package/skills/quick-wins/agents/openai.yaml +4 -0
  98. package/skills/redirect-trace/SKILL.md +51 -0
  99. package/skills/redirect-trace/agents/openai.yaml +4 -0
  100. package/skills/refresh-priorities/SKILL.md +48 -0
  101. package/skills/refresh-priorities/agents/openai.yaml +4 -0
  102. package/skills/search-performance-overview/SKILL.md +48 -0
  103. package/skills/search-performance-overview/agents/openai.yaml +4 -0
  104. package/skills/second-page/SKILL.md +50 -0
  105. package/skills/second-page/agents/openai.yaml +4 -0
  106. package/skills/segment-impact/SKILL.md +50 -0
  107. package/skills/segment-impact/agents/openai.yaml +4 -0
  108. package/skills/seo/SKILL.md +74 -0
  109. package/skills/seo/agents/openai.yaml +4 -0
  110. package/skills/seo-fix-queue/SKILL.md +50 -0
  111. package/skills/seo-fix-queue/agents/openai.yaml +4 -0
  112. package/skills/seo-geo-readiness/SKILL.md +60 -0
  113. package/skills/seo-geo-readiness/agents/openai.yaml +4 -0
  114. package/skills/seo-site-audit/SKILL.md +59 -0
  115. package/skills/seo-site-audit/agents/openai.yaml +4 -0
  116. package/skills/seo-to-ai-query/SKILL.md +31 -0
  117. package/skills/seo-to-ai-query/agents/openai.yaml +4 -0
  118. package/skills/setup-check/SKILL.md +49 -0
  119. package/skills/setup-check/agents/openai.yaml +4 -0
  120. package/skills/site-crawl/SKILL.md +39 -0
  121. package/skills/site-crawl/agents/openai.yaml +4 -0
  122. package/skills/striking-distance/SKILL.md +52 -0
  123. package/skills/striking-distance/agents/openai.yaml +4 -0
  124. package/skills/technical-watch/SKILL.md +49 -0
  125. package/skills/technical-watch/agents/openai.yaml +4 -0
  126. package/skills/top-fixes/SKILL.md +38 -0
  127. package/skills/top-fixes/agents/openai.yaml +4 -0
  128. package/skills/traffic-anomaly/SKILL.md +52 -0
  129. package/skills/traffic-anomaly/agents/openai.yaml +4 -0
  130. package/skills/update-correlation/SKILL.md +51 -0
  131. package/skills/update-correlation/agents/openai.yaml +4 -0
  132. package/skills/update-postmortem/SKILL.md +49 -0
  133. package/skills/update-postmortem/agents/openai.yaml +4 -0
  134. package/.jshintrc +0 -18
  135. package/.npmignore +0 -3
  136. package/.travis.yml +0 -3
  137. package/Makefile +0 -10
  138. package/index.js +0 -2
  139. package/lib/middleware.js +0 -159
  140. package/lib/seo.js +0 -32
  141. package/test/init.js +0 -43
  142. package/test/middleware.test.js +0 -111
  143. package/test/seo-page-result.html +0 -9
  144. package/test/seo-page.html +0 -9
  145. package/test/seo-routes.js +0 -5
  146. package/test/vendor/jquery-1.11.1.min.js +0 -4
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: index-watch
3
+ description: Monitor a bounded URL set with Google Search Console URL Inspection and interpret exact indexed-state evidence, current reviews, regressions, recoveries, failures, and quota-deferred checks. Use when an agent needs to check whether watched URLs changed indexing state, investigate exact robots/indexing/fetch/canonical evidence, or plan recurring sitemap monitoring without overstating URL Inspection as a live test.
4
+ ---
5
+
6
+ # Index watch
7
+
8
+ Call `seo_list_reports` with category `monitoring` when discovery is needed.
9
+ Call `seo_describe_report` with id `index-watch`, then call `seo_run_report`
10
+ with that id and only the described parameters. Read `structuredContent` as the
11
+ machine contract. Use report id `index-monitor` for a bounded oldest-first
12
+ sitemap sample. Use report id `index-coverage-plan` before monitoring a large
13
+ inventory across multiple Search Console properties.
14
+
15
+ For the shared schema-backed CLI path:
16
+
17
+ ```bash
18
+ seo reports describe index-watch --json
19
+ seo reports run index-watch --params '{"site":"sc-domain:example.com","urls":["https://example.com/a","https://example.com/b"],"dailyLimit":25}' --json
20
+ ```
21
+
22
+ This validates the same parameters used by MCP. The focused commands below add
23
+ saved monitoring state, sitemap selection, and friendlier flags for recurring
24
+ human workflows.
25
+
26
+ ## Run the report
27
+
28
+ 1. Pass the selected Search Console property as `site`.
29
+ 2. Keep explicit `urls` at 100 or fewer. Every URL must belong to the property.
30
+ 3. Use `dailyLimit` only to set a lower local safety limit. It cannot exceed
31
+ Google's documented 2,000 daily inspections per property.
32
+ 4. For sitemap monitoring, check `source.possiblyTruncated`, `dataStatus`,
33
+ `warnings`, `neverAttempted`, `neverSucceeded`, `retryWaiting`, `fresh`,
34
+ `stale`, `due`, `selected`, and `unselectedDue` before summarising coverage.
35
+ 5. Read `currentIssues`, `regressions`, `recoveries`, `failed`, `quotaBlocked`,
36
+ and `deferred` separately.
37
+
38
+ CLI equivalents:
39
+
40
+ ```bash
41
+ seo index-watch --site sc-domain:example.com --urls https://example.com/a,https://example.com/b --json
42
+ seo index-watch --site sc-domain:example.com --sitemaps https://example.com/sitemap.xml --inspect-limit 25 --json
43
+ seo index-watch --site sc-domain:example.com --sitemaps https://example.com/sitemap.xml --plan --json
44
+ ```
45
+
46
+ ## Interpret evidence
47
+
48
+ - `inspectionStatus: succeeded` means Google returned an indexed snapshot.
49
+ - `indexStatus` maps exact verdicts: `PASS` to `indexed`, `NEUTRAL` to
50
+ `excluded`, `FAIL` to `invalid`, and everything else to `unknown`.
51
+ - `currentIssue` means stable enum or canonical evidence needs review against
52
+ the URL's intended state. An excluded URL or alternate canonical may be
53
+ intentional.
54
+ - `changeKind: regression` means a prior clear successful snapshot became an
55
+ issue. `recovery` means the reverse.
56
+ - `baseline` means there is no previous successful snapshot. A first-run issue
57
+ is still a current review and a new alert.
58
+ - `failed`, `quota-blocked`, and `deferred` are operational outcomes, not SEO
59
+ defects. They are not comparable with a successful indexed state.
60
+ - `requestSent: false` means the local quota broker blocked the call before it
61
+ reached Google. Use `retryAt` when it is present.
62
+ - Use `issueCodes` and typed `changes` for machine reasoning. Keep
63
+ `coverageState` as display evidence because Google localises that free text.
64
+
65
+ ## Guardrails
66
+
67
+ - URL Inspection is Google's indexed version for one URL. It is not a live
68
+ crawl and does not guarantee current search appearance.
69
+ - Do not report every `NEUTRAL` verdict or canonical difference as a defect.
70
+ - Do not infer inventory-wide health from the bounded selected sample.
71
+ - Sitemap failures wait 24 hours before automatic selection retries. Do not
72
+ retry quota-blocked or deferred URLs before `retryAt`.
73
+ - The local UTC-day quota ledger cannot observe calls made by other machines or
74
+ Google clients. A provider 429 remains authoritative.
75
+ - Fix authentication and property access failures instead of treating the
76
+ report as sparse data.
77
+ - Prefer BYO Google credentials if shared OAuth project quota becomes a limit.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Index Watch"
3
+ short_description: "Monitor exact Google indexed-state changes safely"
4
+ default_prompt: "Use $index-watch to inspect a bounded URL set, separate current index reviews from regressions and failures, and explain the evidence without treating Google URL Inspection as a live test."
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: internal-links
3
+ description: Find fetched source pages with query evidence relevant to one target URL and no verified contextual link; use when an agent needs bounded link candidates rather than automatic anchor insertion.
4
+ ---
5
+
6
+ # Internal link candidates
7
+
8
+ Use this report to find source pages whose retained GSC queries overlap with demand for a target URL. It resolves target aliases, fetches bounded candidate pages, checks technical state, and inspects observed links and placement before returning a review candidate. Exact query overlap is stronger than lexical overlap, but neither proves that a link belongs in the page or that adding one will improve rankings.
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":"internal-links"}`.
16
+ 3. Call `seo_run_report` with `{"id":"internal-links","params":{"site":"sc-domain:example.com","targetUrl":"https://example.com/guides/seo","days":90,"limit":15,"checkLimit":40,"minImpressions":25}}`.
17
+
18
+ The CLI invokes the same handler:
19
+
20
+ ```sh
21
+ seo reports describe internal-links --json
22
+ seo reports run internal-links --params '{"site":"sc-domain:example.com","targetUrl":"https://example.com/guides/seo","days":90,"limit":15,"checkLimit":40,"minImpressions":25}' --json
23
+ ```
24
+
25
+ `site` and `targetUrl` are required. `checkLimit` bounds fetched candidates; `limit` bounds returned candidates. Increase fetch concurrency or enable JavaScript only when the site and task justify the extra load.
26
+
27
+ ## Interpret and act
28
+
29
+ Check `dataStatus`, target verification, aliases, canonical, technical signals, and source completeness first. Review `selection.attemptedSources`, checked, failed, unchecked, technical exclusions, alias exclusions, and existing-link exclusions. A low `checkLimit` can leave plausible candidates unchecked. Each item includes exact or lexical query matches, shared terms, impressions, fetch diagnostics, technical signals, and `linkEvidence`. Distinguish `missing`, `non-contextual-only`, and `alias-contextual`; respect observed and limited link counts. Priority is a heuristic combining match evidence, not estimated impact.
30
+
31
+ Safe action is to read the source passage, confirm the target is genuinely useful there, choose natural anchor wording, add one contextual link, and recrawl to verify it. Do not insert links in bulk, replace navigation links without reason, link from technically unsuitable pages, or claim ranking impact from a candidate score.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Internal link candidates"
3
+ short_description: "Find verified internal-link review candidates for one target URL"
4
+ default_prompt: "Use $internal-links to run the internal-links report and explain its evidence and limits."
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: link-recovery
3
+ description: Join retained GSC page value with current redirect and indexability checks; use it to prioritise previously visible URLs that may now be broken or misdirected.
4
+ ---
5
+
6
+ # Recover search-value URLs
7
+
8
+ Use `link-recovery` to find retained GSC page rows with prior clicks or
9
+ impressions whose current fetch path ends in a technical problem. This joins
10
+ historical search observations with a present redirect trace, which is useful
11
+ for triage after migrations or URL changes. Prior visibility helps order the
12
+ queue. It does not prove that fixing a URL will restore the same traffic.
13
+
14
+ ## Run the report
15
+
16
+ With MCP, call `seo_list_reports` with `{"category":"monitoring"}`, call
17
+ `seo_describe_report` with `{"id":"link-recovery"}`, then use `seo_run_report`.
18
+ Example:
19
+ `{"id":"link-recovery","params":{"site":"sc-domain:example.com","days":90,"limit":25,"minClicks":1,"minImpressions":100,"js":false,"refresh":true}}`.
20
+
21
+ The CLI has the same schema:
22
+
23
+ ```sh
24
+ seo reports describe link-recovery --json
25
+ seo reports run link-recovery --params '{"site":"sc-domain:example.com","days":90,"limit":25,"minClicks":1,"minImpressions":100,"refresh":true}' --json
26
+ ```
27
+
28
+ The discovery schema currently exposes broad number types. Use positive whole
29
+ days and bounded non-negative thresholds.
30
+
31
+ ## Interpret the output
32
+
33
+ Confirm `range` and `summary.checked` before reading recoverable counts. The
34
+ summary separates high, medium, and low severity and totals observed clicks and
35
+ impressions for affected retained rows. Those `clicksAtRisk` and
36
+ `impressionsAtRisk` values describe the checked period; they are not a forecast
37
+ of future loss or recovery.
38
+
39
+ Each item preserves the original URL, final URL, GSC metrics, primary and full
40
+ issue lists, severity, the redirect `trace`, and a recommendation with evidence,
41
+ effort, and confidence. Inspect chain status, final-page indexability,
42
+ canonicals, and warnings directly. Failed checks, selection limits, or retained
43
+ GSC rows outside the returned set constrain coverage.
44
+
45
+ ## Act safely
46
+
47
+ Restore a page only when it should still exist. Otherwise add one direct 301 to
48
+ the closest equivalent destination and align its canonical after verifying
49
+ intent. Fix server errors and accidental noindex controls before content work.
50
+ Do not redirect unrelated URLs to a homepage, remove intentional controls, or
51
+ promise traffic recovery from historical metrics.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Link recovery"
3
+ short_description: "Find search-value URLs that now fail technical checks"
4
+ default_prompt: "Use $link-recovery to run the link-recovery report and explain its evidence and limits."
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: llms-txt-audit
3
+ description: Inspect an optional llms.txt file and derive a bounded set of suitable page candidates from crawl evidence. Use when reviewing agent-facing site navigation without treating the file as a ranking requirement.
4
+ ---
5
+
6
+ # Audit llms.txt
7
+
8
+ `llms.txt` is optional publisher-provided navigation for agents. Its presence is not a general search requirement or ranking signal, and its absence is not a technical SEO defect. This report checks the observed file response and suggests eligible pages that could belong in a useful inventory.
9
+
10
+ ## Run it
11
+
12
+ For MCP, call `seo_list_reports` with category `crawl` only when discovery is needed. Call `seo_describe_report` with `{ "id": "llms-txt-audit" }`, then `seo_run_report` with:
13
+
14
+ ```json
15
+ {
16
+ "id": "llms-txt-audit",
17
+ "params": { "reportId": "crawl_example_20260710" }
18
+ }
19
+ ```
20
+
21
+ Check MCP `isError`, then read `structuredContent`. The CLI exposes the same contract:
22
+
23
+ ```sh
24
+ seo reports describe llms-txt-audit --json
25
+ seo reports run llms-txt-audit --params '{"reportId":"crawl_example_20260710"}' --json
26
+ ```
27
+
28
+ Using `url` instead of `reportId` starts a fresh crawl. Prefer a saved snapshot when the recommendations will be compared with other reports.
29
+
30
+ ## Interpret the result
31
+
32
+ Review `exists`, the resolved file URL, response status, headline, issues, and `recommendedPages`. Candidate pages are drawn from successfully fetched, indexable pages and exclude common utility or private paths; ordering uses crawl evidence such as internal authority and content depth. That selection is a heuristic inventory, not proof that every important page is present or suitable for publication.
33
+
34
+ Check the source report's date, cap, partial state, failed requests, warnings, and caveats with `crawl-report`. A short recommendation list from a capped crawl is not sitewide evidence. If the file exists, verify that its URLs are current, canonical, public, and aligned with publisher intent. If it does not exist, recommend creating one only when it improves agent navigation. Keep any generated file concise and human-reviewed; never claim that adding it will improve indexing, rankings, traffic, AI selection, or citations.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Audit llms.txt"
3
+ short_description: "Inspect optional llms.txt evidence from a crawl"
4
+ default_prompt: "Use $llms-txt-audit to run the llms-txt-audit report and explain its evidence and limits."
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: measure-change
3
+ description: Measure the before-and-after impact of a saved or ad hoc SEO change with equal finalized Google Search Console windows, optional GA4 landing-page evidence, and an optional control. Use when an agent needs to evaluate a release, page edit, migration, template change, or SEO test without mistaking an incomplete after-period for a decline.
4
+ ---
5
+
6
+ # Measure SEO change
7
+
8
+ Call `seo_list_reports` with category `experiments` when discovery is needed.
9
+ Call `seo_describe_report` with id `measure-change`, then call `seo_run_report`
10
+ with that id and only the described parameters. Read `structuredContent` as the
11
+ machine contract. Use the CLI for CI, saved JSON, or environments without MCP.
12
+
13
+ ```bash
14
+ seo reports describe measure-change --json
15
+ seo reports run measure-change --params '{"site":"sc-domain:example.com","scope":"page","target":"https://example.com/page","title":"Updated page","changedAt":"2025-10-01","beforeDays":28,"afterDays":28}' --json
16
+
17
+ seo tests report \
18
+ --project <project> \
19
+ --scope page \
20
+ --target https://example.com/page \
21
+ --date 2026-06-01 \
22
+ --before 28 \
23
+ --after 28 \
24
+ --json
25
+ ```
26
+
27
+ Describe the report before building ad hoc parameters because the schema keeps
28
+ saved-test and inline-test inputs in one contract. The catalog runner and the
29
+ focused command execute the same measurement logic.
30
+
31
+ For a saved test, pass its `id` instead of the ad hoc site, scope, target, and date fields.
32
+
33
+ ## Workflow
34
+
35
+ 1. Use the same whole-number duration for `beforeDays` and `afterDays`. Raw totals from unequal calendar windows are not comparable.
36
+ 2. Read `dataStatus`, `window`, `source`, `warnings`, and `caveats` before interpreting metrics.
37
+ 3. Confirm `window.effectiveDays` equals `window.requestedDays`. If `afterWindowTruncated` is true, the tool uses an equal shortened baseline, returns `partial`, and withholds a directional verdict.
38
+ 4. Require at least 7 finalized days in each window for a directional verdict. Shorter complete windows remain useful observations but return `not-enough-data`.
39
+ 5. Treat GSC clicks, impressions, CTR, and impression-weighted average position as observed before/after evidence. Timing does not prove that the recorded change caused the movement.
40
+ 6. For query-scoped tests, treat `retained-query-date-aggregates` as partial. A missing retained window returns null metrics and is not a zero or a loss.
41
+ 7. If GA4 is present, check its property timezone and `source.analytics.status`. GA4 day boundaries can differ from GSC Pacific dates; sampling, thresholding, or `(other)` grouping makes GA4 evidence partial.
42
+ 8. Use a control only when it represents a credible unaffected comparison. Adjusted deltas use a control-ratio counterfactual, not raw subtraction across differently sized groups.
43
+ 9. Investigate query mix, devices, countries, indexability, SERP changes, seasonality, and other releases before recommending a rollout or reversal.
44
+
45
+ ## Interpretation rules
46
+
47
+ - Never call `not-enough-data` positive, negative, or flat.
48
+ - Never annualize or forecast the observed delta.
49
+ - Do not compare this run with another run that used different effective window lengths.
50
+ - `clickPct: null` means the before value was zero; it is not an infinite percentage gain.
51
+ - A partial GA4 source does not invalidate complete GSC evidence, but it does limit analytics conclusions.
52
+ - Provider, auth, property, and invalid-date errors are failures, not zero movement.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Measure SEO Change"
3
+ short_description: "Measure equal-window GSC and GA4 change evidence"
4
+ default_prompt: "Use $measure-change to measure this SEO change with equal finalized before and after evidence."
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: monthly-action-plan
3
+ description: Run a calendar-month reporting workflow with a narrative and explicit actions. Use it for a repeatable review whose caveats remain attached to each measurement.
4
+ ---
5
+
6
+ # Monthly workflow
7
+
8
+ This workflow packages the monthly narrative into a sequenced, agent-friendly
9
+ result with explicit steps and actions. It helps keep recurring reviews
10
+ consistent. It can report measured movement, but it cannot establish a cause,
11
+ promise recovery, or turn incomplete provider evidence into a full-property
12
+ conclusion.
13
+
14
+ ## Run it
15
+
16
+ Use the exact MCP discovery flow:
17
+
18
+ 1. Call `seo_list_reports` with `category: "workflows"` and select `monthly-action-plan`.
19
+ 2. Call `seo_describe_report` with `id: "monthly-action-plan"`; confirm its current parameters.
20
+ 3. Call `seo_run_report` with that id and only schema-valid parameters.
21
+
22
+ CLI parity:
23
+
24
+ ```sh
25
+ seo reports describe monthly-action-plan --json
26
+ seo reports run monthly-action-plan --params '{"site":"sc-domain:example.com","month":"2026-05","limit":10,"includeBrand":false}' --json
27
+ ```
28
+
29
+ Supply `month` as `YYYY-MM`. `limit` controls retained output, not the provider's
30
+ underlying completeness. Keep `includeBrand` explicit when comparisons must be
31
+ reproducible across months.
32
+
33
+ ## Interpret and act
34
+
35
+ Inspect the workflow envelope: `summary`, each entry in `steps`, `actions`, and
36
+ the nested `output`. Confirm the requested month, final-data window, provider
37
+ status, skipped sections, warnings, caveats, and retained caps. Follow narrative
38
+ claims back into their structured diagnosis or measurement. A skipped section
39
+ is not a zero, and a top-level successful workflow does not make every nested
40
+ source complete.
41
+
42
+ Use actions as a review queue, not automatic edit instructions. Verify affected
43
+ URLs and intentional controls, reproduce technical defects, and record any
44
+ approved changes for future measurement. Keep month-over-month movement
45
+ separate from explanations. Do not invent click, traffic, ranking, or revenue
46
+ forecasts, and do not attribute movement to an algorithm update or deployment
47
+ from timing alone.
48
+
49
+ Read MCP `structuredContent` as the machine contract. The rendered Markdown is
50
+ the human brief, not an alternative data source for agents.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Monthly workflow"
3
+ short_description: "Run the monthly reporting workflow"
4
+ default_prompt: "Use $monthly-action-plan to run the monthly-action-plan report and explain its evidence and limits."
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: monthly-report
3
+ description: Generate a calendar-month SEO narrative from finalized first-party evidence. Use it to brief humans while preserving source status, caveats, and measured next actions.
4
+ ---
5
+
6
+ # Monthly report
7
+
8
+ Monthly reporting matters because it fixes the analysis to a named calendar
9
+ period and turns several measurements into one reviewable brief. The report can
10
+ show observed movement and prioritized investigations. It cannot establish why
11
+ traffic changed, guarantee that a recommended edit will help, or forecast
12
+ clicks, rankings, revenue, or future performance.
13
+
14
+ ## Run it
15
+
16
+ Use the exact MCP discovery flow:
17
+
18
+ 1. Call `seo_list_reports` with `category: "reporting"` and select `monthly-report`.
19
+ 2. Call `seo_describe_report` with `id: "monthly-report"` and inspect the current schema.
20
+ 3. Call `seo_run_report` with `id: "monthly-report"` and only described parameters.
21
+
22
+ The CLI exposes the same report:
23
+
24
+ ```sh
25
+ seo reports describe monthly-report --json
26
+ seo reports run monthly-report --params '{"site":"sc-domain:example.com","month":"2026-05","limit":10,"includeBrand":false,"verifyContent":true,"verifyLimit":5}' --json
27
+ ```
28
+
29
+ Use `YYYY-MM` for `month`. `limit` bounds retained findings, not provider row
30
+ retrieval. `verifyContent` fetches a bounded subset, so `verifyLimit` must not
31
+ be interpreted as full-site validation.
32
+
33
+ ## Interpret and act
34
+
35
+ Confirm `month`, the underlying date windows, `dataStatus`, source completeness,
36
+ skipped sections, warnings, and caveats before reading the headline. Treat the
37
+ narrative as a rendering of structured evidence. Follow its references into
38
+ the diagnosis, measured changes, priorities, and monitoring results when a
39
+ claim needs verification. A zero from a complete source differs from an
40
+ unavailable, partial, filtered, or capped section.
41
+
42
+ Safe actions start with the highest-evidence priorities: validate affected URLs,
43
+ compare relevant templates, inspect confirmed technical regressions, and assign
44
+ owners to bounded tests. Keep brand filtering and content-verification status
45
+ visible. Record what changed so the next month can measure it. Do not rewrite a
46
+ page merely because it appears in a heuristic opportunity list, and do not
47
+ present update overlap or timing as causation.
48
+
49
+ Read MCP `structuredContent` as the machine contract. Use returned Markdown for
50
+ the human brief, but never parse it to recover data already present in JSON.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Monthly report"
3
+ short_description: "Generate one monthly SEO narrative"
4
+ default_prompt: "Use $monthly-report to run the monthly-report report and explain its evidence and limits."
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: narrative-report
3
+ description: Assemble diagnosis, change measurement, and monitoring evidence into a readable SEO narrative. Use it for an evidence-linked briefing rather than a new source of truth.
4
+ ---
5
+
6
+ # Report narrative
7
+
8
+ This report turns several structured analyses into a coherent explanation. It
9
+ is useful when a person needs the important findings, caveats, and next actions
10
+ without reading every raw section. The narrative summarizes evidence; it does
11
+ not strengthen weak evidence, prove causation, or make missing and partial data
12
+ complete.
13
+
14
+ ## Run it
15
+
16
+ Use the exact MCP discovery flow:
17
+
18
+ 1. Call `seo_list_reports` with `category: "reporting"` and select `narrative-report`.
19
+ 2. Call `seo_describe_report` with `id: "narrative-report"` before constructing parameters.
20
+ 3. Call `seo_run_report` with `id: "narrative-report"` and schema-valid parameters.
21
+
22
+ CLI parity:
23
+
24
+ ```sh
25
+ seo reports describe narrative-report --json
26
+ seo reports run narrative-report --params '{"site":"sc-domain:example.com","days":90,"recentDays":7,"limit":10,"includeBrand":false,"changeLimit":5}' --json
27
+ ```
28
+
29
+ Use explicit date bounds only when the described schema supports the intended
30
+ window; otherwise `days` and `recentDays` keep comparisons consistent.
31
+ `changeLimit` bounds attempted change measurements, while `limit` bounds
32
+ retained report items.
33
+
34
+ ## Interpret and act
35
+
36
+ Read `headline` only after checking top-level caveats. Then inspect `sections`,
37
+ `priorities`, `diagnosis`, `changeMeasurements`,
38
+ `changeMeasurementAttempts`, and `monitoring`. A failed or skipped measurement
39
+ must stay visible; it is not a zero. Preserve each section's dates,
40
+ completeness, thresholds, limits, and evidence references. Treat update timing,
41
+ template groupings, and opportunity scores as investigation context, not
42
+ ranking causes.
43
+
44
+ Safe actions should trace back to observed evidence: reproduce a technical
45
+ failure, inspect the affected URLs, validate an intentional control, or run a
46
+ bounded content change with a recorded date. Keep recommended verification
47
+ steps separate from asserted defects. Do not invent traffic lift, rank gains,
48
+ revenue impact, or certainty that the source does not provide.
49
+
50
+ MCP `structuredContent` is the machine contract. Returned Markdown is for human
51
+ communication and should not replace the underlying JSON evidence.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Report narrative"
3
+ short_description: "Generate a readable SEO narrative from diagnosis, changes, and monitoring evi..."
4
+ default_prompt: "Use $narrative-report to run the narrative-report report and explain its evidence and limits."
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: okf-build
3
+ description: Build a deterministic OKF Markdown knowledge bundle from a bounded crawl and validate its file contract. Use when an agent needs portable site evidence with explicit source selection and caveats.
4
+ ---
5
+
6
+ # Build an OKF bundle
7
+
8
+ An OKF bundle packages crawl-derived concepts, page inventory, link relationships, provenance, and caveats as portable Markdown. The builder ranks eligible pages deterministically and limits the selected concepts. This makes the artifact reproducible, but it does not make extracted claims true or current.
9
+
10
+ ## Run it
11
+
12
+ For MCP, call `seo_list_reports` with category `crawl` only when discovery is needed. Call `seo_describe_report` with `{ "id": "okf-build" }`, then `seo_run_report` with:
13
+
14
+ ```json
15
+ {
16
+ "id": "okf-build",
17
+ "params": {
18
+ "reportId": "crawl_example_20260710",
19
+ "maxConcepts": 25,
20
+ "includeFiles": true,
21
+ "title": "Example site knowledge"
22
+ }
23
+ }
24
+ ```
25
+
26
+ Check `isError`, then use `structuredContent`. CLI parity is:
27
+
28
+ ```sh
29
+ seo reports describe okf-build --json
30
+ seo reports run okf-build --params '{"reportId":"crawl_example_20260710","maxConcepts":25,"includeFiles":true,"title":"Example site knowledge"}' --json
31
+ ```
32
+
33
+ `includeFiles` is opt-in because file bodies can be large. Request only the manifest when discovering scope.
34
+
35
+ ## Inspect the bundle
36
+
37
+ Read the manifest's schema version, report id, source URL, generation time, crawl status, title, concept count, file paths, warnings, and caveats. The `selection` block distinguishes source, eligible, duplicate-final, selected, and limited page counts and records the deterministic ordering. If selected pages equal the limit, treat the bundle as bounded rather than exhaustive.
38
+
39
+ Review the returned validation before using files. Then inspect citations, canonical URLs, titles, summaries, and relationships against source pages, especially for sensitive or time-dependent claims. The generated log and caveat files should travel with the bundle. A successful structural validation does not establish ownership, freshness, factual accuracy, completeness, or safe downstream use. Rebuild from a comparable fresh crawl when the site changes; do not silently merge snapshots with different scope.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Build OKF"
3
+ short_description: "Build a compact OKF site knowledge bundle"
4
+ default_prompt: "Use $okf-build to run the okf-build report and explain its evidence and limits."
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: okf-validate
3
+ description: Validate OKF paths, frontmatter, required files, concept links, and citation structure deterministically. Use before consuming or distributing a bundle, while checking factual quality separately.
4
+ ---
5
+
6
+ # Validate an OKF bundle
7
+
8
+ Validation protects the file contract an agent depends on: required paths, unique files, root metadata, Markdown content, concept frontmatter, links, and citation sections. It does not browse cited sources or determine whether the knowledge is true, current, owned, complete, or safe.
9
+
10
+ ## Run it
11
+
12
+ For MCP, call `seo_list_reports` with category `crawl` only if discovery is needed. Call `seo_describe_report` with `{ "id": "okf-validate" }`, then call `seo_run_report` with:
13
+
14
+ ```json
15
+ {
16
+ "id": "okf-validate",
17
+ "params": {
18
+ "files": [
19
+ { "path": "index.md", "content": "---\nokf: \"0.1\"\ntype: \"index\"\n---\n# Example" },
20
+ { "path": "log.md", "content": "# Log" },
21
+ { "path": "concepts/index.md", "content": "# Concepts" },
22
+ { "path": "inventory/pages.md", "content": "---\ntype: \"inventory\"\n---\n# Pages\n\n# Citations" },
23
+ { "path": "graph/links.md", "content": "---\ntype: \"graph\"\n---\n# Links\n\n# Citations" },
24
+ { "path": "caveats.md", "content": "---\ntype: \"caveats\"\n---\n# Caveats\n\n# Citations" }
25
+ ]
26
+ }
27
+ }
28
+ ```
29
+
30
+ Check `isError`, then consume `structuredContent`.
31
+
32
+ The CLI uses the same strict schema. This minimal six-file bundle is structurally valid:
33
+
34
+ ```sh
35
+ seo reports describe okf-validate --json
36
+ seo reports run okf-validate --params '{"files":[{"path":"index.md","content":"---\nokf: \"0.1\"\ntype: \"index\"\n---\n# Example"},{"path":"log.md","content":"# Log"},{"path":"concepts/index.md","content":"# Concepts"},{"path":"inventory/pages.md","content":"---\ntype: \"inventory\"\n---\n# Pages\n\n# Citations"},{"path":"graph/links.md","content":"---\ntype: \"graph\"\n---\n# Links\n\n# Citations"},{"path":"caveats.md","content":"---\ntype: \"caveats\"\n---\n# Caveats\n\n# Citations"}]}' --json
37
+ ```
38
+
39
+ ## Resolve findings
40
+
41
+ Read `validation.valid`, file and concept counts, then every issue's level, path, and message. Errors invalidate the supported contract and should be fixed file by file. Warnings identify weaker portability or provenance, such as missing citation sections, and still require review even when `valid` is true. Use `explanation.nextActions` as ordering guidance, not as evidence that automated edits are safe.
42
+
43
+ Preserve the original bundle while correcting a copy, rerun validation, and compare issue sets deterministically. After structural success, separately verify cited URLs, claims, dates, access restrictions, publisher intent, and the crawl snapshot recorded by the bundle. Never report `valid: true` as "fact checked."
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Validate OKF"
3
+ short_description: "Validate supplied OKF Markdown files"
4
+ default_prompt: "Use $okf-validate to run the okf-validate report and explain its evidence and limits."
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: page-opportunities
3
+ description: Review one URL against retained GSC demand, peer CTR evidence, and live page content; use when an agent needs query-level opportunities with verification and source limits intact.
4
+ ---
5
+
6
+ # Page opportunities
7
+
8
+ Use this report to investigate how one page performs for the query/page rows retained by Search Console. It compares the target rows with a bounded site-wide peer sample and can fetch the live page to distinguish covered, unverified, technical, framing, ranking, and possible content-gap observations. It does not expose anonymized queries, explain ranking causes, or prove that a benchmark shortfall is recoverable 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":"page-opportunities"}`.
16
+ 3. Call `seo_run_report` with `{"id":"page-opportunities","params":{"site":"sc-domain:example.com","url":"https://example.com/pricing","days":90,"limit":15,"minImpressions":40,"verifyContent":true}}`.
17
+
18
+ The CLI shares that schema and implementation:
19
+
20
+ ```sh
21
+ seo reports describe page-opportunities --json
22
+ seo reports run page-opportunities --params '{"site":"sc-domain:example.com","url":"https://example.com/pricing","days":90,"limit":15,"minImpressions":40,"verifyContent":true}' --json
23
+ ```
24
+
25
+ `site` and `url` are required. Use `includeBrand:true` only when branded demand belongs in the decision. `verifyContent:false` saves a fetch but makes content-specific conclusions unavailable.
26
+
27
+ ## Interpret and act
28
+
29
+ Check `dataStatus`, `range`, `source.targetRowsFetched`, `selection`, and `benchmark` first. A `benchmark.possiblyTruncated` value of true means the peer sample reached its cap. Read `verification.status` and `reason`; only `verified` results support live-page coverage observations. For each `item`, retain the query metrics, opportunity type, benchmark evidence, verification evidence, and recommendation together. `estimatedCtrClickShortfall` is a directional calculation, not a click forecast, and `summary.opportunities` is a review queue rather than a defect count.
30
+
31
+ Safe actions include inspecting the live SERP, resolving status/indexability contradictions, testing title or description framing when the page already answers the query, strengthening a relevant answer, and adding a contextual internal link. Do not rewrite a page from query wording alone, infer an all-clear from partial data, or merge and delete pages without separate intent, canonical, and internal-link evidence.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Page opportunities"
3
+ short_description: "Find first-party opportunities for one URL"
4
+ default_prompt: "Use $page-opportunities to run the page-opportunities report and explain its evidence and limits."
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: performance
3
+ description: Audit and interpret one URL's Lighthouse lab performance and device-specific CrUX field Core Web Vitals with the local seo CLI or MCP server. Use when an agent needs to investigate LCP, INP, CLS, TBT, page-speed diagnostics, mobile-versus-desktop evidence, or performance remediation without confusing lab, field, and fallback measurements.
4
+ ---
5
+
6
+ # Performance
7
+
8
+ Run report id `performance-audit` through `seo_run_report` for structured agent
9
+ output. Call `seo_describe_report` first when its parameters are not already
10
+ known. Pass `url`, choose `strategy` as `mobile` or `desktop`, and use
11
+ `refresh: true` only when a fresh measurement is required.
12
+
13
+ CLI equivalents:
14
+
15
+ ```bash
16
+ seo perf audit --url https://example.com/page --json
17
+ seo perf audit --url https://example.com/page --strategy desktop --refresh --json
18
+ ```
19
+
20
+ Set `SEO_CRUX_API_KEY` to request Chrome UX Report field data. The packaged
21
+ Lighthouse runtime needs a compatible local Chrome installation.
22
+
23
+ ## Interpret the report
24
+
25
+ 1. Check `dataStatus`, `labDataStatus`, `fieldDataStatus`, and `caveats` first.
26
+ 2. Treat CrUX as rolling, device-specific field evidence. Check whether its
27
+ `scope` is the exact URL or the origin and quote the `collectionPeriod`.
28
+ 3. Treat Lighthouse as one controlled navigation lab run. Use its compact
29
+ `labInsights` and metric evidence for diagnosis, not as field experience.
30
+ 4. Treat Lighthouse TBT as a lab responsiveness diagnostic. Never rename it
31
+ INP. Field INP comes from CrUX.
32
+ 5. Use the field p75 thresholds encoded by the report: LCP good at 2,500ms or
33
+ less, INP good at 200ms or less, and CLS good at 0.1 or less. All three must
34
+ be available and good for the field assessment to be good.
35
+ 6. Prefer field findings when field and lab disagree. Explain that their
36
+ populations and measurement conditions differ.
37
+ 7. Keep recommendations tied to returned metrics or insights. Do not infer
38
+ sitewide performance from one URL, device, or run.
39
+
40
+ ## Guardrails
41
+
42
+ - `source: fetch-fallback` is unscored transport evidence. Its duration is the
43
+ complete local fetch workflow, not TTFB, Lighthouse, or Core Web Vitals.
44
+ - Stop performance conclusions when fallback evidence is blocked or non-2xx.
45
+ - `unavailable_no_coverage` means CrUX lacks enough data; it does not mean the
46
+ page passed or failed Core Web Vitals.
47
+ - `request_failed` is an operational provider problem, not a page finding.
48
+ - Missing field metrics make the Core Web Vitals assessment incomplete.
49
+ - Do not request or paste raw Lighthouse output unless a human explicitly
50
+ needs the underlying artifact; compact output is the stable agent contract.