HimanshuGoyal2004 commited on
Commit
a9142dd
Β·
1 Parent(s): 46e1964

server made

Browse files
Files changed (3) hide show
  1. README.md +1 -3
  2. app.py +215 -0
  3. requirements.txt +3 -0
README.md CHANGED
@@ -7,6 +7,4 @@ sdk: gradio
7
  sdk_version: 5.45.0
8
  app_file: app.py
9
  pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
7
  sdk_version: 5.45.0
8
  app_file: app.py
9
  pinned: false
10
+ ---
 
 
app.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ GitHub MCP Server with Gradio Interface
3
+ Provides GitHub repository scanning and file content access via MCP
4
+ """
5
+
6
+ import json
7
+ import os
8
+ import base64
9
+ from typing import Dict, List
10
+ import requests
11
+ import gradio as gr
12
+ from dotenv import load_dotenv
13
+
14
+ # Load environment variables
15
+ load_dotenv()
16
+
17
+ class GitHubMCPServer:
18
+ """GitHub MCP Server for repository scanning and file access"""
19
+
20
+ def __init__(self):
21
+ self.github_token = os.getenv("GITHUB_TOKEN")
22
+ if not self.github_token:
23
+ raise ValueError("GITHUB_TOKEN environment variable is required")
24
+
25
+ self.headers = {
26
+ "Authorization": f"token {self.github_token}",
27
+ "Accept": "application/vnd.github.v3+json"
28
+ }
29
+
30
+ def get_repository_info(self, owner: str, repo: str) -> str:
31
+ """Get basic repository information"""
32
+ try:
33
+ url = f"https://api.github.com/repos/{owner}/{repo}"
34
+ response = requests.get(url, headers=self.headers)
35
+
36
+ if response.status_code == 200:
37
+ data = response.json()
38
+ result = {
39
+ "success": True,
40
+ "data": {
41
+ "name": data["name"],
42
+ "full_name": data["full_name"],
43
+ "description": data.get("description", ""),
44
+ "language": data.get("language", ""),
45
+ "size": data["size"],
46
+ "stars": data["stargazers_count"],
47
+ "forks": data["forks_count"],
48
+ "default_branch": data["default_branch"],
49
+ "created_at": data["created_at"],
50
+ "updated_at": data["updated_at"]
51
+ }
52
+ }
53
+ else:
54
+ result = {
55
+ "success": False,
56
+ "error": f"GitHub API error: {response.status_code}"
57
+ }
58
+
59
+ return json.dumps(result, indent=2)
60
+
61
+ except Exception as e:
62
+ return json.dumps({"success": False, "error": str(e)}, indent=2)
63
+
64
+ def get_file_content(self, owner: str, repo: str, path: str) -> str:
65
+ """Get content of a specific file"""
66
+ try:
67
+ url = f"https://api.github.com/repos/{owner}/{repo}/contents/{path}"
68
+ response = requests.get(url, headers=self.headers)
69
+
70
+ if response.status_code == 200:
71
+ data = response.json()
72
+ if data["type"] == "file" and "content" in data:
73
+ # Decode base64 content
74
+ content = base64.b64decode(data["content"]).decode('utf-8')
75
+ result = {
76
+ "success": True,
77
+ "data": {
78
+ "path": path,
79
+ "content": content[:2000] + "..." if len(content) > 2000 else content, # Truncate for display
80
+ "size": len(content),
81
+ "sha": data["sha"],
82
+ "encoding": data.get("encoding", "base64")
83
+ }
84
+ }
85
+ else:
86
+ result = {
87
+ "success": False,
88
+ "error": "Not a file or content not available"
89
+ }
90
+ else:
91
+ result = {
92
+ "success": False,
93
+ "error": f"GitHub API error: {response.status_code}"
94
+ }
95
+
96
+ return json.dumps(result, indent=2)
97
+
98
+ except Exception as e:
99
+ return json.dumps({"success": False, "error": str(e)}, indent=2)
100
+
101
+ def scan_repository(self, owner: str, repo: str, extensions: str = ".py,.js,.ts,.php,.java") -> str:
102
+ """Scan repository for code files"""
103
+ try:
104
+ ext_list = [ext.strip() for ext in extensions.split(",")]
105
+ all_files = []
106
+ self._scan_directory_sync(owner, repo, "", ext_list, all_files)
107
+
108
+ result = {
109
+ "success": True,
110
+ "data": {
111
+ "total_files": len(all_files),
112
+ "files": all_files[:50] # Limit to first 50 files for display
113
+ }
114
+ }
115
+
116
+ return json.dumps(result, indent=2)
117
+
118
+ except Exception as e:
119
+ return json.dumps({"success": False, "error": str(e)}, indent=2)
120
+
121
+ def _scan_directory_sync(self, owner: str, repo: str, path: str, extensions: List[str], all_files: List[Dict]):
122
+ """Recursively scan directory for files"""
123
+ try:
124
+ url = f"https://api.github.com/repos/{owner}/{repo}/contents/{path}"
125
+ response = requests.get(url, headers=self.headers)
126
+
127
+ if response.status_code == 200:
128
+ data = response.json()
129
+ for item in data:
130
+ if item["type"] == "file":
131
+ if any(item["name"].endswith(ext) for ext in extensions):
132
+ all_files.append({
133
+ "name": item["name"],
134
+ "path": item["path"],
135
+ "type": item["type"],
136
+ "size": item.get("size", 0),
137
+ "sha": item["sha"]
138
+ })
139
+ elif item["type"] == "dir" and len(all_files) < 100:
140
+ self._scan_directory_sync(owner, repo, item["path"], extensions, all_files)
141
+ except Exception:
142
+ pass
143
+
144
+ # Initialize the GitHub MCP server
145
+ github_server = GitHubMCPServer()
146
+
147
+ # Create Gradio interface
148
+ with gr.Blocks(title="GitHub MCP Server", theme=gr.themes.Soft()) as demo:
149
+ gr.Markdown("# πŸ™ GitHub MCP Server")
150
+ gr.Markdown("Access GitHub repositories via Model Context Protocol")
151
+
152
+ with gr.Tabs():
153
+ with gr.Tab("Repository Info"):
154
+ gr.Markdown("### Get Repository Information")
155
+ with gr.Row():
156
+ repo_owner = gr.Textbox(label="Repository Owner", placeholder="octocat")
157
+ repo_name = gr.Textbox(label="Repository Name", placeholder="Hello-World")
158
+
159
+ repo_info_btn = gr.Button("Get Repository Info", variant="primary")
160
+ repo_info_output = gr.Textbox(label="Repository Information", lines=15)
161
+
162
+ repo_info_btn.click(
163
+ fn=github_server.get_repository_info,
164
+ inputs=[repo_owner, repo_name],
165
+ outputs=repo_info_output
166
+ )
167
+
168
+ with gr.Tab("File Content"):
169
+ gr.Markdown("### Get File Content")
170
+ with gr.Row():
171
+ file_owner = gr.Textbox(label="Repository Owner", placeholder="octocat")
172
+ file_repo = gr.Textbox(label="Repository Name", placeholder="Hello-World")
173
+
174
+ file_path = gr.Textbox(label="File Path", placeholder="README.md")
175
+
176
+ file_content_btn = gr.Button("Get File Content", variant="primary")
177
+ file_content_output = gr.Textbox(label="File Content", lines=20)
178
+
179
+ file_content_btn.click(
180
+ fn=github_server.get_file_content,
181
+ inputs=[file_owner, file_repo, file_path],
182
+ outputs=file_content_output
183
+ )
184
+
185
+ with gr.Tab("Repository Scanner"):
186
+ gr.Markdown("### Scan Repository for Code Files")
187
+ with gr.Row():
188
+ scan_owner = gr.Textbox(label="Repository Owner", placeholder="octocat")
189
+ scan_repo = gr.Textbox(label="Repository Name", placeholder="Hello-World")
190
+
191
+ scan_extensions = gr.Textbox(
192
+ label="File Extensions",
193
+ value=".py,.js,.ts,.php,.java",
194
+ placeholder=".py,.js,.ts,.php,.java"
195
+ )
196
+
197
+ scan_btn = gr.Button("Scan Repository", variant="primary")
198
+ scan_output = gr.Textbox(label="Scan Results", lines=20)
199
+
200
+ scan_btn.click(
201
+ fn=github_server.scan_repository,
202
+ inputs=[scan_owner, scan_repo, scan_extensions],
203
+ outputs=scan_output
204
+ )
205
+
206
+ gr.Markdown("---")
207
+ gr.Markdown("πŸ’‘ **Setup**: Add your `GITHUB_TOKEN` to environment variables or `.env` file")
208
+ gr.Markdown("πŸš€ **Deploy**: This server can be deployed on Hugging Face Spaces with MCP support")
209
+
210
+ if __name__ == "__main__":
211
+ print("πŸš€ Starting GitHub MCP Server with Gradio...")
212
+ print("πŸ“‘ Server will provide GitHub repository access via MCP")
213
+ print("πŸ› οΈ Available tools: repository info, file content, repository scanner")
214
+
215
+ demo.launch(mcp_server=True)
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio>=4.0.0
2
+ requests>=2.28.0
3
+ python-dotenv>=1.0.0