Skip to main content
Glama

scan_project

Analyze a project's structure to identify gaps and opportunities for Doxygen documentation.

Instructions

Analyze project structure and identify documentation opportunities

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_pathYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'scan_project' tool. It analyzes a project directory by recursively counting files grouped by extension, then returns a formatted report of the top 15 file types.
    @mcp.tool()
    async def scan_project(
        project_path: str,
    ) -> str:
        """Analyze project structure and identify documentation opportunities"""
        project_path = Path(project_path)
    
        if not project_path.exists():
            return f"❌ Project path does not exist: {project_path}"
    
        try:
            # Count files by extension
            extensions = {}
            total_files = 0
    
            for file_path in project_path.rglob("*"):
                if file_path.is_file():
                    ext = file_path.suffix.lower()
                    if ext:
                        extensions[ext] = extensions.get(ext, 0) + 1
                        total_files += 1
    
            # Sort by frequency
            sorted_extensions = sorted(extensions.items(), key=lambda x: x[1], reverse=True)
    
            result_text = f"""📁 Project Scan Results for: {project_path}
    📊 Total Files Found: {total_files}
    
    📋 Files by Type:
    """
    
            for ext, count in sorted_extensions[:15]:  # Show top 15 extensions
                result_text += f"  📄 {ext}: {count} files\n"
    
            return result_text
    
        except Exception as e:
            return f"❌ Error scanning project: {str(e)}"
  • Registration of scan_project as an MCP tool via the @mcp.tool() decorator on the FastMCP instance 'mcp'.
    @mcp.tool()
  • The DoxygenConfig model (lines 49-193) is a supporting class used by other tools (e.g., create_doxygen_project) that pair with scan_project to enable full project setup workflows.
    class DoxygenConfig(BaseModel):
        """
        @brief Represents a Doxygen configuration with all major options
        
        This class encapsulates all the major configuration options available in Doxygen,
        providing a structured way to manage documentation generation settings. It supports
        multiple programming languages, output formats, and advanced features like diagram
        generation and source browsing.
        
        @details The configuration is designed to be language-agnostic while providing
        specific optimizations for different programming languages. It can generate
        Doxyfile content that is compatible with Doxygen 1.9.0 and later.
        
        @example
        @code{.py}
        config = DoxygenConfig(
            project_name="My API Documentation",
            output_directory="./docs",
            file_patterns=["*.cpp", "*.h"],
            extract_private=False
        )
        doxyfile_content = config.to_doxyfile()
        @endcode
        """
        
        # Project settings
        project_name: str = "My Project"
        project_number: str = ""
        project_brief: str = ""
        project_logo: str = ""
        output_directory: str = "./docs"
        
        # Input settings
        input_paths: List[str] = ["."]
        file_patterns: List[str] = ["*.c", "*.cpp", "*.h", "*.hpp", "*.py", "*.php"]
        recursive: bool = True
        exclude_patterns: List[str] = []
        
        # Language optimization
        optimize_output_for_c: bool = False
        optimize_output_java: bool = False
        optimize_for_fortran: bool = False
        optimize_output_vhdl: bool = False
        
        # Output formats
        generate_html: bool = True
        generate_latex: bool = False
        generate_rtf: bool = False
        generate_man: bool = False
        generate_xml: bool = False
        generate_docbook: bool = False
        
        # Documentation extraction
        extract_all: bool = True
        extract_private: bool = False
        extract_static: bool = True
        extract_local_classes: bool = True
        
        # Diagram generation
        have_dot: bool = True
        class_graph: bool = True
        collaboration_graph: bool = True
        call_graph: bool = False
        caller_graph: bool = False
        include_graph: bool = True
        included_by_graph: bool = True
        
        # Advanced features
        source_browser: bool = True
        inline_sources: bool = False
        strip_code_comments: bool = True
        referenced_by_relation: bool = True
        references_relation: bool = True
        
        def to_doxyfile(self) -> str:
            """
            @brief Convert configuration to Doxyfile format
            @return String containing complete Doxyfile configuration
            
            @details Generates a complete Doxyfile configuration string that can be
            written to disk and used with the doxygen command-line tool. The output
            includes all configured options with appropriate YES/NO values and
            proper escaping for file paths and patterns.
            
            @note The generated Doxyfile is compatible with Doxygen 1.9.0+
            """
            lines = [
                f"# Doxyfile generated by Doxygen MCP Server",
                f"",
                f"# Project related configuration options",
                f"PROJECT_NAME           = \"{self.project_name}\"",
                f"PROJECT_NUMBER         = \"{self.project_number}\"",
                f"PROJECT_BRIEF          = \"{self.project_brief}\"",
                f"PROJECT_LOGO           = \"{self.project_logo}\"",
                f"OUTPUT_DIRECTORY       = \"{self.output_directory}\"",
                f"",
                f"# Build related configuration options",
                f"EXTRACT_ALL            = {'YES' if self.extract_all else 'NO'}",
                f"EXTRACT_PRIVATE        = {'YES' if self.extract_private else 'NO'}",
                f"EXTRACT_STATIC         = {'YES' if self.extract_static else 'NO'}",
                f"EXTRACT_LOCAL_CLASSES  = {'YES' if self.extract_local_classes else 'NO'}",
                f"",
                f"# Input related configuration options",
                f"INPUT                  = {' '.join(self.input_paths)}",
                f"FILE_PATTERNS          = {' '.join(self.file_patterns)}",
                f"RECURSIVE              = {'YES' if self.recursive else 'NO'}",
            ]
            
            if self.exclude_patterns:
                lines.append(f"EXCLUDE_PATTERNS       = {' '.join(self.exclude_patterns)}")
            
            lines.extend([
                f"",
                f"# Language optimization",
                f"OPTIMIZE_OUTPUT_FOR_C  = {'YES' if self.optimize_output_for_c else 'NO'}",
                f"OPTIMIZE_OUTPUT_JAVA   = {'YES' if self.optimize_output_java else 'NO'}",
                f"OPTIMIZE_FOR_FORTRAN   = {'YES' if self.optimize_for_fortran else 'NO'}",
                f"OPTIMIZE_OUTPUT_VHDL   = {'YES' if self.optimize_output_vhdl else 'NO'}",
                f"",
                f"# Output format configuration",
                f"GENERATE_HTML          = {'YES' if self.generate_html else 'NO'}",
                f"GENERATE_LATEX         = {'YES' if self.generate_latex else 'NO'}",
                f"GENERATE_RTF           = {'YES' if self.generate_rtf else 'NO'}",
                f"GENERATE_MAN           = {'YES' if self.generate_man else 'NO'}",
                f"GENERATE_XML           = {'YES' if self.generate_xml else 'NO'}",
                f"GENERATE_DOCBOOK       = {'YES' if self.generate_docbook else 'NO'}",
                f"",
                f"# Diagram generation",
                f"HAVE_DOT               = {'YES' if self.have_dot else 'NO'}",
                f"CLASS_GRAPH            = {'YES' if self.class_graph else 'NO'}",
                f"COLLABORATION_GRAPH    = {'YES' if self.collaboration_graph else 'NO'}",
                f"CALL_GRAPH             = {'YES' if self.call_graph else 'NO'}",
                f"CALLER_GRAPH           = {'YES' if self.caller_graph else 'NO'}",
                f"INCLUDE_GRAPH          = {'YES' if self.include_graph else 'NO'}",
                f"INCLUDED_BY_GRAPH      = {'YES' if self.included_by_graph else 'NO'}",
                f"",
                f"# Source browsing",
                f"SOURCE_BROWSER         = {'YES' if self.source_browser else 'NO'}",
                f"INLINE_SOURCES         = {'YES' if self.inline_sources else 'NO'}",
                f"STRIP_CODE_COMMENTS    = {'YES' if self.strip_code_comments else 'NO'}",
                f"REFERENCED_BY_RELATION = {'YES' if self.referenced_by_relation else 'NO'}",
                f"REFERENCES_RELATION    = {'YES' if self.references_relation else 'NO'}",
            ])
            
            return "\n".join(lines)
Behavior2/5

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

With no annotations, the description bears full burden. It states purpose but does not disclose whether the tool modifies files, requires specific permissions, or has side effects. The read-only nature is implied but not confirmed, and no details about performance or limits are given.

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?

Single sentence of 8 words is highly concise. However, the extreme brevity sacrifices necessary details, making it less effective than a slightly longer, more informative statement. It earns a 4 for efficiency but loses a point for insufficient content.

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?

Given the existence of an output schema and a single parameter, the description is too sparse. It fails to explain what 'documentation opportunities' means, how the output relates to sibling tools, or how the agent should use the results. The tool's role in a documentation pipeline is unclear.

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

Parameters1/5

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

Schema description coverage is 0% and the description omits any explanation of the single parameter 'project_path'. No value is added beyond the schema's basic type and requirement, leaving the agent without guidance on path format, valid values, or scope.

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

Purpose5/5

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

Description uses specific verb ('analyze') and resource ('project structure'), clearly stating its role to identify documentation opportunities, which distinguishes it from sibling tools that handle doxygen installation, configuration, generation, and validation.

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?

No explicit guidance on when to use this tool versus siblings. It does not mention prerequisites, typical workflow position, or scenarios where other tools are preferred, leaving the agent to infer usage from context.

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/Positronikal/doxygen-mcp'

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