Skip to main content
Glama
wrale

mcp-server-tree-sitter

by wrale

analyze_project

Analyze project structure and dependencies with customizable scan depth for detailed insights, supporting context-aware progress reporting in codebase analysis.

Instructions

Analyze overall project structure.

    Args:
        project: Project name
        scan_depth: Depth of detailed analysis (higher is slower)
        ctx: Optional MCP context for progress reporting

    Returns:
        Project analysis
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ctxNo
projectYes
scan_depthNo

Implementation Reference

  • The handler function for the 'analyze_project' MCP tool. It is registered via @mcp_server.tool() decorator and delegates to the core analysis helper.
    def analyze_project(project: str, scan_depth: int = 3, ctx: Optional[Any] = None) -> Dict[str, Any]:
        """Analyze overall project structure.
    
        Args:
            project: Project name
            scan_depth: Depth of detailed analysis (higher is slower)
            ctx: Optional MCP context for progress reporting
    
        Returns:
            Project analysis
        """
        from ..tools.analysis import analyze_project_structure
    
        return analyze_project_structure(project_registry.get_project(project), language_registry, scan_depth, ctx)
  • The core helper function implementing the project analysis logic, scanning languages, entry points, build files, directory/file counts, and symbol extraction from sample files.
    def analyze_project_structure(
        project: Any, language_registry: Any, scan_depth: int = 3, mcp_ctx: Optional[Any] = None
    ) -> Dict[str, Any]:
        """
        Analyze the overall structure of a project.
    
        Args:
            project: Project object
            language_registry: Language registry object
            scan_depth: Depth to scan for detailed analysis (higher is slower)
            mcp_ctx: Optional MCP context for progress reporting
    
        Returns:
            Project structure analysis
        """
        root = project.root_path
    
        # Create context for progress reporting
        ctx = MCPContext(mcp_ctx)
    
        with ctx.progress_scope(100, "Analyzing project structure") as progress:
            # Update language information (5%)
            project.scan_files(language_registry)
            progress.update(5)
    
        # Count files by language
        languages = project.languages
    
        # Find potential entry points based on common patterns
        entry_points = []
        entry_patterns = {
            "python": ["__main__.py", "main.py", "app.py", "run.py", "manage.py"],
            "javascript": ["index.js", "app.js", "main.js", "server.js"],
            "typescript": ["index.ts", "app.ts", "main.ts", "server.ts"],
            "go": ["main.go"],
            "rust": ["main.rs"],
            "java": ["Main.java", "App.java"],
        }
    
        for language, patterns in entry_patterns.items():
            if language in languages:
                for pattern in patterns:
                    # Look for pattern in root and src directories
                    for entry_path in ["", "src/", "lib/"]:
                        candidate = root / entry_path / pattern
                        if candidate.is_file():
                            rel_path = str(candidate.relative_to(root))
                            entry_points.append(
                                {
                                    "path": rel_path,
                                    "language": language,
                                }
                            )
    
        # Look for build configuration files
        build_files = []
        build_patterns = {
            "python": [
                "setup.py",
                "pyproject.toml",
                "requirements.txt",
                "Pipfile",
                "environment.yml",
            ],
            "javascript": ["package.json", "yarn.lock", "npm-shrinkwrap.json"],
            "typescript": ["tsconfig.json"],
            "go": ["go.mod", "go.sum"],
            "rust": ["Cargo.toml", "Cargo.lock"],
            "java": ["pom.xml", "build.gradle", "build.gradle.kts"],
            "generic": ["Makefile", "CMakeLists.txt", "Dockerfile", "docker-compose.yml"],
        }
    
        for category, patterns in build_patterns.items():
            for pattern in patterns:
                candidate = root / pattern
                if candidate.is_file():
                    rel_path = str(candidate.relative_to(root))
                    build_files.append(
                        {
                            "path": rel_path,
                            "type": category,
                        }
                    )
    
        # Analyze directory structure
        dir_counts: Counter = Counter()
        file_counts: Counter = Counter()
    
        for current_dir, dirs, files in os.walk(root):
            rel_dir = os.path.relpath(current_dir, root)
            if rel_dir == ".":
                rel_dir = ""
    
            # Skip hidden directories and common excludes
            # Get config from dependency injection
            from ..api import get_config
    
            config = get_config()
            dirs[:] = [d for d in dirs if not d.startswith(".") and d not in config.security.excluded_dirs]
    
            # Count directories
            dir_counts[rel_dir] = len(dirs)
    
            # Count files by extension
            for file in files:
                if file.startswith("."):
                    continue
    
                ext = os.path.splitext(file)[1].lower()[1:]
                if ext:
                    key = f"{rel_dir}/.{ext}" if rel_dir else f".{ext}"
                    file_counts[key] += 1
    
        # Detailed analysis of key files if scan_depth > 0
        key_files_analysis = {}
    
        if scan_depth > 0:
            # Analyze a sample of files from each language
            for language, _ in languages.items():
                extensions = [ext for ext, lang in language_registry._language_map.items() if lang == language]
    
                if not extensions:
                    continue
    
                # Find sample files
                sample_files = []
                for ext in extensions:
                    # Look for files with this extension
                    pattern = f"**/*.{ext}"
                    for path in root.glob(pattern):
                        if path.is_file():
                            rel_path = str(path.relative_to(root))
                            sample_files.append(rel_path)
    
                            if len(sample_files) >= scan_depth:
                                break
    
                    if len(sample_files) >= scan_depth:
                        break
    
                # Analyze sample files
                if sample_files:
                    language_analysis = []
    
                    for file_path in sample_files:
                        try:
                            symbols = extract_symbols(project, file_path, language_registry)
    
                            # Summarize symbols
                            symbol_counts = {
                                symbol_type: len(symbols_list) for symbol_type, symbols_list in symbols.items()
                            }
    
                            language_analysis.append(
                                {
                                    "file": file_path,
                                    "symbols": symbol_counts,
                                }
                            )
                        except Exception:
                            # Skip problematic files
                            continue
    
                    if language_analysis:
                        key_files_analysis[language] = language_analysis
    
        return {
            "name": project.name,
            "path": str(project.root_path),
            "languages": languages,
            "entry_points": entry_points,
            "build_files": build_files,
            "dir_counts": dict(dir_counts),
            "file_counts": dict(file_counts),
            "total_files": sum(languages.values()),
            "key_files_analysis": key_files_analysis,
        }

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/wrale/mcp-server-tree-sitter'

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