Skip to main content
Glama
djm81

Log Analyzer MCP

by djm81

create_coverage_report

Generate HTML and XML coverage reports by running analysis scripts to document test execution results and code coverage metrics.

Instructions

Run the coverage report script and generate HTML and XML reports.

Args:
    force_rebuild: Whether to force rebuilding the report even if it exists

Returns:
    Dictionary containing execution results and report paths

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
force_rebuildNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The MCP tool handler function for 'create_coverage_report', registered via @mcp.tool() decorator. It delegates the core logic to the run_coverage_script helper.
    @mcp.tool()
    async def create_coverage_report(force_rebuild: bool = False) -> dict[str, Any]:
        """
        Run the coverage report script and generate HTML and XML reports.
    
        Args:
            force_rebuild: Whether to force rebuilding the report even if it exists
    
        Returns:
            Dictionary containing execution results and report paths
        """
        return await run_coverage_script(force_rebuild)
  • Core helper function implementing the coverage report generation by running 'hatch run hatch-test.py3.12:run-cov' and 'hatch run hatch-test.py3.12:cov-report' commands, handling outputs, errors, and timeouts.
    async def run_coverage_script(force_rebuild: bool = False) -> dict[str, Any]:
        """
        Run the coverage report script and generate HTML and XML reports.
        Now uses hatch scripts for better integration.
        """
        logger.info("Running coverage script...")
        # Correctly reference PROJECT_ROOT from the logger_setup module
        from log_analyzer_mcp.common import logger_setup as common_logger_setup  # Ensure this import is here or global
    
        current_project_root = common_logger_setup.PROJECT_ROOT
        # Define different timeouts for different steps
        timeout_run_cov = 300  # Longer timeout for running tests with coverage
        timeout_cov_report = 120  # Shorter timeout for generating the report
    
        # Command parts for running the coverage script via hatch
        # This assumes 'run-cov' and 'cov-report' are defined in hatch envs.
        # Step 1: Run tests with coverage enabled
        cmd_parts_run_cov = ["hatch", "run", "hatch-test.py3.12:run-cov"]  # Example: Target specific py version
        # Step 2: Generate combined report (HTML and XML)
        cmd_parts_report = ["hatch", "run", "hatch-test.py3.12:cov-report"]  # Example
    
        outputs = []
        errors_encountered = []
    
        steps_with_timeouts = [
            ("run-cov", cmd_parts_run_cov, timeout_run_cov),
            ("cov-report", cmd_parts_report, timeout_cov_report),
        ]
    
        for step_name, cmd_parts, current_timeout_seconds in steps_with_timeouts:
            logger.info(
                "Executing coverage step '%s': %s (timeout: %ss)", step_name, " ".join(cmd_parts), current_timeout_seconds
            )
            try:
                # Use functools.partial for subprocess.run
                configured_subprocess_run_step = functools.partial(
                    subprocess.run,
                    cmd_parts,
                    cwd=current_project_root,
                    capture_output=True,
                    text=True,  # Decode stdout/stderr as text
                    check=False,  # Handle non-zero exit manually
                    timeout=current_timeout_seconds,  # Use current step's timeout
                )
                process = await anyio.to_thread.run_sync(configured_subprocess_run_step)  # type: ignore[attr-defined]
                stdout_output: str = process.stdout
                stderr_output: str = process.stderr
                rc = process.returncode
    
                outputs.append(f"--- {step_name} STDOUT ---\n{stdout_output}")
                if stderr_output:
                    outputs.append(f"--- {step_name} STDERR ---\n{stderr_output}")
    
                if rc != 0:
                    error_msg = f"Coverage step '{step_name}' failed with return code {rc}."
                    logger.error("%s\nSTDERR:\n%s", error_msg, stderr_output)
                    errors_encountered.append(error_msg)
                    # Optionally break if a step fails, or collect all errors
                    # break
    
            except subprocess.TimeoutExpired as e:
                stdout_output = e.stdout.decode("utf-8", errors="replace") if e.stdout else ""
                stderr_output = e.stderr.decode("utf-8", errors="replace") if e.stderr else ""
                error_msg = f"Coverage step '{step_name}' timed out after {current_timeout_seconds} seconds."
                logger.error("%s: %s", error_msg, e)
                errors_encountered.append(error_msg)
                outputs.append(f"--- {step_name} TIMEOUT STDOUT ---\n{stdout_output}")
                outputs.append(f"--- {step_name} TIMEOUT STDERR ---\n{stderr_output}")
                # break
            except Exception as e:  # pylint: disable=broad-exception-caught
                error_msg = f"Error during coverage step '{step_name}': {e}"
                logger.error(error_msg, exc_info=True)
                errors_encountered.append(error_msg)
                # break
    
        # Ensure a dictionary is always returned, even if errors occurred.
        final_success = not errors_encountered
        overall_message = (
            "Coverage script steps completed." if final_success else "Errors encountered during coverage script execution."
        )
        # Placeholder for actual report paths, adapt as needed
        coverage_xml_report_path = os.path.join(logs_base_dir, "tests", "coverage", "coverage.xml")
        coverage_html_index_path = os.path.join(logs_base_dir, "tests", "coverage", "html", "index.html")
    
        return {
            "success": final_success,
            "message": overall_message,
            "details": "\n".join(outputs),
            "errors": errors_encountered,
            "coverage_xml_path": coverage_xml_report_path if final_success else None,  # Example path
            "coverage_html_index": coverage_html_index_path if final_success else None,  # Example path
            "timestamp": datetime.now().isoformat(),
        }
  • Pydantic BaseModel defining the input parameters for the create_coverage_report tool, including the force_rebuild flag.
    class CreateCoverageReportInput(BaseModel):
        """Parameters for creating coverage report."""
    
        force_rebuild: bool = Field(
            default=False, description="Whether to force rebuilding the coverage report even if it already exists"
        )
  • The @mcp.tool() decorator registers the create_coverage_report function as an MCP tool, with the tool name inferred from the function name.
    @mcp.tool()
    async def create_coverage_report(force_rebuild: bool = False) -> dict[str, Any]:
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions generating reports but lacks details on execution behavior, such as whether it runs tests, requires specific permissions, has side effects (e.g., file creation), or handles errors. The description is minimal and doesn't compensate for the absence of annotations, leaving key behavioral traits unclear.

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 highly concise and well-structured, with three sentences that efficiently cover the tool's purpose, parameter, and return value. Each sentence earns its place: the first states the action, the second explains the parameter, and the third describes the output. There is no wasted text, making it easy to parse and understand quickly.

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

Completeness3/5

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

Given the tool's moderate complexity (generating reports with one parameter) and the presence of an output schema (which handles return values), the description is partially complete. It covers the basic purpose and parameter semantics but lacks behavioral details and usage guidelines. Without annotations, it should do more to explain execution behavior and context, but the output schema reduces the need to describe returns, keeping it at a minimal viable level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaningful context for the single parameter 'force_rebuild' by explaining it as 'Whether to force rebuilding the report even if it exists.' This clarifies the parameter's purpose beyond the schema's title ('Force Rebuild') and default value. With 0% schema description coverage and only one parameter, the description effectively compensates by providing essential semantics, though it could include more detail on when to use this option.

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: 'Run the coverage report script and generate HTML and XML reports.' It specifies the verb ('Run'), resource ('coverage report script'), and outputs ('HTML and XML reports'), making it easy to understand what the tool does. However, it doesn't explicitly differentiate from sibling tools like 'analyze_tests' or 'run_tests_*', which might also involve test-related operations.

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. It doesn't mention prerequisites, such as whether tests need to be run first, or compare it to sibling tools like 'analyze_tests' for test analysis. The only implied usage is generating coverage reports, but without context on timing or alternatives, this is insufficient for informed tool selection.

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/djm81/log_analyzer_mcp'

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