forked from AOSSIE-Org/Devr.AI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgithub_mcp_client.py
More file actions
105 lines (90 loc) · 3.93 KB
/
github_mcp_client.py
File metadata and controls
105 lines (90 loc) · 3.93 KB
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
101
102
103
104
105
import logging
import os
from typing import Dict, Any, Optional
import aiohttp
import asyncio
logger = logging.getLogger(__name__)
class GitHubMCPClient:
"""
Client for communicating with the GitHub MCP server.
"""
def __init__(self, mcp_server_url: str = "http://localhost:8001"):
self.mcp_server_url = mcp_server_url
self.session: Optional[aiohttp.ClientSession] = None
# Default org pulled from environment
self.org = os.getenv("GITHUB_ORG", "Aossie-org")
async def __aenter__(self):
# Async context manager entry
self.session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=15))
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
# Async context manager exit
if self.session:
await self.session.close()
async def get_github_supp(self, repo: str, owner: Optional[str] = None) -> Dict[str, Any]:
"""
Fetch metadata for a single repository.
Owner defaults to org from environment if not provided.
"""
if not self.session:
raise RuntimeError("Client not initialized. Use async context manager.")
owner = owner or self.org
try:
payload = {"owner": owner, "repo": repo}
async with self.session.post(
f"{self.mcp_server_url}/github_support",
json=payload,
headers={"Content-Type": "application/json"},
) as response:
if response.status == 200:
result = await response.json()
if result.get("status") == "success":
return result.get("data", {})
else:
return {"error": result.get("error", "Unknown error")}
else:
logger.error(f"MCP server error: {response.status}")
return {"error": f"MCP server error: {response.status}"}
except aiohttp.ClientError as e:
logger.error(f"Error communicating with MCP server: {e}")
return {"error": f"Communication error: {str(e)}"}
except Exception as e:
logger.error(f"Unexpected error: {e}")
return {"error": f"Unexpected error: {str(e)}"}
async def list_org_repos(self, org: str) -> Dict[str, Any]:
if not self.session:
raise RuntimeError("Client not initialized. Use async context manager.")
try:
payload = {"org": org}
async with self.session.post(
f"{self.mcp_server_url}/list_org_repos",
json=payload,
headers={"Content-Type": "application/json"},
) as response:
if response.status == 200:
result = await response.json()
if result.get("status") == "success":
return result.get("data", [])
else:
return {"error": result.get("error", "Unknown error")}
else:
logger.error(f"MCP server error: {response.status}")
return {"error": f"MCP server error: {response.status}"}
except aiohttp.ClientError as e:
logger.error(f"Error communicating with MCP server: {e}")
return {"error": f"Communication error: {str(e)}"}
except Exception as e:
logger.error(f"Unexpected error: {e}")
return {"error": f"Unexpected error: {str(e)}"}
async def is_server_available(self) -> bool:
"""
Health check for MCP server.
"""
if not self.session:
return False
try:
async with self.session.get(f"{self.mcp_server_url}/health", timeout=5) as response:
return response.status == 200
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
logger.debug(f"Health check failed: {e}")
return False