readme_best_practices
Analyze README files against best practices and generate improvement templates to enhance project documentation quality.
Instructions
Analyze README files against best practices checklist and generate templates for improvement
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| readme_path | Yes | Path to the README file to analyze | |
| project_type | No | Type of project for tailored analysis | library |
| generate_template | No | Generate README templates and community files | |
| output_directory | No | Directory to write generated templates and community files | |
| include_community_files | No | Generate community health files (CONTRIBUTING.md, CODE_OF_CONDUCT.md, etc.) | |
| target_audience | No | Target audience for recommendations | mixed |
Implementation Reference
- Main handler function that validates input, reads README, generates checklist, calculates score, provides recommendations, and optionally generates templates and community files.export async function readmeBestPractices( input: Partial<ReadmeBestPracticesInput>, ): Promise< MCPToolResponse<{ bestPracticesReport: BestPracticesReport; recommendations: string[]; nextSteps: string[]; }> > { const startTime = Date.now(); try { // Validate input with defaults const validatedInput = ReadmeBestPracticesInputSchema.parse(input); const { readme_path, project_type, generate_template, output_directory, include_community_files, target_audience, } = validatedInput; // Read README content let readmeContent = ""; try { readmeContent = await readFile(readme_path, "utf-8"); } catch (error) { if (!generate_template) { return { success: false, error: { code: "README_NOT_FOUND", message: "README file not found. Use generate_template: true to create a new README.", details: error instanceof Error ? error.message : "Unknown error", resolution: "Set generate_template: true to create a new README from template", }, metadata: { toolVersion: "1.0.0", executionTime: Date.now() - startTime, timestamp: new Date().toISOString(), }, }; } } // Generate checklist based on project type and content const checklist = generateChecklist( readmeContent, project_type, target_audience, ); // Calculate overall score const { score, grade } = calculateOverallScore(checklist); // Generate recommendations const recommendations = generateRecommendations( checklist, project_type, target_audience, ); // Generate templates if requested const templates = generate_template ? generateTemplates(project_type, generate_template) : {}; // Generate community files if requested const communityFiles = include_community_files ? generateCommunityFiles(project_type) : {}; // Calculate summary metrics const summary = calculateSummaryMetrics(checklist); // Write files if output directory specified if (output_directory && generate_template) { await writeGeneratedFiles( templates, communityFiles, output_directory, readme_path, ); } const report: BestPracticesReport = { overallScore: score, grade, checklist, recommendations, templates, communityFiles, summary, }; const nextSteps = generateNextSteps( report.checklist, true, output_directory, ); return { success: true, data: { bestPracticesReport: report, recommendations, nextSteps, }, metadata: { toolVersion: "1.0.0", executionTime: Date.now() - startTime, timestamp: new Date().toISOString(), analysisId: `readme-best-practices-${Date.now()}`, }, }; } catch (error) { return { success: false, error: { code: "ANALYSIS_FAILED", message: "Failed to analyze README best practices", details: error instanceof Error ? error.message : "Unknown error", resolution: "Check README file path and permissions, ensure valid project type", }, metadata: { toolVersion: "1.0.0", executionTime: Date.now() - startTime, timestamp: new Date().toISOString(), }, }; } }
- Zod schema for input validation, defining parameters such as readme_path, project_type, generate_template, output_directory, include_community_files, and target_audience with descriptions and defaults.const ReadmeBestPracticesInputSchema = z.object({ readme_path: z.string().describe("Path to the README file to analyze"), project_type: z .enum(["library", "application", "tool", "documentation", "framework"]) .optional() .default("library") .describe("Type of project for tailored analysis"), generate_template: z .boolean() .optional() .default(false) .describe("Generate README templates and community files"), output_directory: z .string() .optional() .describe("Directory to write generated templates and community files"), include_community_files: z .boolean() .optional() .default(true) .describe( "Generate community health files (CONTRIBUTING.md, CODE_OF_CONDUCT.md, etc.)", ), target_audience: z .enum(["beginner", "intermediate", "advanced", "mixed"]) .optional() .default("mixed") .describe("Target audience for recommendations"), });
- Core helper function that analyzes README content against best practices checklist items, categorized by severity (critical, important, recommended), with project-type specific checks.function generateChecklist( content: string, projectType: string, _targetAudience: string, ): ChecklistItem[] { const checklist: ChecklistItem[] = []; const lines = content.split("\n"); const lowerContent = content.toLowerCase(); // Essential Sections checklist.push({ category: "Essential Sections", item: "Project Title", present: /^#\s+.+/m.test(content), severity: "critical", description: "Clear, descriptive project title as main heading", example: "# My Awesome Project", }); checklist.push({ category: "Essential Sections", item: "One-line Description", present: />\s*.+/.test(content) || lines.some( (line) => line.trim().length > 20 && line.trim().length < 100 && !line.startsWith("#"), ), severity: "critical", description: "Brief one-line description of what the project does", example: "> A fast, lightweight JavaScript framework for building web applications", }); checklist.push({ category: "Essential Sections", item: "Installation Instructions", present: /install/i.test(lowerContent) && /npm|yarn|pip|cargo|go get|git clone/i.test(lowerContent), severity: "critical", description: "Clear installation or setup instructions", example: "```bash\nnpm install package-name\n```", }); checklist.push({ category: "Essential Sections", item: "Basic Usage Example", present: /usage|example|quick start|getting started/i.test(lowerContent) && /```/.test(content), severity: "critical", description: "Working code example showing basic usage", example: '```javascript\nconst lib = require("package-name");\nlib.doSomething();\n```', }); // Important Sections checklist.push({ category: "Important Sections", item: "Prerequisites/Requirements", present: /prerequisite|requirement|dependencies|node|python|java|version/i.test( lowerContent, ), severity: "important", description: "Clear system requirements and dependencies", example: "- Node.js 16+\n- Docker (optional)", }); checklist.push({ category: "Important Sections", item: "License Information", present: /license/i.test(lowerContent) || /mit|apache|gpl|bsd/i.test(lowerContent), severity: "important", description: "Clear license information", example: "## License\n\nMIT License - see [LICENSE](LICENSE) file", }); checklist.push({ category: "Important Sections", item: "Contributing Guidelines", present: /contribut/i.test(lowerContent), severity: "important", description: "Information on how to contribute to the project", example: "See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines", }); // Community Health checklist.push({ category: "Community Health", item: "Code of Conduct", present: /code of conduct/i.test(lowerContent), severity: "recommended", description: "Link to code of conduct for community projects", example: "Please read our [Code of Conduct](CODE_OF_CONDUCT.md)", }); checklist.push({ category: "Community Health", item: "Issue Templates", present: /issue template|bug report|feature request/i.test(lowerContent), severity: "recommended", description: "Reference to issue templates for better bug reports", example: "Use our [issue templates](.github/ISSUE_TEMPLATE/) when reporting bugs", }); // Visual Elements checklist.push({ category: "Visual Elements", item: "Badges", present: /\[!\[.*\]\(.*\)\]\(.*\)/.test(content) || /badge/i.test(lowerContent), severity: "recommended", description: "Status badges for build, version, license, etc.", example: "[](link-url)", }); checklist.push({ category: "Visual Elements", item: "Screenshots/Demo", present: /!\[.*\]\(.*\.(png|jpg|jpeg|gif|webp)\)/i.test(content) || /screenshot|demo|gif/i.test(lowerContent), severity: projectType === "application" || projectType === "tool" ? "important" : "recommended", description: "Visual demonstration of the project (especially for applications)", example: "", }); // Content Quality checklist.push({ category: "Content Quality", item: "Appropriate Length", present: lines.length >= 20 && lines.length <= 300, severity: "important", description: "README length appropriate for project complexity (20-300 lines)", example: "Keep main README focused, link to detailed docs", }); checklist.push({ category: "Content Quality", item: "Clear Section Headers", present: (content.match(/^##\s+/gm) || []).length >= 3, severity: "important", description: "Well-organized content with clear section headers", example: "## Installation\n## Usage\n## Contributing", }); checklist.push({ category: "Content Quality", item: "Working Links", present: !/\[.*\]\(\)/.test(content) && !/\[.*\]\(#\)/.test(content), severity: "important", description: "All links should be functional (no empty or placeholder links)", example: "[Documentation](https://example.com/docs)", }); // Project-specific checks if (projectType === "library" || projectType === "framework") { checklist.push({ category: "Library Specific", item: "API Documentation", present: /api|methods|functions|reference/i.test(lowerContent), severity: "important", description: "API documentation or link to detailed API reference", example: "See [API Documentation](docs/api.md) for detailed method reference", }); } if (projectType === "application" || projectType === "tool") { checklist.push({ category: "Application Specific", item: "Configuration Options", present: /config|settings|options|environment/i.test(lowerContent), severity: "important", description: "Configuration and customization options", example: "See [Configuration Guide](docs/configuration.md)", }); } return checklist; }
- Calculates overall score and letter grade from the checklist using weighted severity scoring.function calculateOverallScore(checklist: ChecklistItem[]): { score: number; grade: string; } { const weights = { critical: 3, important: 2, recommended: 1 }; let totalScore = 0; let maxScore = 0; checklist.forEach((item) => { const weight = weights[item.severity]; maxScore += weight; if (item.present) { totalScore += weight; } }); const percentage = maxScore > 0 ? Math.round((totalScore / maxScore) * 100) : 0; let grade: string; if (percentage >= 90) grade = "A"; else if (percentage >= 80) grade = "B"; else if (percentage >= 70) grade = "C"; else if (percentage >= 60) grade = "D"; else grade = "F"; return { score: percentage, grade }; }