domain-search-mcp 1.2.7 → 1.2.8

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 (2) hide show
  1. package/README.md +479 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4424,6 +4424,485 @@ async function domainResearchPipeline(businessIdea: string) {
4424
4424
  const research = await domainResearchPipeline("ai-powered code review tool");
4425
4425
  ```
4426
4426
 
4427
+ #### Startup-Type Optimized Parameters
4428
+
4429
+ Different startup types require different tool parameter configurations for optimal results:
4430
+
4431
+ ```typescript
4432
+ // Startup type definitions with optimized tool parameters
4433
+ const STARTUP_TYPE_CONFIGS = {
4434
+ tech: {
4435
+ // Tech startups: developer tools, SaaS, APIs
4436
+ tlds: ["io", "dev", "app", "com", "sh"],
4437
+ suggestStyle: "brandable" as const,
4438
+ socialPlatforms: ["github", "twitter", "npm", "pypi", "producthunt"],
4439
+ priceThreshold: 50, // Tech startups accept higher TLD costs
4440
+ industryHint: "tech" as const
4441
+ },
4442
+ ecommerce: {
4443
+ // E-commerce: retail, marketplace, DTC brands
4444
+ tlds: ["com", "co", "shop", "store", "io"],
4445
+ suggestStyle: "brandable" as const,
4446
+ socialPlatforms: ["instagram", "twitter", "tiktok", "pinterest"],
4447
+ priceThreshold: 25, // Lower threshold, .com preferred
4448
+ industryHint: "ecommerce" as const
4449
+ },
4450
+ creative: {
4451
+ // Creative agencies: design, media, content
4452
+ tlds: ["design", "studio", "io", "co", "com"],
4453
+ suggestStyle: "creative" as const,
4454
+ socialPlatforms: ["instagram", "twitter", "dribbble", "behance"],
4455
+ priceThreshold: 35,
4456
+ industryHint: "creative" as const
4457
+ },
4458
+ fintech: {
4459
+ // Financial technology: payments, banking, crypto
4460
+ tlds: ["com", "io", "finance", "money", "app"],
4461
+ suggestStyle: "brandable" as const,
4462
+ socialPlatforms: ["twitter", "linkedin", "github"],
4463
+ priceThreshold: 100, // Premium domains acceptable
4464
+ industryHint: "finance" as const
4465
+ },
4466
+ healthcare: {
4467
+ // Healthcare & wellness startups
4468
+ tlds: ["health", "care", "com", "io", "app"],
4469
+ suggestStyle: "descriptive" as const,
4470
+ socialPlatforms: ["twitter", "linkedin", "facebook"],
4471
+ priceThreshold: 40,
4472
+ industryHint: "health" as const
4473
+ }
4474
+ };
4475
+
4476
+ type StartupType = keyof typeof STARTUP_TYPE_CONFIGS;
4477
+ ```
4478
+
4479
+ #### Complete Startup Research Pipeline with Error Recovery
4480
+
4481
+ Production-ready pipeline with comprehensive error handling and retry logic:
4482
+
4483
+ ```typescript
4484
+ import {
4485
+ searchDomain,
4486
+ tldInfo,
4487
+ suggestDomainsSmart,
4488
+ checkSocials,
4489
+ compareRegistrars
4490
+ } from 'domain-search-mcp';
4491
+
4492
+ interface PipelineResult {
4493
+ success: boolean;
4494
+ startupName: string;
4495
+ startupType: StartupType;
4496
+ domains: DomainRecommendation[];
4497
+ socialAnalysis: SocialAnalysis[];
4498
+ tldContext: TldContext[];
4499
+ errors: PipelineError[];
4500
+ executionTime: number;
4501
+ }
4502
+
4503
+ interface PipelineError {
4504
+ stage: string;
4505
+ error: string;
4506
+ recoverable: boolean;
4507
+ fallbackUsed?: string;
4508
+ }
4509
+
4510
+ // Retry wrapper with exponential backoff
4511
+ async function withRetry<T>(
4512
+ fn: () => Promise<T>,
4513
+ options: { maxRetries: number; baseDelay: number; stageName: string }
4514
+ ): Promise<{ result: T | null; error: PipelineError | null }> {
4515
+ let lastError: Error | null = null;
4516
+
4517
+ for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
4518
+ try {
4519
+ const result = await fn();
4520
+ return { result, error: null };
4521
+ } catch (err) {
4522
+ lastError = err as Error;
4523
+
4524
+ if (attempt < options.maxRetries) {
4525
+ const delay = options.baseDelay * Math.pow(2, attempt);
4526
+ console.log(`⚠️ ${options.stageName} failed, retrying in ${delay}ms...`);
4527
+ await new Promise(r => setTimeout(r, delay));
4528
+ }
4529
+ }
4530
+ }
4531
+
4532
+ return {
4533
+ result: null,
4534
+ error: {
4535
+ stage: options.stageName,
4536
+ error: lastError?.message || 'Unknown error',
4537
+ recoverable: false
4538
+ }
4539
+ };
4540
+ }
4541
+
4542
+ async function startupDomainResearchPipeline(
4543
+ startupName: string,
4544
+ startupType: StartupType = 'tech'
4545
+ ): Promise<PipelineResult> {
4546
+ const startTime = Date.now();
4547
+ const config = STARTUP_TYPE_CONFIGS[startupType];
4548
+ const errors: PipelineError[] = [];
4549
+
4550
+ console.log(`\n🚀 Starting domain research for "${startupName}" (${startupType} startup)`);
4551
+ console.log(` Preferred TLDs: ${config.tlds.join(', ')}`);
4552
+ console.log(` Social platforms: ${config.socialPlatforms.join(', ')}`);
4553
+
4554
+ // Stage 1: Get TLD context with error recovery
4555
+ console.log('\n📋 Stage 1: Fetching TLD information...');
4556
+ const tldResults: TldContext[] = [];
4557
+
4558
+ for (const tld of config.tlds) {
4559
+ const { result, error } = await withRetry(
4560
+ () => tldInfo({ tld, detailed: true }),
4561
+ { maxRetries: 2, baseDelay: 1000, stageName: `tld_info(${tld})` }
4562
+ );
4563
+
4564
+ if (result) {
4565
+ tldResults.push({
4566
+ tld: result.tld,
4567
+ description: result.description,
4568
+ priceRange: result.price_range,
4569
+ typicalUse: result.typical_use,
4570
+ restrictions: result.restrictions,
4571
+ recommendation: result.recommendation
4572
+ });
4573
+ console.log(` ✅ .${tld}: ${result.description.substring(0, 50)}...`);
4574
+ } else if (error) {
4575
+ errors.push(error);
4576
+ console.log(` ⚠️ .${tld}: Failed to fetch info`);
4577
+ }
4578
+ }
4579
+
4580
+ // Stage 2: Generate smart suggestions with startup context
4581
+ console.log('\n💡 Stage 2: Generating domain suggestions...');
4582
+
4583
+ const { result: suggestions, error: suggestError } = await withRetry(
4584
+ () => suggestDomainsSmart({
4585
+ query: startupName,
4586
+ tld: config.tlds[0], // Primary TLD
4587
+ style: config.suggestStyle,
4588
+ industry: config.industryHint,
4589
+ max_suggestions: 20,
4590
+ include_premium: config.priceThreshold > 50
4591
+ }),
4592
+ { maxRetries: 2, baseDelay: 1500, stageName: 'suggest_domains_smart' }
4593
+ );
4594
+
4595
+ if (suggestError) {
4596
+ errors.push(suggestError);
4597
+ console.log(' ⚠️ Smart suggestions failed, falling back to basic search');
4598
+ }
4599
+
4600
+ // Stage 3: Check availability across all preferred TLDs
4601
+ console.log('\n🔍 Stage 3: Checking domain availability...');
4602
+
4603
+ const { result: availability, error: searchError } = await withRetry(
4604
+ () => searchDomain({
4605
+ domain_name: startupName,
4606
+ tlds: config.tlds
4607
+ }),
4608
+ { maxRetries: 3, baseDelay: 1000, stageName: 'search_domain' }
4609
+ );
4610
+
4611
+ if (searchError) {
4612
+ errors.push(searchError);
4613
+ }
4614
+
4615
+ // Stage 4: Social media availability with platform-specific handling
4616
+ console.log('\n🌐 Stage 4: Checking social media availability...');
4617
+
4618
+ const { result: socialResults, error: socialError } = await withRetry(
4619
+ () => checkSocials({
4620
+ name: startupName.toLowerCase().replace(/[^a-z0-9]/g, ''),
4621
+ platforms: config.socialPlatforms
4622
+ }),
4623
+ { maxRetries: 2, baseDelay: 2000, stageName: 'check_socials' }
4624
+ );
4625
+
4626
+ // Process social results with confidence levels
4627
+ const socialAnalysis: SocialAnalysis[] = [];
4628
+ if (socialResults) {
4629
+ for (const platform of socialResults.platforms) {
4630
+ socialAnalysis.push({
4631
+ platform: platform.platform,
4632
+ available: platform.available,
4633
+ confidence: platform.confidence || 'unknown',
4634
+ url: platform.profile_url,
4635
+ recommendation: getSocialRecommendation(platform, startupType)
4636
+ });
4637
+
4638
+ const status = platform.available ? '✅' : '❌';
4639
+ const conf = platform.confidence ? ` (${platform.confidence})` : '';
4640
+ console.log(` ${status} ${platform.platform}${conf}`);
4641
+ }
4642
+ } else if (socialError) {
4643
+ errors.push({
4644
+ ...socialError,
4645
+ fallbackUsed: 'Manual verification recommended'
4646
+ });
4647
+ }
4648
+
4649
+ // Stage 5: Price comparison for available domains
4650
+ console.log('\n💰 Stage 5: Comparing registrar pricing...');
4651
+
4652
+ const domains: DomainRecommendation[] = [];
4653
+ const availableDomains = availability?.results.filter(r => r.available) || [];
4654
+
4655
+ for (const domain of availableDomains.slice(0, 5)) {
4656
+ const domainName = domain.domain.split('.')[0];
4657
+ const tld = domain.domain.split('.').pop()!;
4658
+
4659
+ const { result: pricing } = await withRetry(
4660
+ () => compareRegistrars({ domain: domainName, tld }),
4661
+ { maxRetries: 1, baseDelay: 1000, stageName: `compare_registrars(${domain.domain})` }
4662
+ );
4663
+
4664
+ const tldContext = tldResults.find(t => t.tld === tld);
4665
+
4666
+ domains.push({
4667
+ domain: domain.domain,
4668
+ available: true,
4669
+ priceFirstYear: pricing?.best_first_year?.price || domain.price_first_year,
4670
+ priceRenewal: pricing?.best_renewal?.price,
4671
+ bestRegistrar: pricing?.best_first_year?.registrar || domain.registrar,
4672
+ tldInfo: tldContext,
4673
+ withinBudget: (domain.price_first_year || 0) <= config.priceThreshold,
4674
+ score: calculateDomainScore(domain, tldContext, socialAnalysis, config)
4675
+ });
4676
+
4677
+ console.log(` ${domain.domain}: $${domain.price_first_year}/yr`);
4678
+ }
4679
+
4680
+ // Sort by score
4681
+ domains.sort((a, b) => (b.score || 0) - (a.score || 0));
4682
+
4683
+ const executionTime = Date.now() - startTime;
4684
+
4685
+ console.log(`\n✨ Research complete in ${executionTime}ms`);
4686
+ console.log(` ${domains.length} available domains found`);
4687
+ console.log(` ${errors.length} errors encountered`);
4688
+
4689
+ return {
4690
+ success: errors.length === 0,
4691
+ startupName,
4692
+ startupType,
4693
+ domains,
4694
+ socialAnalysis,
4695
+ tldContext: tldResults,
4696
+ errors,
4697
+ executionTime
4698
+ };
4699
+ }
4700
+
4701
+ // Helper: Calculate domain score based on multiple factors
4702
+ function calculateDomainScore(
4703
+ domain: any,
4704
+ tldContext: TldContext | undefined,
4705
+ social: SocialAnalysis[],
4706
+ config: typeof STARTUP_TYPE_CONFIGS[StartupType]
4707
+ ): number {
4708
+ let score = 50; // Base score
4709
+
4710
+ // Price factor (lower is better, up to threshold)
4711
+ const price = domain.price_first_year || 0;
4712
+ if (price <= config.priceThreshold * 0.5) score += 20;
4713
+ else if (price <= config.priceThreshold) score += 10;
4714
+ else score -= 10;
4715
+
4716
+ // TLD preference factor
4717
+ const tldIndex = config.tlds.indexOf(domain.domain.split('.').pop());
4718
+ if (tldIndex === 0) score += 15; // Primary TLD
4719
+ else if (tldIndex <= 2) score += 10;
4720
+ else if (tldIndex > -1) score += 5;
4721
+
4722
+ // Social availability factor
4723
+ const availableSocials = social.filter(s => s.available).length;
4724
+ score += availableSocials * 5;
4725
+
4726
+ // Length factor (shorter is better)
4727
+ const nameLength = domain.domain.split('.')[0].length;
4728
+ if (nameLength <= 6) score += 10;
4729
+ else if (nameLength <= 10) score += 5;
4730
+ else if (nameLength > 15) score -= 5;
4731
+
4732
+ return Math.max(0, Math.min(100, score));
4733
+ }
4734
+
4735
+ // Helper: Get platform-specific recommendations
4736
+ function getSocialRecommendation(
4737
+ platform: any,
4738
+ startupType: StartupType
4739
+ ): string {
4740
+ if (platform.available) {
4741
+ return `Register @${platform.name} immediately to secure brand consistency`;
4742
+ }
4743
+
4744
+ const alternatives: Record<string, string> = {
4745
+ twitter: 'Consider @get[name], @[name]app, or @[name]hq',
4746
+ github: 'Use organization account or add suffix like -app, -io',
4747
+ instagram: 'Try [name].official, get[name], or [name]_app',
4748
+ npm: 'Use scoped package @[org]/[name]',
4749
+ linkedin: 'Create company page with full business name'
4750
+ };
4751
+
4752
+ return alternatives[platform.platform] || 'Consider alternative naming';
4753
+ }
4754
+
4755
+ // Usage with different startup types
4756
+ const techStartupReport = await startupDomainResearchPipeline("codeflow", "tech");
4757
+ const ecommerceReport = await startupDomainResearchPipeline("shopwave", "ecommerce");
4758
+ const creativeReport = await startupDomainResearchPipeline("pixelcraft", "creative");
4759
+ ```
4760
+
4761
+ #### Formatted Report Output by Startup Type
4762
+
4763
+ Generate customized reports based on startup category:
4764
+
4765
+ ```typescript
4766
+ function formatStartupReport(result: PipelineResult): string {
4767
+ const { startupName, startupType, domains, socialAnalysis, tldContext, errors } = result;
4768
+
4769
+ let report = `
4770
+ ╔══════════════════════════════════════════════════════════════╗
4771
+ ║ DOMAIN RESEARCH REPORT: ${startupName.toUpperCase().padEnd(35)}║
4772
+ ║ Type: ${startupType.toUpperCase()} STARTUP${' '.repeat(45 - startupType.length)}║
4773
+ ║ Generated: ${new Date().toISOString().split('T')[0]}${' '.repeat(40)}║
4774
+ ╚══════════════════════════════════════════════════════════════╝
4775
+ `;
4776
+
4777
+ // TLD Analysis Section
4778
+ report += `\n┌─ TLD ANALYSIS ${'─'.repeat(46)}┐\n`;
4779
+ for (const tld of tldContext) {
4780
+ report += `│ .${tld.tld.padEnd(6)} │ ${tld.description.substring(0, 40).padEnd(40)} │\n`;
4781
+ report += `│ │ Price: $${tld.priceRange.min}-$${tld.priceRange.max}/yr`.padEnd(52) + `│\n`;
4782
+ }
4783
+ report += `└${'─'.repeat(60)}┘\n`;
4784
+
4785
+ // Domain Recommendations Section
4786
+ report += `\n┌─ TOP DOMAIN RECOMMENDATIONS ${'─'.repeat(31)}┐\n`;
4787
+ report += `│ Rank │ Domain${' '.repeat(20)}│ Price │ Score │\n`;
4788
+ report += `├──────┼${'-'.repeat(26)}┼────────┼───────┤\n`;
4789
+
4790
+ domains.slice(0, 5).forEach((d, i) => {
4791
+ const rank = `#${i + 1}`.padEnd(4);
4792
+ const domain = d.domain.padEnd(25);
4793
+ const price = `$${d.priceFirstYear}`.padEnd(6);
4794
+ const score = `${d.score}/100`;
4795
+ report += `│ ${rank} │ ${domain} │ ${price} │ ${score.padEnd(5)} │\n`;
4796
+ });
4797
+ report += `└${'─'.repeat(60)}┘\n`;
4798
+
4799
+ // Social Media Section
4800
+ report += `\n┌─ SOCIAL MEDIA AVAILABILITY ${'─'.repeat(32)}┐\n`;
4801
+ for (const social of socialAnalysis) {
4802
+ const status = social.available ? '✅ Available' : '❌ Taken';
4803
+ const conf = social.confidence !== 'unknown' ? ` (${social.confidence})` : '';
4804
+ report += `│ ${social.platform.padEnd(12)} │ ${status}${conf}`.padEnd(48) + `│\n`;
4805
+ if (!social.available) {
4806
+ report += `│ │ → ${social.recommendation.substring(0, 35)}`.padEnd(48) + `│\n`;
4807
+ }
4808
+ }
4809
+ report += `└${'─'.repeat(60)}┘\n`;
4810
+
4811
+ // Recommendations by startup type
4812
+ report += `\n┌─ ${startupType.toUpperCase()} STARTUP RECOMMENDATIONS ${'─'.repeat(26)}┐\n`;
4813
+
4814
+ const typeRecommendations: Record<StartupType, string[]> = {
4815
+ tech: [
4816
+ '→ Prioritize .io or .dev for developer credibility',
4817
+ '→ Secure GitHub org and npm package name',
4818
+ '→ Consider .sh for CLI tools'
4819
+ ],
4820
+ ecommerce: [
4821
+ '→ .com is essential for consumer trust',
4822
+ '→ Secure Instagram and TikTok handles',
4823
+ '→ Consider .shop or .store as secondary'
4824
+ ],
4825
+ creative: [
4826
+ '→ .design or .studio signals creative focus',
4827
+ '→ Instagram presence is critical',
4828
+ '→ Shorter names work better for branding'
4829
+ ],
4830
+ fintech: [
4831
+ '→ .com required for financial credibility',
4832
+ '→ Avoid hyphens - trust signals matter',
4833
+ '→ LinkedIn company page essential'
4834
+ ],
4835
+ healthcare: [
4836
+ '→ .health TLD builds trust',
4837
+ '→ Avoid playful names - professionalism matters',
4838
+ '→ Verify regulatory compliance for domain use'
4839
+ ]
4840
+ };
4841
+
4842
+ for (const rec of typeRecommendations[startupType]) {
4843
+ report += `│ ${rec.padEnd(58)} │\n`;
4844
+ }
4845
+ report += `└${'─'.repeat(60)}┘\n`;
4846
+
4847
+ // Error summary if any
4848
+ if (errors.length > 0) {
4849
+ report += `\n⚠️ WARNINGS: ${errors.length} issues encountered during research\n`;
4850
+ errors.forEach(e => {
4851
+ report += ` • ${e.stage}: ${e.error}\n`;
4852
+ });
4853
+ }
4854
+
4855
+ return report;
4856
+ }
4857
+
4858
+ // Generate and print formatted report
4859
+ const result = await startupDomainResearchPipeline("nexaflow", "tech");
4860
+ console.log(formatStartupReport(result));
4861
+ ```
4862
+
4863
+ **Sample Output:**
4864
+ ```
4865
+ ╔══════════════════════════════════════════════════════════════╗
4866
+ ║ DOMAIN RESEARCH REPORT: NEXAFLOW ║
4867
+ ║ Type: TECH STARTUP ║
4868
+ ║ Generated: 2024-01-15 ║
4869
+ ╚══════════════════════════════════════════════════════════════╝
4870
+
4871
+ ┌─ TLD ANALYSIS ──────────────────────────────────────────────┐
4872
+ │ .io │ Popular with tech startups and SaaS │
4873
+ │ │ Price: $32-$44/yr │
4874
+ │ .dev │ Google TLD for developers │
4875
+ │ │ Price: $12-$16/yr │
4876
+ │ .app │ Mobile and web applications │
4877
+ │ │ Price: $14-$18/yr │
4878
+ └──────────────────────────────────────────────────────────────┘
4879
+
4880
+ ┌─ TOP DOMAIN RECOMMENDATIONS ─────────────────────────────────┐
4881
+ │ Rank │ Domain │ Price │ Score │
4882
+ ├──────┼──────────────────────────┼────────┼───────┤
4883
+ │ #1 │ nexaflow.dev │ $14.95 │ 85/100│
4884
+ │ #2 │ nexaflow.io │ $39.95 │ 78/100│
4885
+ │ #3 │ nexaflow.app │ $14.95 │ 75/100│
4886
+ │ #4 │ nexaflow.com │ $9.95 │ 72/100│
4887
+ │ #5 │ nexaflow.sh │ $24.95 │ 65/100│
4888
+ └──────────────────────────────────────────────────────────────┘
4889
+
4890
+ ┌─ SOCIAL MEDIA AVAILABILITY ──────────────────────────────────┐
4891
+ │ github │ ✅ Available (high) │
4892
+ │ twitter │ ❌ Taken (high) │
4893
+ │ │ → Consider @getnexaflow, @nexaflowapp │
4894
+ │ npm │ ✅ Available (high) │
4895
+ │ pypi │ ✅ Available (high) │
4896
+ │ producthunt │ ✅ Available (medium) │
4897
+ └──────────────────────────────────────────────────────────────┘
4898
+
4899
+ ┌─ TECH STARTUP RECOMMENDATIONS ───────────────────────────────┐
4900
+ │ → Prioritize .io or .dev for developer credibility │
4901
+ │ → Secure GitHub org and npm package name │
4902
+ │ → Consider .sh for CLI tools │
4903
+ └──────────────────────────────────────────────────────────────┘
4904
+ ```
4905
+
4427
4906
  ## Security
4428
4907
 
4429
4908
  - API keys are never logged (automatic secret masking)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domain-search-mcp",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "description": "Fast domain availability aggregator MCP server. Check availability across Porkbun, Namecheap, RDAP, and WHOIS. Compare pricing. Get suggestions.",
5
5
  "main": "dist/server.js",
6
6
  "types": "dist/server.d.ts",