@automatelab/ai-seo-mcp 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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +145 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/config.d.ts +8 -0
  8. package/dist/lib/config.d.ts.map +1 -0
  9. package/dist/lib/config.js +11 -0
  10. package/dist/lib/config.js.map +1 -0
  11. package/dist/lib/crawlers.json +6 -0
  12. package/dist/lib/entities.d.ts +17 -0
  13. package/dist/lib/entities.d.ts.map +1 -0
  14. package/dist/lib/entities.js +113 -0
  15. package/dist/lib/entities.js.map +1 -0
  16. package/dist/lib/fetch.d.ts +33 -0
  17. package/dist/lib/fetch.d.ts.map +1 -0
  18. package/dist/lib/fetch.js +190 -0
  19. package/dist/lib/fetch.js.map +1 -0
  20. package/dist/lib/html.d.ts +45 -0
  21. package/dist/lib/html.d.ts.map +1 -0
  22. package/dist/lib/html.js +166 -0
  23. package/dist/lib/html.js.map +1 -0
  24. package/dist/lib/llms-txt.d.ts +25 -0
  25. package/dist/lib/llms-txt.d.ts.map +1 -0
  26. package/dist/lib/llms-txt.js +149 -0
  27. package/dist/lib/llms-txt.js.map +1 -0
  28. package/dist/lib/robots.d.ts +26 -0
  29. package/dist/lib/robots.d.ts.map +1 -0
  30. package/dist/lib/robots.js +83 -0
  31. package/dist/lib/robots.js.map +1 -0
  32. package/dist/lib/schema-types.json +56 -0
  33. package/dist/lib/schema.d.ts +20 -0
  34. package/dist/lib/schema.d.ts.map +1 -0
  35. package/dist/lib/schema.js +311 -0
  36. package/dist/lib/schema.js.map +1 -0
  37. package/dist/lib/score.d.ts +32 -0
  38. package/dist/lib/score.d.ts.map +1 -0
  39. package/dist/lib/score.js +62 -0
  40. package/dist/lib/score.js.map +1 -0
  41. package/dist/tools/audit-canonical.d.ts +26 -0
  42. package/dist/tools/audit-canonical.d.ts.map +1 -0
  43. package/dist/tools/audit-canonical.js +122 -0
  44. package/dist/tools/audit-canonical.js.map +1 -0
  45. package/dist/tools/audit-page.d.ts +31 -0
  46. package/dist/tools/audit-page.d.ts.map +1 -0
  47. package/dist/tools/audit-page.js +221 -0
  48. package/dist/tools/audit-page.js.map +1 -0
  49. package/dist/tools/audit-schema.d.ts +34 -0
  50. package/dist/tools/audit-schema.d.ts.map +1 -0
  51. package/dist/tools/audit-schema.js +65 -0
  52. package/dist/tools/audit-schema.js.map +1 -0
  53. package/dist/tools/check-robots.d.ts +22 -0
  54. package/dist/tools/check-robots.d.ts.map +1 -0
  55. package/dist/tools/check-robots.js +142 -0
  56. package/dist/tools/check-robots.js.map +1 -0
  57. package/dist/tools/check-sitemap.d.ts +27 -0
  58. package/dist/tools/check-sitemap.d.ts.map +1 -0
  59. package/dist/tools/check-sitemap.js +214 -0
  60. package/dist/tools/check-sitemap.js.map +1 -0
  61. package/dist/tools/check-technical.d.ts +50 -0
  62. package/dist/tools/check-technical.d.ts.map +1 -0
  63. package/dist/tools/check-technical.js +209 -0
  64. package/dist/tools/check-technical.js.map +1 -0
  65. package/dist/tools/extract-entities.d.ts +35 -0
  66. package/dist/tools/extract-entities.d.ts.map +1 -0
  67. package/dist/tools/extract-entities.js +69 -0
  68. package/dist/tools/extract-entities.js.map +1 -0
  69. package/dist/tools/generate-llms-txt.d.ts +32 -0
  70. package/dist/tools/generate-llms-txt.d.ts.map +1 -0
  71. package/dist/tools/generate-llms-txt.js +157 -0
  72. package/dist/tools/generate-llms-txt.js.map +1 -0
  73. package/dist/tools/rewrite-for-aeo.d.ts +50 -0
  74. package/dist/tools/rewrite-for-aeo.d.ts.map +1 -0
  75. package/dist/tools/rewrite-for-aeo.js +119 -0
  76. package/dist/tools/rewrite-for-aeo.js.map +1 -0
  77. package/dist/tools/rewrite-for-geo.d.ts +51 -0
  78. package/dist/tools/rewrite-for-geo.d.ts.map +1 -0
  79. package/dist/tools/rewrite-for-geo.js +115 -0
  80. package/dist/tools/rewrite-for-geo.js.map +1 -0
  81. package/dist/tools/score-ai-overview-eligibility.d.ts +34 -0
  82. package/dist/tools/score-ai-overview-eligibility.d.ts.map +1 -0
  83. package/dist/tools/score-ai-overview-eligibility.js +186 -0
  84. package/dist/tools/score-ai-overview-eligibility.js.map +1 -0
  85. package/dist/tools/score-citation-worthiness.d.ts +51 -0
  86. package/dist/tools/score-citation-worthiness.d.ts.map +1 -0
  87. package/dist/tools/score-citation-worthiness.js +145 -0
  88. package/dist/tools/score-citation-worthiness.js.map +1 -0
  89. package/dist/tools/validate-llms-txt.d.ts +33 -0
  90. package/dist/tools/validate-llms-txt.d.ts.map +1 -0
  91. package/dist/tools/validate-llms-txt.js +62 -0
  92. package/dist/tools/validate-llms-txt.js.map +1 -0
  93. package/dist/types.d.ts +48 -0
  94. package/dist/types.d.ts.map +1 -0
  95. package/dist/types.js +3 -0
  96. package/dist/types.js.map +1 -0
  97. package/package.json +60 -0
  98. package/src/lib/crawlers.json +6 -0
  99. package/src/lib/schema-types.json +56 -0
@@ -0,0 +1,142 @@
1
+ // Tool: check_robots
2
+ // Parses a domain's robots.txt and reports per-crawler allow/disallow posture.
3
+ import { z } from "zod";
4
+ import { fetchRobotsTxt, checkCrawlerStatus, CRAWLERS } from "../lib/robots.js";
5
+ export const checkRobotsInputSchema = z.object({
6
+ domain: z.string().min(3),
7
+ });
8
+ function normalizeDomain(domain) {
9
+ let d = domain.trim();
10
+ if (d.startsWith("http://") || d.startsWith("https://")) {
11
+ try {
12
+ const url = new URL(d);
13
+ return url.hostname;
14
+ }
15
+ catch {
16
+ return d;
17
+ }
18
+ }
19
+ return d.replace(/\/$/, "");
20
+ }
21
+ export async function checkRobots(input) {
22
+ const hostname = normalizeDomain(input.domain);
23
+ const robotsUrl = `https://${hostname}/robots.txt`;
24
+ const fetched_at = new Date().toISOString();
25
+ const findings = [];
26
+ const robotsText = await fetchRobotsTxt(robotsUrl);
27
+ if (!robotsText) {
28
+ findings.push({
29
+ severity: "warning",
30
+ category: "robots",
31
+ where: robotsUrl,
32
+ message: "robots.txt not found (404 or empty response).",
33
+ fix: "Create a robots.txt file at the domain root. All AI crawlers default to allow-all when it is absent.",
34
+ estimated_impact: "medium",
35
+ });
36
+ }
37
+ // Evaluate each crawler category
38
+ const training_crawlers = {};
39
+ for (const agent of CRAWLERS.training) {
40
+ training_crawlers[agent] = checkCrawlerStatus(robotsText, robotsUrl, agent);
41
+ }
42
+ const search_crawlers = {};
43
+ for (const agent of CRAWLERS.search) {
44
+ search_crawlers[agent] = checkCrawlerStatus(robotsText, robotsUrl, agent);
45
+ }
46
+ const user_triggered = {};
47
+ for (const agent of CRAWLERS.user_triggered) {
48
+ user_triggered[agent] = checkCrawlerStatus(robotsText, robotsUrl, agent);
49
+ }
50
+ // Emit findings for key conditions
51
+ for (const agent of CRAWLERS.training) {
52
+ if (training_crawlers[agent] !== "disallowed") {
53
+ findings.push({
54
+ severity: "warning",
55
+ category: "robots",
56
+ where: `robots.txt User-agent: ${agent}`,
57
+ message: `${agent} is not disallowed. Your content may be harvested for model training.`,
58
+ fix: `Add:\nUser-agent: ${agent}\nDisallow: /`,
59
+ estimated_impact: "medium",
60
+ });
61
+ }
62
+ }
63
+ // OAI-SearchBot should be explicitly allowed
64
+ if (search_crawlers["OAI-SearchBot"] === "not-mentioned") {
65
+ findings.push({
66
+ severity: "info",
67
+ category: "robots",
68
+ where: "robots.txt User-agent: OAI-SearchBot",
69
+ message: "OAI-SearchBot is not mentioned. Explicit Allow: / increases ChatGPT search citation probability.",
70
+ fix: "Add:\nUser-agent: OAI-SearchBot\nAllow: /",
71
+ });
72
+ }
73
+ // PerplexityBot blocked warning
74
+ if (search_crawlers["PerplexityBot"] === "disallowed") {
75
+ findings.push({
76
+ severity: "warning",
77
+ category: "robots",
78
+ where: "robots.txt User-agent: PerplexityBot",
79
+ message: "PerplexityBot is blocked. This prevents citations in Perplexity AI answers.",
80
+ fix: "Remove the PerplexityBot Disallow directive or add Allow: /.",
81
+ estimated_impact: "high",
82
+ });
83
+ }
84
+ // GPTBot blocked but OAI-SearchBot not explicitly allowed
85
+ if (training_crawlers["GPTBot"] === "disallowed" &&
86
+ search_crawlers["OAI-SearchBot"] !== "allowed") {
87
+ findings.push({
88
+ severity: "warning",
89
+ category: "robots",
90
+ where: "robots.txt",
91
+ message: "GPTBot is blocked (training) but OAI-SearchBot is not explicitly allowed (search). These are independently controllable.",
92
+ fix: "Add:\nUser-agent: OAI-SearchBot\nAllow: /\nto preserve ChatGPT search citations.",
93
+ estimated_impact: "high",
94
+ });
95
+ }
96
+ // Robots-token-only notes
97
+ for (const token of CRAWLERS.robots_token_only) {
98
+ const lowerText = (robotsText ?? "").toLowerCase();
99
+ if (lowerText.includes(token.toLowerCase())) {
100
+ findings.push({
101
+ severity: "info",
102
+ category: "robots",
103
+ where: `robots.txt User-agent: ${token}`,
104
+ message: `${token} is a training-opt-out token, not an HTTP crawler. It does not affect search crawling.`,
105
+ fix: "No action needed - this token correctly controls training data opt-out.",
106
+ });
107
+ }
108
+ }
109
+ // Google-Agent always present as info
110
+ findings.push({
111
+ severity: "info",
112
+ category: "robots",
113
+ where: "robots.txt User-agent: Google-Agent",
114
+ message: "Google-Agent (Mariner) ignores robots.txt per Google's documentation. You cannot opt out via robots.txt.",
115
+ fix: "No robots.txt action possible for Google-Agent. Use noindex meta tags if you need page-level exclusion.",
116
+ });
117
+ // Determine recommended posture
118
+ const allTrainingBlocked = CRAWLERS.training.every((a) => training_crawlers[a] === "disallowed");
119
+ const allSearchAllowedOrUnmentioned = CRAWLERS.search.every((a) => search_crawlers[a] !== "disallowed");
120
+ const allTrainingAllowed = CRAWLERS.training.every((a) => training_crawlers[a] !== "disallowed");
121
+ const allSearchBlocked = CRAWLERS.search.every((a) => search_crawlers[a] === "disallowed");
122
+ let recommended_posture = "custom";
123
+ if (allTrainingBlocked && allSearchAllowedOrUnmentioned) {
124
+ recommended_posture = "block_training_allow_search";
125
+ }
126
+ else if (allTrainingAllowed && !allSearchBlocked) {
127
+ recommended_posture = "allow_all";
128
+ }
129
+ else if (allTrainingBlocked && allSearchBlocked) {
130
+ recommended_posture = "block_all";
131
+ }
132
+ return {
133
+ robots_url: robotsUrl,
134
+ fetched_at,
135
+ training_crawlers,
136
+ search_crawlers,
137
+ user_triggered,
138
+ findings,
139
+ recommended_posture,
140
+ };
141
+ }
142
+ //# sourceMappingURL=check-robots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-robots.js","sourceRoot":"","sources":["../../src/tools/check-robots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+ import { type HostDelayMap } from "../lib/fetch.js";
3
+ import type { Finding } from "../types.js";
4
+ export declare const checkSitemapInputSchema: z.ZodObject<{
5
+ domain: z.ZodString;
6
+ max_urls_to_check: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ domain: string;
9
+ max_urls_to_check: number;
10
+ }, {
11
+ domain: string;
12
+ max_urls_to_check?: number | undefined;
13
+ }>;
14
+ export type CheckSitemapInput = z.infer<typeof checkSitemapInputSchema>;
15
+ export interface SitemapResult {
16
+ sitemap_url: string | null;
17
+ status: "found" | "missing" | "error";
18
+ total_urls: number;
19
+ urls_with_lastmod: number;
20
+ stale_urls: number;
21
+ has_image_sitemap: boolean;
22
+ has_video_sitemap: boolean;
23
+ sitemap_index: boolean;
24
+ findings: Finding[];
25
+ }
26
+ export declare function checkSitemap(input: CheckSitemapInput, hostDelays?: HostDelayMap, robotsCache?: Map<string, string>): Promise<SitemapResult>;
27
+ //# sourceMappingURL=check-sitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-sitemap.d.ts","sourceRoot":"","sources":["../../src/tools/check-sitemap.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,uBAAuB;;;;;;;;;EAGlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAsFD,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,UAAU,CAAC,EAAE,YAAY,EACzB,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC,aAAa,CAAC,CA0IxB"}
@@ -0,0 +1,214 @@
1
+ // Tool: check_sitemap
2
+ // Validates a domain's XML sitemap for presence, accessibility, and AI-search attributes.
3
+ import { z } from "zod";
4
+ import { politeFetch } from "../lib/fetch.js";
5
+ import { fetchRobotsTxt } from "../lib/robots.js";
6
+ import { XMLParser } from "fast-xml-parser";
7
+ export const checkSitemapInputSchema = z.object({
8
+ domain: z.string().min(3),
9
+ max_urls_to_check: z.number().int().min(1).max(500).optional().default(100),
10
+ });
11
+ function normalizeDomain(domain) {
12
+ if (domain.startsWith("http://") || domain.startsWith("https://")) {
13
+ try {
14
+ return new URL(domain).hostname;
15
+ }
16
+ catch {
17
+ return domain;
18
+ }
19
+ }
20
+ return domain.replace(/\/$/, "");
21
+ }
22
+ function isStale(lastmod) {
23
+ try {
24
+ const d = new Date(lastmod).getTime();
25
+ const ageDays = (Date.now() - d) / (1000 * 60 * 60 * 24);
26
+ return ageDays > 90;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ function parseSitemapXml(xml, sitemapUrl) {
33
+ const parser = new XMLParser({ ignoreAttributes: false });
34
+ let parsed;
35
+ try {
36
+ parsed = parser.parse(xml);
37
+ }
38
+ catch {
39
+ return { urls: [], isSitemapIndex: false, childSitemaps: [] };
40
+ }
41
+ // Sitemap index
42
+ const sitemapIndex = parsed["sitemapindex"];
43
+ if (sitemapIndex) {
44
+ const sitemaps = sitemapIndex["sitemap"];
45
+ const sitemapList = Array.isArray(sitemaps)
46
+ ? sitemaps
47
+ : sitemaps
48
+ ? [sitemaps]
49
+ : [];
50
+ const childSitemaps = sitemapList
51
+ .map((s) => String(s["loc"] ?? ""))
52
+ .filter(Boolean);
53
+ return { urls: [], isSitemapIndex: true, childSitemaps };
54
+ }
55
+ // Regular sitemap
56
+ const urlset = parsed["urlset"];
57
+ if (!urlset)
58
+ return { urls: [], isSitemapIndex: false, childSitemaps: [] };
59
+ const urlEntries = urlset["url"];
60
+ const urlList = Array.isArray(urlEntries)
61
+ ? urlEntries
62
+ : urlEntries
63
+ ? [urlEntries]
64
+ : [];
65
+ const urls = urlList.map((u) => ({
66
+ loc: String(u["loc"] ?? ""),
67
+ lastmod: u["lastmod"] ? String(u["lastmod"]) : undefined,
68
+ priority: u["priority"] ? String(u["priority"]) : undefined,
69
+ changefreq: u["changefreq"] ? String(u["changefreq"]) : undefined,
70
+ }));
71
+ // Check for image/video namespaces in raw XML
72
+ const hasImage = xml.includes("image:") || xml.includes("xmlns:image");
73
+ const hasVideo = xml.includes("video:") || xml.includes("xmlns:video");
74
+ return {
75
+ urls,
76
+ isSitemapIndex: false,
77
+ childSitemaps: [],
78
+ };
79
+ }
80
+ export async function checkSitemap(input, hostDelays, robotsCache) {
81
+ const hostname = normalizeDomain(input.domain);
82
+ const findings = [];
83
+ let sitemapUrl = null;
84
+ let allUrls = [];
85
+ let isSitemapIndex = false;
86
+ let hasImageSitemap = false;
87
+ let hasVideoSitemap = false;
88
+ // Try to discover sitemap
89
+ const candidates = [
90
+ `https://${hostname}/sitemap.xml`,
91
+ `https://${hostname}/sitemap_index.xml`,
92
+ ];
93
+ // Check robots.txt for Sitemap: directive
94
+ const robotsText = await fetchRobotsTxt(`https://${hostname}/robots.txt`);
95
+ if (robotsText) {
96
+ const sitemapMatch = robotsText.match(/^Sitemap:\s*(.+)$/im);
97
+ if (sitemapMatch && sitemapMatch[1]) {
98
+ const robotsSitemapUrl = sitemapMatch[1].trim();
99
+ if (!candidates.includes(robotsSitemapUrl)) {
100
+ candidates.unshift(robotsSitemapUrl); // try first
101
+ }
102
+ }
103
+ }
104
+ let sitemapXml = null;
105
+ for (const candidate of candidates) {
106
+ try {
107
+ const res = await politeFetch(candidate, {
108
+ respectRobots: false, // sitemaps are always allowed
109
+ hostDelays,
110
+ robotsCache,
111
+ });
112
+ if (res.statusCode === 200) {
113
+ sitemapUrl = candidate;
114
+ sitemapXml = res.body;
115
+ break;
116
+ }
117
+ }
118
+ catch {
119
+ // try next candidate
120
+ }
121
+ }
122
+ if (!sitemapXml || !sitemapUrl) {
123
+ findings.push({
124
+ severity: "critical",
125
+ category: "sitemap",
126
+ where: `https://${hostname}/sitemap.xml`,
127
+ message: "No sitemap found at standard locations.",
128
+ fix: "Create a sitemap.xml and declare it in robots.txt with 'Sitemap: https://yourdomain.com/sitemap.xml'.",
129
+ estimated_impact: "medium",
130
+ });
131
+ return {
132
+ sitemap_url: null,
133
+ status: "missing",
134
+ total_urls: 0,
135
+ urls_with_lastmod: 0,
136
+ stale_urls: 0,
137
+ has_image_sitemap: false,
138
+ has_video_sitemap: false,
139
+ sitemap_index: false,
140
+ findings,
141
+ };
142
+ }
143
+ hasImageSitemap = sitemapXml.includes("image:") || sitemapXml.includes("xmlns:image");
144
+ hasVideoSitemap = sitemapXml.includes("video:") || sitemapXml.includes("xmlns:video");
145
+ const { urls, isSitemapIndex: isIndex, childSitemaps } = parseSitemapXml(sitemapXml, sitemapUrl);
146
+ isSitemapIndex = isIndex;
147
+ allUrls = urls;
148
+ // Load child sitemaps (up to 3 levels, capped at max_urls_to_check)
149
+ if (isIndex && childSitemaps.length > 0) {
150
+ let loaded = 0;
151
+ for (const childUrl of childSitemaps) {
152
+ if (allUrls.length >= input.max_urls_to_check)
153
+ break;
154
+ if (loaded >= 3)
155
+ break; // max 3 child sitemaps for now
156
+ try {
157
+ const childRes = await politeFetch(childUrl, {
158
+ respectRobots: false,
159
+ hostDelays,
160
+ robotsCache,
161
+ });
162
+ const { urls: childUrls } = parseSitemapXml(childRes.body, childUrl);
163
+ if (childRes.body.includes("image:"))
164
+ hasImageSitemap = true;
165
+ if (childRes.body.includes("video:"))
166
+ hasVideoSitemap = true;
167
+ allUrls.push(...childUrls);
168
+ loaded++;
169
+ }
170
+ catch {
171
+ // skip failed child sitemaps
172
+ }
173
+ }
174
+ }
175
+ // Cap at max_urls_to_check
176
+ const checked = allUrls.slice(0, input.max_urls_to_check);
177
+ const total_urls = checked.length;
178
+ const urls_with_lastmod = checked.filter((u) => !!u.lastmod).length;
179
+ const stale_urls = checked.filter((u) => u.lastmod && isStale(u.lastmod)).length;
180
+ // Findings
181
+ const missingLastmod = total_urls - urls_with_lastmod;
182
+ if (total_urls > 0 && missingLastmod / total_urls > 0.5) {
183
+ findings.push({
184
+ severity: "warning",
185
+ category: "sitemap",
186
+ where: "sitemap.xml",
187
+ message: `${Math.round((missingLastmod / total_urls) * 100)}% of URLs are missing lastmod dates - reduces freshness signals.`,
188
+ fix: "Add <lastmod> to all <url> entries. Use ISO 8601 format (YYYY-MM-DD).",
189
+ estimated_impact: "medium",
190
+ });
191
+ }
192
+ if (total_urls > 0 && stale_urls / total_urls > 0.5) {
193
+ findings.push({
194
+ severity: "warning",
195
+ category: "sitemap",
196
+ where: "sitemap.xml",
197
+ message: `${Math.round((stale_urls / total_urls) * 100)}% of URLs have lastmod older than 90 days.`,
198
+ fix: "Update lastmod dates when content changes. Stale content signals reduce AI citation probability.",
199
+ estimated_impact: "medium",
200
+ });
201
+ }
202
+ return {
203
+ sitemap_url: sitemapUrl,
204
+ status: "found",
205
+ total_urls,
206
+ urls_with_lastmod,
207
+ stale_urls,
208
+ has_image_sitemap: hasImageSitemap,
209
+ has_video_sitemap: hasVideoSitemap,
210
+ sitemap_index: isSitemapIndex,
211
+ findings,
212
+ };
213
+ }
214
+ //# sourceMappingURL=check-sitemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-sitemap.js","sourceRoot":"","sources":["../../src/tools/check-sitemap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { type HostDelayMap } from "../lib/fetch.js";
3
+ import type { Finding } from "../types.js";
4
+ export declare const checkTechnicalInputSchema: z.ZodObject<{
5
+ url: z.ZodString;
6
+ respect_robots: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ url: string;
9
+ respect_robots: boolean;
10
+ }, {
11
+ url: string;
12
+ respect_robots?: boolean | undefined;
13
+ }>;
14
+ export type CheckTechnicalInput = z.infer<typeof checkTechnicalInputSchema>;
15
+ export interface TechnicalResult {
16
+ url: string;
17
+ https: boolean;
18
+ canonical: {
19
+ present: boolean;
20
+ value: string | null;
21
+ self_referential: boolean;
22
+ cross_domain: boolean;
23
+ };
24
+ noindex: boolean;
25
+ noindex_header: boolean;
26
+ og_tags: {
27
+ title: boolean;
28
+ description: boolean;
29
+ image: boolean;
30
+ url: boolean;
31
+ type: boolean;
32
+ };
33
+ twitter_card: {
34
+ present: boolean;
35
+ card_type: string | null;
36
+ };
37
+ hreflang: {
38
+ present: boolean;
39
+ count: number;
40
+ x_default: boolean;
41
+ };
42
+ title_og_match: boolean;
43
+ meta_description: {
44
+ present: boolean;
45
+ length: number;
46
+ };
47
+ findings: Finding[];
48
+ }
49
+ export declare function checkTechnical(input: CheckTechnicalInput, hostDelays?: HostDelayMap, robotsCache?: Map<string, string>): Promise<TechnicalResult>;
50
+ //# sourceMappingURL=check-technical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-technical.d.ts","sourceRoot":"","sources":["../../src/tools/check-technical.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA+B,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEjF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,yBAAyB;;;;;;;;;EAGpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,YAAY,EAAE,OAAO,CAAC;KACvB,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE;QACP,KAAK,EAAE,OAAO,CAAC;QACf,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,EAAE,OAAO,CAAC;QACf,GAAG,EAAE,OAAO,CAAC;QACb,IAAI,EAAE,OAAO,CAAC;KACf,CAAC;IACF,YAAY,EAAE;QACZ,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,EAC1B,UAAU,CAAC,EAAE,YAAY,EACzB,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC,eAAe,CAAC,CAgN1B"}