Skip to main content
Glama

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
NameRequiredDescriptionDefault
readme_pathYesPath to the README file to analyze
project_typeNoType of project for tailored analysislibrary
generate_templateNoGenerate README templates and community files
output_directoryNoDirectory to write generated templates and community files
include_community_filesNoGenerate community health files (CONTRIBUTING.md, CODE_OF_CONDUCT.md, etc.)
target_audienceNoTarget audience for recommendationsmixed

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: "[![Build Status](badge-url)](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: "![Demo](demo.gif)",
      });
    
      // 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 };
    }
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions analysis and generation but omits critical details: whether this is a read-only operation, what permissions are needed, how generated files are handled, or any rate limits. The description is insufficient for a tool with 6 parameters and potential file system interactions.

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 a single, efficient sentence that front-loads the core functionality. Every word earns its place with zero wasted text, making it easy to parse quickly.

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

Completeness2/5

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

For a tool with 6 parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain what the analysis output looks like, how recommendations are presented, or the scope of generated templates. Given the complexity and lack of structured data, more behavioral context is needed.

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?

Schema description coverage is 100%, so the schema fully documents all 6 parameters. The description adds minimal value beyond the schema, only implying that 'generate_template' relates to 'templates for improvement'. Baseline 3 is appropriate when the schema does the heavy lifting.

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

Purpose4/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 ('analyze', 'generate') and resources ('README files', 'templates for improvement'). It distinguishes from some siblings like 'analyze_readme' by mentioning best practices analysis and template generation, though not all sibling differentiation is explicit.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'analyze_readme', 'evaluate_readme_health', 'optimize_readme', or 'generate_readme_template'. It lacks context about prerequisites, exclusions, or comparative advantages.

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/tosin2013/documcp'

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