Skip to main content
Glama
NullVoxPopuli

Ember MCP Server

get_best_practices

Access Ember.js best practices and recommendations for specific development topics, including modern patterns, anti-patterns to avoid, performance tips, and community-approved approaches.

Instructions

Get Ember best practices and recommendations for specific topics. This includes modern patterns, anti-patterns to avoid, performance tips, and community-approved approaches. Always use this when providing implementation advice.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
topicYesTopic to get best practices for (e.g., 'component patterns', 'state management', 'testing', 'performance')

Implementation Reference

  • Main tool handler that extracts the 'topic' argument, calls the documentation service to retrieve best practices, handles empty results, formats the output using formatBestPractices, and returns the MCP-formatted text content.
    async handleGetBestPractices(args) {
      const { topic } = args;
      const practices = await this.docService.getBestPractices(topic);
    
      if (practices.length === 0) {
        return {
          content: [
            {
              type: "text",
              text: `No best practices found for "${topic}". Try searching with search_ember_docs for general information.`,
            },
          ],
        };
      }
    
      const formattedPractices = formatBestPractices(practices, topic, this.docService.deprecationManager);
      return {
        content: [
          {
            type: "text",
            text: formattedPractices,
          },
        ],
      };
    }
  • Core helper function in DocumentationService that implements the best practices search logic: matches topic terms (with singular/plural inflection), scores documents based on best practice keywords, extracts relevant content, examples, and anti-patterns, deduplicates, sorts by relevance, and returns formatted practice objects.
    async getBestPractices(topic) {
      const practices = [];
      const topicLower = topic.toLowerCase();
      const topicTerms = topicLower.split(/\s+/).filter(term => term.length > 2);
    
      // Search in community articles and guides
      const communityDocs = this.sections["community-bloggers"] || [];
      const allSections = [
        ...communityDocs,
        ...Object.entries(this.sections)
          .filter(([name]) => !["api-docs", "community-bloggers"].includes(name))
          .flatMap(([_, items]) => items),
      ];
    
      // Best practice keywords (weighted by relevance)
      const strongKeywords = BEST_PRACTICES_KEYWORDS.strong;
      const weakKeywords = BEST_PRACTICES_KEYWORDS.weak;
    
      // Track seen content to avoid duplicates
      const seenTitles = new Set();
    
      for (const doc of allSections) {
        const content = doc.content.toLowerCase();
    
        // Calculate relevance score
        let score = 0;
    
        // Topic term matching with inflection
        // Try exact match, singular form, and plural form
        const matchedTerms = topicTerms.filter(term => {
          if (content.includes(term)) return true;
    
          // Try singular form (e.g., "templates" -> "template", "classes" -> "class")
          const singular = this.toSingular(term);
          if (singular !== term && content.includes(singular)) return true;
    
          // Try plural form (e.g., "template" -> "templates")
          const plural = pluralize.plural(term);
          if (plural !== term && content.includes(plural)) return true;
    
          return false;
        });
    
        // Require at least one term to match
        if (matchedTerms.length === 0) {
          continue;
        }
    
        // Score based on topic term matches
        // Give more weight to each matched term to reward relevance
        score += matchedTerms.length * SEARCH_CONFIG.BP_TERM_MATCH_WEIGHT;
    
        // Bonus for all terms present
        if (matchedTerms.length === topicTerms.length) {
          score += SEARCH_CONFIG.BP_ALL_TERMS_BONUS;
        }
    
        // Strong keyword matches
        const strongMatches = strongKeywords.filter(keyword => content.includes(keyword));
        score += strongMatches.length * SEARCH_CONFIG.BP_STRONG_KEYWORD_WEIGHT;
    
        // Weak keyword matches (only if strong matches exist)
        if (strongMatches.length > 0) {
          const weakMatches = weakKeywords.filter(keyword => content.includes(keyword));
          score += weakMatches.length * SEARCH_CONFIG.BP_WEAK_KEYWORD_WEIGHT;
        }
    
        // Simpler threshold: just require at least one term match + some best-practice signal
        // The scoring already rewards multiple term matches and keyword presence
        const minThreshold = SEARCH_CONFIG.BP_MIN_THRESHOLD;
    
        // Skip if score is too low (not a best practice document)
        if (score < minThreshold) {
          continue;
        }
    
        const title = this.extractTitle(doc.content);
    
        // Skip duplicates
        if (seenTitles.has(title.toLowerCase())) {
          continue;
        }
        seenTitles.add(title.toLowerCase());
    
        const relevantSections = this.extractBestPracticeSections(
          doc.content,
          topicLower
        );
    
        if (relevantSections.content) {
          practices.push({
            title,
            content: relevantSections.content,
            examples: relevantSections.examples,
            antiPatterns: relevantSections.antiPatterns,
            references: [generateUrl("community-bloggers", title)],
            score: score, // Store for sorting
          });
        }
      }
    
      // Sort by relevance score (descending) and return top results
      practices.sort((a, b) => b.score - a.score);
      return practices.slice(0, SEARCH_CONFIG.MAX_BEST_PRACTICES).map(practice => {
        // Remove score before returning (internal only)
        const { score, ...practiceWithoutScore } = practice;
        return practiceWithoutScore;
      });
    }
  • JSON schema defining the input parameters for the get_best_practices tool: requires a 'topic' string parameter.
    inputSchema: {
      type: "object",
      properties: {
        topic: {
          type: "string",
          description:
            "Topic to get best practices for (e.g., 'component patterns', 'state management', 'testing', 'performance')",
        },
      },
      required: ["topic"],
    },
  • index.js:185-186 (registration)
    Tool name registration in the CallToolRequestHandler switch statement dispatcher.
    case "get_best_practices":
      return await this.handleGetBestPractices(args);
  • index.js:100-115 (registration)
    Tool registration in the ListToolsRequestSchema handler, defining name, description, and input schema for the MCP tools list.
    {
      name: "get_best_practices",
      description:
        "Get Ember best practices and recommendations for specific topics. This includes modern patterns, anti-patterns to avoid, performance tips, and community-approved approaches. Always use this when providing implementation advice.",
      inputSchema: {
        type: "object",
        properties: {
          topic: {
            type: "string",
            description:
              "Topic to get best practices for (e.g., 'component patterns', 'state management', 'testing', 'performance')",
          },
        },
        required: ["topic"],
      },
    },

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/NullVoxPopuli/ember-mcp'

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