@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.
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +11 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/crawlers.json +6 -0
- package/dist/lib/entities.d.ts +17 -0
- package/dist/lib/entities.d.ts.map +1 -0
- package/dist/lib/entities.js +113 -0
- package/dist/lib/entities.js.map +1 -0
- package/dist/lib/fetch.d.ts +33 -0
- package/dist/lib/fetch.d.ts.map +1 -0
- package/dist/lib/fetch.js +190 -0
- package/dist/lib/fetch.js.map +1 -0
- package/dist/lib/html.d.ts +45 -0
- package/dist/lib/html.d.ts.map +1 -0
- package/dist/lib/html.js +166 -0
- package/dist/lib/html.js.map +1 -0
- package/dist/lib/llms-txt.d.ts +25 -0
- package/dist/lib/llms-txt.d.ts.map +1 -0
- package/dist/lib/llms-txt.js +149 -0
- package/dist/lib/llms-txt.js.map +1 -0
- package/dist/lib/robots.d.ts +26 -0
- package/dist/lib/robots.d.ts.map +1 -0
- package/dist/lib/robots.js +83 -0
- package/dist/lib/robots.js.map +1 -0
- package/dist/lib/schema-types.json +56 -0
- package/dist/lib/schema.d.ts +20 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +311 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/lib/score.d.ts +32 -0
- package/dist/lib/score.d.ts.map +1 -0
- package/dist/lib/score.js +62 -0
- package/dist/lib/score.js.map +1 -0
- package/dist/tools/audit-canonical.d.ts +26 -0
- package/dist/tools/audit-canonical.d.ts.map +1 -0
- package/dist/tools/audit-canonical.js +122 -0
- package/dist/tools/audit-canonical.js.map +1 -0
- package/dist/tools/audit-page.d.ts +31 -0
- package/dist/tools/audit-page.d.ts.map +1 -0
- package/dist/tools/audit-page.js +221 -0
- package/dist/tools/audit-page.js.map +1 -0
- package/dist/tools/audit-schema.d.ts +34 -0
- package/dist/tools/audit-schema.d.ts.map +1 -0
- package/dist/tools/audit-schema.js +65 -0
- package/dist/tools/audit-schema.js.map +1 -0
- package/dist/tools/check-robots.d.ts +22 -0
- package/dist/tools/check-robots.d.ts.map +1 -0
- package/dist/tools/check-robots.js +142 -0
- package/dist/tools/check-robots.js.map +1 -0
- package/dist/tools/check-sitemap.d.ts +27 -0
- package/dist/tools/check-sitemap.d.ts.map +1 -0
- package/dist/tools/check-sitemap.js +214 -0
- package/dist/tools/check-sitemap.js.map +1 -0
- package/dist/tools/check-technical.d.ts +50 -0
- package/dist/tools/check-technical.d.ts.map +1 -0
- package/dist/tools/check-technical.js +209 -0
- package/dist/tools/check-technical.js.map +1 -0
- package/dist/tools/extract-entities.d.ts +35 -0
- package/dist/tools/extract-entities.d.ts.map +1 -0
- package/dist/tools/extract-entities.js +69 -0
- package/dist/tools/extract-entities.js.map +1 -0
- package/dist/tools/generate-llms-txt.d.ts +32 -0
- package/dist/tools/generate-llms-txt.d.ts.map +1 -0
- package/dist/tools/generate-llms-txt.js +157 -0
- package/dist/tools/generate-llms-txt.js.map +1 -0
- package/dist/tools/rewrite-for-aeo.d.ts +50 -0
- package/dist/tools/rewrite-for-aeo.d.ts.map +1 -0
- package/dist/tools/rewrite-for-aeo.js +119 -0
- package/dist/tools/rewrite-for-aeo.js.map +1 -0
- package/dist/tools/rewrite-for-geo.d.ts +51 -0
- package/dist/tools/rewrite-for-geo.d.ts.map +1 -0
- package/dist/tools/rewrite-for-geo.js +115 -0
- package/dist/tools/rewrite-for-geo.js.map +1 -0
- package/dist/tools/score-ai-overview-eligibility.d.ts +34 -0
- package/dist/tools/score-ai-overview-eligibility.d.ts.map +1 -0
- package/dist/tools/score-ai-overview-eligibility.js +186 -0
- package/dist/tools/score-ai-overview-eligibility.js.map +1 -0
- package/dist/tools/score-citation-worthiness.d.ts +51 -0
- package/dist/tools/score-citation-worthiness.d.ts.map +1 -0
- package/dist/tools/score-citation-worthiness.js +145 -0
- package/dist/tools/score-citation-worthiness.js.map +1 -0
- package/dist/tools/validate-llms-txt.d.ts +33 -0
- package/dist/tools/validate-llms-txt.d.ts.map +1 -0
- package/dist/tools/validate-llms-txt.js +62 -0
- package/dist/tools/validate-llms-txt.js.map +1 -0
- package/dist/types.d.ts +48 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
- package/src/lib/crawlers.json +6 -0
- 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"}
|