Skip to main content
Glama
saiprashanths

Code Analysis MCP Server

get_repo_structure

Analyze repository file and directory structure to understand codebase organization. Specify subdirectory paths and traversal depth for targeted exploration.

Instructions

Get the structure of files and directories in the repository.

Args:
    sub_path: Optional subdirectory path relative to repository root
    depth: Optional maximum depth to traverse (default is 3)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sub_pathNo
depthNo

Implementation Reference

  • Decorator that registers the get_repo_structure as an MCP tool.
    @mcp.tool()
  • The main asynchronous handler function implementing the tool logic. It checks if the repository is initialized, determines the target path, calls the analyzer's get_structure method, formats the result, and handles errors.
    async def get_repo_structure(sub_path: Optional[str] = None, depth: Optional[int] = None) -> str:
        """Get the structure of files and directories in the repository.
        
        Args:
            sub_path: Optional subdirectory path relative to repository root
            depth: Optional maximum depth to traverse (default is 3)
        """
        if not mcp.repo_path or not mcp.analyzer:
            return "No code repository has been initialized yet. Please use initialize_repository first."
    
        try:
            target_path = mcp.repo_path
            if sub_path:
                target_path = mcp.repo_path / sub_path
                if not mcp.analyzer._is_safe_path(target_path):
                    return "Error: Invalid path - directory traversal not allowed"
    
            structure = mcp.analyzer.get_structure(
                target_path,
                sub_path or '',
                max_depth=depth
            )
            return mcp.analyzer.format_structure(structure)
        except Exception as e:
            return f"Error analyzing repository structure: {str(e)}"
  • Helper method in RepoStructureAnalyzer that formats the FileStructure object into a human-readable tree string with sizes and summaries.
    def format_structure(self, structure: FileStructure) -> str:
        """Format the file structure into a readable string."""
        output = []
    
        def format_size(size: int) -> str:
            units = ['B', 'KB', 'MB', 'GB']
            value = float(size)
            index = 0
            while value >= 1024 and index < len(units) - 1:
                value /= 1024
                index += 1
            return f"{value:.1f} {units[index]}"
    
        def format_item(item: FileStructure, level: int = 0) -> None:
            indent = '  ' * level
            
            if item.type == 'directory':
                output.append(f"{indent}📁 {item.path}/")
                
                if item.summary:
                    summary = item.summary
                    output.append(
                        f"{indent}   Contains: {summary.file_count} files, "
                        f"{summary.dir_count} directories, "
                        f"{format_size(summary.total_size)}"
                    )
                elif item.children:
                    for child in item.children:
                        format_item(child, level + 1)
            else:
                output.append(f"{indent}📄 {item.path} ({format_size(item.size or 0)})")
    
        format_item(structure)
        return '\n'.join(output)
  • Core recursive helper method in RepoStructureAnalyzer that builds the FileStructure tree, respecting depth limits, ignore patterns, and safety checks.
    def get_structure(
        self,
        current_path: Path,
        relative_path: str = '',
        current_depth: int = 0,
        max_depth: Optional[int] = None
    ) -> FileStructure:
        """Recursively get the structure of files and directories."""
        if max_depth is None:
            max_depth = self.MAX_DEPTH
    
        # Verify path safety
        if not self._is_safe_path(current_path):
            raise ValueError(f"Invalid path: {current_path}")
    
        # Skip symbolic links
        if current_path.is_symlink():
            raise ValueError(f"Symbolic links are not supported: {current_path}")
    
        stats = current_path.stat()
        rel_path = relative_path or current_path.name
    
        if relative_path and self.should_ignore(relative_path):
            raise ValueError(f"Path {relative_path} is ignored")
    
        if current_path.is_file():
            return FileStructure(
                path=rel_path,
                type="file",
                size=stats.st_size
            )
    
        if current_path.is_dir():
            children = []
            summary = Summary()
    
            if current_depth < max_depth:
                try:
                    entries = list(current_path.iterdir())
                    
                    for entry in entries:
                        if len(children) >= self.MAX_CHILDREN:
                            if entry.is_file() and not entry.is_symlink():
                                summary.file_count += 1
                                summary.total_size += entry.stat().st_size
                            elif entry.is_dir() and not entry.is_symlink():
                                summary.dir_count += 1
                            continue
    
                        entry_relative_path = str(entry.relative_to(self.repo_path))
    
                        try:
                            if self.should_ignore(entry_relative_path):
                                continue
    
                            if entry.is_symlink():
                                continue
    
                            entry_stats = entry.stat()
                            
                            if entry.is_file():
                                summary.file_count += 1
                                summary.total_size += entry_stats.st_size
                            elif entry.is_dir():
                                summary.dir_count += 1
    
                            child = self.get_structure(
                                entry,
                                entry_relative_path,
                                current_depth + 1,
                                max_depth
                            )
                            children.append(child)
    
                        except Exception as error:
                            print(f"Error processing {entry}: {error}")
                            continue
    
                except Exception as error:
                    print(f"Error reading directory {current_path}: {error}")
    
            return FileStructure(
                path=rel_path,
                type="directory",
                children=children if children else None,
                summary=summary if current_depth >= max_depth or len(children) >= self.MAX_CHILDREN else None
            )
    
        raise ValueError(f"Unsupported file type at {current_path}")
  • Docstring defining the input parameters and purpose, used by MCP for tool schema.
    """Get the structure of files and directories in the repository.
    
    Args:
        sub_path: Optional subdirectory path relative to repository root
        depth: Optional maximum depth to traverse (default is 3)
    """
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. It states what the tool does but lacks behavioral details such as whether this is a read-only operation, potential rate limits, error conditions, or the format of the returned structure. The description doesn't contradict annotations, but it's insufficient for a mutation-free tool with zero annotation coverage.

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 appropriately sized and front-loaded with the purpose in the first sentence, followed by parameter details. It's efficient with no wasted sentences, though the parameter explanations could be slightly more integrated into the flow.

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 (2 optional parameters) and lack of annotations or output schema, the description is partially complete. It covers the purpose and parameters well but misses behavioral context and usage guidelines, leaving gaps for an AI agent to understand full tool behavior.

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

Parameters5/5

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

The description adds significant meaning beyond the input schema, which has 0% description coverage. It explains that 'sub_path' is an 'Optional subdirectory path relative to repository root' and 'depth' is an 'Optional maximum depth to traverse (default is 3)', providing clear semantics and default values not present in the schema.

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: 'Get the structure of files and directories in the repository.' This is a specific verb ('Get') and resource ('structure of files and directories'), though it doesn't explicitly distinguish from sibling tools like 'get_repo_info' or 'read_file'.

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 sibling tools like 'get_repo_info' (which might provide metadata) or 'read_file' (which reads file contents), nor does it specify prerequisites or exclusions for usage.

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/saiprashanths/code-analysis-mcp'

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