search_ember_docs
Search Ember.js documentation for API references, guides, and community resources to find solutions for development questions.
Instructions
Search through Ember.js documentation including API docs, guides, and community content. Returns relevant documentation with links to official sources. Use this for general queries about Ember concepts, features, or usage.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query (e.g., 'component lifecycle', 'tracked properties', 'routing') | |
| category | No | Filter by documentation category (default: all) | |
| limit | No | Maximum number of results (default: 5) |
Implementation Reference
- index.js:214-238 (handler)Main handler for the 'search_ember_docs' tool. Parses arguments, calls DocumentationService.search(), handles empty results, and formats output using formatSearchResults.async handleSearchDocs(args) { const { query, category = "all", limit = 5 } = args; const results = await this.docService.search(query, category, limit); if (results.length === 0) { return { content: [ { type: "text", text: `No results found for "${query}". Try different keywords or broader search terms.`, }, ], }; } const formattedResults = formatSearchResults(results, this.docService.deprecationManager); return { content: [ { type: "text", text: formattedResults, }, ], }; }
- lib/documentation-service.js:214-314 (handler)Core implementation of the search logic in DocumentationService.search(). Performs full-text search on parsed documentation sections with sophisticated relevance scoring, term matching, proximity bonuses, category filtering, and deprecation checks.async search(query, category = "all", limit = 5) { const results = []; const queryLower = query.toLowerCase(); const searchTerms = queryLower.split(/\s+/).filter(term => term.length > 0); const sectionsToSearch = category === "all" ? Object.keys(this.sections) : category === "api" ? ["api-docs"] : category === "guides" ? Object.keys(this.sections).filter( (s) => !["api-docs", "community-bloggers"].includes(s) ) : category === "community" ? ["community-bloggers"] : []; for (const sectionName of sectionsToSearch) { const sectionItems = this.sections[sectionName] || []; for (const item of sectionItems) { const content = item.content.toLowerCase(); const title = this.extractTitle(item.content); const titleLower = title.toLowerCase(); // Calculate relevance score with better weighting let score = 0; let matchedTerms = []; let termPositions = []; // Exact phrase match - highest value if (content.includes(queryLower)) { score += SEARCH_CONFIG.EXACT_PHRASE_BONUS; matchedTerms.push(queryLower); } // Check each term searchTerms.forEach((term) => { const matches = (content.match(new RegExp(term, "gi")) || []).length; if (matches > 0) { matchedTerms.push(term); // Title matches are highly relevant if (titleLower.includes(term)) { score += SEARCH_CONFIG.TITLE_MATCH_BONUS; } // Base score for term presence score += matches * SEARCH_CONFIG.TERM_MATCH_WEIGHT; // Find first position of this term for proximity scoring const pos = content.indexOf(term); if (pos !== -1) { termPositions.push({ term, pos }); } } }); // All terms present - significant bonus if (matchedTerms.length === searchTerms.length) { score += SEARCH_CONFIG.ALL_TERMS_BONUS; // Proximity bonus: terms close together are more relevant if (termPositions.length > 1) { termPositions.sort((a, b) => a.pos - b.pos); const spread = termPositions[termPositions.length - 1].pos - termPositions[0].pos; // If all terms within proximity threshold, add proximity bonus if (spread < SEARCH_CONFIG.PROXIMITY_THRESHOLD) { score += Math.floor((SEARCH_CONFIG.PROXIMITY_THRESHOLD - spread) / SEARCH_CONFIG.PROXIMITY_BONUS_DIVISOR); } } } // Only include results with meaningful matches // Require at least 2 terms or a high-value single match if (score >= SEARCH_CONFIG.MIN_SCORE && (matchedTerms.length >= 2 || score >= SEARCH_CONFIG.MIN_SCORE_SINGLE_TERM)) { const excerpt = this.extractExcerpt(item.content, searchTerms, termPositions); // Check if this result is for a deprecated API const deprecationInfo = this.deprecationManager.checkSearchResult({ title, content: item.content }); results.push({ title, category: this.categorizeSectionName(sectionName), excerpt, score, url: generateUrl(sectionName, title), apiLink: generateApiLink(item.content), matchedTerms: matchedTerms.length, totalTerms: searchTerms.length, deprecationInfo: deprecationInfo, }); } } } // Sort by score and return top results results.sort((a, b) => b.score - a.score); return results.slice(0, limit); }
- index.js:56-77 (schema)Input schema definition for the search_ember_docs tool, defining parameters query (required), category, and limit.inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query (e.g., 'component lifecycle', 'tracked properties', 'routing')", }, category: { type: "string", enum: ["all", "api", "guides", "community"], description: "Filter by documentation category (default: all)", }, limit: { type: "number", description: "Maximum number of results (default: 5)", default: 5, }, }, required: ["query"], },
- index.js:50-169 (registration)Tool registration in ListToolsRequestSchema handler, defining search_ember_docs with name, description, and schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: "search_ember_docs", description: "Search through Ember.js documentation including API docs, guides, and community content. Returns relevant documentation with links to official sources. Use this for general queries about Ember concepts, features, or usage.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query (e.g., 'component lifecycle', 'tracked properties', 'routing')", }, category: { type: "string", enum: ["all", "api", "guides", "community"], description: "Filter by documentation category (default: all)", }, limit: { type: "number", description: "Maximum number of results (default: 5)", default: 5, }, }, required: ["query"], }, }, { name: "get_api_reference", description: "Get detailed API reference documentation for a specific Ember class, module, or method. Returns full API documentation including parameters, return values, examples, and links to official API docs.", inputSchema: { type: "object", properties: { name: { type: "string", description: "Name of the API element (e.g., 'Component', '@glimmer/component', 'Service', 'Router')", }, type: { type: "string", enum: ["class", "module", "method", "property"], description: "Type of API element (optional)", }, }, required: ["name"], }, }, { 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"], }, }, { name: "get_ember_version_info", description: "Get information about Ember versions, including current stable version, what's new in recent releases, and migration guides. Useful for understanding version-specific features and deprecations.", inputSchema: { type: "object", properties: { version: { type: "string", description: "Specific version to get info about (optional, returns latest if not specified)", }, }, }, }, { name: "get_npm_package_info", description: "Get comprehensive information about an npm package including latest version, description, dependencies, maintainers, and more. Essential for understanding package details before upgrading dependencies.", inputSchema: { type: "object", properties: { packageName: { type: "string", description: "Name of the npm package (e.g., 'ember-source', '@glimmer/component', 'ember-cli')", }, }, required: ["packageName"], }, }, { name: "compare_npm_versions", description: "Compare a current package version with the latest available version on npm. Shows if an update is needed and provides version details to help with dependency upgrades.", inputSchema: { type: "object", properties: { packageName: { type: "string", description: "Name of the npm package (e.g., 'ember-source', '@glimmer/component')", }, currentVersion: { type: "string", description: "Current version being used (e.g., '4.12.0', '1.1.2')", }, }, required: ["packageName", "currentVersion"], }, }, ], }));
- lib/formatters.js:14-57 (helper)Helper function to format search results into structured Markdown output, including titles, categories, relevance scores, deprecation warnings, excerpts, and links.export function formatSearchResults(results, deprecationManager) { let output = `# Ember Documentation Search Results\n\n`; output += `Found ${results.length} result(s):\n\n`; results.forEach((result, index) => { output += `## ${index + 1}. ${result.title}`; // Add deprecation indicator if applicable if (result.deprecationInfo && result.deprecationInfo.status !== 'possibly-deprecated') { output += ` ${deprecationManager.generateWarning(result.title, 'short')}`; } output += `\n\n`; output += `**Category:** ${result.category}`; // Show match quality if (result.matchedTerms !== undefined && result.totalTerms !== undefined) { output += ` | **Match:** ${result.matchedTerms}/${result.totalTerms} terms`; } if (result.score !== undefined) { output += ` (relevance: ${result.score})`; } output += `\n\n`; // Add inline deprecation warning if applicable if (result.deprecationInfo && result.deprecationInfo.status !== 'possibly-deprecated') { output += `${deprecationManager.generateWarning(result.title, 'inline')}\n\n`; } output += `${result.excerpt}\n\n`; if (result.url) { output += `**Link:** ${result.url}\n\n`; } if (result.apiLink) { output += `**API Reference:** ${result.apiLink}\n\n`; } output += `---\n\n`; }); return output; }