Skip to main content
Glama

local_project_hints

Analyze project structure to generate navigation hints with word clouds, folder analysis, and architecture detection for better codebase understanding.

Instructions

πŸ“Š Generate intelligent project navigation hints with word clouds, folder analysis, and architecture detection. Supports multiple output formats including markdown and HTML, with AI-powered analysis and configurable performance options. Accepts absolute paths or relative paths (when workspace can be detected).

Input Schema

NameRequiredDescriptionDefault
projectPathNoProject directory path. Can be absolute (recommended) or relative to workspace. Examples: "C:\Dev\my-project", "/Users/username/project", or "." for current workspace.
formatNoOutput format preference - structured for detailed analysis, compact for quick overview, json for raw data, markdown for documentation, html for visual reportscompact
maxFilesNoMaximum number of files to analyze for performance
folderPathNoAnalyze specific folder instead of entire project (optional)
includeContentNoInclude file content analysis for deeper insights (may impact performance)
useAINoEnable AI-powered folder analysis for better purpose detection (requires OpenAI API key)
maxFileSizeForSymbolsNoMaximum file size in bytes for symbol extraction (performance tuning)

Input Schema (JSON Schema)

{ "properties": { "folderPath": { "description": "Analyze specific folder instead of entire project (optional)", "type": "string" }, "format": { "default": "compact", "description": "Output format preference - structured for detailed analysis, compact for quick overview, json for raw data, markdown for documentation, html for visual reports", "enum": [ "structured", "compact", "json", "markdown", "html" ], "type": "string" }, "includeContent": { "default": false, "description": "Include file content analysis for deeper insights (may impact performance)", "type": "boolean" }, "maxFileSizeForSymbols": { "default": 50000, "description": "Maximum file size in bytes for symbol extraction (performance tuning)", "maximum": 200000, "minimum": 10000, "type": "number" }, "maxFiles": { "default": 100, "description": "Maximum number of files to analyze for performance", "maximum": 200, "minimum": 10, "type": "number" }, "projectPath": { "description": "Project directory path. Can be absolute (recommended) or relative to workspace. Examples: \"C:\\Dev\\my-project\", \"/Users/username/project\", or \".\" for current workspace.", "type": "string" }, "useAI": { "default": true, "description": "Enable AI-powered folder analysis for better purpose detection (requires OpenAI API key)", "type": "boolean" } }, "type": "object" }

Implementation Reference

  • Main handler function that executes the tool logic: validates input, resolves paths, generates project hints using ProjectHintsGenerator, handles different formats (compact, structured, json, markdown, html), folder-specific analysis, file composition analysis, and returns formatted results or errors.
    export async function handleProjectHints(args: any): Promise<any> { const { projectPath, format = 'compact', maxFiles = 100, folderPath, includeContent = false, useAI = true, maxFileSizeForSymbols = 50000, query, } = args; // Validate that projectPath is provided and is absolute if (!projectPath) { throw new Error( '❌ projectPath is required. Please provide an absolute path to the project directory.' ); } const resolvedProjectPath = validateAndResolvePath(projectPath); logger.info('πŸ“Š Generating project hints', { originalPath: projectPath, resolvedPath: resolvedProjectPath, format, maxFiles, folderPath, }); try { const hintsGenerator = new ProjectHintsGenerator(); if (folderPath && folderPath !== '.') { // Folder-specific analysis const folderHints = await hintsGenerator.generateFolderDocumentation( resolvedProjectPath, folderPath, { useAI, maxDepth: 2, includeSubfolders: true, } ); return { success: true, hints: formatFolderHints(folderHints, format), type: 'folder-specific', metadata: { folderPath, keyFiles: folderHints.keyFiles.length, subFolders: folderHints.subFolders.length, confidence: folderHints.confidence, }, }; } else { // Use the core ProjectHintsGenerator which handles embedding-assisted features logger.info('πŸ“Š Generating project hints with core generator', { format, maxFiles, useEmbeddingAssisted: hintsGenerator['shouldUseEmbeddingAssistedHints']?.(), }); const hintsResult = await hintsGenerator.generateProjectHints(resolvedProjectPath, { maxFiles, includeContent, useAI, maxFileSizeForSymbols, format: 'json', // Get raw hints object for processing }); // Type guard to ensure we have the ProjectHints object const hints = hintsResult as ProjectHints; // Handle different output formats let formattedHints: string; logger.info('🎨 Formatting hints', { requestedFormat: format }); if (format === 'html') { // Regenerate with the desired format using the generator's built-in formatting logger.info('πŸ”„ Regenerating with built-in HTML formatting'); formattedHints = (await hintsGenerator.generateProjectHints(resolvedProjectPath, { maxFiles, includeContent, useAI, maxFileSizeForSymbols, format, })) as string; logger.info('βœ… Generated formatted hints', { format, length: formattedHints.length, preview: formattedHints.substring(0, 100) + '...', }); } else if (format === 'structured') { // Use enhanced structured format that includes embedding-assisted features logger.info('πŸ”§ Using structured format with potential embedding enhancement'); const fileDiscovery = new FileDiscovery(resolvedProjectPath, { maxFileSize: maxFileSizeForSymbols, }); const allFiles = await fileDiscovery.discoverFiles(); const limitedFiles = fileDiscovery.sortByRelevance(allFiles).slice(0, maxFiles); // Analyze file composition across the project const fileCompositionStructured = analyzeFileComposition(allFiles, limitedFiles); const enhancedSummary = await buildEnhancedProjectSummary( resolvedProjectPath, limitedFiles, query ); // Add answer draft if query provided if (query) { const answerDraft = generateAnswerDraft(enhancedSummary, query); if (answerDraft) { (enhancedSummary as any).answerDraft = answerDraft; } } formattedHints = formatProjectHints(enhancedSummary, format); return { success: true, hints: formattedHints, type: 'enhanced-project-wide', metadata: { filesAnalyzed: enhancedSummary.summary.files, capabilities: enhancedSummary.capabilities.domains, hintsCount: enhancedSummary.hints.length, riskScore: enhancedSummary.risks.score, nextMode: enhancedSummary.next.mode, hasQuery: !!query, enhanced: true, embeddingAssisted: hintsGenerator['shouldUseEmbeddingAssistedHints']?.() || false, fileComposition: fileCompositionStructured, }, }; } else { // Use local formatting for remaining cases logger.info('πŸ“ Using local formatting for', { format }); formattedHints = formatProjectHints(hints, format); } // Analyze file composition for metadata const fileDiscoveryForComposition = new FileDiscovery(resolvedProjectPath, { maxFileSize: maxFileSizeForSymbols, }); const allFilesForComposition = await fileDiscoveryForComposition.discoverFiles(); const limitedFilesForComposition = fileDiscoveryForComposition .sortByRelevance(allFilesForComposition) .slice(0, maxFiles); const fileComposition = analyzeFileComposition( allFilesForComposition, limitedFilesForComposition ); return { success: true, hints: formattedHints, type: 'project-wide', metadata: { filesAnalyzed: hints.totalFiles, foldersFound: Object.keys(hints.folderHints).length, primaryLanguages: hints.primaryLanguages, architecturePatterns: hints.architectureKeywords, topFunctions: hints.symbolHints.functions.slice(0, 10).map((f: any) => f.word), codebaseSize: hints.codebaseSize, enhanced: false, embeddingAssisted: hintsGenerator['shouldUseEmbeddingAssistedHints']?.() || false, fileComposition, }, }; } } catch (error) { logger.error('❌ Project hints generation failed', { error: error instanceof Error ? error.message : String(error), }); return { success: false, error: error instanceof Error ? error.message : String(error), fallback: `Could not analyze project structure for ${projectPath}. Ensure the path exists and contains supported code files.`, }; } }
  • Tool definition including inputSchema with parameters for projectPath, output format, maxFiles to analyze, folderPath, includeContent, useAI, and maxFileSizeForSymbols.
    export const localProjectHintsTool = { name: 'local_project_hints', description: 'πŸ“Š Generate intelligent project navigation hints with word clouds, folder analysis, and architecture detection. Supports multiple output formats including markdown and HTML, with AI-powered analysis and configurable performance options. Accepts absolute paths or relative paths (when workspace can be detected).', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Project directory path. Can be absolute (recommended) or relative to workspace. Examples: "C:\\Dev\\my-project", "/Users/username/project", or "." for current workspace.', }, format: { type: 'string', enum: ['structured', 'compact', 'json', 'markdown', 'html'], default: 'compact', description: 'Output format preference - structured for detailed analysis, compact for quick overview, json for raw data, markdown for documentation, html for visual reports', }, maxFiles: { type: 'number', default: 100, minimum: 10, maximum: 200, description: 'Maximum number of files to analyze for performance', }, folderPath: { type: 'string', description: 'Analyze specific folder instead of entire project (optional)', }, includeContent: { type: 'boolean', default: false, description: 'Include file content analysis for deeper insights (may impact performance)', }, useAI: { type: 'boolean', default: true, description: 'Enable AI-powered folder analysis for better purpose detection (requires OpenAI API key)', }, maxFileSizeForSymbols: { type: 'number', default: 50000, minimum: 10000, maximum: 200000, description: 'Maximum file size in bytes for symbol extraction (performance tuning)', }, }, }, };
  • src/index.ts:126-142 (registration)
    Registers localProjectHintsTool in the MCP server's tools array and maps 'local_project_hints' to handleProjectHints in the handlers object used by setRequestHandler(CallToolRequestSchema).
    this.tools = [ ...(allowLocalContext ? [localSemanticCompactTool] : []), localProjectHintsTool, localFileSummaryTool, frontendInsightsTool, localDebugContextTool, astGrepTool, ]; this.handlers = { ...(allowLocalContext ? { local_context: handleSemanticCompact } : {}), local_project_hints: handleProjectHints, local_file_summary: handleFileSummary, frontend_insights: handleFrontendInsights, local_debug_context: handleLocalDebugContext, ast_grep_search: handleAstGrep, };
  • Aggregates and exports localTools array including localProjectHintsTool and localHandlers map with 'local_project_hints': handleProjectHints, imported into src/index.ts for final MCP registration.
    export const localTools = [ ...(allowLocalContext ? [localSemanticCompactTool] : []), localProjectHintsTool, localFileSummaryTool, frontendInsightsTool, localDebugContextTool, manageEmbeddingsTool, astGrepTool, ]; export const localHandlers = { ...(allowLocalContext ? { local_context: handleSemanticCompact } : {}), local_project_hints: handleProjectHints, local_file_summary: handleFileSummary, frontend_insights: handleFrontendInsights, local_debug_context: handleLocalDebugContext, manage_embeddings: handleManageEmbeddings, ast_grep_search: handleAstGrep, };

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/sbarron/AmbianceMCP'

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