promptrix-mcp
Version:
MCP Server for Promptrix - AI prompt enhancement and optimization for Claude Code
160 lines • 7.83 kB
JavaScript
/**
* Prompt Quality Analyzer
*
* Analyzes prompt quality and provides improvement suggestions.
*/
/**
* Quality Analyzer class for consistent prompt analysis
*/
export class QualityAnalyzer {
analyzePromptQuality(prompt) {
const issues = {
tooShort: false,
lacksSpecificity: false,
missingContext: false,
poorStructure: false,
ambiguousLanguage: false
};
const suggestions = [];
let score = 80; // Start with lower base score for stricter evaluation
// Check length - stricter penalties
if (prompt.length < 15) {
issues.tooShort = true;
suggestions.push("Your prompt is too brief. Add more specific details");
score -= 35;
}
else if (prompt.length < 30) {
issues.tooShort = true;
suggestions.push("Consider adding more details and context");
score -= 25;
}
else if (prompt.length < 50) {
suggestions.push("Adding more context could improve results");
score -= 15;
}
// Enhanced specificity checks - more comprehensive vague word detection
const vagueWords = /\b(some|any|stuff|things|something|anything|good|bad|nice|cool|awesome|great|fine|ok|okay)\b/gi;
const informalWords = /\b(func|app|thingy|gonna|wanna|kinda|sorta)\b/gi;
const casualWords = /\b(hey|hi|hello|yo|sup)\b/gi;
const vagueMatches = prompt.match(vagueWords) || [];
const informalMatches = prompt.match(informalWords) || [];
const casualMatches = prompt.match(casualWords) || [];
if (vagueMatches.length > 0 || informalMatches.length > 0) {
issues.lacksSpecificity = true;
suggestions.push("Replace vague or informal terms with specific technical language");
score -= 20 + (vagueMatches.length + informalMatches.length) * 5;
}
if (casualMatches.length > 0) {
suggestions.push("Use professional language instead of casual greetings");
score -= 10;
}
// Grammar and punctuation checks
const hasProperCapitalization = /^[A-Z]/.test(prompt.trim());
const hasEndingPunctuation = /[.!?]$/.test(prompt.trim());
const hasMissingArticles = /\b(create|write|make|build)\s+(?!a|an|the)\b[a-z]/gi.test(prompt);
if (!hasProperCapitalization) {
suggestions.push("Start your prompt with a capital letter");
score -= 10;
}
if (!hasEndingPunctuation && prompt.length > 20) {
suggestions.push("End your prompt with proper punctuation");
score -= 8;
}
if (hasMissingArticles) {
suggestions.push("Include proper articles (a, an, the) for better clarity");
score -= 12;
}
// Enhanced context detection
const hasContext = /\b(for|in|with|about|regarding|concerning|related to|context|background|purpose|goal|use case|requirement|specification)\b/i.test(prompt);
const hasExamples = /\b(example|sample|instance|demo|illustration)\b/i.test(prompt);
const hasConstraints = /\b(must|should|need|require|constraint|limit|restriction)\b/i.test(prompt);
if (!hasContext && prompt.length > 25) {
issues.missingContext = true;
suggestions.push("Add context about your specific use case or goal");
score -= 20;
}
// Structure analysis - more stringent
const hasStructure = prompt.includes('\n') || prompt.includes(':') || prompt.includes('-') || prompt.includes('1.') || prompt.includes('•') || prompt.includes(',');
const sentences = prompt.split(/[.!?]+/).filter(s => s.trim().length > 0);
const isLongButUnstructured = prompt.length > 80 && !hasStructure && sentences.length < 2;
if (isLongButUnstructured) {
issues.poorStructure = true;
suggestions.push("Break down complex requests into structured points or sentences");
score -= 18;
}
// Ambiguous language detection - expanded
const ambiguousWords = /\b(maybe|perhaps|might|could|should|probably|possibly|sometimes|usually|often|generally)\b/gi;
const weakWords = /\b(just|simply|basically|kind of|sort of|pretty much)\b/gi;
const ambiguousMatches = prompt.match(ambiguousWords) || [];
const weakMatches = prompt.match(weakWords) || [];
if (ambiguousMatches.length > 0 || weakMatches.length > 0) {
issues.ambiguousLanguage = true;
suggestions.push("Use definitive language instead of uncertain or weak terms");
score -= 12 + (ambiguousMatches.length + weakMatches.length) * 3;
}
// Action word analysis - commands vs questions
const hasQuestionMarks = (prompt.match(/\?/g) || []).length;
const hasCommands = /\b(create|make|write|build|generate|develop|design|implement|explain|describe|analyze|show|demonstrate|provide|give)\b/i.test(prompt);
if (hasQuestionMarks > 1 && !hasCommands) {
suggestions.push("Use clear commands instead of multiple questions");
score -= 8;
}
if (!hasCommands && !hasQuestionMarks) {
suggestions.push("Include clear action words to specify what you want");
score -= 15;
}
// Positive indicators - refined scoring
let bonusPoints = 0;
if (hasExamples)
bonusPoints += 8;
if (hasConstraints)
bonusPoints += 6;
if (hasContext)
bonusPoints += 10;
if (/\b(specific|detailed|comprehensive|step-by-step|requirements?)\b/i.test(prompt))
bonusPoints += 8;
if (hasProperCapitalization && hasEndingPunctuation)
bonusPoints += 5;
if (prompt.includes('please') || prompt.includes('thank you'))
bonusPoints += 3;
score += bonusPoints;
// Technical depth bonus
const technicalTerms = /\b(function|class|method|API|database|algorithm|framework|library|module|component)\b/gi;
const techMatches = prompt.match(technicalTerms) || [];
if (techMatches.length > 0) {
score += Math.min(10, techMatches.length * 3);
}
// Ensure score bounds
score = Math.max(0, Math.min(100, score));
// Calculate confidence - adjusted for stricter analysis
let confidence = 0.85;
if (prompt.length < 25)
confidence = 0.95; // Very confident about short prompts
if (prompt.length > 200)
confidence = 0.75; // Less confident about very long prompts
if (suggestions.length > 4)
confidence = 0.8; // Less confident with many issues
return {
overall: Math.round(score),
issues,
suggestions: suggestions.length > 0 ? suggestions : ['Your prompt looks good!'],
confidence: Math.round(confidence * 100) / 100
};
}
formatIssues(issues) {
const issueDescriptions = {
tooShort: '❌ Prompt is too brief',
lacksSpecificity: '❌ Contains vague or unclear terms',
missingContext: '❌ Missing context or background information',
poorStructure: '❌ Lacks clear structure for complex request',
ambiguousLanguage: '❌ Uses uncertain or ambiguous language'
};
const detectedIssues = Object.entries(issues)
.filter(([_, hasIssue]) => hasIssue)
.map(([issue, _]) => issueDescriptions[issue]);
return detectedIssues.length > 0
? detectedIssues.join('\n')
: '✅ No significant issues detected';
}
}
//# sourceMappingURL=quality-analyzer.js.map