@automatelab/ai-seo-mcp 0.3.0 → 0.4.1

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 (61) hide show
  1. package/README.md +37 -18
  2. package/dist/cli/audit-cli.d.ts +3 -0
  3. package/dist/cli/audit-cli.d.ts.map +1 -0
  4. package/dist/cli/audit-cli.js +136 -0
  5. package/dist/cli/audit-cli.js.map +1 -0
  6. package/dist/index.js +710 -227
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/cache.d.ts +12 -0
  9. package/dist/lib/cache.d.ts.map +1 -0
  10. package/dist/lib/cache.js +51 -0
  11. package/dist/lib/cache.js.map +1 -0
  12. package/dist/lib/config.js +1 -1
  13. package/dist/lib/fetch.d.ts +5 -0
  14. package/dist/lib/fetch.d.ts.map +1 -1
  15. package/dist/lib/fetch.js +42 -1
  16. package/dist/lib/fetch.js.map +1 -1
  17. package/dist/lib/headless.d.ts +13 -0
  18. package/dist/lib/headless.d.ts.map +1 -0
  19. package/dist/lib/headless.js +73 -0
  20. package/dist/lib/headless.js.map +1 -0
  21. package/dist/lib/scorecard-html.js +94 -94
  22. package/dist/output-schemas.d.ts +658 -0
  23. package/dist/output-schemas.d.ts.map +1 -0
  24. package/dist/output-schemas.js +265 -0
  25. package/dist/output-schemas.js.map +1 -0
  26. package/dist/tools/audit-page.d.ts +11 -0
  27. package/dist/tools/audit-page.d.ts.map +1 -1
  28. package/dist/tools/audit-page.js +49 -2
  29. package/dist/tools/audit-page.js.map +1 -1
  30. package/dist/tools/audit-schema.d.ts +2 -1
  31. package/dist/tools/audit-schema.d.ts.map +1 -1
  32. package/dist/tools/audit-schema.js +2 -1
  33. package/dist/tools/audit-schema.js.map +1 -1
  34. package/dist/tools/audit-site.d.ts +41 -0
  35. package/dist/tools/audit-site.d.ts.map +1 -0
  36. package/dist/tools/audit-site.js +120 -0
  37. package/dist/tools/audit-site.js.map +1 -0
  38. package/dist/tools/audit-sitemap.d.ts +66 -0
  39. package/dist/tools/audit-sitemap.d.ts.map +1 -0
  40. package/dist/tools/audit-sitemap.js +264 -0
  41. package/dist/tools/audit-sitemap.js.map +1 -0
  42. package/dist/tools/check-technical.d.ts +2 -1
  43. package/dist/tools/check-technical.d.ts.map +1 -1
  44. package/dist/tools/check-technical.js +2 -1
  45. package/dist/tools/check-technical.js.map +1 -1
  46. package/dist/tools/diff-pages.js +2 -2
  47. package/dist/tools/diff-pages.js.map +1 -1
  48. package/dist/tools/extract-entities.d.ts +8 -1
  49. package/dist/tools/extract-entities.d.ts.map +1 -1
  50. package/dist/tools/extract-entities.js +110 -3
  51. package/dist/tools/extract-entities.js.map +1 -1
  52. package/dist/tools/save-audit-report.d.ts +22 -0
  53. package/dist/tools/save-audit-report.d.ts.map +1 -0
  54. package/dist/tools/save-audit-report.js +133 -0
  55. package/dist/tools/save-audit-report.js.map +1 -0
  56. package/dist/tools/test-citation.d.ts +51 -0
  57. package/dist/tools/test-citation.d.ts.map +1 -0
  58. package/dist/tools/test-citation.js +159 -0
  59. package/dist/tools/test-citation.js.map +1 -0
  60. package/package.json +8 -1
  61. package/smithery.yaml +13 -0
package/README.md CHANGED
@@ -17,7 +17,7 @@ Works inside Claude, Cursor, Windsurf, Codex, and any MCP client that speaks std
17
17
  - **AI crawler access** - GPTBot, OAI-SearchBot, ClaudeBot, and PerplexityBot allowed or blocked in `robots.txt`
18
18
  - **`llms.txt`** - present, spec-compliant, links alive
19
19
  - **Structured answer extraction** - FAQ headings, BLUF paragraphs, answer-ready blocks
20
- - **Schema completeness** - FAQPage, Article, Organization, Person; flags deprecated patterns
20
+ - **[[schema]] completeness** - FAQPage, Article, Organization, Person; flags deprecated patterns
21
21
  - **Entity clarity** - named entity density and `sameAs` coverage that help AI systems identify the subject
22
22
  - **Citation formatting** - canonical URL hygiene, `og:url`, `hreflang`, noindex traps
23
23
  - **Sitemap freshness** - `lastmod` signals that tell crawlers the page is current
@@ -26,13 +26,13 @@ Works inside Claude, Cursor, Windsurf, Codex, and any MCP client that speaks std
26
26
 
27
27
  ## Run an audit. Get a list of citation-blockers, ranked.
28
28
 
29
- > **You:** Run an AI-SEO audit on `https://automatelab.tech/how-to-connect-zapier-to-notion`.
29
+ > **You:** Run an AI-SEO audit on `https://automatelab.tech/launching-the-ai-seo-mcp/`.
30
30
 
31
31
  Result (truncated):
32
32
 
33
33
  ```json
34
34
  {
35
- "url": "https://automatelab.tech/how-to-connect-zapier-to-notion",
35
+ "url": "https://automatelab.tech/launching-the-ai-seo-mcp/",
36
36
  "score": 61,
37
37
  "grade": "C",
38
38
  "dimension_scores": {
@@ -88,6 +88,19 @@ Add to `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/App
88
88
 
89
89
  Restart Claude Desktop. Any MCP client that supports stdio transport works - same `command` / `args` pattern.
90
90
 
91
+ ### Optional: headless rendering for SPAs
92
+
93
+ By default `audit_page` reads raw HTML — fast, but misses content on React/Vue/Angular SPAs. Pass `render: "headless"` to spin up Chromium and audit the rendered DOM (adds 3-10s per audit).
94
+
95
+ One-time install:
96
+
97
+ ```bash
98
+ npm install playwright-core
99
+ npx playwright install chromium
100
+ ```
101
+
102
+ Then call `audit_page` with `render: "headless"`. Use static for everything else — most marketing sites and docs render fine without it.
103
+
91
104
  ---
92
105
 
93
106
  ## Further reading
@@ -97,24 +110,30 @@ Restart Claude Desktop. Any MCP client that supports stdio transport works - sam
97
110
  ---
98
111
 
99
112
  <details>
100
- <summary>All 14 tools</summary>
113
+ <summary>MCP tool surface (18 tools)</summary>
101
114
 
102
115
  | Tool | Purpose |
103
116
  |------|---------|
104
- | `audit_page` | Composite AI-SEO audit with 8-dimension scoring (schema, technical, structure, robots, freshness, authority, entity density, sitemap). |
105
- | `audit_schema` | Validate JSON-LD against Schema.org rules and AI-citation best practice. Flags deprecated patterns. |
106
- | `audit_canonical` | Canonical link integrity, trailing-slash hygiene, `og:url` consistency. |
107
- | `check_robots` | Parse `robots.txt` and report per-crawler allow/disallow for all known AI crawlers. Surfaces the GPTBot-blocked-but-OAI-SearchBot-allowed trap. |
108
- | `check_sitemap` | Validate XML sitemaps: presence, URL count, `lastmod` freshness, image/video extensions. |
109
- | `check_technical` | HEAD tag audit: canonical, OpenGraph, Twitter Card, hreflang, HTTPS, noindex, title hygiene. |
110
- | `score_ai_overview_eligibility` | Score a page's probability of appearing in Google AI Overviews using current correlation factors. |
111
- | `generate_llms_txt` | Generate `llms.txt` and optionally `llms-full.txt` from a domain's sitemap. |
112
- | `validate_llms_txt` | Lint an existing `llms.txt` for spec compliance and broken links. |
113
- | `score_citation_worthiness` | Score how citable a page or text block is for Perplexity, ChatGPT, Google AI Overviews, and Claude. |
114
- | `rewrite_for_aeo` | Rewrite content for Answer Engine Optimization (BLUF structure, FAQ format, schema additions). |
115
- | `rewrite_for_geo` | Rewrite content for Generative Engine Optimization (entity definitions, comparison tables, synthesis-ready structure). |
116
- | `extract_entities` | Extract named entities, `sameAs` links, and citation-density score from a page's content and structured data. |
117
- | `diff_pages` | Compare two URLs for AI citation-worthiness: side-by-side dimension scores, gap analysis, and prioritized fix recommendations for url_a. |
117
+ | `audit.page` | Composite AI-SEO audit with 8-dimension scoring (schema, technical, structure, robots, freshness, authority, entity density, sitemap). |
118
+ | `audit.schema` | Validate JSON-LD against Schema.org rules and AI-citation best practice. Flags deprecated patterns. |
119
+ | `audit.canonical` | Canonical link integrity, trailing-slash hygiene, `og:url` consistency. |
120
+ | `audit.site` | Single-call site sweep: `audit.page` + `check.robots` + `check.sitemap` + `audit.schema` with overall grade and top-5 fixes. |
121
+ | `audit.sitemap` | Site-wide content audit: stride-sample N URLs from the sitemap, run `audit.page` on each, return distribution + worst pages + top findings. |
122
+ | `check.robots` | Parse `robots.txt` and report per-crawler allow/disallow for all known AI crawlers. Surfaces the GPTBot-blocked-but-OAI-SearchBot-allowed trap. |
123
+ | `check.sitemap` | Validate XML sitemaps: presence, URL count, `lastmod` freshness, image/video extensions. |
124
+ | `check.technical` | HEAD tag audit: canonical, OpenGraph, Twitter Card, hreflang, HTTPS, noindex, title hygiene. |
125
+ | `score.ai_overview_eligibility` | Score a page's probability of appearing in Google AI Overviews using current correlation factors. |
126
+ | `score.citation_worthiness` | Score how citable a page or text block is for Perplexity, ChatGPT, Google AI Overviews, and Claude. |
127
+ | `score.test_citation` | Simulate "would an AI engine cite this for this query?" via MCP sampling, with deterministic heuristic fallback. |
128
+ | `llms_txt.generate` | Generate `llms.txt` and optionally `llms-full.txt` from a domain's sitemap. |
129
+ | `llms_txt.validate` | Lint an existing `llms.txt` for spec compliance and broken links. |
130
+ | `rewrite.aeo` | Rewrite content for Answer Engine Optimization (BLUF structure, FAQ format, schema additions). |
131
+ | `rewrite.geo` | Rewrite content for Generative Engine Optimization (entity definitions, comparison tables, synthesis-ready structure). |
132
+ | `extract.entities` | Extract named entities, `sameAs` links, and citation-density score from a page's content and structured data. |
133
+ | `diff.pages` | Compare two URLs for AI citation-worthiness: side-by-side dimension scores, gap analysis, and prioritized fix recommendations for url_a. |
134
+ | `report.save` | Render an `audit.page` / `audit.site` result as a Markdown report and write it to disk under `MCP_WORKSPACE_ROOT`. |
135
+
136
+ > **v0.4.0** renamed tools from flat `snake_case` to dot-notation (`audit.page`, `check.robots`, …) for a navigable hierarchy. Update any saved invocations.
118
137
 
119
138
  Environment variables: see [ENV.md](./ENV.md).
120
139
 
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=audit-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-cli.d.ts","sourceRoot":"","sources":["../../src/cli/audit-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ // CLI wrapper around audit_page / audit_site, used by the ai-seo GitHub Action.
3
+ // Not part of the MCP protocol; reads flags and prints results to stdout/stderr.
4
+ //
5
+ // Usage:
6
+ // ai-seo-audit --urls "https://a.com,https://b.com/post" [--min-score 70] [--respect-robots true] [--report-path report.md]
7
+ //
8
+ // Exit code:
9
+ // 0 all audited URLs scored >= min-score
10
+ // 1 any URL scored < min-score (regression)
11
+ // 2 bad arguments / runtime error
12
+ import { appendFileSync } from "node:fs";
13
+ import { auditPage } from "../tools/audit-page.js";
14
+ import { saveAuditReport } from "../tools/save-audit-report.js";
15
+ function parseArgs(argv) {
16
+ const args = {
17
+ urls: [],
18
+ minScore: 70,
19
+ respectRobots: true,
20
+ reportPath: null,
21
+ failOnRegression: true,
22
+ };
23
+ for (let i = 0; i < argv.length; i++) {
24
+ const a = argv[i];
25
+ const next = () => {
26
+ const v = argv[i + 1];
27
+ if (v === undefined)
28
+ throw new Error(`flag ${a} requires a value`);
29
+ i++;
30
+ return v;
31
+ };
32
+ switch (a) {
33
+ case "--urls":
34
+ args.urls = next().split(",").map((s) => s.trim()).filter(Boolean);
35
+ break;
36
+ case "--min-score":
37
+ args.minScore = Number(next());
38
+ break;
39
+ case "--respect-robots":
40
+ args.respectRobots = next().toLowerCase() !== "false";
41
+ break;
42
+ case "--report-path":
43
+ args.reportPath = next();
44
+ break;
45
+ case "--fail-on-regression":
46
+ args.failOnRegression = next().toLowerCase() !== "false";
47
+ break;
48
+ case "--help":
49
+ case "-h":
50
+ console.log("Usage: ai-seo-audit --urls <csv> [--min-score N] [--respect-robots true|false] [--report-path FILE] [--fail-on-regression true|false]");
51
+ process.exit(0);
52
+ break;
53
+ default:
54
+ throw new Error(`unknown flag: ${a}`);
55
+ }
56
+ }
57
+ if (args.urls.length === 0)
58
+ throw new Error("at least one URL is required via --urls");
59
+ if (!Number.isFinite(args.minScore))
60
+ throw new Error("--min-score must be a number");
61
+ return args;
62
+ }
63
+ function emitGithubOutput(key, value) {
64
+ const file = process.env["GITHUB_OUTPUT"];
65
+ if (!file)
66
+ return;
67
+ const safe = String(value).replace(/\r?\n/g, " ");
68
+ try {
69
+ appendFileSync(file, `${key}=${safe}\n`);
70
+ }
71
+ catch {
72
+ // best-effort; CI step will still see stdout/stderr
73
+ }
74
+ }
75
+ async function main() {
76
+ let args;
77
+ try {
78
+ args = parseArgs(process.argv.slice(2));
79
+ }
80
+ catch (err) {
81
+ console.error("[ai-seo-audit] argument error:", err instanceof Error ? err.message : String(err));
82
+ process.exit(2);
83
+ }
84
+ const results = [];
85
+ let anyBelow = false;
86
+ let minObserved = 100;
87
+ for (const url of args.urls) {
88
+ try {
89
+ const result = await auditPage({
90
+ url,
91
+ include_raw_html: false,
92
+ respect_robots: args.respectRobots,
93
+ generate_report: false,
94
+ render: "static",
95
+ });
96
+ const below = result.score < args.minScore;
97
+ if (below)
98
+ anyBelow = true;
99
+ if (result.score < minObserved)
100
+ minObserved = result.score;
101
+ console.log(`${below ? "❌" : "✅"} ${url} — score=${result.score} grade=${result.grade} quality=${result.content_quality}`);
102
+ results.push(result);
103
+ }
104
+ catch (err) {
105
+ console.error(`[ai-seo-audit] failed for ${url}:`, err instanceof Error ? err.message : String(err));
106
+ anyBelow = true;
107
+ }
108
+ }
109
+ if (args.reportPath && results.length > 0) {
110
+ // Save the first result; users who pass multiple URLs typically want one report per run,
111
+ // and the action wires --report-path to a single file. Multi-URL reporting can be added if asked.
112
+ try {
113
+ const saved = await saveAuditReport({
114
+ audit_result: results[0],
115
+ path: args.reportPath,
116
+ overwrite: true,
117
+ });
118
+ console.log(`[ai-seo-audit] wrote ${saved.bytes_written}b -> ${saved.saved_to}`);
119
+ emitGithubOutput("report_path", saved.saved_to);
120
+ }
121
+ catch (err) {
122
+ console.error("[ai-seo-audit] could not save report:", err instanceof Error ? err.message : String(err));
123
+ }
124
+ }
125
+ emitGithubOutput("min_score_observed", minObserved);
126
+ emitGithubOutput("urls_audited", results.length);
127
+ if (anyBelow && args.failOnRegression) {
128
+ process.exit(1);
129
+ }
130
+ process.exit(0);
131
+ }
132
+ main().catch((err) => {
133
+ console.error("[ai-seo-audit] fatal:", err);
134
+ process.exit(2);
135
+ });
136
+ //# sourceMappingURL=audit-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-cli.js","sourceRoot":"","sources":["../../src/cli/audit-cli.ts"],"names":[],"mappings":"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"}