Spaces:
Sleeping
Sleeping
File size: 3,794 Bytes
42c47d4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
"""MCP Tools - CodeAtlas functions exposed via MCP protocol"""
import logging
from typing import Optional
from .server import mcp
from ..core.repository import RepositoryLoader
from ..core.analyzer import CodeAnalyzer
from ..core.diagram import DiagramGenerator
logger = logging.getLogger("codeatlas.mcp.tools")
@mcp.tool()
def analyze_codebase(api_key: str, github_url: Optional[str] = None, file_path: Optional[str] = None, model_name: str = "gemini-2.5-flash") -> str:
"""Analyze a codebase and generate a Graphviz DOT architecture diagram."""
logger.info(f"analyze_codebase: url={github_url}, file={file_path}, model={model_name}")
if not github_url and not file_path:
return "Error: Please provide either a GitHub URL or a file path."
if not api_key:
return "Error: API key is required."
loader = RepositoryLoader()
result = loader.load_from_file(file_path) if file_path else loader.load_from_github(github_url)
if result.error:
return f"Error: {result.error}"
logger.info(f"Loaded: {result.stats.files_processed} files, {result.stats.total_characters:,} chars")
analyzer = CodeAnalyzer(api_key=api_key, model_name=model_name)
analysis = analyzer.generate_diagram(result.context)
if not analysis.success:
return f"Error: {analysis.error}"
DiagramGenerator()._save_diagram(analysis.content, "raw", result.repo_name)
return analysis.content
@mcp.tool()
def get_architecture_summary(api_key: str, github_url: Optional[str] = None, file_path: Optional[str] = None, model_name: str = "gemini-2.5-flash") -> str:
"""Generate a text summary of a codebase's architecture."""
logger.info(f"get_architecture_summary: url={github_url}, file={file_path}")
if not github_url and not file_path:
return "Error: Please provide either a GitHub URL or a file path."
if not api_key:
return "Error: API key is required."
loader = RepositoryLoader()
result = loader.load_from_file(file_path) if file_path else loader.load_from_github(github_url)
if result.error:
return f"Error: {result.error}"
analyzer = CodeAnalyzer(api_key=api_key, model_name=model_name)
analysis = analyzer.generate_summary(result.context)
return analysis.content if analysis.success else f"Error: {analysis.error}"
@mcp.tool()
def chat_with_codebase(api_key: str, question: str, github_url: Optional[str] = None, file_path: Optional[str] = None, model_name: str = "gemini-2.5-flash") -> str:
"""Ask questions about a codebase and get AI-powered answers."""
logger.info(f"chat_with_codebase: question={question[:50]}...")
if not github_url and not file_path:
return "Error: Please provide either a GitHub URL or a file path."
if not api_key:
return "Error: API key is required."
if not question or not question.strip():
return "Error: Please provide a question."
loader = RepositoryLoader()
result = loader.load_from_file(file_path) if file_path else loader.load_from_github(github_url)
if result.error:
return f"Error: {result.error}"
analyzer = CodeAnalyzer(api_key=api_key, model_name=model_name)
response = analyzer.chat(question, result.context)
return response.content if response.success else f"Error: {response.error}"
@mcp.tool()
def list_recent_analyses() -> str:
"""List recently analyzed codebases."""
history = DiagramGenerator().get_history(limit=10)
if not history:
return "No recent analyses found."
lines = ["Recent Analyses:"]
for i, d in enumerate(history, 1):
lines.append(f"{i}. {d.repo_name} — {d.formatted_timestamp}")
return "\n".join(lines)
|