seo-gravity-mcp 1.0.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 thedevbob005
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # šŸš€ SEO Gravity MCP Server
2
+
3
+ The core Model Context Protocol (MCP) server for **SEO Gravity**.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install
9
+ npm run build
10
+ ```
11
+
12
+ ## Running the MCP Server
13
+
14
+ ```bash
15
+ node dist/index.js
16
+ ```
17
+
18
+ ## Available Tools (28 Tools)
19
+
20
+ See root [README.md](../README.md) or [SEO_GRAVITY_MCP_SPEC.md](../SEO_GRAVITY_MCP_SPEC.md) for full documentation of all 28 tools.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,521 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
5
+ // Import Tool Handlers
6
+ import { analyzeSerp, profileCompetitor, analyzeCompetitorContentGap, diffCompetitor, analyzeForumDiscussions } from './tools/serp.js';
7
+ import { auditGeoAiReadiness, generateLlmsTxt, auditAiBotsRobots } from './tools/geo.js';
8
+ import { scoreInformationGain, auditEeat } from './tools/eeat.js';
9
+ import { auditOnPage, generateContentBrief, scoreReadability } from './tools/onpage.js';
10
+ import { auditTechnical, diffJsRendering, validateRobotsTxt, inspectSitemap, analyzeInternalLinks } from './tools/technical.js';
11
+ import { getKeywordSuggestions, findQuestions, clusterKeywords, classifySearchIntent } from './tools/keywords.js';
12
+ import { mapEntitySalience, generateSchemaMarkup, validateSchema } from './tools/schema.js';
13
+ import { auditPageSpeed, submitIndexNow, auditContentDecay } from './tools/performance.js';
14
+ // Define the 28 MCP Tools
15
+ const TOOLS = [
16
+ // 1. SERP & Competitor Intelligence
17
+ {
18
+ name: 'seo_serp_analyze',
19
+ description: 'Scrapes live Google SERP for any keyword. Returns top ranking URLs, snippets, People Also Ask (PAA), Related Searches, and rich SERP features.',
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ query: { type: 'string', description: 'Search keyword / phrase' },
24
+ country: { type: 'string', description: 'Two-letter country code (default "us")' },
25
+ language: { type: 'string', description: 'Language code (default "en")' },
26
+ num_results: { type: 'number', description: 'Number of results to fetch (default 10)' }
27
+ },
28
+ required: ['query']
29
+ }
30
+ },
31
+ {
32
+ name: 'seo_competitor_content_gap',
33
+ description: 'Compares your page URL or draft text against top 3-5 ranking competitor pages to identify missing TF-IDF semantic entities, heading subtopics, and content depth gaps.',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: {
37
+ target_url_or_text: { type: 'string', description: 'Your page URL, local file path, or draft content' },
38
+ target_keyword: { type: 'string', description: 'Target keyword to rank for' },
39
+ competitor_urls: { type: 'array', items: { type: 'string' }, description: 'Optional list of competitor URLs (auto-scraped if omitted)' }
40
+ },
41
+ required: ['target_url_or_text', 'target_keyword']
42
+ }
43
+ },
44
+ {
45
+ name: 'seo_competitor_profile',
46
+ description: 'Deep extraction of a single competitor URL: heading tree (H1-H4), schema types, word count, reading grade, meta tags, and internal/external link ratio.',
47
+ inputSchema: {
48
+ type: 'object',
49
+ properties: {
50
+ url: { type: 'string', description: 'Competitor page URL' }
51
+ },
52
+ required: ['url']
53
+ }
54
+ },
55
+ {
56
+ name: 'seo_competitor_diff',
57
+ description: 'Side-by-side scorecard comparing your page vs a competitor across 25+ ranking signals (title, H1, keyword density, schema, image alt, etc.).',
58
+ inputSchema: {
59
+ type: 'object',
60
+ properties: {
61
+ my_url: { type: 'string', description: 'Your page URL or local server URL' },
62
+ competitor_url: { type: 'string', description: 'Competitor URL' },
63
+ focus_keyword: { type: 'string', description: 'Primary keyword to evaluate' }
64
+ },
65
+ required: ['my_url', 'competitor_url', 'focus_keyword']
66
+ }
67
+ },
68
+ {
69
+ name: 'seo_forum_discussions_pulse',
70
+ description: 'Scrapes Reddit, Quora, and forum discussions currently ranking on Google for a topic. Extracts real user problems, sentiments, and consensus.',
71
+ inputSchema: {
72
+ type: 'object',
73
+ properties: {
74
+ topic_or_keyword: { type: 'string', description: 'Topic or keyword to query' }
75
+ },
76
+ required: ['topic_or_keyword']
77
+ }
78
+ },
79
+ // 2. GEO & AI Search (AEO)
80
+ {
81
+ name: 'seo_geo_ai_readiness_audit',
82
+ description: 'Evaluates content for citation readiness in Google AI Overviews, Perplexity.ai, and ChatGPT Search (checks direct definitions, semantic chunking, tables, and stats).',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ url_or_text: { type: 'string', description: 'Page URL, raw HTML, or text draft' },
87
+ target_query: { type: 'string', description: 'Search query to test' }
88
+ },
89
+ required: ['url_or_text', 'target_query']
90
+ }
91
+ },
92
+ {
93
+ name: 'seo_llms_txt_generate',
94
+ description: 'Generates standard /llms.txt and /llms-full.txt markdown files to provide clean, structured context for AI search bots.',
95
+ inputSchema: {
96
+ type: 'object',
97
+ properties: {
98
+ site_name: { type: 'string', description: 'Site or project name' },
99
+ site_description: { type: 'string', description: 'Concise summary of site purpose' },
100
+ key_pages: {
101
+ type: 'array',
102
+ items: {
103
+ type: 'object',
104
+ properties: {
105
+ title: { type: 'string' },
106
+ url: { type: 'string' },
107
+ description: { type: 'string' }
108
+ },
109
+ required: ['title', 'url', 'description']
110
+ },
111
+ description: 'Key pages to index for LLMs'
112
+ }
113
+ },
114
+ required: ['site_name', 'site_description', 'key_pages']
115
+ }
116
+ },
117
+ {
118
+ name: 'seo_ai_bots_robots_audit',
119
+ description: 'Audits robots.txt permissions specifically for generative AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, Bytespider).',
120
+ inputSchema: {
121
+ type: 'object',
122
+ properties: {
123
+ domain_or_url: { type: 'string', description: 'Website domain or URL' }
124
+ },
125
+ required: ['domain_or_url']
126
+ }
127
+ },
128
+ // 3. Information Gain & E-E-A-T
129
+ {
130
+ name: 'seo_information_gain_score',
131
+ description: 'Quantifies content novelty vs top 10 Google results (Google Information Gain Patent) to detect and fix generic AI fluff.',
132
+ inputSchema: {
133
+ type: 'object',
134
+ properties: {
135
+ my_content_or_url: { type: 'string', description: 'Your content draft, local file, or live URL' },
136
+ keyword: { type: 'string', description: 'Target search query' }
137
+ },
138
+ required: ['my_content_or_url', 'keyword']
139
+ }
140
+ },
141
+ {
142
+ name: 'seo_eeat_audit',
143
+ description: 'Audits Google E-E-A-T trust signals (Person schema, author bylines, sameAs Wikidata/LinkedIn links, editorial policies, update dates).',
144
+ inputSchema: {
145
+ type: 'object',
146
+ properties: {
147
+ url_or_html: { type: 'string', description: 'Page URL or raw HTML' }
148
+ },
149
+ required: ['url_or_html']
150
+ }
151
+ },
152
+ // 4. On-Page & Content Strategy
153
+ {
154
+ name: 'seo_onpage_audit',
155
+ description: 'Comprehensive on-page audit of a URL, local file, or raw HTML (title pixel width, meta CTR, heading hierarchy, image alt, and slug).',
156
+ inputSchema: {
157
+ type: 'object',
158
+ properties: {
159
+ url_or_html: { type: 'string', description: 'URL, local file path, or raw HTML string' },
160
+ focus_keyword: { type: 'string', description: 'Optional primary keyword to verify' }
161
+ },
162
+ required: ['url_or_html']
163
+ }
164
+ },
165
+ {
166
+ name: 'seo_content_brief_generate',
167
+ description: 'Generates a data-backed Content Outline & Brief with target word count, H1/H2/H3 structure, semantic entities, and PAA FAQs.',
168
+ inputSchema: {
169
+ type: 'object',
170
+ properties: {
171
+ primary_keyword: { type: 'string', description: 'Primary keyword to target' },
172
+ secondary_keywords: { type: 'array', items: { type: 'string' }, description: 'Supporting secondary keywords' },
173
+ search_intent: {
174
+ type: 'string',
175
+ enum: ['Informational', 'Transactional', 'Commercial Investigation', 'Navigational'],
176
+ description: 'Optional intent classification'
177
+ }
178
+ },
179
+ required: ['primary_keyword']
180
+ }
181
+ },
182
+ {
183
+ name: 'seo_readability_score',
184
+ description: 'Computes Flesch Reading Ease, Flesch-Kincaid Grade Level, Gunning Fog index, passive voice %, and complex sentence breakdowns.',
185
+ inputSchema: {
186
+ type: 'object',
187
+ properties: {
188
+ text_or_url: { type: 'string', description: 'Text, markdown, or URL to score' }
189
+ },
190
+ required: ['text_or_url']
191
+ }
192
+ },
193
+ // 5. Technical SEO & JS Hydration
194
+ {
195
+ name: 'seo_technical_audit',
196
+ description: 'Inspects HTTP status code, redirect chains, canonical consistency, meta robots (noindex/nofollow), hreflang, SSL, and OpenGraph tags.',
197
+ inputSchema: {
198
+ type: 'object',
199
+ properties: {
200
+ url: { type: 'string', description: 'URL to audit' }
201
+ },
202
+ required: ['url']
203
+ }
204
+ },
205
+ {
206
+ name: 'seo_js_rendering_diff',
207
+ description: 'Compares raw server HTML response against the hydrated client DOM (JavaScript SEO) to spot hidden content or broken tags.',
208
+ inputSchema: {
209
+ type: 'object',
210
+ properties: {
211
+ url: { type: 'string', description: 'URL to diff (supports localhost or live sites)' }
212
+ },
213
+ required: ['url']
214
+ }
215
+ },
216
+ {
217
+ name: 'seo_robots_txt_validate',
218
+ description: 'Tests if specific URLs or paths are crawlable by search engine bots (Googlebot, Bingbot, GPTBot) based on robots.txt rules.',
219
+ inputSchema: {
220
+ type: 'object',
221
+ properties: {
222
+ domain_or_url: { type: 'string', description: 'Website domain or URL' },
223
+ test_path: { type: 'string', description: 'Subpath to test (default "/")' },
224
+ user_agent: { type: 'string', description: 'Bot name to test (default "Googlebot")' }
225
+ },
226
+ required: ['domain_or_url']
227
+ }
228
+ },
229
+ {
230
+ name: 'seo_sitemap_inspect',
231
+ description: 'Parses and validates XML sitemaps or sitemap index files, verifies lastmod tags, and checks URL limits.',
232
+ inputSchema: {
233
+ type: 'object',
234
+ properties: {
235
+ sitemap_url: { type: 'string', description: 'URL of sitemap.xml or sitemap_index.xml' }
236
+ },
237
+ required: ['sitemap_url']
238
+ }
239
+ },
240
+ {
241
+ name: 'seo_internal_links_analyze',
242
+ description: 'Analyzes internal links, anchor text distribution, generic anchor alerts, and nofollow internal flags.',
243
+ inputSchema: {
244
+ type: 'object',
245
+ properties: {
246
+ url: { type: 'string', description: 'Page URL to analyze' }
247
+ },
248
+ required: ['url']
249
+ }
250
+ },
251
+ // 6. Keyword Research & Intent Clustering
252
+ {
253
+ name: 'seo_keyword_suggestions',
254
+ description: 'Extracts keyword suggestions and long-tail variations using Google Autocomplete and the Alphabet Soup method.',
255
+ inputSchema: {
256
+ type: 'object',
257
+ properties: {
258
+ seed_keyword: { type: 'string', description: 'Seed keyword' },
259
+ include_alphabet_soup: { type: 'boolean', description: 'Generate a-z suggestions (default true)' }
260
+ },
261
+ required: ['seed_keyword']
262
+ }
263
+ },
264
+ {
265
+ name: 'seo_questions_find',
266
+ description: 'Finds question queries asked by users across Google (Who, What, Where, When, Why, How, Can, Is).',
267
+ inputSchema: {
268
+ type: 'object',
269
+ properties: {
270
+ topic: { type: 'string', description: 'Topic or keyword' }
271
+ },
272
+ required: ['topic']
273
+ }
274
+ },
275
+ {
276
+ name: 'seo_keyword_cluster',
277
+ description: 'Clusters a list of keywords into distinct Topic Pillars and Supporting Articles using semantic similarity.',
278
+ inputSchema: {
279
+ type: 'object',
280
+ properties: {
281
+ keywords: { type: 'array', items: { type: 'string' }, description: 'List of keywords to cluster' },
282
+ similarity_threshold: { type: 'number', description: 'Clustering sensitivity 0.1 - 1.0 (default 0.6)' }
283
+ },
284
+ required: ['keywords']
285
+ }
286
+ },
287
+ {
288
+ name: 'seo_search_intent_classify',
289
+ description: 'Classifies keywords into Informational, Navigational, Commercial Investigation, or Transactional intent.',
290
+ inputSchema: {
291
+ type: 'object',
292
+ properties: {
293
+ keywords: { type: 'array', items: { type: 'string' }, description: 'Keywords to classify' }
294
+ },
295
+ required: ['keywords']
296
+ }
297
+ },
298
+ // 7. Schema & Entity Graph
299
+ {
300
+ name: 'seo_entity_salience_map',
301
+ description: 'Extracts core entities, computes salience scores, and extracts Subject-Predicate-Object (SPO) relationship triples.',
302
+ inputSchema: {
303
+ type: 'object',
304
+ properties: {
305
+ text_or_url: { type: 'string', description: 'Page URL, raw HTML, or text' }
306
+ },
307
+ required: ['text_or_url']
308
+ }
309
+ },
310
+ {
311
+ name: 'seo_schema_generate',
312
+ description: 'Generates validated Schema.org JSON-LD scripts (Article, FAQPage, Product, LocalBusiness, BreadcrumbList, Organization).',
313
+ inputSchema: {
314
+ type: 'object',
315
+ properties: {
316
+ schema_type: {
317
+ type: 'string',
318
+ enum: ['Article', 'FAQPage', 'Product', 'HowTo', 'LocalBusiness', 'Organization', 'BreadcrumbList', 'SoftwareApplication'],
319
+ description: 'Type of schema to generate'
320
+ },
321
+ data: { type: 'object', description: 'Schema properties payload' }
322
+ },
323
+ required: ['schema_type', 'data']
324
+ }
325
+ },
326
+ {
327
+ name: 'seo_schema_validate',
328
+ description: 'Validates on-page or pasted JSON-LD structured data against Schema.org and Google Rich Result requirements.',
329
+ inputSchema: {
330
+ type: 'object',
331
+ properties: {
332
+ url_or_jsonld: { type: 'string', description: 'Page URL or raw JSON-LD string' }
333
+ },
334
+ required: ['url_or_jsonld']
335
+ }
336
+ },
337
+ // 8. Performance, IndexNow & Maintenance
338
+ {
339
+ name: 'seo_pagespeed_audit',
340
+ description: 'Checks Core Web Vitals (LCP, FCP, CLS, TTFB) with performance optimization fixes.',
341
+ inputSchema: {
342
+ type: 'object',
343
+ properties: {
344
+ url: { type: 'string', description: 'Page URL to test' },
345
+ strategy: { type: 'string', enum: ['mobile', 'desktop'], description: 'Device strategy (default "mobile")' }
346
+ },
347
+ required: ['url']
348
+ }
349
+ },
350
+ {
351
+ name: 'seo_indexnow_submit',
352
+ description: 'Submits newly created or updated URLs directly to Bing & Yandex via the IndexNow API protocol.',
353
+ inputSchema: {
354
+ type: 'object',
355
+ properties: {
356
+ host: { type: 'string', description: 'Website domain host (e.g. "example.com")' },
357
+ key: { type: 'string', description: 'IndexNow API key' },
358
+ key_location: { type: 'string', description: 'URL location of the key file' },
359
+ url_list: { type: 'array', items: { type: 'string' }, description: 'Array of URLs to submit' }
360
+ },
361
+ required: ['host', 'key', 'key_location', 'url_list']
362
+ }
363
+ },
364
+ {
365
+ name: 'seo_content_decay_audit',
366
+ description: 'Scans content for freshness decay (stale year references e.g. "2020", outdated statistics, broken external links).',
367
+ inputSchema: {
368
+ type: 'object',
369
+ properties: {
370
+ url_or_text: { type: 'string', description: 'Page URL or draft text to audit' }
371
+ },
372
+ required: ['url_or_text']
373
+ }
374
+ }
375
+ ];
376
+ // Initialize Server
377
+ const server = new Server({
378
+ name: 'seo-gravity-mcp',
379
+ version: '1.0.0'
380
+ }, {
381
+ capabilities: {
382
+ tools: {}
383
+ }
384
+ });
385
+ // Register list_tools handler
386
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
387
+ return { tools: TOOLS };
388
+ });
389
+ // Register call_tool handler
390
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
391
+ const { name, arguments: args } = request.params;
392
+ const a = (args || {});
393
+ try {
394
+ let result;
395
+ switch (name) {
396
+ // 1. SERP & Competitors
397
+ case 'seo_serp_analyze':
398
+ result = await analyzeSerp(a.query, a.country, a.language, a.num_results);
399
+ break;
400
+ case 'seo_competitor_content_gap':
401
+ result = await analyzeCompetitorContentGap(a.target_url_or_text, a.target_keyword, a.competitor_urls);
402
+ break;
403
+ case 'seo_competitor_profile':
404
+ result = await profileCompetitor(a.url);
405
+ break;
406
+ case 'seo_competitor_diff':
407
+ result = await diffCompetitor(a.my_url, a.competitor_url, a.focus_keyword);
408
+ break;
409
+ case 'seo_forum_discussions_pulse':
410
+ result = await analyzeForumDiscussions(a.topic_or_keyword);
411
+ break;
412
+ // 2. GEO & AI Search
413
+ case 'seo_geo_ai_readiness_audit':
414
+ result = await auditGeoAiReadiness(a.url_or_text, a.target_query);
415
+ break;
416
+ case 'seo_llms_txt_generate':
417
+ result = generateLlmsTxt(a.site_name, a.site_description, a.key_pages);
418
+ break;
419
+ case 'seo_ai_bots_robots_audit':
420
+ result = await auditAiBotsRobots(a.domain_or_url);
421
+ break;
422
+ // 3. E-E-A-T & Info Gain
423
+ case 'seo_information_gain_score':
424
+ result = await scoreInformationGain(a.my_content_or_url, a.keyword);
425
+ break;
426
+ case 'seo_eeat_audit':
427
+ result = await auditEeat(a.url_or_html);
428
+ break;
429
+ // 4. On-Page
430
+ case 'seo_onpage_audit':
431
+ result = await auditOnPage(a.url_or_html, a.focus_keyword);
432
+ break;
433
+ case 'seo_content_brief_generate':
434
+ result = await generateContentBrief(a.primary_keyword, a.secondary_keywords, a.search_intent);
435
+ break;
436
+ case 'seo_readability_score':
437
+ result = await scoreReadability(a.text_or_url);
438
+ break;
439
+ // 5. Technical
440
+ case 'seo_technical_audit':
441
+ result = await auditTechnical(a.url);
442
+ break;
443
+ case 'seo_js_rendering_diff':
444
+ result = await diffJsRendering(a.url);
445
+ break;
446
+ case 'seo_robots_txt_validate':
447
+ result = await validateRobotsTxt(a.domain_or_url, a.test_path, a.user_agent);
448
+ break;
449
+ case 'seo_sitemap_inspect':
450
+ result = await inspectSitemap(a.sitemap_url);
451
+ break;
452
+ case 'seo_internal_links_analyze':
453
+ result = await analyzeInternalLinks(a.url);
454
+ break;
455
+ // 6. Keywords
456
+ case 'seo_keyword_suggestions':
457
+ result = await getKeywordSuggestions(a.seed_keyword, a.include_alphabet_soup);
458
+ break;
459
+ case 'seo_questions_find':
460
+ result = await findQuestions(a.topic);
461
+ break;
462
+ case 'seo_keyword_cluster':
463
+ result = clusterKeywords(a.keywords, a.similarity_threshold);
464
+ break;
465
+ case 'seo_search_intent_classify':
466
+ result = classifySearchIntent(a.keywords);
467
+ break;
468
+ // 7. Schema
469
+ case 'seo_entity_salience_map':
470
+ result = await mapEntitySalience(a.text_or_url);
471
+ break;
472
+ case 'seo_schema_generate':
473
+ result = generateSchemaMarkup(a.schema_type, a.data);
474
+ break;
475
+ case 'seo_schema_validate':
476
+ result = await validateSchema(a.url_or_jsonld);
477
+ break;
478
+ // 8. Performance & Maintenance
479
+ case 'seo_pagespeed_audit':
480
+ result = await auditPageSpeed(a.url, a.strategy);
481
+ break;
482
+ case 'seo_indexnow_submit':
483
+ result = await submitIndexNow(a.host, a.key, a.key_location, a.url_list);
484
+ break;
485
+ case 'seo_content_decay_audit':
486
+ result = await auditContentDecay(a.url_or_text);
487
+ break;
488
+ default:
489
+ throw new Error(`Unknown SEO Gravity MCP tool: ${name}`);
490
+ }
491
+ return {
492
+ content: [
493
+ {
494
+ type: 'text',
495
+ text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
496
+ }
497
+ ]
498
+ };
499
+ }
500
+ catch (error) {
501
+ return {
502
+ isError: true,
503
+ content: [
504
+ {
505
+ type: 'text',
506
+ text: `SEO Gravity Tool Execution Error (${name}): ${error.message}`
507
+ }
508
+ ]
509
+ };
510
+ }
511
+ });
512
+ // Start the Server using Stdio transport
513
+ async function main() {
514
+ const transport = new StdioServerTransport();
515
+ await server.connect(transport);
516
+ console.error('SEO Gravity MCP Server running on stdio');
517
+ }
518
+ main().catch((err) => {
519
+ console.error('Fatal error starting SEO Gravity MCP Server:', err);
520
+ process.exit(1);
521
+ });
package/dist/test.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/test.js ADDED
@@ -0,0 +1,76 @@
1
+ import { auditOnPage } from './tools/onpage.js';
2
+ import { auditGeoAiReadiness, generateLlmsTxt } from './tools/geo.js';
3
+ import { clusterKeywords, classifySearchIntent } from './tools/keywords.js';
4
+ import { generateSchemaMarkup, validateSchema } from './tools/schema.js';
5
+ import { auditContentDecay } from './tools/performance.js';
6
+ async function runTests() {
7
+ console.log('🧪 Starting SEO Gravity MCP Comprehensive Test Suite...\n');
8
+ // Test 1: On-Page Audit
9
+ console.log('1ļøāƒ£ Testing On-Page Audit...');
10
+ const sampleHtml = `
11
+ <!DOCTYPE html>
12
+ <html>
13
+ <head>
14
+ <title>Best Project Management Software in 2026 - Top 10 Picks</title>
15
+ <meta name="description" content="Discover the best project management software tools for agile teams in 2026. Compare pricing, features, and user ratings. Start free today.">
16
+ <link rel="canonical" href="https://example.com/best-project-management-software">
17
+ </head>
18
+ <body>
19
+ <h1>Best Project Management Software for Teams</h1>
20
+ <h2>1. Why Project Management Tools Matter</h2>
21
+ <p>Project management software refers to digital platforms designed to plan, organize, and allocate resources efficiently across engineering and marketing teams.</p>
22
+ <h2>2. Top Features Comparison</h2>
23
+ <p>Key features include Gantt charts, real-time collaboration, and API integrations.</p>
24
+ <img src="hero.png" alt="Project management dashboard preview">
25
+ <a href="/pricing">View Pricing</a>
26
+ <a href="https://wikipedia.org/wiki/Project_management">Learn more on Wikipedia</a>
27
+ </body>
28
+ </html>
29
+ `;
30
+ const onpage = await auditOnPage(sampleHtml, 'project management software');
31
+ console.log(`āœ… On-Page Score: ${onpage.overallScore}/100 | Title status: ${onpage.titleAudit.status} | H1 count: ${onpage.headingsAudit.h1Count}`);
32
+ // Test 2: GEO / AEO Readiness Audit
33
+ console.log('\n2ļøāƒ£ Testing GEO & AI Search Readiness Audit...');
34
+ const geo = await auditGeoAiReadiness(sampleHtml, 'best project management software');
35
+ console.log(`āœ… GEO Score: ${geo.overallGeoScore}/100 | Citation Likelihood: ${geo.citationLikelihood} | Direct Answer: ${geo.checks.directAnswerParagraph.passed}`);
36
+ // Test 3: LLMS.txt Generation
37
+ console.log('\n3ļøāƒ£ Testing llms.txt Generation...');
38
+ const llms = generateLlmsTxt('SaaS Suite', 'Cloud workspace tools', [
39
+ { title: 'Home', url: 'https://example.com', description: 'Main landing page' },
40
+ { title: 'Docs', url: 'https://example.com/docs', description: 'API reference' }
41
+ ]);
42
+ console.log(`āœ… llms.txt generated (${llms.llmsTxt.length} chars)`);
43
+ // Test 4: Schema Generation & Validation
44
+ console.log('\n4ļøāƒ£ Testing Schema.org JSON-LD Generation & Validation...');
45
+ const schema = generateSchemaMarkup('FAQPage', {
46
+ items: [
47
+ { question: 'What is project management software?', answer: 'It is a platform to coordinate team tasks and roadmaps.' },
48
+ { question: 'Is it free to start?', answer: 'Yes, free tiers are available for small teams.' }
49
+ ]
50
+ });
51
+ const val = await validateSchema(schema.jsonLdScript.replace(/<script[^>]*>/, '').replace(/<\/script>/, ''));
52
+ console.log(`āœ… Schema Generated & Validated (${val.schemasDetectedCount} schemas detected, Valid: ${val.schemas[0]?.isValid})`);
53
+ // Test 5: Keyword Clustering & Intent Classification
54
+ console.log('\n5ļøāƒ£ Testing Keyword Clustering & Search Intent Classification...');
55
+ const keywords = [
56
+ 'best running shoes',
57
+ 'buy running shoes online',
58
+ 'how to choose running shoes',
59
+ 'running shoes for flat feet',
60
+ 'running shoes review',
61
+ 'running shoes sale discount'
62
+ ];
63
+ const clusters = clusterKeywords(keywords);
64
+ const intents = classifySearchIntent(keywords);
65
+ console.log(`āœ… Clustered ${keywords.length} keywords into ${clusters.clusterCount} cluster(s)`);
66
+ console.log(`āœ… Intent sample: "${keywords[1]}" -> ${intents[1].intent} (${(intents[1].confidenceScore * 100).toFixed(0)}% confidence)`);
67
+ // Test 6: Content Decay Audit
68
+ console.log('\n6ļøāƒ£ Testing Content Decay Audit...');
69
+ const decay = await auditContentDecay('In 2019, our study showed that 45% of users preferred desktop over mobile.');
70
+ console.log(`āœ… Freshness Score: ${decay.freshnessScore}/100 | Decay level: ${decay.decayLevel} | Stale years found: ${decay.staleYearReferences.join(', ')}`);
71
+ console.log('\nšŸŽ‰ ALL CORE TEST SUITES PASSED CLEANLY!\n');
72
+ }
73
+ runTests().catch(err => {
74
+ console.error('Test failed:', err);
75
+ process.exit(1);
76
+ });
@@ -0,0 +1,3 @@
1
+ import { InformationGainReport, EeatAuditReport } from '../types/seo.js';
2
+ export declare function scoreInformationGain(myContentOrUrl: string, targetKeyword: string): Promise<InformationGainReport>;
3
+ export declare function auditEeat(urlOrHtml: string): Promise<EeatAuditReport>;