seo-gravity-mcp 1.0.2 → 1.2.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 (67) hide show
  1. package/README.md +118 -105
  2. package/dist/adapters/adapterRegistry.d.ts +7 -0
  3. package/dist/adapters/adapterRegistry.js +30 -0
  4. package/dist/adapters/astroAdapter.d.ts +17 -0
  5. package/dist/adapters/astroAdapter.js +191 -0
  6. package/dist/adapters/nextAppAdapter.d.ts +17 -0
  7. package/dist/adapters/nextAppAdapter.js +265 -0
  8. package/dist/adapters/nextPagesAdapter.d.ts +17 -0
  9. package/dist/adapters/nextPagesAdapter.js +209 -0
  10. package/dist/adapters/remixAdapter.d.ts +16 -0
  11. package/dist/adapters/remixAdapter.js +118 -0
  12. package/dist/adapters/staticAdapter.d.ts +16 -0
  13. package/dist/adapters/staticAdapter.js +117 -0
  14. package/dist/adapters/svelteKitAdapter.d.ts +16 -0
  15. package/dist/adapters/svelteKitAdapter.js +122 -0
  16. package/dist/adapters/types.d.ts +39 -0
  17. package/dist/adapters/types.js +1 -0
  18. package/dist/adapters/viteReactAdapter.d.ts +16 -0
  19. package/dist/adapters/viteReactAdapter.js +189 -0
  20. package/dist/benchmark/correlationBenchmark.d.ts +1 -0
  21. package/dist/benchmark/correlationBenchmark.js +96 -0
  22. package/dist/benchmark/invariantBenchmark.d.ts +1 -0
  23. package/dist/benchmark/invariantBenchmark.js +47 -0
  24. package/dist/cli.d.ts +8 -0
  25. package/dist/cli.js +162 -0
  26. package/dist/index.d.ts +3 -1
  27. package/dist/index.js +8 -646
  28. package/dist/invariants/registry.d.ts +12 -0
  29. package/dist/invariants/registry.js +178 -0
  30. package/dist/invariants/types.d.ts +38 -0
  31. package/dist/invariants/types.js +1 -0
  32. package/dist/providers/providerRegistry.d.ts +65 -0
  33. package/dist/providers/providerRegistry.js +64 -0
  34. package/dist/providers/types.d.ts +22 -0
  35. package/dist/providers/types.js +1 -0
  36. package/dist/server/registry.d.ts +3 -0
  37. package/dist/server/registry.js +559 -0
  38. package/dist/server/server.d.ts +70 -0
  39. package/dist/server/server.js +53 -0
  40. package/dist/server/types.d.ts +7 -0
  41. package/dist/server/types.js +1 -0
  42. package/dist/test.js +108 -138
  43. package/dist/tools/orchestration.js +23 -21
  44. package/dist/types/canonical.d.ts +64 -0
  45. package/dist/types/canonical.js +1 -0
  46. package/dist/types/findings.d.ts +22 -0
  47. package/dist/types/findings.js +1 -1
  48. package/dist/types/seo.d.ts +24 -0
  49. package/dist/utils/astLocator.d.ts +14 -0
  50. package/dist/utils/astLocator.js +137 -0
  51. package/dist/utils/cacheManager.d.ts +29 -0
  52. package/dist/utils/cacheManager.js +60 -0
  53. package/dist/utils/experimentEngine.d.ts +26 -0
  54. package/dist/utils/experimentEngine.js +41 -0
  55. package/dist/utils/findingEngine.d.ts +2 -1
  56. package/dist/utils/findingEngine.js +1 -0
  57. package/dist/utils/gitDiffEngine.d.ts +28 -0
  58. package/dist/utils/gitDiffEngine.js +109 -0
  59. package/dist/utils/opportunityEngine.d.ts +19 -0
  60. package/dist/utils/opportunityEngine.js +61 -0
  61. package/dist/utils/projectScanner.d.ts +4 -2
  62. package/dist/utils/projectScanner.js +14 -346
  63. package/dist/utils/sarifExporter.d.ts +64 -0
  64. package/dist/utils/sarifExporter.js +81 -0
  65. package/dist/utils/snapshotEngine.d.ts +3 -1
  66. package/dist/utils/snapshotEngine.js +232 -94
  67. package/package.json +8 -5
@@ -0,0 +1,559 @@
1
+ // Import Tool Handlers
2
+ import { analyzeSerp, profileCompetitor, analyzeCompetitorContentGap, diffCompetitor, analyzeForumDiscussions } from '../tools/serp.js';
3
+ import { auditGeoAiReadiness, generateLlmsTxt, auditAiBotsRobots } from '../tools/geo.js';
4
+ import { scoreInformationGain, auditEeat } from '../tools/eeat.js';
5
+ import { auditOnPage, generateContentBrief, scoreReadability } from '../tools/onpage.js';
6
+ import { auditTechnical, diffJsRendering, validateRobotsTxt, inspectSitemap, analyzeInternalLinks } from '../tools/technical.js';
7
+ import { getKeywordSuggestions, findQuestions, clusterKeywords, classifySearchIntent } from '../tools/keywords.js';
8
+ import { mapEntitySalience, generateSchemaMarkup, validateSchema } from '../tools/schema.js';
9
+ import { auditPageSpeed, submitIndexNow, auditContentDecay } from '../tools/performance.js';
10
+ import { auditProject, diagnoseSeo, prioritizeFindings, generateFixPlan, createSnapshotTool, compareSnapshotsTool, checkRegression } from '../tools/orchestration.js';
11
+ export const TOOLS = [
12
+ // ==========================================
13
+ // Layer 0. Agent Orchestration & Remediation
14
+ // ==========================================
15
+ {
16
+ name: 'seo_project_audit',
17
+ description: 'Flagship project audit: scans codebase for framework (Next.js, Astro, Vite, Remix, SvelteKit), maps discovered routes to source files, builds crawl graph, and computes multidimensional SEO scores (Technical, Content, AI Readiness, Discoverability, Entity).',
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ project_path: { type: 'string', description: 'Absolute or relative path to project workspace root' },
22
+ base_url: { type: 'string', description: 'Optional live or dev server URL (e.g. "http://localhost:3000")' },
23
+ crawl_depth: { type: 'number', description: 'Crawl depth for internal link graph analysis (default 2)' }
24
+ },
25
+ required: ['project_path']
26
+ }
27
+ },
28
+ {
29
+ name: 'seo_diagnose',
30
+ description: 'Deep root-cause diagnostic: correlates an observed SEO issue or URL back to specific source code files, components, and line numbers with actionable code fix blueprints.',
31
+ inputSchema: {
32
+ type: 'object',
33
+ properties: {
34
+ project_path: { type: 'string', description: 'Path to project workspace root' },
35
+ target_url_or_file: { type: 'string', description: 'URL, route path (e.g. "/blog/[slug]"), or file path to diagnose' },
36
+ focus_issue_id: { type: 'string', description: 'Optional specific finding ID (e.g. "SEO-CANONICAL-001")' }
37
+ },
38
+ required: ['project_path', 'target_url_or_file']
39
+ }
40
+ },
41
+ {
42
+ name: 'seo_prioritize',
43
+ description: 'Ranks and organizes SEO findings into actionable sprints (Quick Wins, Critical Blockers, Architectural Improvements) using (Impact × Confidence × Reach) / Effort formula.',
44
+ inputSchema: {
45
+ type: 'object',
46
+ properties: {
47
+ project_path: { type: 'string', description: 'Path to project workspace root (or provide raw findings array)' },
48
+ max_count: { type: 'number', description: 'Max items per sprint category (default 20)' }
49
+ },
50
+ required: ['project_path']
51
+ }
52
+ },
53
+ {
54
+ name: 'seo_fix_plan',
55
+ description: 'Generates an end-to-end, multi-step code modification and verification plan for AI coding agents to autonomously resolve detected SEO issues.',
56
+ inputSchema: {
57
+ type: 'object',
58
+ properties: {
59
+ project_path: { type: 'string', description: 'Path to project workspace root' },
60
+ finding_ids: { type: 'array', items: { type: 'string' }, description: 'Optional list of specific finding IDs to target' }
61
+ },
62
+ required: ['project_path']
63
+ }
64
+ },
65
+ {
66
+ name: 'seo_snapshot_create',
67
+ description: 'Creates and saves a structured project snapshot (schema seo.gravity/v1) containing all discovered routes, findings, crawl graph, and multidimensional scores.',
68
+ inputSchema: {
69
+ type: 'object',
70
+ properties: {
71
+ project_path: { type: 'string', description: 'Path to project workspace root' },
72
+ base_url: { type: 'string', description: 'Optional live/dev server URL' },
73
+ output_path: { type: 'string', description: 'Optional file path to save snapshot JSON (e.g. ".seo-snapshot.json")' }
74
+ },
75
+ required: ['project_path']
76
+ }
77
+ },
78
+ {
79
+ name: 'seo_snapshot_compare',
80
+ description: 'Compares a baseline snapshot against a current snapshot to identify resolved issues, new regressions, and overall SEO score deltas.',
81
+ inputSchema: {
82
+ type: 'object',
83
+ properties: {
84
+ baseline_snapshot: { type: 'string', description: 'Baseline snapshot file path or serialized JSON string' },
85
+ current_snapshot: { type: 'string', description: 'Current snapshot file path or serialized JSON string' }
86
+ },
87
+ required: ['baseline_snapshot', 'current_snapshot']
88
+ }
89
+ },
90
+ {
91
+ name: 'seo_regression_check',
92
+ description: 'Verifies that recent code modifications did not introduce any new critical SEO regressions compared to a baseline snapshot. Perfect for CI/CD gates.',
93
+ inputSchema: {
94
+ type: 'object',
95
+ properties: {
96
+ project_path: { type: 'string', description: 'Path to project workspace root' },
97
+ baseline_snapshot: { type: 'string', description: 'Baseline snapshot file path or serialized JSON string' },
98
+ base_url: { type: 'string', description: 'Optional live/dev server URL' }
99
+ },
100
+ required: ['project_path', 'baseline_snapshot']
101
+ }
102
+ },
103
+ // ==========================================
104
+ // Layer 1. SERP & Competitor Intelligence
105
+ // ==========================================
106
+ {
107
+ name: 'seo_serp_analyze',
108
+ description: 'Extracts real-time Google SERP organic rankings, People Also Ask (PAA) questions, Related Searches, and intent distribution.',
109
+ inputSchema: {
110
+ type: 'object',
111
+ properties: {
112
+ query: { type: 'string', description: 'Search term to analyze' },
113
+ country: { type: 'string', description: 'Country code (e.g. "us", "uk", "in") (default "us")' },
114
+ language: { type: 'string', description: 'Language code (e.g. "en", "es") (default "en")' },
115
+ num_results: { type: 'number', description: 'Number of results to fetch (default 10)' }
116
+ },
117
+ required: ['query']
118
+ }
119
+ },
120
+ {
121
+ name: 'seo_competitor_content_gap',
122
+ description: 'Discovers high-priority content gaps and missing subtopics by comparing target content against top-ranking SERP competitor pages.',
123
+ inputSchema: {
124
+ type: 'object',
125
+ properties: {
126
+ target_url_or_text: { type: 'string', description: 'Your page URL or drafted markdown/HTML content' },
127
+ target_keyword: { type: 'string', description: 'Primary keyword to rank for' },
128
+ competitor_urls: { type: 'array', items: { type: 'string' }, description: 'List of top-ranking competitor URLs (1-5 URLs)' }
129
+ },
130
+ required: ['target_url_or_text', 'target_keyword']
131
+ }
132
+ },
133
+ {
134
+ name: 'seo_competitor_profile',
135
+ description: 'Performs comprehensive on-page technical, content, and schema profiling of a single competitor URL.',
136
+ inputSchema: {
137
+ type: 'object',
138
+ properties: {
139
+ url: { type: 'string', description: 'Competitor URL to inspect' }
140
+ },
141
+ required: ['url']
142
+ }
143
+ },
144
+ {
145
+ name: 'seo_competitor_diff',
146
+ description: 'Direct side-by-side technical & content comparison between your page and a competitor page.',
147
+ inputSchema: {
148
+ type: 'object',
149
+ properties: {
150
+ my_url: { type: 'string', description: 'Your page URL or local dev URL' },
151
+ competitor_url: { type: 'string', description: 'Competitor page URL' },
152
+ focus_keyword: { type: 'string', description: 'Target search query' }
153
+ },
154
+ required: ['my_url', 'competitor_url']
155
+ }
156
+ },
157
+ {
158
+ name: 'seo_forum_discussions_pulse',
159
+ description: 'Mines real-user discussions, pain points, and terminology from Reddit and developer forums.',
160
+ inputSchema: {
161
+ type: 'object',
162
+ properties: {
163
+ topic_or_keyword: { type: 'string', description: 'Topic, niche, or keyword to research' }
164
+ },
165
+ required: ['topic_or_keyword']
166
+ }
167
+ },
168
+ // ==========================================
169
+ // Layer 2. Generative Engine Optimization (GEO & AI Search)
170
+ // ==========================================
171
+ {
172
+ name: 'seo_geo_ai_readiness_audit',
173
+ description: 'Audits content for Generative Engine Optimization (GEO): checks direct answerability, extractability, structured entity definitions, and table formats for ChatGPT, Perplexity, and Google AI Overviews.',
174
+ inputSchema: {
175
+ type: 'object',
176
+ properties: {
177
+ url_or_text: { type: 'string', description: 'Page URL or raw content to audit' },
178
+ target_query: { type: 'string', description: 'Primary search query the user might ask an AI' }
179
+ },
180
+ required: ['url_or_text']
181
+ }
182
+ },
183
+ {
184
+ name: 'seo_llms_txt_generate',
185
+ description: 'Generates a standard-compliant /llms.txt and /llms-full.txt file for AI agent documentation discovery.',
186
+ inputSchema: {
187
+ type: 'object',
188
+ properties: {
189
+ site_name: { type: 'string', description: 'Brand or product name' },
190
+ site_description: { type: 'string', description: 'Short summary of the site and offering' },
191
+ key_pages: {
192
+ type: 'array',
193
+ items: {
194
+ type: 'object',
195
+ properties: {
196
+ title: { type: 'string' },
197
+ url: { type: 'string' },
198
+ description: { type: 'string' }
199
+ },
200
+ required: ['title', 'url']
201
+ },
202
+ description: 'Key pages, documentation, or product URLs'
203
+ }
204
+ },
205
+ required: ['site_name', 'site_description', 'key_pages']
206
+ }
207
+ },
208
+ {
209
+ name: 'seo_ai_bots_robots_audit',
210
+ description: 'Audits robots.txt to verify access permissions for AI search crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot).',
211
+ inputSchema: {
212
+ type: 'object',
213
+ properties: {
214
+ domain_or_url: { type: 'string', description: 'Target domain or URL (e.g. "example.com")' }
215
+ },
216
+ required: ['domain_or_url']
217
+ }
218
+ },
219
+ // ==========================================
220
+ // Layer 3. Information Gain & E-E-A-T
221
+ // ==========================================
222
+ {
223
+ name: 'seo_information_gain_score',
224
+ description: 'Measures Information Gain: evaluates unique insights, proprietary data points, novel methodologies, and counter-intuitive findings.',
225
+ inputSchema: {
226
+ type: 'object',
227
+ properties: {
228
+ my_content_or_url: { type: 'string', description: 'Your content draft or live URL' },
229
+ keyword: { type: 'string', description: 'Primary topic or keyword' }
230
+ },
231
+ required: ['my_content_or_url', 'keyword']
232
+ }
233
+ },
234
+ {
235
+ name: 'seo_eeat_audit',
236
+ description: 'Audits Experience, Expertise, Authoritativeness, and Trustworthiness (E-E-A-T) signals.',
237
+ inputSchema: {
238
+ type: 'object',
239
+ properties: {
240
+ url_or_html: { type: 'string', description: 'Page URL or raw HTML' }
241
+ },
242
+ required: ['url_or_html']
243
+ }
244
+ },
245
+ // ==========================================
246
+ // Layer 4. Content & On-Page SEO
247
+ // ==========================================
248
+ {
249
+ name: 'seo_onpage_audit',
250
+ description: 'Complete on-page SEO analyzer: checks Title tag, Meta Description, Heading hierarchy, Keyword density, Canonical URLs, and OpenGraph/Twitter social meta tags.',
251
+ inputSchema: {
252
+ type: 'object',
253
+ properties: {
254
+ url_or_html: { type: 'string', description: 'Live URL or raw HTML string' },
255
+ focus_keyword: { type: 'string', description: 'Optional target focus keyword' }
256
+ },
257
+ required: ['url_or_html']
258
+ }
259
+ },
260
+ {
261
+ name: 'seo_content_brief_generate',
262
+ description: 'Generates a comprehensive SEO content brief with optimal word count, H2/H3 outline, required semantic entities, and search intent guidelines.',
263
+ inputSchema: {
264
+ type: 'object',
265
+ properties: {
266
+ primary_keyword: { type: 'string', description: 'Target primary keyword' },
267
+ secondary_keywords: { type: 'array', items: { type: 'string' }, description: 'List of supporting keywords' },
268
+ search_intent: { type: 'string', enum: ['Informational', 'Transactional', 'Commercial', 'Navigational'], description: 'Target intent' }
269
+ },
270
+ required: ['primary_keyword']
271
+ }
272
+ },
273
+ {
274
+ name: 'seo_readability_score',
275
+ description: 'Calculates Flesch Reading Ease and Flesch-Kincaid Grade Level with actionable tips to simplify complex sentences.',
276
+ inputSchema: {
277
+ type: 'object',
278
+ properties: {
279
+ text_or_url: { type: 'string', description: 'Draft text or live page URL' }
280
+ },
281
+ required: ['text_or_url']
282
+ }
283
+ },
284
+ // ==========================================
285
+ // Layer 5. Technical SEO & Crawlability
286
+ // ==========================================
287
+ {
288
+ name: 'seo_technical_audit',
289
+ description: 'Performs technical SEO inspection: HTTP status, Canonical consistency, Meta Robots (noindex/nofollow), Hreflang, Mixed Content, and Security headers.',
290
+ inputSchema: {
291
+ type: 'object',
292
+ properties: {
293
+ url: { type: 'string', description: 'Page URL to audit' }
294
+ },
295
+ required: ['url']
296
+ }
297
+ },
298
+ {
299
+ name: 'seo_js_rendering_diff',
300
+ description: 'Compares raw static HTML vs client-side JavaScript rendered DOM to detect hydration mismatches and client-rendered links.',
301
+ inputSchema: {
302
+ type: 'object',
303
+ properties: {
304
+ url: { type: 'string', description: 'Page URL to test' }
305
+ },
306
+ required: ['url']
307
+ }
308
+ },
309
+ {
310
+ name: 'seo_robots_txt_validate',
311
+ description: 'Tests if specific URLs or paths are crawlable by search engine bots (Googlebot, Bingbot, GPTBot) based on robots.txt rules.',
312
+ inputSchema: {
313
+ type: 'object',
314
+ properties: {
315
+ domain_or_url: { type: 'string', description: 'Website domain or URL' },
316
+ test_path: { type: 'string', description: 'Subpath to test (default "/")' },
317
+ user_agent: { type: 'string', description: 'Bot name to test (default "Googlebot")' }
318
+ },
319
+ required: ['domain_or_url']
320
+ }
321
+ },
322
+ {
323
+ name: 'seo_sitemap_inspect',
324
+ description: 'Parses and validates XML sitemaps or sitemap index files, verifies lastmod tags, and checks URL limits.',
325
+ inputSchema: {
326
+ type: 'object',
327
+ properties: {
328
+ sitemap_url: { type: 'string', description: 'URL of sitemap.xml or sitemap_index.xml' }
329
+ },
330
+ required: ['sitemap_url']
331
+ }
332
+ },
333
+ {
334
+ name: 'seo_internal_links_analyze',
335
+ description: 'Analyzes internal links, anchor text distribution, generic anchor alerts, and nofollow internal flags.',
336
+ inputSchema: {
337
+ type: 'object',
338
+ properties: {
339
+ url: { type: 'string', description: 'Page URL to analyze' }
340
+ },
341
+ required: ['url']
342
+ }
343
+ },
344
+ // ==========================================
345
+ // Layer 6. Keyword Research & Intent
346
+ // ==========================================
347
+ {
348
+ name: 'seo_keyword_suggestions',
349
+ description: 'Extracts keyword suggestions and long-tail variations using Google Autocomplete and the Alphabet Soup method.',
350
+ inputSchema: {
351
+ type: 'object',
352
+ properties: {
353
+ seed_keyword: { type: 'string', description: 'Seed keyword' },
354
+ include_alphabet_soup: { type: 'boolean', description: 'Generate a-z suggestions (default true)' }
355
+ },
356
+ required: ['seed_keyword']
357
+ }
358
+ },
359
+ {
360
+ name: 'seo_questions_find',
361
+ description: 'Finds question queries asked by users across Google (Who, What, Where, When, Why, How, Can, Is).',
362
+ inputSchema: {
363
+ type: 'object',
364
+ properties: {
365
+ topic: { type: 'string', description: 'Topic or keyword' }
366
+ },
367
+ required: ['topic']
368
+ }
369
+ },
370
+ {
371
+ name: 'seo_keyword_cluster',
372
+ description: 'Clusters a list of keywords into distinct Topic Pillars and Supporting Articles using semantic similarity.',
373
+ inputSchema: {
374
+ type: 'object',
375
+ properties: {
376
+ keywords: { type: 'array', items: { type: 'string' }, description: 'List of keywords to cluster' },
377
+ similarity_threshold: { type: 'number', description: 'Clustering similarity threshold (0.1 to 0.9, default 0.4)' }
378
+ },
379
+ required: ['keywords']
380
+ }
381
+ },
382
+ {
383
+ name: 'seo_search_intent_classify',
384
+ description: 'Classifies search intent (Informational, Transactional, Commercial, Navigational) for a batch of keywords.',
385
+ inputSchema: {
386
+ type: 'object',
387
+ properties: {
388
+ keywords: { type: 'array', items: { type: 'string' }, description: 'Array of keywords to classify' }
389
+ },
390
+ required: ['keywords']
391
+ }
392
+ },
393
+ // ==========================================
394
+ // Layer 7. Schema Markup & Structured Data
395
+ // ==========================================
396
+ {
397
+ name: 'seo_entity_salience_map',
398
+ description: 'Extracts core entities, computes salience scores, and extracts Subject-Predicate-Object (SPO) relationship triples.',
399
+ inputSchema: {
400
+ type: 'object',
401
+ properties: {
402
+ text_or_url: { type: 'string', description: 'Page URL, raw HTML, or text' }
403
+ },
404
+ required: ['text_or_url']
405
+ }
406
+ },
407
+ {
408
+ name: 'seo_schema_generate',
409
+ description: 'Generates validated Schema.org JSON-LD scripts (Article, FAQPage, Product, LocalBusiness, BreadcrumbList, Organization).',
410
+ inputSchema: {
411
+ type: 'object',
412
+ properties: {
413
+ schema_type: {
414
+ type: 'string',
415
+ enum: ['Article', 'FAQPage', 'Product', 'HowTo', 'LocalBusiness', 'Organization', 'BreadcrumbList', 'SoftwareApplication'],
416
+ description: 'Type of schema to generate'
417
+ },
418
+ data: { type: 'object', description: 'Schema properties payload' }
419
+ },
420
+ required: ['schema_type', 'data']
421
+ }
422
+ },
423
+ {
424
+ name: 'seo_schema_validate',
425
+ description: 'Validates on-page or pasted JSON-LD structured data against Schema.org and Google Rich Result requirements.',
426
+ inputSchema: {
427
+ type: 'object',
428
+ properties: {
429
+ url_or_jsonld: { type: 'string', description: 'Page URL or raw JSON-LD string' }
430
+ },
431
+ required: ['url_or_jsonld']
432
+ }
433
+ },
434
+ // ==========================================
435
+ // Layer 8. Performance & Maintenance
436
+ // ==========================================
437
+ {
438
+ name: 'seo_pagespeed_audit',
439
+ description: 'Checks Core Web Vitals (LCP, FCP, CLS, TTFB) with performance optimization fixes.',
440
+ inputSchema: {
441
+ type: 'object',
442
+ properties: {
443
+ url: { type: 'string', description: 'Page URL to test' },
444
+ strategy: { type: 'string', enum: ['mobile', 'desktop'], description: 'Device strategy (default "mobile")' }
445
+ },
446
+ required: ['url']
447
+ }
448
+ },
449
+ {
450
+ name: 'seo_indexnow_submit',
451
+ description: 'Submits newly created or updated URLs directly to Bing & Yandex via the IndexNow API protocol.',
452
+ inputSchema: {
453
+ type: 'object',
454
+ properties: {
455
+ host: { type: 'string', description: 'Website domain host (e.g. "example.com")' },
456
+ key: { type: 'string', description: 'IndexNow API key' },
457
+ key_location: { type: 'string', description: 'URL location of the key file' },
458
+ url_list: { type: 'array', items: { type: 'string' }, description: 'Array of URLs to submit' }
459
+ },
460
+ required: ['host', 'key', 'key_location', 'url_list']
461
+ }
462
+ },
463
+ {
464
+ name: 'seo_content_decay_audit',
465
+ description: 'Scans content for freshness decay (stale year references e.g. "2020", outdated statistics, broken external links).',
466
+ inputSchema: {
467
+ type: 'object',
468
+ properties: {
469
+ url_or_text: { type: 'string', description: 'Page URL or draft text to audit' }
470
+ },
471
+ required: ['url_or_text']
472
+ }
473
+ }
474
+ ];
475
+ export async function executeTool(name, a) {
476
+ switch (name) {
477
+ // 0. Agent Orchestration & Remediation
478
+ case 'seo_project_audit':
479
+ return auditProject(a.project_path, a.base_url, a.crawl_depth);
480
+ case 'seo_diagnose':
481
+ return diagnoseSeo(a.project_path, a.target_url_or_file, a.focus_issue_id);
482
+ case 'seo_prioritize':
483
+ return prioritizeFindings(a.project_path, a.max_count);
484
+ case 'seo_fix_plan':
485
+ return generateFixPlan(a.project_path, a.finding_ids);
486
+ case 'seo_snapshot_create':
487
+ return createSnapshotTool(a.project_path, a.base_url, a.output_path);
488
+ case 'seo_snapshot_compare':
489
+ return compareSnapshotsTool(a.baseline_snapshot, a.current_snapshot);
490
+ case 'seo_regression_check':
491
+ return checkRegression(a.project_path, a.baseline_snapshot, a.base_url);
492
+ // 1. SERP & Competitors
493
+ case 'seo_serp_analyze':
494
+ return analyzeSerp(a.query, a.country, a.language, a.num_results);
495
+ case 'seo_competitor_content_gap':
496
+ return analyzeCompetitorContentGap(a.target_url_or_text, a.target_keyword, a.competitor_urls);
497
+ case 'seo_competitor_profile':
498
+ return profileCompetitor(a.url);
499
+ case 'seo_competitor_diff':
500
+ return diffCompetitor(a.my_url, a.competitor_url, a.focus_keyword);
501
+ case 'seo_forum_discussions_pulse':
502
+ return analyzeForumDiscussions(a.topic_or_keyword);
503
+ // 2. GEO & AI Search
504
+ case 'seo_geo_ai_readiness_audit':
505
+ return auditGeoAiReadiness(a.url_or_text, a.target_query);
506
+ case 'seo_llms_txt_generate':
507
+ return generateLlmsTxt(a.site_name, a.site_description, a.key_pages);
508
+ case 'seo_ai_bots_robots_audit':
509
+ return auditAiBotsRobots(a.domain_or_url);
510
+ // 3. E-E-A-T & Info Gain
511
+ case 'seo_information_gain_score':
512
+ return scoreInformationGain(a.my_content_or_url, a.keyword);
513
+ case 'seo_eeat_audit':
514
+ return auditEeat(a.url_or_html);
515
+ // 4. On-Page
516
+ case 'seo_onpage_audit':
517
+ return auditOnPage(a.url_or_html, a.focus_keyword);
518
+ case 'seo_content_brief_generate':
519
+ return generateContentBrief(a.primary_keyword, a.secondary_keywords, a.search_intent);
520
+ case 'seo_readability_score':
521
+ return scoreReadability(a.text_or_url);
522
+ // 5. Technical
523
+ case 'seo_technical_audit':
524
+ return auditTechnical(a.url);
525
+ case 'seo_js_rendering_diff':
526
+ return diffJsRendering(a.url);
527
+ case 'seo_robots_txt_validate':
528
+ return validateRobotsTxt(a.domain_or_url, a.test_path, a.user_agent);
529
+ case 'seo_sitemap_inspect':
530
+ return inspectSitemap(a.sitemap_url);
531
+ case 'seo_internal_links_analyze':
532
+ return analyzeInternalLinks(a.url);
533
+ // 6. Keywords
534
+ case 'seo_keyword_suggestions':
535
+ return getKeywordSuggestions(a.seed_keyword, a.include_alphabet_soup);
536
+ case 'seo_questions_find':
537
+ return findQuestions(a.topic);
538
+ case 'seo_keyword_cluster':
539
+ return clusterKeywords(a.keywords, a.similarity_threshold);
540
+ case 'seo_search_intent_classify':
541
+ return classifySearchIntent(a.keywords);
542
+ // 7. Schema
543
+ case 'seo_entity_salience_map':
544
+ return mapEntitySalience(a.text_or_url);
545
+ case 'seo_schema_generate':
546
+ return generateSchemaMarkup(a.schema_type, a.data);
547
+ case 'seo_schema_validate':
548
+ return validateSchema(a.url_or_jsonld);
549
+ // 8. Performance & Maintenance
550
+ case 'seo_pagespeed_audit':
551
+ return auditPageSpeed(a.url, a.strategy);
552
+ case 'seo_indexnow_submit':
553
+ return submitIndexNow(a.host, a.key, a.key_location, a.url_list);
554
+ case 'seo_content_decay_audit':
555
+ return auditContentDecay(a.url_or_text);
556
+ default:
557
+ throw new Error(`Unknown SEO Gravity MCP tool: ${name}`);
558
+ }
559
+ }
@@ -0,0 +1,70 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { ServerOptions } from './types.js';
3
+ export declare function createMcpServer(options?: ServerOptions): Server<{
4
+ method: string;
5
+ params?: {
6
+ [x: string]: unknown;
7
+ _meta?: {
8
+ [x: string]: unknown;
9
+ progressToken?: string | number | undefined;
10
+ "io.modelcontextprotocol/related-task"?: {
11
+ taskId: string;
12
+ } | undefined;
13
+ } | undefined;
14
+ } | undefined;
15
+ }, {
16
+ method: string;
17
+ params?: {
18
+ [x: string]: unknown;
19
+ _meta?: {
20
+ [x: string]: unknown;
21
+ progressToken?: string | number | undefined;
22
+ "io.modelcontextprotocol/related-task"?: {
23
+ taskId: string;
24
+ } | undefined;
25
+ } | undefined;
26
+ } | undefined;
27
+ }, {
28
+ [x: string]: unknown;
29
+ _meta?: {
30
+ [x: string]: unknown;
31
+ progressToken?: string | number | undefined;
32
+ "io.modelcontextprotocol/related-task"?: {
33
+ taskId: string;
34
+ } | undefined;
35
+ } | undefined;
36
+ }>;
37
+ export declare function startStdioServer(options?: ServerOptions): Promise<Server<{
38
+ method: string;
39
+ params?: {
40
+ [x: string]: unknown;
41
+ _meta?: {
42
+ [x: string]: unknown;
43
+ progressToken?: string | number | undefined;
44
+ "io.modelcontextprotocol/related-task"?: {
45
+ taskId: string;
46
+ } | undefined;
47
+ } | undefined;
48
+ } | undefined;
49
+ }, {
50
+ method: string;
51
+ params?: {
52
+ [x: string]: unknown;
53
+ _meta?: {
54
+ [x: string]: unknown;
55
+ progressToken?: string | number | undefined;
56
+ "io.modelcontextprotocol/related-task"?: {
57
+ taskId: string;
58
+ } | undefined;
59
+ } | undefined;
60
+ } | undefined;
61
+ }, {
62
+ [x: string]: unknown;
63
+ _meta?: {
64
+ [x: string]: unknown;
65
+ progressToken?: string | number | undefined;
66
+ "io.modelcontextprotocol/related-task"?: {
67
+ taskId: string;
68
+ } | undefined;
69
+ } | undefined;
70
+ }>>;
@@ -0,0 +1,53 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
+ import { TOOLS, executeTool } from './registry.js';
5
+ export function createMcpServer(options = {}) {
6
+ const server = new Server({
7
+ name: options.name || 'seo-gravity-mcp',
8
+ version: options.version || '1.2.0'
9
+ }, {
10
+ capabilities: {
11
+ tools: {}
12
+ }
13
+ });
14
+ // List tools handler
15
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
16
+ return { tools: TOOLS };
17
+ });
18
+ // Call tool handler
19
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
20
+ const { name, arguments: args } = request.params;
21
+ const a = (args || {});
22
+ try {
23
+ const result = await executeTool(name, a);
24
+ return {
25
+ content: [
26
+ {
27
+ type: 'text',
28
+ text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
29
+ }
30
+ ]
31
+ };
32
+ }
33
+ catch (error) {
34
+ return {
35
+ isError: true,
36
+ content: [
37
+ {
38
+ type: 'text',
39
+ text: `SEO Gravity Tool Execution Error (${name}): ${error.message}`
40
+ }
41
+ ]
42
+ };
43
+ }
44
+ });
45
+ return server;
46
+ }
47
+ export async function startStdioServer(options = {}) {
48
+ const server = createMcpServer(options);
49
+ const transport = new StdioServerTransport();
50
+ await server.connect(transport);
51
+ console.error(`SEO Gravity MCP Server (v${options.version || '1.2.0'}) running on stdio`);
52
+ return server;
53
+ }