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) """

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