Skip to main content
Glama

search_symbols

Search Apple developer symbols by keywords with wildcard support to explore classes, protocols, and APIs across iOS, macOS, and other platforms.

Instructions

Search and discover symbols within the currently selected technology. Use this for exploration and finding symbols by keywords. Supports wildcards (* and ?). For specific known symbols, use get_documentation instead.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
maxResultsNoOptional maximum number of results (default 20)
platformNoOptional platform filter (iOS, macOS, etc.)
queryYesSearch keywords with wildcard support (* for any characters, ? for single character)
symbolTypeNoOptional symbol kind filter (class, protocol, etc.)

Implementation Reference

  • The buildSearchSymbolsHandler function that executes the search_symbols tool logic. It searches a local symbol index (built from cache if needed), falls back to framework search if index is small, applies filters, and returns formatted Markdown results.
    export const buildSearchSymbolsHandler = (context: ServerContext) => {
    	const {client, state} = context;
    	const noTechnology = buildNoTechnologyMessage(context);
    
    	return async (args: {maxResults?: number; platform?: string; query: string; symbolType?: string}): Promise<ToolResponse> => {
    		const activeTechnology = state.getActiveTechnology();
    		if (!activeTechnology) {
    			return noTechnology();
    		}
    
    		const {query, maxResults = 20, platform, symbolType} = args;
    
    		// Get or create technology-specific local index from state
    		const techLocalIndex = state.getLocalSymbolIndex(client);
    
    		// Build local index from cached files if not already built
    		if (techLocalIndex.getSymbolCount() === 0) {
    			try {
    				console.error('📚 Building symbol index from cache...');
    				await techLocalIndex.buildIndexFromCache();
    				console.error(`✅ Index built with ${techLocalIndex.getSymbolCount()} symbols`);
    			} catch (error) {
    				console.warn('Failed to build local symbol index:', error instanceof Error ? error.message : String(error));
    			}
    		}
    
    		// Comprehensive download disabled - it was broken and blocking
    		// If local index is empty/small, use direct framework search as fallback
    		let symbolResults = techLocalIndex.search(query, maxResults * 2);
    
    		if (symbolResults.length === 0 && techLocalIndex.getSymbolCount() < 50) {
    			// Fallback: search framework.references directly (fast, no download needed)
    			console.error('📋 Using framework references for search...');
    			const frameworkResults = await client.searchFramework(activeTechnology.title, query, {maxResults: maxResults * 2, platform, symbolType});
    			symbolResults = frameworkResults.map(r => ({
    				id: r.path ?? r.title,
    				title: r.title,
    				path: r.path ?? '',
    				kind: r.symbolKind ?? 'symbol',
    				abstract: r.description,
    				platforms: r.platforms ? r.platforms.split(', ') : [],
    				tokens: [],
    				filePath: '',
    			}));
    		}
    
    		// Apply filters
    		let filteredResults = symbolResults;
    		if (platform) {
    			const platformLower = platform.toLowerCase();
    			filteredResults = filteredResults.filter(result =>
    				result.platforms.some(p => p.toLowerCase().includes(platformLower)));
    		}
    
    		if (symbolType) {
    			const typeLower = symbolType.toLowerCase();
    			filteredResults = filteredResults.filter(result =>
    				result.kind.toLowerCase().includes(typeLower));
    		}
    
    		filteredResults = filteredResults.slice(0, maxResults);
    
    		// Validate result relevance
    		const technologyIdentifier = activeTechnology.identifier.replace('doc://com.apple.documentation/', '').replace(/^documentation\//, '');
    		const isRelevantResult = (result: LocalSymbolIndexEntry) => {
    			const resultPath = result.path.toLowerCase();
    			const technologyPath = technologyIdentifier.toLowerCase();
    			return resultPath.includes(technologyPath);
    		};
    
    		const relevantResults = filteredResults.filter(result => isRelevantResult(result));
    		const hasIrrelevantResults = relevantResults.length < filteredResults.length;
    
    		const lines = [
    			header(1, `🔍 Search Results for "${query}"`),
    			'',
    			bold('Technology', activeTechnology.title),
    			bold('Matches', filteredResults.length.toString()),
    			bold('Total Symbols Indexed', techLocalIndex.getSymbolCount().toString()),
    			'',
    		];
    
    		// Add status information
    		if (techLocalIndex.getSymbolCount() < 50) {
    			lines.push(
    				'⚠️ **Limited Results:** Only basic symbols are indexed.',
    				'For comprehensive results, additional symbols are being downloaded in the background.',
    				'',
    			);
    		} else {
    			lines.push(
    				'✅ **Comprehensive Index:** Full symbol database is available.',
    				'',
    			);
    		}
    
    		lines.push(header(2, 'Symbols'), '');
    
    		// Show warning if results seem irrelevant
    		if (hasIrrelevantResults && filteredResults.length > 0) {
    			lines.push(
    				'⚠️ **Note:** Some results may not be from the selected technology.',
    				'For specific symbol names, try using `get_documentation` instead.',
    				'',
    			);
    		}
    
    		if (filteredResults.length > 0) {
    			for (const result of filteredResults) {
    				const platforms = result.platforms.length > 0 ? result.platforms.join(', ') : 'All platforms';
    				lines.push(
    					`### ${result.title}`,
    					`   • **Kind:** ${result.kind}`,
    					`   • **Path:** ${result.path}`,
    					`   • **Platforms:** ${platforms}`,
    					`   ${result.abstract}`,
    					'',
    				);
    			}
    		} else {
    			// Check if this looks like a specific symbol name that should use direct documentation lookup
    			const isSpecificSymbol = /^[A-Z][a-zA-Z\d]*$/.test(query) || /^[A-Z][a-zA-Z\d]*\.[A-Z][a-zA-Z\d]*$/.test(query);
    
    			lines.push(
    				'No symbols matched those terms within this technology.',
    				'',
    				'**Search Tips:**',
    				'• Try wildcards: `Grid*` or `*Item`',
    				'• Use broader keywords: "grid" instead of "griditem"',
    				'• Check spelling and try synonyms',
    				'',
    			);
    
    			if (isSpecificSymbol) {
    				lines.push(
    					'**💡 Suggestion:** This looks like a specific symbol name.',
    					'Try using `get_documentation` instead for direct access:',
    					'',
    					'```',
    					`get_documentation { "path": "${query}" }`,
    					'```',
    					'',
    				);
    			}
    
    			lines.push(
    				'**Note:** If this is your first search, symbols are being downloaded in the background.',
    				'Try searching again in a few moments for more comprehensive results.',
    				'',
    			);
    		}
    
    		return {
    			content: [{text: lines.join('\n'), type: 'text'}],
    		};
    	};
    };
  • Tool definition object for search_symbols, including name, description, input schema, and handler assignment, added to the toolDefinitions array for MCP server registration.
    {
    	name: 'search_symbols',
    	description: 'Search and discover symbols within the currently selected technology. '
    		+ 'Use this for exploration and finding symbols by keywords. Supports wildcards (* and ?). '
    		+ 'For specific known symbols, use get_documentation instead.',
    	inputSchema: {
    		type: 'object',
    		required: ['query'],
    		properties: {
    			maxResults: {
    				type: 'number',
    				description: 'Optional maximum number of results (default 20)',
    			},
    			platform: {
    				type: 'string',
    				description: 'Optional platform filter (iOS, macOS, etc.)',
    			},
    			query: {
    				type: 'string',
    				description: 'Search keywords with wildcard support (* for any characters, ? for single character)',
    			},
    			symbolType: {
    				type: 'string',
    				description: 'Optional symbol kind filter (class, protocol, etc.)',
    			},
    		},
    	},
    	handler: buildSearchSymbolsHandler(context),
    },
  • Input schema defining parameters for the search_symbols tool: required query string, optional maxResults, platform, and symbolType.
    inputSchema: {
    	type: 'object',
    	required: ['query'],
    	properties: {
    		maxResults: {
    			type: 'number',
    			description: 'Optional maximum number of results (default 20)',
    		},
    		platform: {
    			type: 'string',
    			description: 'Optional platform filter (iOS, macOS, etc.)',
    		},
    		query: {
    			type: 'string',
    			description: 'Search keywords with wildcard support (* for any characters, ? for single character)',
    		},
    		symbolType: {
    			type: 'string',
    			description: 'Optional symbol kind filter (class, protocol, etc.)',
    		},
    	},
    },
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'supports wildcards (* and ?)' which adds useful context about search capabilities, but doesn't cover important behavioral aspects like pagination behavior (only mentions maxResults default), error handling, or what happens when no results are found. The description is adequate but has clear gaps in behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is perfectly concise and well-structured in just two sentences. The first sentence states the purpose and primary use case, the second provides important behavioral detail (wildcard support) and sibling differentiation. Every sentence earns its place with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (4 parameters, no output schema, no annotations), the description is reasonably complete but has gaps. It covers purpose, usage guidelines, and some behavioral aspects, but doesn't address what the tool returns (no output schema means the description should ideally mention return format) or important constraints like rate limits or authentication requirements.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 100% description coverage, so the baseline is 3. The description adds some value by mentioning wildcard support in the context of the query parameter ('Search keywords with wildcard support'), but doesn't provide additional semantic context beyond what's already documented in the schema descriptions for each parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('search and discover symbols') and resource ('within the currently selected technology'), distinguishing it from sibling tools like get_documentation (for specific known symbols) and choose_technology/current_technology/discover_technologies (which handle technology selection rather than symbol search).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: 'Use this for exploration and finding symbols by keywords' and 'For specific known symbols, use get_documentation instead.' This clearly defines when to use this tool versus alternatives, including both positive guidance (when to use) and negative guidance (when not to use).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/MightyDillah/apple-doc-mcp'

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