Skip to main content
Glama

MCP Prompt Enhancer

by soniankur948
PromptEnhancer.ts22.2 kB
/** * PromptEnhancer * * Intelligently enhances prompts with relevant context: * - Combines original prompt with adaptive context * - Filters context based on task type and focus area * - Formats enhanced prompts for optimal LLM performance */ import ProjectContextManager, { ProjectContext } from '../context/ProjectContextManager'; import TaskTracker, { TaskType, FocusArea, TaskContext } from '../tracker/TaskTracker'; import logger from '../utils/Logger'; export interface PromptEnhancerConfig { maxContextSize: number; includeGitInfo: boolean; includeDependencies: boolean; includePatterns: boolean; contextFormat: 'markdown' | 'json' | 'plain'; autoEvaluateNeed: boolean; } export interface EnhancePromptOptions { prompt: string; taskType?: TaskType; focusFiles?: string[]; includeFullContext?: boolean; } export interface PromptEnhancementResult { enhancedPrompt: string; originalPrompt: string; contextAdded: boolean; taskType: TaskType; focusArea: FocusArea; contextSize: number; } export class PromptEnhancer { private config: PromptEnhancerConfig; private projectContextManager: ProjectContextManager; private taskTracker: TaskTracker; private log = logger.createChildLogger('PromptEnhancer'); constructor( projectContextManager: ProjectContextManager, taskTracker: TaskTracker, config: Partial<PromptEnhancerConfig> = {} ) { this.projectContextManager = projectContextManager; this.taskTracker = taskTracker; this.config = { maxContextSize: config.maxContextSize || 8000, includeGitInfo: config.includeGitInfo !== undefined ? config.includeGitInfo : true, includeDependencies: config.includeDependencies !== undefined ? config.includeDependencies : true, includePatterns: config.includePatterns !== undefined ? config.includePatterns : true, contextFormat: config.contextFormat || 'markdown', autoEvaluateNeed: config.autoEvaluateNeed !== undefined ? config.autoEvaluateNeed : true, }; this.log.info('PromptEnhancer initialized'); } /** * Enhance a prompt with relevant context */ public async enhancePrompt(options: EnhancePromptOptions): Promise<PromptEnhancementResult> { const { prompt, taskType, focusFiles, includeFullContext } = options; this.log.debug('Enhancing prompt'); // Update task tracker with prompt const taskContext = this.taskTracker.updateFromPrompt(prompt); // Override task type if provided if (taskType) { this.taskTracker.setTaskType(taskType); } // Add focus files if provided if (focusFiles && focusFiles.length > 0) { this.taskTracker.addRelevantFiles(focusFiles); } // Get updated task context const updatedTaskContext = this.taskTracker.getTaskContext(); // Evaluate if prompt enhancement is needed when auto-evaluation is enabled if (this.config.autoEvaluateNeed && !this.isEnhancementNeeded(prompt, updatedTaskContext)) { this.log.info('Prompt enhancement not needed, returning original prompt'); // Record the skip action this.taskTracker.recordAction( 'skip_enhancement', updatedTaskContext.relevantFiles, `Skipped enhancement for ${updatedTaskContext.taskType} task - not needed` ); // Return the original prompt without enhancement return { enhancedPrompt: prompt, originalPrompt: prompt, contextAdded: false, taskType: updatedTaskContext.taskType, focusArea: updatedTaskContext.focusArea, contextSize: 0 }; } // Get project context const projectContext = await this.projectContextManager.getContext(); // Generate enhanced prompt const enhancementResult = this.generateEnhancedPrompt( prompt, projectContext, updatedTaskContext, includeFullContext || false ); // Record the enhancement action this.taskTracker.recordAction( 'enhance_prompt', updatedTaskContext.relevantFiles, `Enhanced prompt for ${updatedTaskContext.taskType} task` ); return enhancementResult; } /** * Determine if prompt enhancement is needed */ private isEnhancementNeeded(prompt: string, taskContext: TaskContext): boolean { // Always enhance prompts in these cases const alwaysEnhanceCases = [ // First time analyzing a project or requesting full context taskContext.recentActions.length === 0, // Specific keywords that indicate a need for context prompt.toLowerCase().includes('analyze'), prompt.toLowerCase().includes('understand'), prompt.toLowerCase().includes('review'), prompt.toLowerCase().includes('help me with'), prompt.toLowerCase().includes('show me'), // Tasks likely to need context taskContext.taskType === TaskType.ANALYSIS, taskContext.taskType === TaskType.DEBUGGING, taskContext.taskType === TaskType.REFACTORING ]; // Skip enhancement in these cases const skipEnhanceCases = [ // Simple questions that don't need context prompt.toLowerCase().includes('what is'), prompt.toLowerCase().includes('how do i'), prompt.toLowerCase().includes('can you explain'), // Very short prompts (likely follow-up questions) prompt.length < 50 && taskContext.recentActions.length > 0, // Prompts that explicitly ask to skip context prompt.toLowerCase().includes('no context'), prompt.toLowerCase().includes('without context') ]; // Check if any always-enhance conditions are met if (alwaysEnhanceCases.some(condition => !!condition)) { this.log.debug('Enhancement needed: meets enhancement criteria'); return true; } // Check if any skip-enhancement conditions are met if (skipEnhanceCases.some(condition => !!condition)) { this.log.debug('Enhancement not needed: meets skip criteria'); return false; } // Default to enhancing if no skip conditions were met return true; } /** * Generate enhanced prompt with context */ private generateEnhancedPrompt( originalPrompt: string, projectContext: ProjectContext, taskContext: TaskContext, includeFullContext: boolean ): PromptEnhancementResult { // Start with the context section let contextSection = ''; if (includeFullContext) { // Full project context for initial analysis or when explicitly requested contextSection = this.generateFullContext(projectContext); } else { // Task-specific context for ongoing work contextSection = this.generateTaskSpecificContext(projectContext, taskContext); } // Measure context size (rough approximation of tokens) const contextSize = Math.ceil(contextSection.length / 4); // Format the enhanced prompt let enhancedPrompt = ''; if (contextSection.trim().length > 0) { enhancedPrompt = this.formatEnhancedPrompt(originalPrompt, contextSection); } else { enhancedPrompt = originalPrompt; } return { enhancedPrompt, originalPrompt, contextAdded: contextSection.trim().length > 0, taskType: taskContext.taskType, focusArea: taskContext.focusArea, contextSize, }; } /** * Generate full project context */ private generateFullContext(projectContext: ProjectContext): string { this.log.debug('Generating full project context'); let context = ''; // Project overview context += this.formatSection('Project Overview', [ `Project Name: ${projectContext.projectName}`, `Frameworks: ${projectContext.frameworks.join(', ') || 'None detected'}`, ]); // Dependencies (if enabled) if (this.config.includeDependencies && Object.keys(projectContext.dependencies).length > 0) { const dependencyList = Object.entries(projectContext.dependencies) .map(([name, version]) => `${name}: ${version}`) .join('\n'); context += this.formatSection('Dependencies', [dependencyList]); } // File structure context += this.formatSection('File Structure', [ this.formatFileStructure(projectContext.fileStructure) ]); // Git information (if enabled) if (this.config.includeGitInfo && projectContext.recentChanges.length > 0) { const gitChanges = projectContext.recentChanges .map(change => `- ${change.message} (by ${change.author} on ${change.date.split('T')[0]})`) .join('\n'); context += this.formatSection('Recent Changes', [gitChanges]); const branchInfo = [ `Current Branch: ${projectContext.branchInfo.currentBranch}`, `All Branches: ${projectContext.branchInfo.branches.join(', ')}` ].join('\n'); context += this.formatSection('Branch Information', [branchInfo]); } // Code patterns (if enabled) if (this.config.includePatterns && projectContext.patterns.length > 0) { const patternSections = projectContext.patterns.map(pattern => { return `${pattern.type.toUpperCase()} PATTERN: ${pattern.pattern}\n\nExamples:\n${pattern.examples.map(ex => '```\n' + ex + '\n```').join('\n\n')}`; }).join('\n\n'); context += this.formatSection('Code Patterns', [patternSections]); } return context; } /** * Generate task-specific context */ private generateTaskSpecificContext( projectContext: ProjectContext, taskContext: TaskContext ): string { this.log.debug(`Generating task-specific context for ${taskContext.taskType} task in ${taskContext.focusArea} area`); let context = ''; // Task overview context += this.formatSection('Task Context', [ `Task Type: ${taskContext.taskType}`, `Focus Area: ${taskContext.focusArea}`, ]); // Include frameworks and project type info for all tasks context += this.formatSection('Project Type', [ `Frameworks: ${projectContext.frameworks.join(', ') || 'None detected'}`, ]); // Add task-specific context based on task type switch (taskContext.taskType) { case TaskType.CREATION: context += this.generateCreationTaskContext(projectContext, taskContext); break; case TaskType.DEBUGGING: context += this.generateDebuggingTaskContext(projectContext, taskContext); break; case TaskType.REFACTORING: context += this.generateRefactoringTaskContext(projectContext, taskContext); break; case TaskType.STYLING: context += this.generateStylingTaskContext(projectContext, taskContext); break; case TaskType.API: context += this.generateApiTaskContext(projectContext, taskContext); break; default: // For general tasks or other types, include minimal context context += this.generateGeneralTaskContext(projectContext, taskContext); break; } // Add relevant files info if (taskContext.relevantFiles.length > 0) { context += this.formatSection('Relevant Files', [ taskContext.relevantFiles.join('\n') ]); } // Add recent actions if available if (taskContext.recentActions.length > 0) { const recentActionsText = taskContext.recentActions .map(action => { const filesText = action.files && action.files.length > 0 ? ` (files: ${action.files.join(', ')})` : ''; return `- ${action.description}${filesText}`; }) .join('\n'); context += this.formatSection('Recent Actions', [recentActionsText]); } return context; } /** * Generate context for creation tasks */ private generateCreationTaskContext( projectContext: ProjectContext, taskContext: TaskContext ): string { let context = ''; // For creation tasks, include: // 1. Dependencies (for setup) if (this.config.includeDependencies) { const relevantDeps = this.filterRelevantDependencies(projectContext, taskContext.focusArea); if (Object.keys(relevantDeps).length > 0) { const depsText = Object.entries(relevantDeps) .map(([name, version]) => `${name}: ${version}`) .join('\n'); context += this.formatSection('Relevant Dependencies', [depsText]); } } // 2. Code patterns for the focus area if (this.config.includePatterns) { const relevantPatterns = this.filterRelevantPatterns(projectContext, taskContext.focusArea); if (relevantPatterns.length > 0) { const patternsText = relevantPatterns.map(pattern => { return `${pattern.type.toUpperCase()} PATTERN: ${pattern.pattern}\n\nExample:\n\`\`\`\n${pattern.examples[0] || ''}\n\`\`\``; }).join('\n\n'); context += this.formatSection('Relevant Patterns', [patternsText]); } } return context; } /** * Generate context for debugging tasks */ private generateDebuggingTaskContext( projectContext: ProjectContext, taskContext: TaskContext ): string { let context = ''; // For debugging tasks, include: // 1. Recent changes that might be related to the bug if (this.config.includeGitInfo && projectContext.recentChanges.length > 0) { const recentChangesText = projectContext.recentChanges .slice(0, 5) // Focus on the most recent changes .map(change => `- ${change.message} (${change.date.split('T')[0]})`) .join('\n'); context += this.formatSection('Recent Changes', [recentChangesText]); } return context; } /** * Generate context for refactoring tasks */ private generateRefactoringTaskContext( projectContext: ProjectContext, taskContext: TaskContext ): string { let context = ''; // For refactoring tasks, include: // 1. Code patterns that might be relevant if (this.config.includePatterns) { const relevantPatterns = this.filterRelevantPatterns(projectContext, taskContext.focusArea); if (relevantPatterns.length > 0) { const patternsText = relevantPatterns.map(pattern => { return `${pattern.type.toUpperCase()}: ${pattern.pattern}\n\nExample:\n\`\`\`\n${pattern.examples[0] || ''}\n\`\`\``; }).join('\n\n'); context += this.formatSection('Code Patterns', [patternsText]); } } return context; } /** * Generate context for styling tasks */ private generateStylingTaskContext( projectContext: ProjectContext, taskContext: TaskContext ): string { let context = ''; // For styling tasks, include: // 1. Check for styling-related dependencies if (this.config.includeDependencies) { const stylingDeps = this.filterStylingDependencies(projectContext); if (Object.keys(stylingDeps).length > 0) { const depsText = Object.entries(stylingDeps) .map(([name, version]) => `${name}: ${version}`) .join('\n'); context += this.formatSection('Styling Dependencies', [depsText]); } } return context; } /** * Generate context for API tasks */ private generateApiTaskContext( projectContext: ProjectContext, taskContext: TaskContext ): string { let context = ''; // For API tasks, include: // 1. API-related patterns if (this.config.includePatterns) { const apiPatterns = projectContext.patterns.filter(pattern => pattern.type === 'route' || pattern.pattern.toLowerCase().includes('api') ); if (apiPatterns.length > 0) { const patternsText = apiPatterns.map(pattern => { return `${pattern.type.toUpperCase()}: ${pattern.pattern}\n\nExample:\n\`\`\`\n${pattern.examples[0] || ''}\n\`\`\``; }).join('\n\n'); context += this.formatSection('API Patterns', [patternsText]); } } return context; } /** * Generate context for general tasks */ private generateGeneralTaskContext( projectContext: ProjectContext, taskContext: TaskContext ): string { // For general tasks, minimal context is already provided by the main method return ''; } /** * Filter dependencies relevant to the focus area */ private filterRelevantDependencies( projectContext: ProjectContext, focusArea: FocusArea ): Record<string, string> { const deps = { ...projectContext.dependencies }; const filtered: Record<string, string> = {}; // Keywords for different focus areas const keywords: Record<FocusArea, string[]> = { [FocusArea.FRONTEND]: ['react', 'vue', 'angular', 'svelte', 'component', 'ui', 'dom'], [FocusArea.BACKEND]: ['express', 'koa', 'nest', 'node', 'server', 'api'], [FocusArea.DATABASE]: ['mongo', 'postgres', 'mysql', 'sqlite', 'prisma', 'sequelize', 'typeorm'], [FocusArea.STYLING]: ['css', 'sass', 'less', 'tailwind', 'styled', 'emotion', 'bootstrap'], [FocusArea.TESTING]: ['jest', 'mocha', 'chai', 'cypress', 'testing', 'test'], [FocusArea.STATE]: ['redux', 'mobx', 'zustand', 'recoil', 'context', 'state'], [FocusArea.DEPLOYMENT]: ['docker', 'kubernetes', 'aws', 'azure', 'vercel', 'netlify'], [FocusArea.GENERAL]: [], [FocusArea.AUTHENTICATION]: ['auth', 'login', 'register', 'user', 'permission', 'role', 'jwt', 'session'], [FocusArea.COMPONENTS]: ['component', 'button', 'form', 'input', 'modal', 'menu', 'navigation'], [FocusArea.ROUTING]: ['route', 'router', 'navigation', 'link', 'path', 'url', 'history', 'params'], }; // If focus area is general, return a subset of important dependencies if (focusArea === FocusArea.GENERAL) { const importantDeps = Object.keys(deps).filter(dep => !dep.startsWith('@types/') && !dep.includes('eslint') && !dep.includes('prettier') ).slice(0, 10); for (const dep of importantDeps) { filtered[dep] = deps[dep]; } return filtered; } // Otherwise, filter by focus area keywords const areaKeywords = keywords[focusArea] || []; for (const [dep, version] of Object.entries(deps)) { if (areaKeywords.some(keyword => dep.toLowerCase().includes(keyword))) { filtered[dep] = version; } } return filtered; } /** * Filter styling-related dependencies */ private filterStylingDependencies(projectContext: ProjectContext): Record<string, string> { const deps = { ...projectContext.dependencies }; const filtered: Record<string, string> = {}; const stylingKeywords = [ 'css', 'sass', 'scss', 'less', 'style', 'styled', 'tailwind', 'bootstrap', 'emotion', 'jss', 'material-ui', 'chakra', 'theme' ]; for (const [dep, version] of Object.entries(deps)) { if (stylingKeywords.some(keyword => dep.toLowerCase().includes(keyword))) { filtered[dep] = version; } } return filtered; } /** * Filter patterns relevant to the focus area */ private filterRelevantPatterns( projectContext: ProjectContext, focusArea: FocusArea ) { // Map focus areas to pattern types const focusToPatternType: Partial<Record<FocusArea, string[]>> = { [FocusArea.FRONTEND]: ['component', 'jsx', 'tsx', 'react', 'vue'], [FocusArea.BACKEND]: ['route', 'controller', 'service', 'middleware'], [FocusArea.DATABASE]: ['model', 'schema', 'query', 'database'], // Remove FocusArea.API which doesn't exist }; const relevantTypes = focusToPatternType[focusArea] || []; if (relevantTypes.length === 0) { // If no specific mapping, return the first 2 patterns (if available) return projectContext.patterns.slice(0, 2); } // Filter patterns by relevance to the focus area return projectContext.patterns.filter(pattern => relevantTypes.some(type => pattern.type.includes(type) || pattern.pattern.toLowerCase().includes(type) ) ).slice(0, 3); } /** * Format file structure into a readable string */ private formatFileStructure(structure: any, prefix = '', depth = 0, maxDepth = 3): string { if (depth > maxDepth) { return `${prefix}...`; // Truncate at max depth } let result = ''; // Add directories for (const [dirName, dirContent] of Object.entries(structure.directories)) { result += `${prefix}${dirName}/\n`; result += this.formatFileStructure( dirContent, `${prefix} `, depth + 1, maxDepth ); } // Add files for (const file of structure.files) { result += `${prefix}${file}\n`; } return result; } /** * Format a section of the context */ private formatSection(title: string, content: string[]): string { if (content.every(item => item.trim() === '')) { return ''; } switch (this.config.contextFormat) { case 'markdown': return `## ${title}\n\n${content.join('\n\n')}\n\n`; case 'json': return `"${title}": ${JSON.stringify(content)},\n`; case 'plain': default: return `${title.toUpperCase()}:\n${content.join('\n')}\n\n`; } } /** * Format the final enhanced prompt */ private formatEnhancedPrompt(originalPrompt: string, contextSection: string): string { switch (this.config.contextFormat) { case 'markdown': return `# Context Information\n\n${contextSection}\n# Original Prompt\n\n${originalPrompt}`; case 'json': return `{\n"context": {\n${contextSection}},\n"prompt": "${originalPrompt.replace(/"/g, '\\"')}"\n}`; case 'plain': default: return `CONTEXT INFORMATION:\n\n${contextSection}\nORIGINAL PROMPT:\n\n${originalPrompt}`; } } } export default PromptEnhancer;

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/soniankur948/prompt-enhancer'

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