Skip to main content
Glama

search_unified

Search Apple's Human Interface Guidelines and technical documentation simultaneously to find design principles and implementation details across iOS, macOS, watchOS, tvOS, and visionOS platforms.

Instructions

Unified search across both HIG design guidelines and technical documentation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query (keywords, component names, design concepts)
platformNoOptional: Filter by Apple platform

Implementation Reference

  • Main handler function implementing the unified search across HIG design guidelines and technical documentation, combining results with cross-references.
    async searchUnified(args: { query: string; platform?: ApplePlatform; }): Promise<{ results: UnifiedSearchResult[]; designResults: SearchResult[]; technicalResults: TechnicalSearchResult[]; total: number; query: string; sources: string[]; crossReferences: Array<{ designSection: string; technicalSymbol: string; relevance: number; }>; }> { const { query, platform } = args; // Use sensible defaults internally const includeDesign = true; const includeTechnical = true; const maxResults = 20; // Input validation if (!query || typeof query !== 'string' || query.trim().length === 0) { throw new Error('Invalid query: must be a non-empty string'); } if (query.length > 100) { throw new Error('Query too long: maximum 100 characters allowed'); } const sources: string[] = []; let designResults: SearchResult[] = []; let technicalResults: TechnicalSearchResult[] = []; try { // Search design guidelines if requested if (includeDesign) { sources.push('design-guidelines'); try { const designSearch = await this.searchHumanInterfaceGuidelines({ query, platform }); designResults = designSearch.results; } catch { // Fall through to fallback } } // Search technical documentation if requested if (includeTechnical) { sources.push('technical-documentation'); try { const technicalSearch = await this.searchTechnicalDocumentation({ query, platform }); technicalResults = technicalSearch.results; } catch { // Fall through to fallback } } // Generate cross-references between design and technical content const crossReferences = this.generateCrossReferences(designResults, technicalResults, query); // Combine and rank results using unified scoring const unifiedResults = this.combineAndRankResults( designResults, technicalResults, crossReferences, maxResults ); return { results: unifiedResults, designResults, technicalResults, total: unifiedResults.length, query: query.trim(), sources, crossReferences }; } catch (error) { throw new Error(`Unified search failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } }
  • src/server.ts:202-220 (registration)
    Tool registration entry in the ListToolsRequestSchema handler, defining name, description, and input schema.
    name: 'search_unified', title: 'Unified Search', description: 'Unified search across both HIG design guidelines and technical documentation', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query (keywords, component names, design concepts)', }, platform: { type: 'string', enum: ['iOS', 'macOS', 'watchOS', 'tvOS', 'visionOS', 'universal'], description: 'Optional: Filter by Apple platform', }, }, required: ['query'], }, },
  • TypeScript interface defining the input arguments for the search_unified tool.
    export interface SearchUnifiedArgs { query: string; searchType?: 'design' | 'technical' | 'both'; platform?: ApplePlatform; category?: HIGCategory; framework?: string; symbolType?: string; includeImplementation?: boolean; limit?: number; }
  • Dispatch case in CallToolRequestSchema handler that routes to the toolProvider's searchUnified method.
    case 'search_unified': { result = await this.toolProvider.searchUnified(args as any); break;
  • Helper method that generates cross-references between design guidelines and technical API symbols to enrich unified search results.
    private generateCrossReferences( designResults: SearchResult[], technicalResults: TechnicalSearchResult[], query: string ): Array<{ designSection: string; technicalSymbol: string; relevance: number; }> { const crossReferences: Array<{ designSection: string; technicalSymbol: string; relevance: number; }> = []; // Common UI component mappings const componentMappings = new Map([ // Buttons ['button', ['Button', 'UIButton', 'NSButton', 'SwiftUI.Button']], ['buttons', ['Button', 'UIButton', 'NSButton', 'SwiftUI.Button']], // Navigation ['navigation', ['NavigationView', 'UINavigationController', 'NSNavigationController', 'NavigationStack']], ['navigation bar', ['NavigationView', 'UINavigationBar', 'NSNavigationItem']], // Lists ['list', ['List', 'UITableView', 'NSTableView', 'UICollectionView']], ['table', ['UITableView', 'NSTableView', 'TableView']], // Text ['text', ['Text', 'UILabel', 'NSTextField', 'TextField']], ['label', ['Text', 'UILabel', 'NSTextField']], // Images ['image', ['Image', 'UIImageView', 'NSImageView']], ['icon', ['Image', 'UIImageView', 'NSImageView', 'SF Symbols']], // Controls ['picker', ['Picker', 'UIPickerView', 'NSPopUpButton']], ['slider', ['Slider', 'UISlider', 'NSSlider']], ['switch', ['Toggle', 'UISwitch', 'NSSwitch']], ['toggle', ['Toggle', 'UISwitch', 'NSSwitch']], // Layout ['stack', ['VStack', 'HStack', 'ZStack', 'UIStackView', 'NSStackView']], ['scroll', ['ScrollView', 'UIScrollView', 'NSScrollView']], // Sheets and Popups ['sheet', ['Sheet', 'UIModalPresentationStyle', 'NSModalSession']], ['alert', ['Alert', 'UIAlertController', 'NSAlert']], ['popup', ['Popover', 'UIPopoverController', 'NSPopover']] ]); // Extract key terms from query for mapping const queryTerms = query.toLowerCase().split(/\s+/).filter(term => term.length > 2); for (const designResult of designResults) { for (const technicalResult of technicalResults) { let relevance = 0; // Direct title matching const designTitle = designResult.title.toLowerCase(); const technicalTitle = technicalResult.title.toLowerCase(); // Check if design title contains technical symbol name or vice versa if (designTitle.includes(technicalTitle) || technicalTitle.includes(designTitle)) { relevance += 0.8; } // Component mapping-based relevance for (const [designTerm, technicalSymbols] of componentMappings) { if (designTitle.includes(designTerm)) { for (const symbol of technicalSymbols) { if (technicalTitle.includes(symbol.toLowerCase())) { relevance += 0.6; break; } } } } // Query term overlap between design and technical content for (const term of queryTerms) { if (designTitle.includes(term) && technicalTitle.includes(term)) { relevance += 0.3; } } // Platform consistency boost if (designResult.platform && technicalResult.platforms && typeof technicalResult.platforms === 'string') { const designPlatform = designResult.platform.toLowerCase(); const technicalPlatforms = technicalResult.platforms.toLowerCase(); if (technicalPlatforms.includes(designPlatform)) { relevance += 0.2; } } // Framework preference: slightly boost UIKit/AppKit over SwiftUI in cross-references for backward compatibility if (technicalResult.framework === 'UIKit' || technicalResult.framework === 'AppKit') { relevance += 0.1; } // Only include cross-references with meaningful relevance if (relevance >= 0.4) { const crossRefKey = `${designResult.title}:${technicalResult.title}`; // Avoid duplicate cross-references if (!crossReferences.some(ref => `${ref.designSection}:${ref.technicalSymbol}` === crossRefKey)) { crossReferences.push({ designSection: designResult.title, technicalSymbol: technicalResult.title, relevance: Math.round(relevance * 100) / 100 }); } } } } // Sort by relevance and limit to top cross-references return crossReferences .sort((a, b) => b.relevance - a.relevance) .slice(0, 10); }

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/tmaasen/apple-dev-mcp'

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