Skip to main content
Glama

suggest_domains_smart

Generate brandable domain name suggestions using AI from keywords or business descriptions, combining semantic analysis with GoDaddy's AI for comprehensive results.

Instructions

AI-powered domain name suggestion engine.

Generate creative, brandable domain names from keywords or business descriptions. Combines our semantic engine with GoDaddy's AI suggestions for maximum coverage.

Features:

  • Dual-source suggestions: Our semantic engine + GoDaddy AI

  • Understands natural language queries ("coffee shop in seattle")

  • Auto-detects industry for contextual suggestions

  • Generates portmanteau/blended names (instagram = instant + telegram)

  • Applies modern naming patterns (ly, ify, io, hub, etc.)

  • Filters premium domains by default

  • Pre-verified availability via GoDaddy

Examples:

  • suggest_domains_smart("ai customer service") → AI-themed suggestions

  • suggest_domains_smart("organic coffee", industry="food") → Food-focused names

  • suggest_domains_smart("vibecoding", style="short") → Minimal length names

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesKeywords, business description, or base domain name.
tldNoTLD to check (e.g., 'com'). Defaults to 'com'.
industryNoIndustry for contextual suggestions. Auto-detected if omitted.
styleNoSuggestion style preference.
max_suggestionsNoMaximum suggestions to return (1-50). Defaults to 15.
include_premiumNoInclude premium domains. Defaults to false.

Implementation Reference

  • Core handler function that executes the tool: parses input, generates domain suggestions from internal semantic engine and GoDaddy, checks availability in batches, scores and filters results based on style and premium preferences, generates insights and related terms.
    export async function executeSuggestDomainsSmart( input: SuggestDomainsSmartInput, ): Promise<SuggestDomainsSmartResponse> { try { const { query, tld, industry, style, max_suggestions, include_premium } = suggestDomainsSmartSchema.parse(input); // Normalize and analyze input const normalizedQuery = query.toLowerCase().trim(); const detectedWords = segmentWords(normalizedQuery); const detectedIndustry = industry || detectIndustry(detectedWords); // Track source statistics const sourceStats = { semantic_engine: 0, godaddy_suggest: 0, merged: 0, }; // ======================================== // STEP 1: Generate suggestions from BOTH sources in parallel // ======================================== // Source 1: Our semantic engine const semanticSuggestions = generateSmartSuggestions(normalizedQuery, { maxSuggestions: max_suggestions * 3, includePortmanteau: style === 'creative' || style === 'brandable', includeSynonyms: style !== 'short', includeIndustryTerms: !!detectedIndustry, industry: detectedIndustry || undefined, }); sourceStats.semantic_engine = semanticSuggestions.length; // Source 2: GoDaddy's AI suggestions (parallel call) let godaddySuggestions: GodaddySuggestion[] = []; try { godaddySuggestions = await godaddyPublicAdapter.suggestDomains(query, { tlds: [tld], limit: max_suggestions * 2, }); sourceStats.godaddy_suggest = godaddySuggestions.length; logger.debug('GoDaddy suggestions received', { count: godaddySuggestions.length, sample: godaddySuggestions.slice(0, 3).map(s => s.domain), }); } catch (error) { // GoDaddy might fail - continue with just semantic suggestions logger.warn('GoDaddy suggestions failed, using semantic engine only', { error: error instanceof Error ? error.message : 'unknown', }); } // ======================================== // STEP 2: Merge and deduplicate suggestions // ======================================== // Track which domains came from which source const domainSources = new Map<string, 'semantic_engine' | 'godaddy_suggest' | 'both'>(); // Add semantic suggestions (need availability check) const styledSuggestions = applyStyleFilter(semanticSuggestions, style, normalizedQuery); for (const name of styledSuggestions) { const fullDomain = `${name}.${tld}`.toLowerCase(); domainSources.set(fullDomain, 'semantic_engine'); } // Add GoDaddy suggestions (already have availability) for (const gs of godaddySuggestions) { const fullDomain = gs.domain.toLowerCase(); if (domainSources.has(fullDomain)) { domainSources.set(fullDomain, 'both'); // Found in both sources sourceStats.merged++; } else { domainSources.set(fullDomain, 'godaddy_suggest'); } } // ======================================== // STEP 3: Check availability for semantic suggestions // (GoDaddy suggestions already have availability info) // ======================================== const available: SmartSuggestion[] = []; const premium: SmartSuggestion[] = []; let unavailableCount = 0; let totalChecked = 0; // First, add pre-checked GoDaddy suggestions (no API call needed!) for (const gs of godaddySuggestions) { const fullDomain = gs.domain.toLowerCase(); const source = domainSources.get(fullDomain) || 'godaddy_suggest'; const name = fullDomain.replace(`.${tld}`, ''); const suggestion: SmartSuggestion = { domain: fullDomain, available: gs.available, price_first_year: null, // GoDaddy doesn't provide pricing price_renewal: null, registrar: 'godaddy', premium: gs.premium, premium_detected: gs.premium, privacy_included: false, score: scoreDomainName(name, normalizedQuery), category: !gs.available ? 'unavailable' : gs.premium ? 'premium' : gs.auction ? 'auction' : 'standard', source, }; if (!gs.available) { unavailableCount++; } else if (gs.premium || gs.auction) { if (include_premium) { premium.push(suggestion); } } else { available.push(suggestion); } } // Then, check semantic suggestions that weren't in GoDaddy results const semanticOnlyCandidates = styledSuggestions .filter(name => { const fullDomain = `${name}.${tld}`.toLowerCase(); return domainSources.get(fullDomain) === 'semantic_engine'; }) .slice(0, max_suggestions); // Limit API calls const BATCH_SIZE = 5; for (let i = 0; i < semanticOnlyCandidates.length; i += BATCH_SIZE) { const batch = semanticOnlyCandidates.slice(i, i + BATCH_SIZE); const batchResults = await Promise.all( batch.map(async (name) => { try { const response = await searchDomain(name, [tld]); const result = response.results.find((r) => r.domain === `${name}.${tld}`); return { name, result: result || null }; } catch { return { name, result: null }; } }), ); for (const { name, result } of batchResults) { totalChecked++; if (!result) { unavailableCount++; continue; } const isPremiumDomain = result.premium || isPremiumPrice(tld, result.price_first_year); const fullDomain = `${name}.${tld}`.toLowerCase(); const suggestion: SmartSuggestion = { domain: fullDomain, available: result.available, price_first_year: result.price_first_year, price_renewal: result.price_renewal, registrar: result.registrar, premium: result.premium || false, premium_detected: isPremiumPrice(tld, result.price_first_year), privacy_included: result.privacy_included || false, score: scoreDomainName(name, normalizedQuery), category: !result.available ? 'unavailable' : isPremiumDomain ? 'premium' : 'standard', source: 'semantic_engine', }; if (!result.available) { unavailableCount++; } else if (isPremiumDomain) { if (include_premium) { premium.push(suggestion); } } else { available.push(suggestion); } } // Early exit if we have enough available if (available.length >= max_suggestions && !include_premium) { break; } } // ======================================== // STEP 4: Sort and finalize results // ======================================== // Sort by score, prefer 'both' source items (validated by multiple sources) available.sort((a, b) => { // Boost 'both' source items const aBoost = a.source === 'both' ? 2 : 0; const bBoost = b.source === 'both' ? 2 : 0; return (b.score + bBoost) - (a.score + aBoost); }); premium.sort((a, b) => b.score - a.score); // Limit results const finalAvailable = available.slice(0, max_suggestions); const finalPremium = include_premium ? premium.slice(0, Math.floor(max_suggestions / 2)) : []; // ======================================== // STEP 5: Generate insights // ======================================== const insights: string[] = []; // Source info insights.push(`🔍 Sources: Semantic Engine (${sourceStats.semantic_engine}) + GoDaddy AI (${sourceStats.godaddy_suggest})`); if (sourceStats.merged > 0) { insights.push(`🔗 ${sourceStats.merged} suggestions found in both sources`); } if (detectedIndustry) { insights.push(`🎯 Detected industry: ${detectedIndustry}`); } if (detectedWords.length > 1) { insights.push(`📝 Parsed keywords: ${detectedWords.join(', ')}`); } if (finalAvailable.length > 0) { insights.push(`✅ Found ${finalAvailable.length} available domain${finalAvailable.length > 1 ? 's' : ''}`); const best = finalAvailable[0]!; const priceStr = best.price_first_year !== null ? `$${best.price_first_year}/yr` : 'via ' + best.registrar; const sourceStr = best.source === 'both' ? ' (verified by both sources)' : ''; insights.push(`⭐ Top pick: ${best.domain} (${priceStr})${sourceStr}`); } else { insights.push(`❌ No standard-priced domains available`); } if (premium.length > 0) { insights.push(`💎 ${premium.length} premium domain${premium.length > 1 ? 's' : ''} available`); } if (finalAvailable.length < 3) { insights.push(`💡 Try different keywords or a different TLD (.io, .co, .dev)`); } // Get related terms for user reference const relatedTerms: string[] = []; for (const word of detectedWords.slice(0, 3)) { const synonyms = getSynonyms(word); relatedTerms.push(...synonyms.slice(0, 2)); } if (detectedIndustry) { const industryTerms = getIndustryTerms(detectedIndustry); relatedTerms.push(...industryTerms.slice(0, 4)); } return { query: normalizedQuery, detected_words: detectedWords, detected_industry: detectedIndustry, tld, style, sources: sourceStats, total_checked: totalChecked + godaddySuggestions.length, results: { available: finalAvailable, premium: finalPremium, unavailable_count: unavailableCount, }, insights, related_terms: [...new Set(relatedTerms)].slice(0, 10), }; } catch (error) { throw wrapError(error); } }
  • Zod input schema defining parameters for the tool: query, tld, industry, style, max_suggestions, include_premium.
    export const suggestDomainsSmartSchema = z.object({ query: z .string() .min(1) .max(200) .describe( "Search query - can be keywords, business description, or domain name. " + "Examples: 'coffee shop seattle', 'ai startup', 'vibecoding'" ), tld: z .string() .optional() .default('com') .describe("Primary TLD to check. Defaults to 'com'."), industry: z .enum(['tech', 'startup', 'finance', 'health', 'food', 'creative', 'ecommerce', 'education', 'gaming', 'social']) .optional() .describe("Industry context for better suggestions. Auto-detected if not provided."), style: z .enum(['brandable', 'descriptive', 'short', 'creative']) .optional() .default('brandable') .describe( "Suggestion style: 'brandable' (unique names), 'descriptive' (keyword-based), " + "'short' (minimal length), 'creative' (playful combinations)." ), max_suggestions: z .number() .int() .min(1) .max(50) .optional() .default(15) .describe("Maximum suggestions to return (1-50). Defaults to 15."), include_premium: z .boolean() .optional() .default(false) .describe("Include premium-priced domains in results. Defaults to false."), });
  • MCP Tool object definition including name, description, and JSON inputSchema for registration.
    export const suggestDomainsSmartTool = { name: 'suggest_domains_smart', description: `AI-powered domain name suggestion engine. Generate creative, brandable domain names from keywords or business descriptions. Combines our semantic engine with GoDaddy's AI suggestions for maximum coverage. Features: - Dual-source suggestions: Our semantic engine + GoDaddy AI - Understands natural language queries ("coffee shop in seattle") - Auto-detects industry for contextual suggestions - Generates portmanteau/blended names (instagram = instant + telegram) - Applies modern naming patterns (ly, ify, io, hub, etc.) - Filters premium domains by default - Pre-verified availability via GoDaddy Examples: - suggest_domains_smart("ai customer service") → AI-themed suggestions - suggest_domains_smart("organic coffee", industry="food") → Food-focused names - suggest_domains_smart("vibecoding", style="short") → Minimal length names`, inputSchema: { type: 'object', properties: { query: { type: 'string', description: "Keywords, business description, or base domain name.", }, tld: { type: 'string', description: "TLD to check (e.g., 'com'). Defaults to 'com'.", }, industry: { type: 'string', enum: ['tech', 'startup', 'finance', 'health', 'food', 'creative', 'ecommerce', 'education', 'gaming', 'social'], description: "Industry for contextual suggestions. Auto-detected if omitted.", }, style: { type: 'string', enum: ['brandable', 'descriptive', 'short', 'creative'], description: "Suggestion style preference.", }, max_suggestions: { type: 'number', description: "Maximum suggestions to return (1-50). Defaults to 15.", }, include_premium: { type: 'boolean', description: "Include premium domains. Defaults to false.", }, }, required: ['query'], }, };
  • src/server.ts:58-66 (registration)
    Server registration: adds suggestDomainsSmartTool to the list of available tools served by the MCP server.
    const TOOLS: Tool[] = [ searchDomainTool as Tool, bulkSearchTool as Tool, compareRegistrarsTool as Tool, suggestDomainsTool as Tool, suggestDomainsSmartTool as Tool, tldInfoTool as Tool, checkSocialsTool as Tool, ];
  • src/server.ts:194-204 (registration)
    Tool dispatcher switch case that maps incoming tool calls to the executeSuggestDomainsSmart handler.
    case 'suggest_domains_smart': return executeSuggestDomainsSmart({ query: args.query as string, tld: (args.tld as string) || 'com', industry: args.industry as | 'tech' | 'startup' | 'finance' | 'health' | 'food' | 'creative' | 'ecommerce' | 'education' | 'gaming' | 'social' | undefined, style: (args.style as 'brandable' | 'descriptive' | 'short' | 'creative') || 'brandable', max_suggestions: (args.max_suggestions as number) || 15, include_premium: (args.include_premium as boolean) || false, });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dorukardahan/domain-search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server