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 +21 -0
- package/README.md +20 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +521 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +76 -0
- package/dist/tools/eeat.d.ts +3 -0
- package/dist/tools/eeat.js +155 -0
- package/dist/tools/geo.d.ts +17 -0
- package/dist/tools/geo.js +190 -0
- package/dist/tools/keywords.d.ts +26 -0
- package/dist/tools/keywords.js +112 -0
- package/dist/tools/onpage.d.ts +15 -0
- package/dist/tools/onpage.js +254 -0
- package/dist/tools/performance.d.ts +32 -0
- package/dist/tools/performance.js +142 -0
- package/dist/tools/schema.d.ts +8 -0
- package/dist/tools/schema.js +191 -0
- package/dist/tools/serp.d.ts +6 -0
- package/dist/tools/serp.js +225 -0
- package/dist/tools/technical.d.ts +36 -0
- package/dist/tools/technical.js +277 -0
- package/dist/types/seo.d.ts +354 -0
- package/dist/types/seo.js +1 -0
- package/dist/utils/jsdomRenderer.d.ts +5 -0
- package/dist/utils/jsdomRenderer.js +79 -0
- package/dist/utils/nlp.d.ts +41 -0
- package/dist/utils/nlp.js +214 -0
- package/dist/utils/scraper.d.ts +36 -0
- package/dist/utils/scraper.js +129 -0
- package/dist/utils/searchEngines.d.ts +17 -0
- package/dist/utils/searchEngines.js +197 -0
- package/package.json +61 -0
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.
|
package/dist/index.d.ts
ADDED
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>;
|