Skip to main content
Glama
gcorroto
by gcorroto

jenkins_get_coverage_report

Retrieve code coverage reports from Jenkins builds to analyze test effectiveness and identify untested code areas for specific applications, packages, or classes.

Instructions

Obtener reporte de cobertura de código de un build

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
appYesNombre de la aplicación
buildNumberYesNúmero del build
packageNameNoNombre del paquete específico
classNameNoNombre de la clase específica
branchNoRama de Git (por defecto: main)

Implementation Reference

  • index.ts:253-303 (registration)
    Registration of the 'jenkins_get_coverage_report' MCP tool, including input schema (Zod), description, and the handler function that delegates to JenkinsService.getCoverageReport and formats the output.
    server.tool(
      "jenkins_get_coverage_report",
      "Obtener reporte de cobertura de código de un build",
      {
        app: z.string().describe("Nombre de la aplicación"),
        buildNumber: z.number().describe("Número del build"),
        packageName: z.string().optional().describe("Nombre del paquete específico"),
        className: z.string().optional().describe("Nombre de la clase específica"),
        branch: z.string().optional().describe("Rama de Git (por defecto: main)")
      },
      async (args) => {
        try {
          const result = await getJenkinsService().getCoverageReport(
            args.app, 
            args.buildNumber, 
            args.packageName, 
            args.className,
            args.branch || 'main'
          );
          
          let coverageText: string;
          
          if ('instructionCoverage' in result) {
             // Es un CoverageReport (backend)
             coverageText = `📊 **Reporte de Cobertura - Build #${args.buildNumber}**\n\n` +
               `**Instrucciones:** ${result.instructionCoverage?.percentage || 0}% (${result.instructionCoverage?.covered || 0}/${result.instructionCoverage?.total || 0})\n` +
               `**Ramas:** ${result.branchCoverage?.percentage || 0}% (${result.branchCoverage?.covered || 0}/${result.branchCoverage?.total || 0})\n` +
               `**Líneas:** ${result.lineCoverage?.percentage || 0}% (${result.lineCoverage?.covered || 0}/${result.lineCoverage?.total || 0})`;
           } else {
             // Es un CoverageSummary (frontend)
             const summary = result as CoverageSummary;
             const stmtPercent = summary.statements > 0 ? ((summary.statements - summary.uncoveredStatements) / summary.statements * 100).toFixed(2) : 0;
             const funcPercent = summary.functions > 0 ? ((summary.functions - summary.uncoveredFunctions) / summary.functions * 100).toFixed(2) : 0;
             const branchPercent = summary.branches > 0 ? ((summary.branches - summary.uncoveredBranches) / summary.branches * 100).toFixed(2) : 0;
             
             coverageText = `📊 **Resumen de Cobertura - Build #${args.buildNumber}**\n\n` +
               `**Declaraciones:** ${stmtPercent}% (${summary.statements - summary.uncoveredStatements}/${summary.statements})\n` +
               `**Funciones:** ${funcPercent}% (${summary.functions - summary.uncoveredFunctions}/${summary.functions})\n` +
               `**Ramas:** ${branchPercent}% (${summary.branches - summary.uncoveredBranches}/${summary.branches})`;
           }
    
          return {
            content: [{ type: "text", text: coverageText }],
          };
        } catch (error: any) {
          return {
            content: [{ type: "text", text: `❌ **Error:** ${error.message}` }],
          };
        }
      }
    );
  • Core implementation of coverage report fetching in JenkinsService: attempts JaCoCo backend first, falls back to frontend coverage report, computes summaries based on parameters.
    async getCoverageReport(app: string, buildNumber: number, packageName?: string, className?: string, branch: string = 'main'): Promise<CoverageReport | CoverageSummary> {
      if (!validateAppName(app)) {
        throw new Error('Invalid app name.');
      }
    
      // Primero intentar con backend (jacoco)
      try {
        const backendUrl = `${buildJobBuildUrl('', app, buildNumber, branch)}/jacoco/jacoco.exec`;
        await this.client.get(backendUrl);
        // Si existe, procesar reporte backend
        return await this.getCoverageReportBackend(app, buildNumber, branch);
      } catch (error: any) {
        // Si falla, intentar con frontend coverage
        try {
          const frontendReport = await this.getCoverageReportFrontend(app, buildNumber, branch);
          
          if (packageName) {
            return this.calculatePackageSummary(frontendReport, packageName, className);
          } else if (className) {
            return this.calculateClassSummary(frontendReport, className);
          } else {
            return this.calculateTotalSummary(frontendReport);
          }
        } catch (frontendError: any) {
          throw handleHttpError(frontendError, `Failed to get coverage report for app: ${app}, build: ${buildNumber}, branch: ${branch}`);
        }
      }
    }
  • Helper function to compute total coverage summary from frontend coverage report data.
    private calculateTotalSummary(report: CoverageReportFront): CoverageSummary {
      const summary: CoverageSummary = {
        statements: 0,
        functions: 0,
        branches: 0,
        uncoveredStatements: 0,
        uncoveredFunctions: 0,
        uncoveredBranches: 0
      };
    
      Object.values(report.files).forEach(file => {
        summary.statements += Object.keys(file.statementMap).length;
        summary.functions += Object.keys(file.fnMap).length;
        summary.branches += Object.keys(file.branchMap).length;
    
        // Calcular no cubiertos
        summary.uncoveredStatements += Object.values(file.s).filter(v => v === 0).length;
        summary.uncoveredFunctions += Object.values(file.f).filter(v => v === 0).length;
        summary.uncoveredBranches += Object.values(file.b).flat().filter(v => v === 0).length;
      });
    
      return summary;
    }
  • TypeScript interfaces for CoverageSummary and CoverageReport used in the tool's input/output handling.
    export interface CoverageSummary {
      statements: number;
      functions: number;
      branches: number;
      uncoveredStatements: number;
      uncoveredFunctions: number;
      uncoveredBranches: number;
    }
  • Helper to fetch and process JaCoCo backend coverage report (currently returns placeholder).
    private async getCoverageReportBackend(app: string, buildNumber: number, branch: string = 'main'): Promise<CoverageReport> {
      const jacocoUrl = `${buildJobBuildUrl('', app, buildNumber, branch)}/jacoco/jacoco.exec`;
      const response = await this.client.get(jacocoUrl, { responseType: 'arraybuffer' });
      
      // Aquí deberías procesar el archivo jacoco.exec
      // Por simplicidad, devolvemos un reporte básico
      return {
        instructionCoverage: { covered: 0, missed: 0, percentage: 0, total: 0 },
        branchCoverage: { covered: 0, missed: 0, percentage: 0, total: 0 },
        lineCoverage: { covered: 0, missed: 0, percentage: 0, total: 0 }
      };
    }
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 states it's a read operation ('obtener'), but doesn't describe what format the coverage report returns, whether it includes summary vs detailed data, if it requires specific permissions, or any rate limits. For a tool with 5 parameters and no output schema, this leaves significant behavioral gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient Spanish sentence that gets straight to the point. It's appropriately sized for a tool with clear parameters in the schema. While it could be more informative, it doesn't waste words or include unnecessary elaboration.

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 5 parameters, no annotations, no output schema, and multiple similar siblings, the description is insufficient. It doesn't explain what type of coverage data is returned, how it differs from other coverage tools, or provide context about the Jenkins coverage reporting system. The agent would struggle to understand when and how to use this tool effectively.

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 all parameters are documented in the schema. The description adds no additional parameter semantics beyond implying this tool retrieves coverage reports for builds. It doesn't explain relationships between parameters (e.g., how packageName and className refine the report) or provide usage examples. Baseline 3 is appropriate when schema does the heavy lifting.

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

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Obtener reporte de cobertura de código de un build' clearly states the action (obtener/get) and resource (reporte de cobertura de código/coverage report), but it's vague about scope and doesn't differentiate from siblings like jenkins_get_coverage_lines or jenkins_get_coverage_paths. It specifies 'de un build' which helps somewhat, but doesn't clarify what type of coverage report this returns versus other coverage-related tools.

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. With multiple coverage-related siblings (jenkins_get_coverage_lines, jenkins_get_coverage_paths), there's no indication of what distinguishes this general 'reporte' from those more specific tools. No prerequisites, exclusions, or comparison context is provided.

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/gcorroto/mcp-jenkins'

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