Zoro-147 commited on
Commit
22c4490
·
verified ·
1 Parent(s): b311b0f

Update server.py

Browse files
Files changed (1) hide show
  1. server.py +117 -0
server.py CHANGED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Module 1: Basic MCP Server - Starter Code
4
+ TODO: Implement tools for analyzing git changes and suggesting PR templates
5
+ """
6
+
7
+ import json
8
+ import subprocess
9
+ from pathlib import Path
10
+
11
+ from mcp.server.fastmcp import FastMCP
12
+
13
+ # Initialize the FastMCP server
14
+ mcp = FastMCP("pr-agent")
15
+
16
+ # PR template directory (shared across all modules)
17
+ TEMPLATES_DIR = Path(__file__).parent.parent.parent / "templates"
18
+
19
+
20
+ @mcp.tool()
21
+ async def analyze_file_changes(base_branch: str = "main",
22
+ include_diff: bool = True,
23
+ max_diff_lines: int = 500) -> str:
24
+ """Analyze file changes with smart output limiting.
25
+
26
+ Args:
27
+ base_branch: Branch to compare against
28
+ include_diff: Whether to include the actual diff
29
+ max_diff_lines: Maximum diff lines to include (default 500)
30
+ """
31
+ try:
32
+ # Get the diff
33
+ result = subprocess.run(
34
+ ["git", "diff", f"{base_branch}...HEAD"],
35
+ capture_output=True,
36
+ text=True
37
+ )
38
+
39
+ diff_output = result.stdout
40
+ diff_lines = diff_output.split('\n')
41
+
42
+ # Smart truncation if needed
43
+ if len(diff_lines) > max_diff_lines:
44
+ truncated_diff = '\n'.join(diff_lines[:max_diff_lines])
45
+ truncated_diff += f"\n\n... Output truncated. Showing {max_diff_lines} of {len(diff_lines)} lines ..."
46
+ diff_output = truncated_diff
47
+
48
+ # Get summary statistics
49
+ stats_result = subprocess.run(
50
+ ["git", "diff", "--stat", f"{base_branch}...HEAD"],
51
+ capture_output=True,
52
+ text=True
53
+ )
54
+
55
+ return json.dumps({
56
+ "stats": stats_result.stdout,
57
+ "total_lines": len(diff_lines),
58
+ "diff": diff_output if include_diff else "Use include_diff=true to see diff",
59
+ "files_changed": self._get_changed_files(base_branch)
60
+ })
61
+
62
+ except Exception as e:
63
+ return json.dumps({"error": str(e)})
64
+
65
+
66
+ @mcp.tool()
67
+ async def get_pr_templates() -> str:
68
+ """List available PR templates with their content."""
69
+ templates = {}
70
+ if not TEMPLATES_DIR.exists():
71
+ return json.dumps({"error": f"Templates directory not found: {TEMPLATES_DIR}"})
72
+
73
+ try:
74
+ for template_file in TEMPLATES_DIR.glob("*.md"):
75
+ templates[template_file.stem] = template_file.read_text()
76
+ return json.dumps(templates)
77
+ except Exception as e:
78
+ return json.dumps({"error": f"Failed to read PR templates: {str(e)}"})
79
+
80
+
81
+ @mcp.tool()
82
+ async def suggest_template(changes_summary: str, change_type: str) -> str:
83
+ """Let Claude analyze the changes and suggest the most appropriate PR template.
84
+
85
+ Args:
86
+ changes_summary: Your analysis of what the changes do
87
+ change_type: The type of change you've identified (bug, feature, docs, refactor, test, etc.)
88
+ """
89
+ templates = json.loads(await get_pr_templates())
90
+ if "error" in templates:
91
+ return json.dumps(templates) # Propagate error from get_pr_templates
92
+
93
+ # Simple mapping logic. This can be made more sophisticated.
94
+ suggested_template_name = "default"
95
+ if change_type.lower() in ["bug", "fix"]:
96
+ suggested_template_name = "bug_fix"
97
+ elif change_type.lower() in ["feat", "feature"]:
98
+ suggested_template_name = "feature"
99
+ elif change_type.lower() in ["docs", "documentation"]:
100
+ suggested_template_name = "documentation"
101
+ elif change_type.lower() in ["refactor"]:
102
+ suggested_template_name = "refactor"
103
+ elif change_type.lower() in ["test", "tests"]:
104
+ suggested_template_name = "testing"
105
+
106
+ # Fallback if specific template not found but default exists
107
+ if suggested_template_name not in templates and "default" in templates:
108
+ suggested_template_name = "default"
109
+
110
+ if suggested_template_name in templates:
111
+ return json.dumps({"suggested_template": suggested_template_name, "content": templates[suggested_template_name]})
112
+ else:
113
+ return json.dumps({"error": f"No suitable template found for change type '{change_type}'. Available templates: {list(templates.keys())}"})
114
+
115
+
116
+ if __name__ == "__main__":
117
+ mcp.run()