@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,145 @@
1
+ // Tool: score_citation_worthiness
2
+ // Scores how citable a page or text block is for AI engines.
3
+ import { z } from "zod";
4
+ import { politeFetch } from "../lib/fetch.js";
5
+ import { parseBody } from "../lib/html.js";
6
+ import { parseJsonLd, getAllSchemaTypes } from "../lib/schema.js";
7
+ export const scoreCitationWorthinessInputSchema = z
8
+ .object({
9
+ url: z.string().url().optional(),
10
+ text: z.string().optional(),
11
+ target_query: z.string().optional(),
12
+ respect_robots: z.boolean().optional().default(true),
13
+ })
14
+ .refine((d) => d.url !== undefined || d.text !== undefined, {
15
+ message: "One of url or text is required",
16
+ });
17
+ function computeBluf(bodyText, targetQuery) {
18
+ const first100Words = bodyText.split(/\s+/).slice(0, 100).join(" ");
19
+ // Direct answer heuristic: a sentence with a number, or containing the target query
20
+ if (targetQuery && first100Words.toLowerCase().includes(targetQuery.toLowerCase()))
21
+ return true;
22
+ if (/\b\d+\b/.test(first100Words) && /\.\s/.test(first100Words))
23
+ return true;
24
+ return false;
25
+ }
26
+ function computeStatisticDensity(bodyText) {
27
+ const wordCount = bodyText.split(/\s+/).filter((w) => w.length > 0).length;
28
+ if (wordCount === 0)
29
+ return 0;
30
+ const statMatches = bodyText.match(/\b\d[\d,.'%]+\b/g) ?? [];
31
+ const statsPerThousand = (statMatches.length / wordCount) * 1000;
32
+ return Math.min(100, Math.round(statsPerThousand * 10)); // >10 stats/1000 words = 100
33
+ }
34
+ function computeEntityClarity(bodyText) {
35
+ const definitionPatterns = /\b\w+\s+(is an?\s+|refers to\s+|means\s+|defined as\s+)/gi;
36
+ const definitions = (bodyText.match(definitionPatterns) ?? []).length;
37
+ const uniqueNouns = new Set(bodyText.match(/\b[A-Z][a-z]+\b/g) ?? []).size;
38
+ if (uniqueNouns === 0)
39
+ return 0;
40
+ return Math.min(100, Math.round((definitions / Math.max(1, uniqueNouns)) * 100 * 10));
41
+ }
42
+ function countFaqBlocks(h3s, paragraphs) {
43
+ // FAQ block = H3 ending in "?" followed by a paragraph
44
+ return h3s.filter((h) => h.endsWith("?")).length;
45
+ }
46
+ export async function scoreCitationWorthiness(input, hostDelays, robotsCache) {
47
+ const findings = [];
48
+ let bodyText = "";
49
+ let h3s = [];
50
+ let paragraphs = [];
51
+ let hasStructuredData = false;
52
+ let wordCount = 0;
53
+ if (input.url) {
54
+ const result = await politeFetch(input.url, {
55
+ respectRobots: input.respect_robots,
56
+ hostDelays,
57
+ robotsCache,
58
+ });
59
+ const body = parseBody(result.body, input.url);
60
+ bodyText = body.bodyText;
61
+ h3s = body.h3s;
62
+ paragraphs = body.paragraphs;
63
+ wordCount = body.wordCount;
64
+ const jsonLdBlocks = parseJsonLd(result.body);
65
+ const foundTypes = getAllSchemaTypes(jsonLdBlocks);
66
+ hasStructuredData = foundTypes.length > 0;
67
+ }
68
+ else {
69
+ bodyText = input.text;
70
+ wordCount = bodyText.split(/\s+/).filter((w) => w.length > 0).length;
71
+ // Extract H3-like lines from plain text (lines ending in ?)
72
+ const lines = bodyText.split("\n");
73
+ h3s = lines.filter((l) => l.trim().endsWith("?") && l.trim().length < 100);
74
+ paragraphs = lines.filter((l) => l.trim().split(/\s+/).length >= 20);
75
+ }
76
+ // Sub-scores
77
+ const bluf_present = computeBluf(bodyText, input.target_query);
78
+ const faq_blocks = countFaqBlocks(h3s, paragraphs);
79
+ const statistic_density = computeStatisticDensity(bodyText);
80
+ const entity_clarity = computeEntityClarity(bodyText);
81
+ const totalHeadings = h3s.length + (input.text ? 0 : 0); // simplified
82
+ const questionHeadings = h3s.filter((h) => h.endsWith("?")).length;
83
+ const heading_question_ratio = totalHeadings > 0 ? Math.round((questionHeadings / totalHeadings) * 100) : 0;
84
+ // Longest self-contained paragraph (word count proxy)
85
+ const answer_completeness = paragraphs.length > 0
86
+ ? Math.min(100, Math.max(...paragraphs.map((p) => p.split(/\s+/).filter((w) => w.length > 0).length)) / 2)
87
+ : 0;
88
+ // Engine-specific scores
89
+ const blufScore = bluf_present ? 100 : 0;
90
+ const faqScore = Math.min(100, faq_blocks * 25);
91
+ const structuredDataScore = hasStructuredData ? 80 : 0;
92
+ // Perplexity: faq_blocks 40%, bluf_present 30%, statistic_density 30%
93
+ const perplexity = Math.round(faqScore * 0.4 + blufScore * 0.3 + statistic_density * 0.3);
94
+ // ChatGPT: answer_completeness 35%, structured_data 35%, bluf_present 30%
95
+ const chatgpt = Math.round(answer_completeness * 0.35 + structuredDataScore * 0.35 + blufScore * 0.3);
96
+ // Google AI Overviews: faq_blocks 30%, entity_clarity 30%, heading_question_ratio 20%, statistic_density 20%
97
+ const google_ai_overviews = Math.round(faqScore * 0.3 +
98
+ entity_clarity * 0.3 +
99
+ heading_question_ratio * 0.2 +
100
+ statistic_density * 0.2);
101
+ // Claude: statistic_density 35%, bluf_present 35%, entity_clarity 30%
102
+ const claude = Math.round(statistic_density * 0.35 + blufScore * 0.35 + entity_clarity * 0.30);
103
+ const overall_score = Math.round((perplexity + chatgpt + google_ai_overviews + claude) / 4);
104
+ // Improvements
105
+ const improvements = [];
106
+ if (!bluf_present) {
107
+ improvements.push("Add a direct 40-60 word answer in the first paragraph (BLUF - Bottom Line Up Front).");
108
+ }
109
+ if (faq_blocks < 3) {
110
+ improvements.push("Structure 3-5 FAQ-formatted Q&A blocks with H3 headings ending in '?'.");
111
+ }
112
+ if (statistic_density < 30) {
113
+ improvements.push("Include at least 3 cited statistics with year and source to increase statistic density.");
114
+ }
115
+ if (entity_clarity < 20) {
116
+ improvements.push("Define key terms inline (e.g., 'X is a type of Y that...') to improve entity clarity.");
117
+ }
118
+ const topImprovements = improvements.slice(0, 3);
119
+ // Findings
120
+ if (overall_score < 40) {
121
+ findings.push({
122
+ severity: "warning",
123
+ category: "structure",
124
+ where: "page-level",
125
+ message: `Low citation worthiness score (${overall_score}/100).`,
126
+ fix: "Apply BLUF structure, add FAQ blocks, and include cited statistics.",
127
+ estimated_impact: "high",
128
+ });
129
+ }
130
+ return {
131
+ overall_score,
132
+ engine_scores: { perplexity, chatgpt, google_ai_overviews, claude },
133
+ sub_scores: {
134
+ bluf_present,
135
+ faq_blocks,
136
+ statistic_density,
137
+ entity_clarity,
138
+ heading_question_ratio,
139
+ answer_completeness,
140
+ },
141
+ improvements: topImprovements,
142
+ findings,
143
+ };
144
+ }
145
+ //# sourceMappingURL=score-citation-worthiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score-citation-worthiness.js","sourceRoot":"","sources":["../../src/tools/score-citation-worthiness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import { type HostDelayMap } from "../lib/fetch.js";
3
+ import type { Finding } from "../types.js";
4
+ export declare const validateLlmsTxtInputSchema: z.ZodEffects<z.ZodObject<{
5
+ url: z.ZodOptional<z.ZodString>;
6
+ content: z.ZodOptional<z.ZodString>;
7
+ check_links: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ check_links: boolean;
10
+ url?: string | undefined;
11
+ content?: string | undefined;
12
+ }, {
13
+ url?: string | undefined;
14
+ content?: string | undefined;
15
+ check_links?: boolean | undefined;
16
+ }>, {
17
+ check_links: boolean;
18
+ url?: string | undefined;
19
+ content?: string | undefined;
20
+ }, {
21
+ url?: string | undefined;
22
+ content?: string | undefined;
23
+ check_links?: boolean | undefined;
24
+ }>;
25
+ export type ValidateLlmsTxtInput = z.infer<typeof validateLlmsTxtInputSchema>;
26
+ export interface ValidateLlmsTxtResult {
27
+ valid: boolean;
28
+ links_total: number;
29
+ links_broken: number;
30
+ findings: Finding[];
31
+ }
32
+ export declare function validateLlmsTxt(input: ValidateLlmsTxtInput, hostDelays?: HostDelayMap, robotsCache?: Map<string, string>): Promise<ValidateLlmsTxtResult>;
33
+ //# sourceMappingURL=validate-llms-txt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-llms-txt.d.ts","sourceRoot":"","sources":["../../src/tools/validate-llms-txt.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;EAQnC,CAAC;AAEL,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,EAC3B,UAAU,CAAC,EAAE,YAAY,EACzB,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC,qBAAqB,CAAC,CAoDhC"}
@@ -0,0 +1,62 @@
1
+ // Tool: validate_llms_txt
2
+ // Validates an existing llms.txt or llms-full.txt against the spec.
3
+ import { z } from "zod";
4
+ import { politeFetch, politeHead } from "../lib/fetch.js";
5
+ import { validateLlmsTxtContent, extractLlmsLinks } from "../lib/llms-txt.js";
6
+ export const validateLlmsTxtInputSchema = z
7
+ .object({
8
+ url: z.string().url().optional(),
9
+ content: z.string().optional(),
10
+ check_links: z.boolean().optional().default(true),
11
+ })
12
+ .refine((d) => d.url !== undefined || d.content !== undefined, {
13
+ message: "One of url or content is required",
14
+ });
15
+ export async function validateLlmsTxt(input, hostDelays, robotsCache) {
16
+ let content;
17
+ if (input.url) {
18
+ // If given a domain-style URL, append /llms.txt
19
+ let fetchUrl = input.url;
20
+ if (!fetchUrl.endsWith(".txt") && !fetchUrl.includes("llms")) {
21
+ fetchUrl = fetchUrl.replace(/\/$/, "") + "/llms.txt";
22
+ }
23
+ const result = await politeFetch(fetchUrl, {
24
+ respectRobots: false,
25
+ hostDelays,
26
+ robotsCache,
27
+ });
28
+ content = result.body;
29
+ }
30
+ else {
31
+ content = input.content;
32
+ }
33
+ const findings = validateLlmsTxtContent(content);
34
+ let links_total = 0;
35
+ let links_broken = 0;
36
+ if (input.check_links) {
37
+ const links = extractLlmsLinks(content);
38
+ links_total = links.length;
39
+ const delays = hostDelays ?? new Map();
40
+ for (const link of links) {
41
+ const status = await politeHead(link.url, { hostDelays: delays });
42
+ if (status === null || status === 404 || status === 410) {
43
+ links_broken++;
44
+ findings.push({
45
+ severity: "warning",
46
+ category: "llms_txt",
47
+ where: link.url,
48
+ message: `Broken link: "${link.title}" returns ${status ?? "no response"}.`,
49
+ fix: `Update or remove the link to ${link.url}.`,
50
+ });
51
+ }
52
+ }
53
+ }
54
+ const valid = !findings.some((f) => f.severity === "critical");
55
+ return {
56
+ valid,
57
+ links_total,
58
+ links_broken,
59
+ findings,
60
+ };
61
+ }
62
+ //# sourceMappingURL=validate-llms-txt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-llms-txt.js","sourceRoot":"","sources":["../../src/tools/validate-llms-txt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export type Severity = "critical" | "warning" | "info";
2
+ export type FindingCategory = "schema" | "robots" | "technical" | "freshness" | "structure" | "authority" | "presence" | "sitemap" | "llms_txt";
3
+ export interface Finding {
4
+ /** Severity determines triage priority. critical = blocks citation, warning = hurts probability, info = nice-to-have. */
5
+ severity: Severity;
6
+ category: FindingCategory;
7
+ /** Where the issue was found. Use CSS selector, JSON-LD path like "Article.author", robots.txt line ref, or "page-level". */
8
+ where: string;
9
+ /** Human-readable message. Sentence case. <=120 chars. Do not repeat the fix here. */
10
+ message: string;
11
+ /** Concrete, copy-pasteable fix. Code snippets are acceptable. <=300 chars. */
12
+ fix: string;
13
+ /** Estimated impact on AI citation probability if this finding is resolved. Omit for info-level findings. */
14
+ estimated_impact?: "high" | "medium" | "low";
15
+ }
16
+ export interface AuditResult {
17
+ url: string;
18
+ fetched_at: string;
19
+ findings: Finding[];
20
+ score: number;
21
+ grade: "A" | "B" | "C" | "D" | "F";
22
+ }
23
+ export type ToolError = {
24
+ type: "invalid_url";
25
+ message: string;
26
+ } | {
27
+ type: "fetch_timeout";
28
+ url: string;
29
+ timeout_ms: number;
30
+ } | {
31
+ type: "robots_blocked";
32
+ url: string;
33
+ user_agent: string;
34
+ } | {
35
+ type: "non_html_response";
36
+ url: string;
37
+ content_type: string;
38
+ } | {
39
+ type: "parse_error";
40
+ url: string;
41
+ detail: string;
42
+ } | {
43
+ type: "fetch_error";
44
+ url: string;
45
+ status?: number;
46
+ message: string;
47
+ };
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,UAAU,GACV,SAAS,GACT,UAAU,CAAC;AAEf,MAAM,WAAW,OAAO;IACtB,yHAAyH;IACzH,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,6HAA6H;IAC7H,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,6GAA6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC9C;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;CACpC;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ // Shared types for the AI-SEO MCP server.
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@automatelab/ai-seo-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for AI-SEO auditing: schema, robots.txt, llms.txt, citation scoring, and AEO/GEO rewrites",
5
+ "license": "MIT",
6
+ "author": "automatelab.tech",
7
+ "homepage": "https://github.com/AutomateLab-tech/ai-seo",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/AutomateLab-tech/ai-seo.git"
11
+ },
12
+ "engines": { "node": ">=20" },
13
+ "type": "module",
14
+ "bin": {
15
+ "ai-seo-mcp": "dist/index.js"
16
+ },
17
+ "main": "dist/index.js",
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsx src/index.ts",
21
+ "start": "node dist/index.js",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "lint": "eslint src tests --ext .ts",
25
+ "typecheck": "tsc --noEmit"
26
+ },
27
+ "dependencies": {
28
+ "@modelcontextprotocol/sdk": "1.29.0",
29
+ "cheerio": "1.0.0",
30
+ "fast-xml-parser": "5.8.0",
31
+ "robots-parser": "3.0.1",
32
+ "undici": "7.25.0",
33
+ "zod": "3.25.76"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "22.19.19",
37
+ "tsx": "4.22.0",
38
+ "typescript": "5.7.3",
39
+ "vitest": "3.2.4"
40
+ },
41
+ "files": [
42
+ "dist",
43
+ "src/lib/crawlers.json",
44
+ "src/lib/schema-types.json",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "keywords": [
49
+ "mcp",
50
+ "seo",
51
+ "ai-seo",
52
+ "aeo",
53
+ "geo",
54
+ "ai-overview",
55
+ "schema",
56
+ "robots",
57
+ "llms-txt",
58
+ "citation"
59
+ ]
60
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "training": ["GPTBot", "ClaudeBot", "CCBot", "Meta-ExternalAgent", "Amazonbot"],
3
+ "search": ["OAI-SearchBot", "Claude-SearchBot", "PerplexityBot", "Bingbot", "DuckAssistBot"],
4
+ "user_triggered": ["ChatGPT-User", "Claude-User", "Google-Agent"],
5
+ "robots_token_only": ["Google-Extended", "Applebot-Extended"]
6
+ }
@@ -0,0 +1,56 @@
1
+ [
2
+ "Article",
3
+ "BlogPosting",
4
+ "NewsArticle",
5
+ "FAQPage",
6
+ "Question",
7
+ "Answer",
8
+ "HowTo",
9
+ "HowToStep",
10
+ "HowToSection",
11
+ "HowToTool",
12
+ "HowToSupply",
13
+ "Organization",
14
+ "LocalBusiness",
15
+ "Person",
16
+ "Product",
17
+ "Offer",
18
+ "AggregateOffer",
19
+ "Review",
20
+ "AggregateRating",
21
+ "Rating",
22
+ "BreadcrumbList",
23
+ "ListItem",
24
+ "SoftwareApplication",
25
+ "WebApplication",
26
+ "MobileApplication",
27
+ "WebSite",
28
+ "WebPage",
29
+ "ItemPage",
30
+ "AboutPage",
31
+ "ContactPage",
32
+ "SearchResultsPage",
33
+ "ImageObject",
34
+ "VideoObject",
35
+ "AudioObject",
36
+ "MediaObject",
37
+ "Event",
38
+ "CreativeWork",
39
+ "Book",
40
+ "Course",
41
+ "Recipe",
42
+ "Dataset",
43
+ "SpeakableSpecification",
44
+ "SearchAction",
45
+ "EntryPoint",
46
+ "PostalAddress",
47
+ "GeoCoordinates",
48
+ "OpeningHoursSpecification",
49
+ "PriceSpecification",
50
+ "MonetaryAmount",
51
+ "ContactPoint",
52
+ "Brand",
53
+ "Intangible",
54
+ "Thing",
55
+ "Place"
56
+ ]